mirror of
https://github.com/corda/corda.git
synced 2025-06-19 07:38:22 +00:00
Change ServiceType to a sealed class from an abstract class
Allow AdvertisedServices to have their own identity and keys. Also, rationalise legalIdentity onto the local node's NodeInfo which is available on ServiceHub Fixup after rebase Remove legal identity that was on storage service. Now access via myInfo.legalIdentity and key via keyManagement lookup. Enforce singleton notary per node for now Tidy up based upon Rick's suggestions Handle PR comments clean up imports Fix typo Fixup rename Capitalise comment Eliminate unused variable warning Make changes based upon PR comments Cleanup whitespace changes
This commit is contained in:
@ -44,7 +44,7 @@ class NodeMonitorModelTest {
|
|||||||
thread {
|
thread {
|
||||||
driver {
|
driver {
|
||||||
val aliceNodeFuture = startNode("Alice")
|
val aliceNodeFuture = startNode("Alice")
|
||||||
val notaryNodeFuture = startNode("Notary", advertisedServices = setOf(ServiceInfo(SimpleNotaryService.Type)))
|
val notaryNodeFuture = startNode("Notary", advertisedServices = setOf(ServiceInfo(SimpleNotaryService.type)))
|
||||||
|
|
||||||
aliceNode = aliceNodeFuture.get()
|
aliceNode = aliceNodeFuture.get()
|
||||||
notaryNode = notaryNodeFuture.get()
|
notaryNode = notaryNodeFuture.get()
|
||||||
@ -79,8 +79,8 @@ class NodeMonitorModelTest {
|
|||||||
clientToService.onNext(ClientToServiceCommand.IssueCash(
|
clientToService.onNext(ClientToServiceCommand.IssueCash(
|
||||||
amount = Amount(100, USD),
|
amount = Amount(100, USD),
|
||||||
issueRef = OpaqueBytes(ByteArray(1, { 1 })),
|
issueRef = OpaqueBytes(ByteArray(1, { 1 })),
|
||||||
recipient = aliceNode.identity,
|
recipient = aliceNode.legalIdentity,
|
||||||
notary = notaryNode.identity
|
notary = notaryNode.notaryIdentity
|
||||||
))
|
))
|
||||||
|
|
||||||
vaultUpdates.expectEvents(isStrict = false) {
|
vaultUpdates.expectEvents(isStrict = false) {
|
||||||
@ -105,13 +105,13 @@ class NodeMonitorModelTest {
|
|||||||
clientToService.onNext(ClientToServiceCommand.IssueCash(
|
clientToService.onNext(ClientToServiceCommand.IssueCash(
|
||||||
amount = Amount(100, USD),
|
amount = Amount(100, USD),
|
||||||
issueRef = OpaqueBytes(ByteArray(1, { 1 })),
|
issueRef = OpaqueBytes(ByteArray(1, { 1 })),
|
||||||
recipient = aliceNode.identity,
|
recipient = aliceNode.legalIdentity,
|
||||||
notary = notaryNode.identity
|
notary = notaryNode.notaryIdentity
|
||||||
))
|
))
|
||||||
|
|
||||||
clientToService.onNext(ClientToServiceCommand.PayCash(
|
clientToService.onNext(ClientToServiceCommand.PayCash(
|
||||||
amount = Amount(100, Issued(PartyAndReference(aliceNode.identity, OpaqueBytes(ByteArray(1, { 1 }))), USD)),
|
amount = Amount(100, Issued(PartyAndReference(aliceNode.legalIdentity, OpaqueBytes(ByteArray(1, { 1 }))), USD)),
|
||||||
recipient = aliceNode.identity
|
recipient = aliceNode.legalIdentity
|
||||||
))
|
))
|
||||||
|
|
||||||
var issueSmId: StateMachineRunId? = null
|
var issueSmId: StateMachineRunId? = null
|
||||||
@ -146,7 +146,7 @@ class NodeMonitorModelTest {
|
|||||||
val signaturePubKeys = tx.sigs.map { it.by }.toSet()
|
val signaturePubKeys = tx.sigs.map { it.by }.toSet()
|
||||||
// Only Alice signed
|
// Only Alice signed
|
||||||
require(signaturePubKeys.size == 1)
|
require(signaturePubKeys.size == 1)
|
||||||
require(signaturePubKeys.contains(aliceNode.identity.owningKey))
|
require(signaturePubKeys.contains(aliceNode.legalIdentity.owningKey))
|
||||||
issueTx = tx
|
issueTx = tx
|
||||||
},
|
},
|
||||||
// MOVE
|
// MOVE
|
||||||
@ -156,8 +156,8 @@ class NodeMonitorModelTest {
|
|||||||
val signaturePubKeys = tx.sigs.map { it.by }.toSet()
|
val signaturePubKeys = tx.sigs.map { it.by }.toSet()
|
||||||
// Alice and Notary signed
|
// Alice and Notary signed
|
||||||
require(signaturePubKeys.size == 2)
|
require(signaturePubKeys.size == 2)
|
||||||
require(signaturePubKeys.contains(aliceNode.identity.owningKey))
|
require(signaturePubKeys.contains(aliceNode.legalIdentity.owningKey))
|
||||||
require(signaturePubKeys.contains(notaryNode.identity.owningKey))
|
require(signaturePubKeys.contains(notaryNode.notaryIdentity.owningKey))
|
||||||
moveTx = tx
|
moveTx = tx
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -188,7 +188,9 @@ class FloatingRatePaymentEvent(date: LocalDate,
|
|||||||
class InterestRateSwap() : Contract {
|
class InterestRateSwap() : Contract {
|
||||||
override val legalContractReference = SecureHash.sha256("is_this_the_text_of_the_contract ? TBD")
|
override val legalContractReference = SecureHash.sha256("is_this_the_text_of_the_contract ? TBD")
|
||||||
|
|
||||||
object OracleType : ServiceType("corda.interest_rates")
|
companion object {
|
||||||
|
val oracleType = ServiceType.corda.getSubType("interest_rates")
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This Common area contains all the information that is not leg specific.
|
* This Common area contains all the information that is not leg specific.
|
||||||
@ -657,7 +659,7 @@ class InterestRateSwap() : Contract {
|
|||||||
override val contract = IRS_PROGRAM_ID
|
override val contract = IRS_PROGRAM_ID
|
||||||
|
|
||||||
override val oracleType: ServiceType
|
override val oracleType: ServiceType
|
||||||
get() = OracleType
|
get() = InterestRateSwap.oracleType
|
||||||
|
|
||||||
override val ref = common.tradeID
|
override val ref = common.tradeID
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ fun ServiceHub.fillWithSomeTestCash(howMuch: Amount<Currency>,
|
|||||||
ownedBy: PublicKey? = null): Vault {
|
ownedBy: PublicKey? = null): Vault {
|
||||||
val amounts = calculateRandomlySizedAmounts(howMuch, atLeastThisManyStates, atMostThisManyStates, rng)
|
val amounts = calculateRandomlySizedAmounts(howMuch, atLeastThisManyStates, atMostThisManyStates, rng)
|
||||||
|
|
||||||
val myKey: PublicKey = ownedBy ?: storageService.myLegalIdentityKey.public
|
val myKey: PublicKey = ownedBy ?: myInfo.legalIdentity.owningKey
|
||||||
|
|
||||||
// We will allocate one state to one transaction, for simplicities sake.
|
// We will allocate one state to one transaction, for simplicities sake.
|
||||||
val cash = Cash()
|
val cash = Cash()
|
||||||
|
@ -8,6 +8,7 @@ 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.node.NodeInfo
|
import com.r3corda.core.node.NodeInfo
|
||||||
|
import com.r3corda.core.node.services.ServiceType
|
||||||
import com.r3corda.core.protocols.ProtocolLogic
|
import com.r3corda.core.protocols.ProtocolLogic
|
||||||
import com.r3corda.core.seconds
|
import com.r3corda.core.seconds
|
||||||
import com.r3corda.core.transactions.SignedTransaction
|
import com.r3corda.core.transactions.SignedTransaction
|
||||||
@ -113,7 +114,7 @@ object TwoPartyTradeProtocol {
|
|||||||
progressTracker.nextStep()
|
progressTracker.nextStep()
|
||||||
|
|
||||||
// Check that the tx proposed by the buyer is valid.
|
// Check that the tx proposed by the buyer is valid.
|
||||||
val wtx: WireTransaction = it.verifySignatures(myKeyPair.public, notaryNode.identity.owningKey)
|
val wtx: WireTransaction = it.verifySignatures(myKeyPair.public, notaryNode.notaryIdentity.owningKey)
|
||||||
logger.trace { "Received partially signed transaction: ${it.id}" }
|
logger.trace { "Received partially signed transaction: ${it.id}" }
|
||||||
|
|
||||||
// Download and check all the things that this transaction depends on and verify it is contract-valid,
|
// Download and check all the things that this transaction depends on and verify it is contract-valid,
|
||||||
|
@ -211,7 +211,7 @@ class CommercialPaperTestsGeneric {
|
|||||||
|
|
||||||
// BigCorp™ issues $10,000 of commercial paper, to mature in 30 days, owned initially by itself.
|
// BigCorp™ issues $10,000 of commercial paper, to mature in 30 days, owned initially by itself.
|
||||||
val faceValue = 10000.DOLLARS `issued by` DUMMY_CASH_ISSUER
|
val faceValue = 10000.DOLLARS `issued by` DUMMY_CASH_ISSUER
|
||||||
val issuance = bigCorpServices.storageService.myLegalIdentity.ref(1)
|
val issuance = bigCorpServices.myInfo.legalIdentity.ref(1)
|
||||||
val issueTX: SignedTransaction =
|
val issueTX: SignedTransaction =
|
||||||
CommercialPaper().generateIssue(issuance, faceValue, TEST_TX_TIME + 30.days, DUMMY_NOTARY).apply {
|
CommercialPaper().generateIssue(issuance, faceValue, TEST_TX_TIME + 30.days, DUMMY_NOTARY).apply {
|
||||||
setTime(TEST_TX_TIME, 30.seconds)
|
setTime(TEST_TX_TIME, 30.seconds)
|
||||||
|
@ -3,10 +3,21 @@ package com.r3corda.core.node
|
|||||||
import com.r3corda.core.crypto.Party
|
import com.r3corda.core.crypto.Party
|
||||||
import com.r3corda.core.messaging.SingleMessageRecipient
|
import com.r3corda.core.messaging.SingleMessageRecipient
|
||||||
import com.r3corda.core.node.services.ServiceInfo
|
import com.r3corda.core.node.services.ServiceInfo
|
||||||
|
import com.r3corda.core.node.services.ServiceType
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Information for an advertised service including the service specific identity information.
|
||||||
|
* The identity can be used in protocols and is distinct from the Node's legalIdentity
|
||||||
|
*/
|
||||||
|
data class ServiceEntry(val info: ServiceInfo, val identity: Party)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Info about a network node that acts on behalf of some form of contract party.
|
* Info about a network node that acts on behalf of some form of contract party.
|
||||||
*/
|
*/
|
||||||
data class NodeInfo(val address: SingleMessageRecipient, val identity: Party,
|
data class NodeInfo(val address: SingleMessageRecipient,
|
||||||
var advertisedServices: Set<ServiceInfo> = emptySet(),
|
val legalIdentity: Party,
|
||||||
val physicalLocation: PhysicalLocation? = null)
|
var advertisedServices: List<ServiceEntry> = emptyList(),
|
||||||
|
val physicalLocation: PhysicalLocation? = null) {
|
||||||
|
val notaryIdentity: Party get() = advertisedServices.single { it.info.type.isNotary() }.identity
|
||||||
|
fun serviceIdentities(type: ServiceType): List<Party> = advertisedServices.filter { it.info.type.isSubTypeOf(type) }.map { it.identity }
|
||||||
|
}
|
||||||
|
@ -8,6 +8,7 @@ import com.r3corda.core.contracts.TransactionState
|
|||||||
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.protocols.ProtocolLogic
|
import com.r3corda.core.protocols.ProtocolLogic
|
||||||
|
import java.security.KeyPair
|
||||||
import java.time.Clock
|
import java.time.Clock
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -27,6 +28,7 @@ interface ServiceHub {
|
|||||||
val networkMapCache: NetworkMapCache
|
val networkMapCache: NetworkMapCache
|
||||||
val schedulerService: SchedulerService
|
val schedulerService: SchedulerService
|
||||||
val clock: Clock
|
val clock: Clock
|
||||||
|
val myInfo: NodeInfo
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a list of [SignedTransaction]s, writes them to the local storage for validated transactions and then
|
* Given a list of [SignedTransaction]s, writes them to the local storage for validated transactions and then
|
||||||
@ -52,6 +54,23 @@ interface ServiceHub {
|
|||||||
* @throws IllegalProtocolLogicException or IllegalArgumentException if there are problems with the [logicType] or [args].
|
* @throws IllegalProtocolLogicException or IllegalArgumentException if there are problems with the [logicType] or [args].
|
||||||
*/
|
*/
|
||||||
fun <T : Any> invokeProtocolAsync(logicType: Class<out ProtocolLogic<T>>, vararg args: Any?): ListenableFuture<T>
|
fun <T : Any> invokeProtocolAsync(logicType: Class<out ProtocolLogic<T>>, vararg args: Any?): ListenableFuture<T>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper property to shorten code for fetching the Node's KeyPair associated with the
|
||||||
|
* public legalIdentity Party from the key management service.
|
||||||
|
* Typical use is during signing in protocols and for unit test signing.
|
||||||
|
*/
|
||||||
|
val legalIdentityKey: KeyPair get() = this.keyManagementService.toKeyPair(this.myInfo.legalIdentity.owningKey)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper property to shorten code for fetching the Node's KeyPair associated with the
|
||||||
|
* public notaryIdentity Party from the key management service. It is assumed that this is only
|
||||||
|
* used in contexts where the Node knows it is hosting a Notary Service. Otherwise, it will throw
|
||||||
|
* an IllegalArgumentException.
|
||||||
|
* Typical use is during signing in protocols and for unit test signing.
|
||||||
|
*/
|
||||||
|
val notaryIdentityKey: KeyPair get() = this.keyManagementService.toKeyPair(this.myInfo.notaryIdentity.owningKey)
|
||||||
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Given some [SignedTransaction]s, writes them to the local storage for validated transactions and then
|
* Given some [SignedTransaction]s, writes them to the local storage for validated transactions and then
|
||||||
|
@ -3,7 +3,7 @@ package com.r3corda.core.node.services
|
|||||||
/**
|
/**
|
||||||
* A container for additional information for an advertised service.
|
* A container for additional information for an advertised service.
|
||||||
*
|
*
|
||||||
* @param ServiceType the service type identifier
|
* @param type the ServiceType identifier
|
||||||
* @param name the service name, used for differentiating multiple services of the same type. Can also be used as a
|
* @param name the service name, used for differentiating multiple services of the same type. Can also be used as a
|
||||||
* grouping identifier for nodes collectively running a distributed service.
|
* grouping identifier for nodes collectively running a distributed service.
|
||||||
*/
|
*/
|
||||||
@ -12,7 +12,7 @@ data class ServiceInfo(val type: ServiceType, val name: String? = null) {
|
|||||||
fun parse(encoded: String): ServiceInfo {
|
fun parse(encoded: String): ServiceInfo {
|
||||||
val parts = encoded.split("|")
|
val parts = encoded.split("|")
|
||||||
require(parts.size > 0 && parts.size <= 2) { "Invalid number of elements found" }
|
require(parts.size > 0 && parts.size <= 2) { "Invalid number of elements found" }
|
||||||
val type = object : ServiceType(parts[0]) {}
|
val type = ServiceType.parse(parts[0])
|
||||||
val name = parts.getOrNull(1)
|
val name = parts.getOrNull(1)
|
||||||
return ServiceInfo(type, name)
|
return ServiceInfo(type, name)
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ package com.r3corda.core.node.services
|
|||||||
* map advertisements. Services that are purely local and are not providing functionality to other parts of the network
|
* map advertisements. Services that are purely local and are not providing functionality to other parts of the network
|
||||||
* don't need a declared service type.
|
* don't need a declared service type.
|
||||||
*/
|
*/
|
||||||
abstract class ServiceType(val id: String) {
|
sealed class ServiceType(val id: String) {
|
||||||
init {
|
init {
|
||||||
// Enforce:
|
// Enforce:
|
||||||
//
|
//
|
||||||
@ -14,14 +14,41 @@ abstract class ServiceType(val id: String) {
|
|||||||
require(id.matches(Regex("[a-z][a-zA-Z0-9._]+")))
|
require(id.matches(Regex("[a-z][a-zA-Z0-9._]+")))
|
||||||
}
|
}
|
||||||
|
|
||||||
override operator fun equals(other: Any?): Boolean =
|
private class ServiceTypeImpl(baseId: String, subTypeId: String) : ServiceType("$baseId.$subTypeId") {
|
||||||
if (other is ServiceType) {
|
init {
|
||||||
id == other.id
|
// only allowed one level of subtype
|
||||||
} else {
|
require(subTypeId.matches(Regex("[a-z]\\w+")))
|
||||||
false
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class ServiceTypeDirect(id: String) : ServiceType(id)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val corda: ServiceType
|
||||||
|
get() {
|
||||||
|
val stack = Throwable().stackTrace
|
||||||
|
val caller = stack.first().className
|
||||||
|
require(caller.startsWith("com.r3corda.")) { "Corda ServiceType namespace is reserved for Corda core components" }
|
||||||
|
return ServiceTypeDirect("corda")
|
||||||
|
}
|
||||||
|
|
||||||
|
val notary: ServiceType = corda.getSubType("notary")
|
||||||
|
val regulator: ServiceType = corda.getSubType("regulator")
|
||||||
|
|
||||||
|
fun getServiceType(namespace: String, typeId: String): ServiceType {
|
||||||
|
require(!namespace.startsWith("corda")) { "Corda namespace is protected" }
|
||||||
|
return ServiceTypeImpl(namespace, typeId)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun parse(id: String): ServiceType = ServiceTypeDirect(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getSubType(subTypeId: String): ServiceType = ServiceTypeImpl(id, subTypeId)
|
||||||
|
|
||||||
|
override operator fun equals(other: Any?): Boolean = (other is ServiceType) && (other.id == this.id)
|
||||||
|
|
||||||
fun isSubTypeOf(superType: ServiceType) = (id == superType.id) || id.startsWith(superType.id + ".")
|
fun isSubTypeOf(superType: ServiceType) = (id == superType.id) || id.startsWith(superType.id + ".")
|
||||||
|
fun isNotary() = isSubTypeOf(notary)
|
||||||
|
|
||||||
override fun hashCode(): Int = id.hashCode()
|
override fun hashCode(): Int = id.hashCode()
|
||||||
override fun toString(): String = id.toString()
|
override fun toString(): String = id.toString()
|
||||||
|
@ -191,14 +191,6 @@ interface StorageService {
|
|||||||
val attachments: AttachmentStorage
|
val attachments: AttachmentStorage
|
||||||
|
|
||||||
val stateMachineRecordedTransactionMapping: StateMachineRecordedTransactionMappingStorage
|
val stateMachineRecordedTransactionMapping: StateMachineRecordedTransactionMappingStorage
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the legal identity that this node is configured with. Assumed to be initialised when the node is
|
|
||||||
* first installed.
|
|
||||||
*/
|
|
||||||
//TODO this should be in the IdentityService, or somewhere not here
|
|
||||||
val myLegalIdentity: Party
|
|
||||||
val myLegalIdentityKey: KeyPair
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -52,7 +52,7 @@ abstract class AbstractStateReplacementProtocol<T> {
|
|||||||
|
|
||||||
progressTracker.currentStep = SIGNING
|
progressTracker.currentStep = SIGNING
|
||||||
|
|
||||||
val myKey = serviceHub.storageService.myLegalIdentity.owningKey
|
val myKey = serviceHub.myInfo.legalIdentity.owningKey
|
||||||
val me = listOf(myKey)
|
val me = listOf(myKey)
|
||||||
|
|
||||||
val signatures = if (participants == me) {
|
val signatures = if (participants == me) {
|
||||||
@ -74,7 +74,7 @@ abstract class AbstractStateReplacementProtocol<T> {
|
|||||||
val parties = participants.map {
|
val parties = participants.map {
|
||||||
val participantNode = serviceHub.networkMapCache.getNodeByPublicKey(it) ?:
|
val participantNode = serviceHub.networkMapCache.getNodeByPublicKey(it) ?:
|
||||||
throw IllegalStateException("Participant $it to state $originalState not found on the network")
|
throw IllegalStateException("Participant $it to state $originalState not found on the network")
|
||||||
participantNode.identity
|
participantNode.legalIdentity
|
||||||
}
|
}
|
||||||
|
|
||||||
val participantSignatures = parties.map { getParticipantSignature(it, stx) }
|
val participantSignatures = parties.map { getParticipantSignature(it, stx) }
|
||||||
@ -134,7 +134,7 @@ abstract class AbstractStateReplacementProtocol<T> {
|
|||||||
// TODO: catch only specific exceptions. However, there are numerous validation exceptions
|
// TODO: catch only specific exceptions. However, there are numerous validation exceptions
|
||||||
// that might occur (tx validation/resolution, invalid proposal). Need to rethink how
|
// that might occur (tx validation/resolution, invalid proposal). Need to rethink how
|
||||||
// we manage exceptions and maybe introduce some platform exception hierarchy
|
// we manage exceptions and maybe introduce some platform exception hierarchy
|
||||||
val myIdentity = serviceHub.storageService.myLegalIdentity
|
val myIdentity = serviceHub.myInfo.legalIdentity
|
||||||
val state = maybeProposal.unwrap { it.stateRef }
|
val state = maybeProposal.unwrap { it.stateRef }
|
||||||
val reason = StateReplacementRefused(myIdentity, state, e.message)
|
val reason = StateReplacementRefused(myIdentity, state, e.message)
|
||||||
|
|
||||||
@ -186,7 +186,7 @@ abstract class AbstractStateReplacementProtocol<T> {
|
|||||||
|
|
||||||
private fun checkMySignatureRequired(tx: WireTransaction) {
|
private fun checkMySignatureRequired(tx: WireTransaction) {
|
||||||
// TODO: use keys from the keyManagementService instead
|
// TODO: use keys from the keyManagementService instead
|
||||||
val myKey = serviceHub.storageService.myLegalIdentity.owningKey
|
val myKey = serviceHub.myInfo.legalIdentity.owningKey
|
||||||
require(myKey in tx.mustSign) { "Party is not a participant for any of the input states of transaction ${tx.id}" }
|
require(myKey in tx.mustSign) { "Party is not a participant for any of the input states of transaction ${tx.id}" }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,7 +195,10 @@ abstract class AbstractStateReplacementProtocol<T> {
|
|||||||
subProtocol(ResolveTransactionsProtocol(stx.tx, otherSide))
|
subProtocol(ResolveTransactionsProtocol(stx.tx, otherSide))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun sign(stx: SignedTransaction) = serviceHub.storageService.myLegalIdentityKey.signWithECDSA(stx.txBits)
|
private fun sign(stx: SignedTransaction): DigitalSignature.WithKey {
|
||||||
|
val myKey = serviceHub.legalIdentityKey
|
||||||
|
return myKey.signWithECDSA(stx.txBits)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: similar classes occur in other places (NotaryProtocol), need to consolidate
|
// TODO: similar classes occur in other places (NotaryProtocol), need to consolidate
|
||||||
|
@ -34,7 +34,7 @@ class BroadcastTransactionProtocol(val notarisedTransaction: SignedTransaction,
|
|||||||
|
|
||||||
// TODO: Messaging layer should handle this broadcast for us
|
// TODO: Messaging layer should handle this broadcast for us
|
||||||
val msg = NotifyTxRequest(notarisedTransaction, events)
|
val msg = NotifyTxRequest(notarisedTransaction, events)
|
||||||
participants.filter { it != serviceHub.storageService.myLegalIdentity }.forEach { participant ->
|
participants.filter { it != serviceHub.myInfo.legalIdentity }.forEach { participant ->
|
||||||
send(participant, msg)
|
send(participant, msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,8 @@ object NotaryChangeProtocol: AbstractStateReplacementProtocol<Party>() {
|
|||||||
val newState = state.withNotary(modification)
|
val newState = state.withNotary(modification)
|
||||||
val participants = state.data.participants
|
val participants = state.data.participants
|
||||||
val tx = TransactionType.NotaryChange.Builder(originalState.state.notary).withItems(originalState, newState)
|
val tx = TransactionType.NotaryChange.Builder(originalState.state.notary).withItems(originalState, newState)
|
||||||
tx.signWith(serviceHub.storageService.myLegalIdentityKey)
|
val myKey = serviceHub.legalIdentityKey
|
||||||
|
tx.signWith(myKey)
|
||||||
|
|
||||||
val stx = tx.toSignedTransaction(false)
|
val stx = tx.toSignedTransaction(false)
|
||||||
return Pair(stx, participants)
|
return Pair(stx, participants)
|
||||||
@ -63,7 +64,7 @@ object NotaryChangeProtocol: AbstractStateReplacementProtocol<Party>() {
|
|||||||
override fun verifyProposal(maybeProposal: UntrustworthyData<AbstractStateReplacementProtocol.Proposal<Party>>): AbstractStateReplacementProtocol.Proposal<Party> {
|
override fun verifyProposal(maybeProposal: UntrustworthyData<AbstractStateReplacementProtocol.Proposal<Party>>): AbstractStateReplacementProtocol.Proposal<Party> {
|
||||||
return maybeProposal.unwrap { proposal ->
|
return maybeProposal.unwrap { proposal ->
|
||||||
val newNotary = proposal.modification
|
val newNotary = proposal.modification
|
||||||
val isNotary = serviceHub.networkMapCache.notaryNodes.any { it.identity == newNotary }
|
val isNotary = serviceHub.networkMapCache.notaryNodes.any { it.notaryIdentity == newNotary }
|
||||||
require(isNotary) { "The proposed node $newNotary does not run a Notary service " }
|
require(isNotary) { "The proposed node $newNotary does not run a Notary service " }
|
||||||
|
|
||||||
val state = proposal.stateRef
|
val state = proposal.stateRef
|
||||||
|
@ -49,7 +49,7 @@ object NotaryProtocol {
|
|||||||
"Input states must have the same Notary"
|
"Input states must have the same Notary"
|
||||||
}
|
}
|
||||||
|
|
||||||
val request = SignRequest(stx, serviceHub.storageService.myLegalIdentity)
|
val request = SignRequest(stx, serviceHub.myInfo.legalIdentity)
|
||||||
val response = sendAndReceive<Result>(notaryParty, request)
|
val response = sendAndReceive<Result>(notaryParty, request)
|
||||||
|
|
||||||
return validateResponse(response)
|
return validateResponse(response)
|
||||||
@ -141,8 +141,9 @@ object NotaryProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun <T : Any> sign(bits: SerializedBytes<T>): DigitalSignature.LegallyIdentifiable {
|
private fun <T : Any> sign(bits: SerializedBytes<T>): DigitalSignature.LegallyIdentifiable {
|
||||||
val mySigningKey = serviceHub.storageService.myLegalIdentityKey
|
val myNodeInfo = serviceHub.myInfo
|
||||||
val myIdentity = serviceHub.storageService.myLegalIdentity
|
val myIdentity = myNodeInfo.notaryIdentity
|
||||||
|
val mySigningKey = serviceHub.notaryIdentityKey
|
||||||
return mySigningKey.signWithECDSA(bits, myIdentity)
|
return mySigningKey.signWithECDSA(bits, myIdentity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,7 @@ object TwoPartyDealProtocol {
|
|||||||
abstract val myKeyPair: KeyPair
|
abstract val myKeyPair: KeyPair
|
||||||
|
|
||||||
override fun getCounterpartyMarker(party: Party): Class<*> {
|
override fun getCounterpartyMarker(party: Party): Class<*> {
|
||||||
return if (serviceHub.networkMapCache.regulators.any { it.identity == party }) {
|
return if (serviceHub.networkMapCache.regulators.any { it.legalIdentity == party }) {
|
||||||
MarkerForBogusRegulatorProtocol::class.java
|
MarkerForBogusRegulatorProtocol::class.java
|
||||||
} else {
|
} else {
|
||||||
super.getCounterpartyMarker(party)
|
super.getCounterpartyMarker(party)
|
||||||
@ -104,7 +104,7 @@ object TwoPartyDealProtocol {
|
|||||||
progressTracker.nextStep()
|
progressTracker.nextStep()
|
||||||
|
|
||||||
// Check that the tx proposed by the buyer is valid.
|
// Check that the tx proposed by the buyer is valid.
|
||||||
val wtx: WireTransaction = stx.verifySignatures(myKeyPair.public, notaryNode.identity.owningKey)
|
val wtx: WireTransaction = stx.verifySignatures(myKeyPair.public, notaryNode.notaryIdentity.owningKey)
|
||||||
logger.trace { "Received partially signed transaction: ${stx.id}" }
|
logger.trace { "Received partially signed transaction: ${stx.id}" }
|
||||||
|
|
||||||
checkDependencies(stx)
|
checkDependencies(stx)
|
||||||
@ -155,7 +155,7 @@ object TwoPartyDealProtocol {
|
|||||||
if (regulators.isNotEmpty()) {
|
if (regulators.isNotEmpty()) {
|
||||||
// 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.
|
||||||
regulators.forEach { send(it.identity, fullySigned) }
|
regulators.forEach { send(it.serviceIdentities(ServiceType.regulator).first(), fullySigned) }
|
||||||
}
|
}
|
||||||
|
|
||||||
return fullySigned
|
return fullySigned
|
||||||
@ -277,7 +277,7 @@ object TwoPartyDealProtocol {
|
|||||||
override val progressTracker: ProgressTracker = Primary.tracker()) : Primary() {
|
override val progressTracker: ProgressTracker = Primary.tracker()) : Primary() {
|
||||||
|
|
||||||
override val notaryNode: NodeInfo get() =
|
override val notaryNode: NodeInfo get() =
|
||||||
serviceHub.networkMapCache.notaryNodes.filter { it.identity == payload.notary }.single()
|
serviceHub.networkMapCache.notaryNodes.filter { it.notaryIdentity == payload.notary }.single()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -301,7 +301,7 @@ object TwoPartyDealProtocol {
|
|||||||
// And add a request for timestamping: it may be that none of the contracts need this! But it can't hurt
|
// And add a request for timestamping: it may be that none of the contracts need this! But it can't hurt
|
||||||
// to have one.
|
// to have one.
|
||||||
ptx.setTime(serviceHub.clock.instant(), 30.seconds)
|
ptx.setTime(serviceHub.clock.instant(), 30.seconds)
|
||||||
return Pair(ptx, arrayListOf(deal.parties.single { it.name == serviceHub.storageService.myLegalIdentity.name }.owningKey))
|
return Pair(ptx, arrayListOf(deal.parties.single { it.name == serviceHub.myInfo.legalIdentity.name }.owningKey))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -326,7 +326,7 @@ object TwoPartyDealProtocol {
|
|||||||
|
|
||||||
// validate the party that initiated is the one on the deal and that the recipient corresponds with it.
|
// validate the party that initiated is the one on the deal and that the recipient corresponds with it.
|
||||||
// TODO: this is in no way secure and will be replaced by general session initiation logic in the future
|
// TODO: this is in no way secure and will be replaced by general session initiation logic in the future
|
||||||
val myName = serviceHub.storageService.myLegalIdentity.name
|
val myName = serviceHub.myInfo.legalIdentity.name
|
||||||
// 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()
|
||||||
|
|
||||||
@ -339,7 +339,7 @@ object TwoPartyDealProtocol {
|
|||||||
val fixOf = deal.nextFixingOf()!!
|
val fixOf = deal.nextFixingOf()!!
|
||||||
|
|
||||||
// TODO Do we need/want to substitute in new public keys for the Parties?
|
// TODO Do we need/want to substitute in new public keys for the Parties?
|
||||||
val myName = serviceHub.storageService.myLegalIdentity.name
|
val myName = serviceHub.myInfo.legalIdentity.name
|
||||||
val myOldParty = deal.parties.single { it.name == myName }
|
val myOldParty = deal.parties.single { it.name == myName }
|
||||||
|
|
||||||
val newDeal = deal
|
val newDeal = deal
|
||||||
@ -348,7 +348,7 @@ object TwoPartyDealProtocol {
|
|||||||
|
|
||||||
val oracle = serviceHub.networkMapCache.get(handshake.payload.oracleType).first()
|
val oracle = serviceHub.networkMapCache.get(handshake.payload.oracleType).first()
|
||||||
|
|
||||||
val addFixing = object : RatesFixProtocol(ptx, oracle.identity, fixOf, BigDecimal.ZERO, BigDecimal.ONE) {
|
val addFixing = object : RatesFixProtocol(ptx, oracle.serviceIdentities(handshake.payload.oracleType).first(), fixOf, BigDecimal.ZERO, BigDecimal.ONE) {
|
||||||
@Suspendable
|
@Suspendable
|
||||||
override fun beforeSigning(fix: Fix) {
|
override fun beforeSigning(fix: Fix) {
|
||||||
newDeal.generateFix(ptx, StateAndRef(txState, handshake.payload.ref), fix)
|
newDeal.generateFix(ptx, StateAndRef(txState, handshake.payload.ref), fix)
|
||||||
@ -381,13 +381,13 @@ object TwoPartyDealProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override val myKeyPair: KeyPair get() {
|
override val myKeyPair: KeyPair get() {
|
||||||
val myName = serviceHub.storageService.myLegalIdentity.name
|
val myName = serviceHub.myInfo.legalIdentity.name
|
||||||
val publicKey = dealToFix.state.data.parties.filter { it.name == myName }.single().owningKey
|
val publicKey = dealToFix.state.data.parties.filter { it.name == myName }.single().owningKey
|
||||||
return serviceHub.keyManagementService.toKeyPair(publicKey)
|
return serviceHub.keyManagementService.toKeyPair(publicKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
override val notaryNode: NodeInfo get() =
|
override val notaryNode: NodeInfo get() =
|
||||||
serviceHub.networkMapCache.notaryNodes.filter { it.identity == dealToFix.state.notary }.single()
|
serviceHub.networkMapCache.notaryNodes.filter { it.notaryIdentity == dealToFix.state.notary }.single()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -419,7 +419,7 @@ object TwoPartyDealProtocol {
|
|||||||
// TODO: this is not the eventual mechanism for identifying the parties
|
// TODO: this is not the eventual mechanism for identifying the parties
|
||||||
val fixableDeal = (dealToFix.data as FixableDealState)
|
val fixableDeal = (dealToFix.data as FixableDealState)
|
||||||
val sortedParties = fixableDeal.parties.sortedBy { it.name }
|
val sortedParties = fixableDeal.parties.sortedBy { it.name }
|
||||||
if (sortedParties[0].name == serviceHub.storageService.myLegalIdentity.name) {
|
if (sortedParties[0].name == serviceHub.myInfo.legalIdentity.name) {
|
||||||
val fixing = FixingSession(ref, fixableDeal.oracleType)
|
val fixing = FixingSession(ref, fixableDeal.oracleType)
|
||||||
// Start the Floater which will then kick-off the Fixer
|
// Start the Floater which will then kick-off the Fixer
|
||||||
subProtocol(Floater(sortedParties[1], fixing))
|
subProtocol(Floater(sortedParties[1], fixing))
|
||||||
|
@ -38,7 +38,7 @@ class ValidatingNotaryProtocol(otherSide: Party,
|
|||||||
|
|
||||||
private fun checkSignatures(stx: SignedTransaction) {
|
private fun checkSignatures(stx: SignedTransaction) {
|
||||||
try {
|
try {
|
||||||
stx.verifySignatures(serviceHub.storageService.myLegalIdentity.owningKey)
|
stx.verifySignatures(serviceHub.myInfo.legalIdentity.owningKey)
|
||||||
} catch(e: SignedTransaction.SignaturesMissingException) {
|
} catch(e: SignedTransaction.SignaturesMissingException) {
|
||||||
throw NotaryException(NotaryError.SignaturesMissing(e.missing))
|
throw NotaryException(NotaryError.SignaturesMissing(e.missing))
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ import kotlin.test.assertEquals
|
|||||||
import kotlin.test.assertFailsWith
|
import kotlin.test.assertFailsWith
|
||||||
|
|
||||||
class ServiceInfoTests {
|
class ServiceInfoTests {
|
||||||
val serviceType = object : ServiceType("corda.service.subservice") {}
|
val serviceType = ServiceType.getServiceType("test", "service").getSubType("subservice")
|
||||||
val name = "service.name"
|
val name = "service.name"
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -32,7 +32,7 @@ class ResolveTransactionsProtocolTest {
|
|||||||
val nodes = net.createSomeNodes()
|
val nodes = net.createSomeNodes()
|
||||||
a = nodes.partyNodes[0]
|
a = nodes.partyNodes[0]
|
||||||
b = nodes.partyNodes[1]
|
b = nodes.partyNodes[1]
|
||||||
notary = nodes.notaryNode.info.identity
|
notary = nodes.notaryNode.info.notaryIdentity
|
||||||
net.runNetwork()
|
net.runNetwork()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,7 +44,7 @@ class ResolveTransactionsProtocolTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `resolve from two hashes`() {
|
fun `resolve from two hashes`() {
|
||||||
val (stx1, stx2) = makeTransactions()
|
val (stx1, stx2) = makeTransactions()
|
||||||
val p = ResolveTransactionsProtocol(setOf(stx2.id), a.info.identity)
|
val p = ResolveTransactionsProtocol(setOf(stx2.id), a.info.legalIdentity)
|
||||||
val future = b.services.startProtocol("resolve", p)
|
val future = b.services.startProtocol("resolve", p)
|
||||||
net.runNetwork()
|
net.runNetwork()
|
||||||
val results = future.get()
|
val results = future.get()
|
||||||
@ -56,7 +56,7 @@ class ResolveTransactionsProtocolTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `dependency with an error`() {
|
fun `dependency with an error`() {
|
||||||
val stx = makeTransactions(signFirstTX = false).second
|
val stx = makeTransactions(signFirstTX = false).second
|
||||||
val p = ResolveTransactionsProtocol(setOf(stx.id), a.info.identity)
|
val p = ResolveTransactionsProtocol(setOf(stx.id), a.info.legalIdentity)
|
||||||
val future = b.services.startProtocol("resolve", p)
|
val future = b.services.startProtocol("resolve", p)
|
||||||
net.runNetwork()
|
net.runNetwork()
|
||||||
assertFailsWith(SignatureException::class) {
|
assertFailsWith(SignatureException::class) {
|
||||||
@ -67,7 +67,7 @@ class ResolveTransactionsProtocolTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `resolve from a signed transaction`() {
|
fun `resolve from a signed transaction`() {
|
||||||
val (stx1, stx2) = makeTransactions()
|
val (stx1, stx2) = makeTransactions()
|
||||||
val p = ResolveTransactionsProtocol(stx2, a.info.identity)
|
val p = ResolveTransactionsProtocol(stx2, a.info.legalIdentity)
|
||||||
val future = b.services.startProtocol("resolve", p)
|
val future = b.services.startProtocol("resolve", p)
|
||||||
net.runNetwork()
|
net.runNetwork()
|
||||||
future.get()
|
future.get()
|
||||||
@ -89,7 +89,7 @@ class ResolveTransactionsProtocolTest {
|
|||||||
a.services.recordTransactions(stx)
|
a.services.recordTransactions(stx)
|
||||||
cursor = stx
|
cursor = stx
|
||||||
}
|
}
|
||||||
val p = ResolveTransactionsProtocol(setOf(cursor.id), a.info.identity)
|
val p = ResolveTransactionsProtocol(setOf(cursor.id), a.info.legalIdentity)
|
||||||
p.transactionCountLimit = 40
|
p.transactionCountLimit = 40
|
||||||
val future = b.services.startProtocol("resolve", p)
|
val future = b.services.startProtocol("resolve", p)
|
||||||
net.runNetwork()
|
net.runNetwork()
|
||||||
@ -116,7 +116,7 @@ class ResolveTransactionsProtocolTest {
|
|||||||
|
|
||||||
a.services.recordTransactions(stx2, stx3)
|
a.services.recordTransactions(stx2, stx3)
|
||||||
|
|
||||||
val p = ResolveTransactionsProtocol(setOf(stx3.id), a.info.identity)
|
val p = ResolveTransactionsProtocol(setOf(stx3.id), a.info.legalIdentity)
|
||||||
val future = b.services.startProtocol("resolve", p)
|
val future = b.services.startProtocol("resolve", p)
|
||||||
net.runNetwork()
|
net.runNetwork()
|
||||||
future.get()
|
future.get()
|
||||||
@ -126,7 +126,7 @@ class ResolveTransactionsProtocolTest {
|
|||||||
fun attachment() {
|
fun attachment() {
|
||||||
val id = a.services.storageService.attachments.importAttachment("Some test file".toByteArray().opaque().open())
|
val id = a.services.storageService.attachments.importAttachment("Some test file".toByteArray().opaque().open())
|
||||||
val stx2 = makeTransactions(withAttachment = id).second
|
val stx2 = makeTransactions(withAttachment = id).second
|
||||||
val p = ResolveTransactionsProtocol(stx2, a.info.identity)
|
val p = ResolveTransactionsProtocol(stx2, a.info.legalIdentity)
|
||||||
val future = b.services.startProtocol("resolve", p)
|
val future = b.services.startProtocol("resolve", p)
|
||||||
net.runNetwork()
|
net.runNetwork()
|
||||||
future.get()
|
future.get()
|
||||||
|
@ -37,22 +37,22 @@ class Main : App() {
|
|||||||
driver(portAllocation = portAllocation) {
|
driver(portAllocation = portAllocation) {
|
||||||
|
|
||||||
val aliceNodeFuture = startNode("Alice")
|
val aliceNodeFuture = startNode("Alice")
|
||||||
val notaryNodeFuture = startNode("Notary", advertisedServices = setOf(ServiceInfo(SimpleNotaryService.Type)))
|
val notaryNodeFuture = startNode("Notary", advertisedServices = setOf(ServiceInfo(SimpleNotaryService.type)))
|
||||||
|
|
||||||
val aliceNode = aliceNodeFuture.get()
|
val aliceNode = aliceNodeFuture.get()
|
||||||
val notaryNode = notaryNodeFuture.get()
|
val notaryNode = notaryNodeFuture.get()
|
||||||
|
|
||||||
val aliceClient = startClient(aliceNode).get()
|
val aliceClient = startClient(aliceNode).get()
|
||||||
|
|
||||||
Models.get<IdentityModel>(Main::class).myIdentity.set(aliceNode.identity)
|
Models.get<IdentityModel>(Main::class).myIdentity.set(aliceNode.legalIdentity)
|
||||||
Models.get<NodeMonitorModel>(Main::class).register(aliceNode, aliceClient.config.certificatesPath)
|
Models.get<NodeMonitorModel>(Main::class).register(aliceNode, aliceClient.config.certificatesPath)
|
||||||
|
|
||||||
for (i in 0 .. 10000) {
|
for (i in 0 .. 10000) {
|
||||||
Thread.sleep(500)
|
Thread.sleep(500)
|
||||||
|
|
||||||
val eventGenerator = EventGenerator(
|
val eventGenerator = EventGenerator(
|
||||||
parties = listOf(aliceNode.identity),
|
parties = listOf(aliceNode.legalIdentity),
|
||||||
notary = notaryNode.identity
|
notary = notaryNode.notaryIdentity
|
||||||
)
|
)
|
||||||
|
|
||||||
eventGenerator.clientToServiceCommandGenerator.map { command ->
|
eventGenerator.clientToServiceCommandGenerator.map { command ->
|
||||||
|
@ -236,7 +236,7 @@ class NetworkMapVisualiser : Application() {
|
|||||||
if (change.tracker == tracker) {
|
if (change.tracker == tracker) {
|
||||||
// Protocol done; schedule it for removal in a few seconds. We batch them up to make nicer
|
// Protocol done; schedule it for removal in a few seconds. We batch them up to make nicer
|
||||||
// animations.
|
// animations.
|
||||||
println("Protocol done for ${node.info.identity.name}")
|
println("Protocol done for ${node.info.legalIdentity.name}")
|
||||||
viewModel.doneTrackers += tracker
|
viewModel.doneTrackers += tracker
|
||||||
} else {
|
} else {
|
||||||
// Subprotocol is done; ignore it.
|
// Subprotocol is done; ignore it.
|
||||||
@ -244,7 +244,7 @@ class NetworkMapVisualiser : Application() {
|
|||||||
} else if (!viewModel.trackerBoxes.containsKey(tracker)) {
|
} else if (!viewModel.trackerBoxes.containsKey(tracker)) {
|
||||||
// New protocol started up; add.
|
// New protocol started up; add.
|
||||||
val extraLabel = viewModel.simulation.extraNodeLabels[node]
|
val extraLabel = viewModel.simulation.extraNodeLabels[node]
|
||||||
val label = if (extraLabel != null) "${node.storage.myLegalIdentity.name}: $extraLabel" else node.storage.myLegalIdentity.name
|
val label = if (extraLabel != null) "${node.info.legalIdentity.name}: $extraLabel" else node.info.legalIdentity.name
|
||||||
val widget = view.buildProgressTrackerWidget(label, tracker.topLevelTracker)
|
val widget = view.buildProgressTrackerWidget(label, tracker.topLevelTracker)
|
||||||
bindProgressTracketWidget(tracker.topLevelTracker, widget)
|
bindProgressTracketWidget(tracker.topLevelTracker, widget)
|
||||||
println("Added: ${tracker}, ${widget}")
|
println("Added: ${tracker}, ${widget}")
|
||||||
|
@ -85,7 +85,7 @@ class VisualiserViewModel {
|
|||||||
try {
|
try {
|
||||||
return node.place.coordinate.project(view.mapImage.fitWidth, view.mapImage.fitHeight, 64.3209, 29.8406, -23.2031, 33.0469)
|
return node.place.coordinate.project(view.mapImage.fitWidth, view.mapImage.fitHeight, 64.3209, 29.8406, -23.2031, 33.0469)
|
||||||
} catch(e: Exception) {
|
} catch(e: Exception) {
|
||||||
throw Exception("Cannot project ${node.info.identity}", e)
|
throw Exception("Cannot project ${node.info.legalIdentity}", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ class DriverTests {
|
|||||||
// Check that the node is registered in the network map
|
// Check that the node is registered in the network map
|
||||||
poll("network map cache for $nodeName") {
|
poll("network map cache for $nodeName") {
|
||||||
networkMapCache.get().firstOrNull {
|
networkMapCache.get().firstOrNull {
|
||||||
it.identity.name == nodeName
|
it.legalIdentity.name == nodeName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check that the port is bound
|
// Check that the port is bound
|
||||||
@ -33,8 +33,8 @@ class DriverTests {
|
|||||||
@Test
|
@Test
|
||||||
fun simpleNodeStartupShutdownWorks() {
|
fun simpleNodeStartupShutdownWorks() {
|
||||||
val (notary, regulator) = driver {
|
val (notary, regulator) = driver {
|
||||||
val notary = startNode("TestNotary", setOf(ServiceInfo(SimpleNotaryService.Type)))
|
val notary = startNode("TestNotary", setOf(ServiceInfo(SimpleNotaryService.type)))
|
||||||
val regulator = startNode("Regulator", setOf(ServiceInfo(RegulatorService.Type)))
|
val regulator = startNode("Regulator", setOf(ServiceInfo(RegulatorService.type)))
|
||||||
|
|
||||||
nodeMustBeUp(networkMapCache, notary.get(), "TestNotary")
|
nodeMustBeUp(networkMapCache, notary.get(), "TestNotary")
|
||||||
nodeMustBeUp(networkMapCache, regulator.get(), "Regulator")
|
nodeMustBeUp(networkMapCache, regulator.get(), "Regulator")
|
||||||
|
@ -77,7 +77,7 @@ fun DriverDSLExposedInterface.startClient(localServer: ArtemisMessagingServer) =
|
|||||||
|
|
||||||
fun DriverDSLExposedInterface.startClient(remoteNodeInfo: NodeInfo, providedName: String? = null) =
|
fun DriverDSLExposedInterface.startClient(remoteNodeInfo: NodeInfo, providedName: String? = null) =
|
||||||
startClient(
|
startClient(
|
||||||
providedName = providedName ?: "${remoteNodeInfo.identity.name}-client",
|
providedName = providedName ?: "${remoteNodeInfo.legalIdentity.name}-client",
|
||||||
serverAddress = ArtemisMessagingComponent.toHostAndPort(remoteNodeInfo.address)
|
serverAddress = ArtemisMessagingComponent.toHostAndPort(remoteNodeInfo.address)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -309,7 +309,7 @@ class DriverDSL(
|
|||||||
registerProcess(DriverDSL.startNode(config, quasarJarPath, debugPort))
|
registerProcess(DriverDSL.startNode(config, quasarJarPath, debugPort))
|
||||||
poll("network map cache for $name") {
|
poll("network map cache for $name") {
|
||||||
networkMapCache.partyNodes.forEach {
|
networkMapCache.partyNodes.forEach {
|
||||||
if (it.identity.name == name) {
|
if (it.legalIdentity.name == name) {
|
||||||
return@poll it
|
return@poll it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -383,7 +383,7 @@ class DriverDSL(
|
|||||||
networkMapCache.addMapService(networkMapClient, networkMapAddr, true)
|
networkMapCache.addMapService(networkMapClient, networkMapAddr, true)
|
||||||
networkMapNodeInfo = poll("network map cache for $networkMapName") {
|
networkMapNodeInfo = poll("network map cache for $networkMapName") {
|
||||||
networkMapCache.partyNodes.forEach {
|
networkMapCache.partyNodes.forEach {
|
||||||
if (it.identity.name == networkMapName) {
|
if (it.legalIdentity.name == networkMapName) {
|
||||||
return@poll it
|
return@poll it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,7 @@ import com.r3corda.core.RunOnCallerThread
|
|||||||
import com.r3corda.core.crypto.Party
|
import com.r3corda.core.crypto.Party
|
||||||
import com.r3corda.core.crypto.X509Utilities
|
import com.r3corda.core.crypto.X509Utilities
|
||||||
import com.r3corda.core.messaging.SingleMessageRecipient
|
import com.r3corda.core.messaging.SingleMessageRecipient
|
||||||
import com.r3corda.core.node.CityDatabase
|
import com.r3corda.core.node.*
|
||||||
import com.r3corda.core.node.CordaPluginRegistry
|
|
||||||
import com.r3corda.core.node.NodeInfo
|
|
||||||
import com.r3corda.core.node.PhysicalLocation
|
|
||||||
import com.r3corda.core.node.services.*
|
import com.r3corda.core.node.services.*
|
||||||
import com.r3corda.core.node.services.NetworkMapCache.MapChangeType
|
import com.r3corda.core.node.services.NetworkMapCache.MapChangeType
|
||||||
import com.r3corda.core.protocols.ProtocolLogic
|
import com.r3corda.core.protocols.ProtocolLogic
|
||||||
@ -96,6 +93,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration, val netwo
|
|||||||
val servicesThatAcceptUploads: List<AcceptsFileUpload> = _servicesThatAcceptUploads
|
val servicesThatAcceptUploads: List<AcceptsFileUpload> = _servicesThatAcceptUploads
|
||||||
|
|
||||||
private val protocolFactories = ConcurrentHashMap<Class<*>, (Party) -> ProtocolLogic<*>>()
|
private val protocolFactories = ConcurrentHashMap<Class<*>, (Party) -> ProtocolLogic<*>>()
|
||||||
|
protected val partyKeys = mutableSetOf<KeyPair>()
|
||||||
|
|
||||||
val services = object : ServiceHubInternal() {
|
val services = object : ServiceHubInternal() {
|
||||||
override val networkService: MessagingServiceInternal get() = net
|
override val networkService: MessagingServiceInternal get() = net
|
||||||
@ -106,6 +104,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration, val netwo
|
|||||||
override val identityService: IdentityService get() = identity
|
override val identityService: IdentityService get() = identity
|
||||||
override val schedulerService: SchedulerService get() = scheduler
|
override val schedulerService: SchedulerService get() = scheduler
|
||||||
override val clock: Clock = platformClock
|
override val clock: Clock = platformClock
|
||||||
|
override val myInfo: NodeInfo get() = info
|
||||||
override val schemaService: SchemaService get() = schemas
|
override val schemaService: SchemaService get() = schemas
|
||||||
|
|
||||||
// Internal only
|
// Internal only
|
||||||
@ -130,7 +129,13 @@ abstract class AbstractNode(open val configuration: NodeConfiguration, val netwo
|
|||||||
}
|
}
|
||||||
|
|
||||||
val info: NodeInfo by lazy {
|
val info: NodeInfo by lazy {
|
||||||
NodeInfo(net.myAddress, storage.myLegalIdentity, advertisedServices, findMyLocation())
|
val services = mutableListOf<ServiceEntry>()
|
||||||
|
for (service in advertisedServices) {
|
||||||
|
val identity = obtainKeyPair(configuration.basedir, service.type.id + "-private-key", service.type.id + "-public", service.type.id).first
|
||||||
|
services += ServiceEntry(service, identity)
|
||||||
|
}
|
||||||
|
val legalIdentity = obtainLegalIdentity()
|
||||||
|
NodeInfo(net.myAddress, legalIdentity, services, findMyLocation())
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun findMyLocation(): PhysicalLocation? = CityDatabase[configuration.nearestCity]
|
open fun findMyLocation(): PhysicalLocation? = CityDatabase[configuration.nearestCity]
|
||||||
@ -214,7 +219,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration, val netwo
|
|||||||
|
|
||||||
// TODO: uniquenessProvider creation should be inside makeNotaryService(), but notary service initialisation
|
// TODO: uniquenessProvider creation should be inside makeNotaryService(), but notary service initialisation
|
||||||
// depends on smm, while smm depends on tokenizableServices, which uniquenessProvider is part of
|
// depends on smm, while smm depends on tokenizableServices, which uniquenessProvider is part of
|
||||||
advertisedServices.singleOrNull { it.type.isSubTypeOf(NotaryService.Type) }?.let {
|
advertisedServices.singleOrNull { it.type.isNotary() }?.let {
|
||||||
uniquenessProvider = makeUniquenessProvider()
|
uniquenessProvider = makeUniquenessProvider()
|
||||||
tokenizableServices.add(uniquenessProvider!!)
|
tokenizableServices.add(uniquenessProvider!!)
|
||||||
}
|
}
|
||||||
@ -321,10 +326,10 @@ abstract class AbstractNode(open val configuration: NodeConfiguration, val netwo
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun buildAdvertisedServices() {
|
private fun buildAdvertisedServices() {
|
||||||
val serviceTypes = info.advertisedServices.map { it.type }
|
val serviceTypes = info.advertisedServices.map { it.info.type }
|
||||||
if (NetworkMapService.Type in serviceTypes) makeNetworkMapService()
|
if (NetworkMapService.type in serviceTypes) makeNetworkMapService()
|
||||||
|
|
||||||
val notaryServiceType = serviceTypes.singleOrNull { it.isSubTypeOf(NotaryService.Type) }
|
val notaryServiceType = serviceTypes.singleOrNull { it.isNotary() }
|
||||||
if (notaryServiceType != null) {
|
if (notaryServiceType != null) {
|
||||||
inNodeNotaryService = makeNotaryService(notaryServiceType)
|
inNodeNotaryService = makeNotaryService(notaryServiceType)
|
||||||
}
|
}
|
||||||
@ -335,7 +340,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration, val netwo
|
|||||||
* updates) if one has been supplied.
|
* updates) if one has been supplied.
|
||||||
*/
|
*/
|
||||||
private fun registerWithNetworkMap(): ListenableFuture<Unit> {
|
private fun registerWithNetworkMap(): ListenableFuture<Unit> {
|
||||||
require(networkMapService != null || NetworkMapService.Type in advertisedServices.map { it.type }) {
|
require(networkMapService != null || NetworkMapService.type in advertisedServices.map { it.type }) {
|
||||||
"Initial network map address must indicate a node that provides a network map service"
|
"Initial network map address must indicate a node that provides a network map service"
|
||||||
}
|
}
|
||||||
services.networkMapCache.addNode(info)
|
services.networkMapCache.addNode(info)
|
||||||
@ -365,11 +370,12 @@ abstract class AbstractNode(open val configuration: NodeConfiguration, val netwo
|
|||||||
val instant = platformClock.instant()
|
val instant = platformClock.instant()
|
||||||
val expires = instant + NetworkMapService.DEFAULT_EXPIRATION_PERIOD
|
val expires = instant + NetworkMapService.DEFAULT_EXPIRATION_PERIOD
|
||||||
val reg = NodeRegistration(info, instant.toEpochMilli(), type, expires)
|
val reg = NodeRegistration(info, instant.toEpochMilli(), type, expires)
|
||||||
val request = NetworkMapService.RegistrationRequest(reg.toWire(storage.myLegalIdentityKey.private), net.myAddress)
|
val legalIdentityKey = obtainLegalIdentityKey()
|
||||||
|
val request = NetworkMapService.RegistrationRequest(reg.toWire(legalIdentityKey.private), net.myAddress)
|
||||||
return net.sendRequest(REGISTER_PROTOCOL_TOPIC, request, networkMapAddr, RunOnCallerThread)
|
return net.sendRequest(REGISTER_PROTOCOL_TOPIC, request, networkMapAddr, RunOnCallerThread)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun makeKeyManagementService(): KeyManagementService = PersistentKeyManagementService(setOf(storage.myLegalIdentityKey))
|
protected open fun makeKeyManagementService(): KeyManagementService = PersistentKeyManagementService(partyKeys)
|
||||||
|
|
||||||
open protected fun makeNetworkMapService() {
|
open protected fun makeNetworkMapService() {
|
||||||
inNodeNetworkMapService = PersistentNetworkMapService(services)
|
inNodeNetworkMapService = PersistentNetworkMapService(services)
|
||||||
@ -379,8 +385,8 @@ abstract class AbstractNode(open val configuration: NodeConfiguration, val netwo
|
|||||||
val timestampChecker = TimestampChecker(platformClock, 30.seconds)
|
val timestampChecker = TimestampChecker(platformClock, 30.seconds)
|
||||||
|
|
||||||
return when (type) {
|
return when (type) {
|
||||||
SimpleNotaryService.Type -> SimpleNotaryService(services, timestampChecker, uniquenessProvider!!)
|
SimpleNotaryService.type -> SimpleNotaryService(services, timestampChecker, uniquenessProvider!!)
|
||||||
ValidatingNotaryService.Type -> ValidatingNotaryService(services, timestampChecker, uniquenessProvider!!)
|
ValidatingNotaryService.type -> ValidatingNotaryService(services, timestampChecker, uniquenessProvider!!)
|
||||||
else -> {
|
else -> {
|
||||||
throw IllegalArgumentException("Notary type ${type.id} is not handled by makeNotaryService.")
|
throw IllegalArgumentException("Notary type ${type.id} is not handled by makeNotaryService.")
|
||||||
}
|
}
|
||||||
@ -392,13 +398,14 @@ abstract class AbstractNode(open val configuration: NodeConfiguration, val netwo
|
|||||||
protected open fun makeIdentityService(): IdentityService {
|
protected open fun makeIdentityService(): IdentityService {
|
||||||
val service = InMemoryIdentityService()
|
val service = InMemoryIdentityService()
|
||||||
|
|
||||||
service.registerIdentity(storage.myLegalIdentity)
|
service.registerIdentity(info.legalIdentity)
|
||||||
|
|
||||||
services.networkMapCache.partyNodes.forEach { service.registerIdentity(it.identity) }
|
services.networkMapCache.partyNodes.forEach { service.registerIdentity(it.legalIdentity) }
|
||||||
|
|
||||||
netMapCache.changed.subscribe { mapChange ->
|
netMapCache.changed.subscribe { mapChange ->
|
||||||
|
// TODO how should we handle network map removal
|
||||||
if (mapChange.type == MapChangeType.Added) {
|
if (mapChange.type == MapChangeType.Added) {
|
||||||
service.registerIdentity(mapChange.node.identity)
|
service.registerIdentity(mapChange.node.legalIdentity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -437,35 +444,42 @@ abstract class AbstractNode(open val configuration: NodeConfiguration, val netwo
|
|||||||
val checkpointStorage = initialiseCheckpointService(dir)
|
val checkpointStorage = initialiseCheckpointService(dir)
|
||||||
val transactionStorage = PerFileTransactionStorage(dir.resolve("transactions"))
|
val transactionStorage = PerFileTransactionStorage(dir.resolve("transactions"))
|
||||||
_servicesThatAcceptUploads += attachments
|
_servicesThatAcceptUploads += attachments
|
||||||
val (identity, keyPair) = obtainKeyPair(dir)
|
// Populate the partyKeys set.
|
||||||
|
obtainKeyPair(dir, PRIVATE_KEY_FILE_NAME, PUBLIC_IDENTITY_FILE_NAME)
|
||||||
|
for (service in advertisedServices) {
|
||||||
|
// Ensure all required keys exist.
|
||||||
|
obtainKeyPair(configuration.basedir, service.type.id + "-private-key", service.type.id + "-public", service.type.id)
|
||||||
|
}
|
||||||
val stateMachineTransactionMappingStorage = InMemoryStateMachineRecordedTransactionMappingStorage()
|
val stateMachineTransactionMappingStorage = InMemoryStateMachineRecordedTransactionMappingStorage()
|
||||||
return Pair(
|
return Pair(
|
||||||
constructStorageService(attachments, transactionStorage, stateMachineTransactionMappingStorage, keyPair, identity),
|
constructStorageService(attachments, transactionStorage, stateMachineTransactionMappingStorage),
|
||||||
checkpointStorage
|
checkpointStorage
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun constructStorageService(attachments: NodeAttachmentService,
|
protected open fun constructStorageService(attachments: NodeAttachmentService,
|
||||||
transactionStorage: TransactionStorage,
|
transactionStorage: TransactionStorage,
|
||||||
stateMachineRecordedTransactionMappingStorage: StateMachineRecordedTransactionMappingStorage,
|
stateMachineRecordedTransactionMappingStorage: StateMachineRecordedTransactionMappingStorage) =
|
||||||
keyPair: KeyPair,
|
StorageServiceImpl(attachments, transactionStorage, stateMachineRecordedTransactionMappingStorage)
|
||||||
identity: Party) =
|
|
||||||
StorageServiceImpl(attachments, transactionStorage, stateMachineRecordedTransactionMappingStorage, keyPair, identity)
|
|
||||||
|
|
||||||
private fun obtainKeyPair(dir: Path): Pair<Party, KeyPair> {
|
protected fun obtainLegalIdentity(): Party = obtainKeyPair(configuration.basedir, PRIVATE_KEY_FILE_NAME, PUBLIC_IDENTITY_FILE_NAME).first
|
||||||
|
protected fun obtainLegalIdentityKey(): KeyPair = obtainKeyPair(configuration.basedir, PRIVATE_KEY_FILE_NAME, PUBLIC_IDENTITY_FILE_NAME).second
|
||||||
|
|
||||||
|
private fun obtainKeyPair(dir: Path, privateKeyFileName: String, publicKeyFileName: String, serviceName: String? = null): Pair<Party, KeyPair> {
|
||||||
// Load the private identity key, creating it if necessary. The identity key is a long term well known key that
|
// Load the private identity key, creating it if necessary. The identity key is a long term well known key that
|
||||||
// is distributed to other peers and we use it (or a key signed by it) when we need to do something
|
// is distributed to other peers and we use it (or a key signed by it) when we need to do something
|
||||||
// "permissioned". The identity file is what gets distributed and contains the node's legal name along with
|
// "permissioned". The identity file is what gets distributed and contains the node's legal name along with
|
||||||
// the public key. Obviously in a real system this would need to be a certificate chain of some kind to ensure
|
// the public key. Obviously in a real system this would need to be a certificate chain of some kind to ensure
|
||||||
// the legal name is actually validated in some way.
|
// the legal name is actually validated in some way.
|
||||||
val privKeyFile = dir.resolve(PRIVATE_KEY_FILE_NAME)
|
val privKeyFile = dir.resolve(privateKeyFileName)
|
||||||
val pubIdentityFile = dir.resolve(PUBLIC_IDENTITY_FILE_NAME)
|
val pubIdentityFile = dir.resolve(publicKeyFileName)
|
||||||
|
val identityName = if (serviceName == null) configuration.myLegalName else configuration.myLegalName + "|" + serviceName
|
||||||
|
|
||||||
return if (!Files.exists(privKeyFile)) {
|
val identityAndKey = if (!Files.exists(privKeyFile)) {
|
||||||
log.info("Identity key not found, generating fresh key!")
|
log.info("Identity key not found, generating fresh key!")
|
||||||
val keyPair: KeyPair = generateKeyPair()
|
val keyPair: KeyPair = generateKeyPair()
|
||||||
keyPair.serialize().writeToFile(privKeyFile)
|
keyPair.serialize().writeToFile(privKeyFile)
|
||||||
val myIdentity = Party(configuration.myLegalName, keyPair.public)
|
val myIdentity = Party(identityName, keyPair.public)
|
||||||
// We include the Party class with the file here to help catch mixups when admins provide files of the
|
// We include the Party class with the file here to help catch mixups when admins provide files of the
|
||||||
// wrong type by mistake.
|
// wrong type by mistake.
|
||||||
myIdentity.serialize().writeToFile(pubIdentityFile)
|
myIdentity.serialize().writeToFile(pubIdentityFile)
|
||||||
@ -475,13 +489,15 @@ abstract class AbstractNode(open val configuration: NodeConfiguration, val netwo
|
|||||||
// This is just a sanity check. It shouldn't fail unless the admin has fiddled with the files and messed
|
// This is just a sanity check. It shouldn't fail unless the admin has fiddled with the files and messed
|
||||||
// things up for us.
|
// things up for us.
|
||||||
val myIdentity = Files.readAllBytes(pubIdentityFile).deserialize<Party>()
|
val myIdentity = Files.readAllBytes(pubIdentityFile).deserialize<Party>()
|
||||||
if (myIdentity.name != configuration.myLegalName)
|
if (myIdentity.name != identityName)
|
||||||
throw ConfigurationException("The legal name in the config file doesn't match the stored identity file:" +
|
throw ConfigurationException("The legal name in the config file doesn't match the stored identity file:" +
|
||||||
"${configuration.myLegalName} vs ${myIdentity.name}")
|
"${identityName} vs ${myIdentity.name}")
|
||||||
// Load the private key.
|
// Load the private key.
|
||||||
val keyPair = Files.readAllBytes(privKeyFile).deserialize<KeyPair>()
|
val keyPair = Files.readAllBytes(privKeyFile).deserialize<KeyPair>()
|
||||||
Pair(myIdentity, keyPair)
|
Pair(myIdentity, keyPair)
|
||||||
}
|
}
|
||||||
|
partyKeys += identityAndKey.second
|
||||||
|
return identityAndKey
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun generateKeyPair() = com.r3corda.core.crypto.generateKeyPair()
|
protected open fun generateKeyPair() = com.r3corda.core.crypto.generateKeyPair()
|
||||||
|
@ -117,7 +117,8 @@ class Node(override val configuration: FullNodeConfiguration, networkMapAddress:
|
|||||||
artemisAddress
|
artemisAddress
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
val myIdentityOrNullIfNetworkMapService = if (networkMapService != null) services.storageService.myLegalIdentityKey.public else null
|
val legalIdentity = obtainLegalIdentity()
|
||||||
|
val myIdentityOrNullIfNetworkMapService = if (networkMapService != null) legalIdentity.owningKey else null
|
||||||
return NodeMessagingClient(configuration, serverAddr, myIdentityOrNullIfNetworkMapService, serverThread,
|
return NodeMessagingClient(configuration, serverAddr, myIdentityOrNullIfNetworkMapService, serverThread,
|
||||||
persistenceTx = { body: () -> Unit -> databaseTransaction(database) { body() } })
|
persistenceTx = { body: () -> Unit -> databaseTransaction(database) { body() } })
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,6 @@ import com.r3corda.core.crypto.toStringShort
|
|||||||
import com.r3corda.core.node.ServiceHub
|
import com.r3corda.core.node.ServiceHub
|
||||||
import com.r3corda.core.node.services.Vault
|
import com.r3corda.core.node.services.Vault
|
||||||
import com.r3corda.core.transactions.TransactionBuilder
|
import com.r3corda.core.transactions.TransactionBuilder
|
||||||
import com.r3corda.node.services.api.ServiceHubInternal
|
|
||||||
import com.r3corda.node.services.messaging.CordaRPCOps
|
import com.r3corda.node.services.messaging.CordaRPCOps
|
||||||
import com.r3corda.node.services.messaging.StateMachineInfo
|
import com.r3corda.node.services.messaging.StateMachineInfo
|
||||||
import com.r3corda.node.services.messaging.StateMachineUpdate
|
import com.r3corda.node.services.messaging.StateMachineUpdate
|
||||||
@ -93,10 +92,11 @@ class ServerRPCOps(
|
|||||||
private fun exitCash(req: ClientToServiceCommand.ExitCash): TransactionBuildResult {
|
private fun exitCash(req: ClientToServiceCommand.ExitCash): TransactionBuildResult {
|
||||||
val builder: TransactionBuilder = TransactionType.General.Builder(null)
|
val builder: TransactionBuilder = TransactionType.General.Builder(null)
|
||||||
try {
|
try {
|
||||||
val issuer = PartyAndReference(services.storageService.myLegalIdentity, req.issueRef)
|
val issuer = PartyAndReference(services.myInfo.legalIdentity, req.issueRef)
|
||||||
Cash().generateExit(builder, req.amount.issuedBy(issuer),
|
Cash().generateExit(builder, req.amount.issuedBy(issuer),
|
||||||
services.vaultService.currentVault.statesOfType<Cash.State>().filter { it.state.data.owner == issuer.party.owningKey })
|
services.vaultService.currentVault.statesOfType<Cash.State>().filter { it.state.data.owner == issuer.party.owningKey })
|
||||||
builder.signWith(services.storageService.myLegalIdentityKey)
|
val myKey = services.legalIdentityKey
|
||||||
|
builder.signWith(myKey)
|
||||||
|
|
||||||
// Work out who the owners of the burnt states were
|
// Work out who the owners of the burnt states were
|
||||||
val inputStatesNullable = services.vaultService.statesForRefs(builder.inputStates())
|
val inputStatesNullable = services.vaultService.statesForRefs(builder.inputStates())
|
||||||
@ -126,9 +126,10 @@ class ServerRPCOps(
|
|||||||
// TODO: Make a lightweight protocol that manages this workflow, rather than embedding it directly in the service
|
// TODO: Make a lightweight protocol that manages this workflow, rather than embedding it directly in the service
|
||||||
private fun issueCash(req: ClientToServiceCommand.IssueCash): TransactionBuildResult {
|
private fun issueCash(req: ClientToServiceCommand.IssueCash): TransactionBuildResult {
|
||||||
val builder: TransactionBuilder = TransactionType.General.Builder(notary = null)
|
val builder: TransactionBuilder = TransactionType.General.Builder(notary = null)
|
||||||
val issuer = PartyAndReference(services.storageService.myLegalIdentity, req.issueRef)
|
val issuer = PartyAndReference(services.myInfo.legalIdentity, req.issueRef)
|
||||||
Cash().generateIssue(builder, req.amount.issuedBy(issuer), req.recipient.owningKey, req.notary)
|
Cash().generateIssue(builder, req.amount.issuedBy(issuer), req.recipient.owningKey, req.notary)
|
||||||
builder.signWith(services.storageService.myLegalIdentityKey)
|
val myKey = services.legalIdentityKey
|
||||||
|
builder.signWith(myKey)
|
||||||
val tx = builder.toSignedTransaction(checkSufficientSignatures = true)
|
val tx = builder.toSignedTransaction(checkSufficientSignatures = true)
|
||||||
// Issuance transactions do not need to be notarised, so we can skip directly to broadcasting it
|
// Issuance transactions do not need to be notarised, so we can skip directly to broadcasting it
|
||||||
val protocol = BroadcastTransactionProtocol(tx, setOf(req), setOf(req.recipient))
|
val protocol = BroadcastTransactionProtocol(tx, setOf(req), setOf(req.recipient))
|
||||||
|
@ -6,6 +6,7 @@ import com.r3corda.core.node.services.ServiceType
|
|||||||
* Placeholder interface for regulator services.
|
* Placeholder interface for regulator services.
|
||||||
*/
|
*/
|
||||||
interface RegulatorService {
|
interface RegulatorService {
|
||||||
object Type : ServiceType("corda.regulator")
|
companion object {
|
||||||
|
val type = ServiceType.regulator
|
||||||
|
}
|
||||||
}
|
}
|
@ -54,7 +54,7 @@ class FullNodeConfiguration(config: Config) : NodeConfiguration {
|
|||||||
advertisedServices.add(ServiceInfo.parse(serviceId))
|
advertisedServices.add(ServiceInfo.parse(serviceId))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (networkMapAddress == null) advertisedServices.add(ServiceInfo(NetworkMapService.Type))
|
if (networkMapAddress == null) advertisedServices.add(ServiceInfo(NetworkMapService.type))
|
||||||
val networkMapMessageAddress: SingleMessageRecipient? = if (networkMapAddress == null) null else NodeMessagingClient.makeNetworkMapAddress(networkMapAddress!!)
|
val networkMapMessageAddress: SingleMessageRecipient? = if (networkMapAddress == null) null else NodeMessagingClient.makeNetworkMapAddress(networkMapAddress!!)
|
||||||
return Node(this, networkMapMessageAddress, advertisedServices)
|
return Node(this, networkMapMessageAddress, advertisedServices)
|
||||||
}
|
}
|
||||||
|
@ -41,11 +41,11 @@ import javax.annotation.concurrent.ThreadSafe
|
|||||||
@ThreadSafe
|
@ThreadSafe
|
||||||
open class InMemoryNetworkMapCache : SingletonSerializeAsToken(), NetworkMapCache {
|
open class InMemoryNetworkMapCache : SingletonSerializeAsToken(), NetworkMapCache {
|
||||||
override val networkMapNodes: List<NodeInfo>
|
override val networkMapNodes: List<NodeInfo>
|
||||||
get() = get(NetworkMapService.Type)
|
get() = get(NetworkMapService.type)
|
||||||
override val regulators: List<NodeInfo>
|
override val regulators: List<NodeInfo>
|
||||||
get() = get(RegulatorService.Type)
|
get() = get(ServiceType.regulator)
|
||||||
override val notaryNodes: List<NodeInfo>
|
override val notaryNodes: List<NodeInfo>
|
||||||
get() = get(NotaryService.Type)
|
get() = get(ServiceType.notary)
|
||||||
override val partyNodes: List<NodeInfo>
|
override val partyNodes: List<NodeInfo>
|
||||||
get() = registeredNodes.map { it.value }
|
get() = registeredNodes.map { it.value }
|
||||||
private val _changed = PublishSubject.create<MapChange>()
|
private val _changed = PublishSubject.create<MapChange>()
|
||||||
@ -58,10 +58,13 @@ open class InMemoryNetworkMapCache : SingletonSerializeAsToken(), NetworkMapCach
|
|||||||
protected var registeredNodes = Collections.synchronizedMap(HashMap<Party, NodeInfo>())
|
protected var registeredNodes = Collections.synchronizedMap(HashMap<Party, NodeInfo>())
|
||||||
|
|
||||||
override fun get() = registeredNodes.map { it.value }
|
override fun get() = registeredNodes.map { it.value }
|
||||||
override fun get(serviceType: ServiceType) = registeredNodes.filterValues { it.advertisedServices.any { it.type.isSubTypeOf(serviceType) } }.map { it.value }
|
override fun get(serviceType: ServiceType) = registeredNodes.filterValues { it.advertisedServices.any { it.info.type.isSubTypeOf(serviceType) } }.map { it.value }
|
||||||
override fun getRecommended(type: ServiceType, contract: Contract, vararg party: Party): NodeInfo? = get(type).firstOrNull()
|
override fun getRecommended(type: ServiceType, contract: Contract, vararg party: Party): NodeInfo? = get(type).firstOrNull()
|
||||||
override fun getNodeByLegalName(name: String) = get().singleOrNull { it.identity.name == name }
|
override fun getNodeByLegalName(name: String) = get().singleOrNull { it.legalIdentity.name == name }
|
||||||
override fun getNodeByPublicKey(publicKey: PublicKey) = get().singleOrNull { it.identity.owningKey == publicKey }
|
override fun getNodeByPublicKey(publicKey: PublicKey) = get().singleOrNull {
|
||||||
|
(it.legalIdentity.owningKey == publicKey)
|
||||||
|
|| it.advertisedServices.any { it.identity.owningKey == publicKey }
|
||||||
|
}
|
||||||
|
|
||||||
override fun addMapService(net: MessagingService, networkMapAddress: SingleMessageRecipient, subscribe: Boolean,
|
override fun addMapService(net: MessagingService, networkMapAddress: SingleMessageRecipient, subscribe: Boolean,
|
||||||
ifChangedSinceVer: Int?): ListenableFuture<Unit> {
|
ifChangedSinceVer: Int?): ListenableFuture<Unit> {
|
||||||
@ -96,7 +99,7 @@ open class InMemoryNetworkMapCache : SingletonSerializeAsToken(), NetworkMapCach
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun addNode(node: NodeInfo) {
|
override fun addNode(node: NodeInfo) {
|
||||||
val oldValue = registeredNodes.put(node.identity, node)
|
val oldValue = registeredNodes.put(node.legalIdentity, node)
|
||||||
if (oldValue == null) {
|
if (oldValue == null) {
|
||||||
_changed.onNext(MapChange(node, oldValue, MapChangeType.Added))
|
_changed.onNext(MapChange(node, oldValue, MapChangeType.Added))
|
||||||
} else if(oldValue != node) {
|
} else if(oldValue != node) {
|
||||||
@ -105,7 +108,7 @@ open class InMemoryNetworkMapCache : SingletonSerializeAsToken(), NetworkMapCach
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun removeNode(node: NodeInfo) {
|
override fun removeNode(node: NodeInfo) {
|
||||||
val oldValue = registeredNodes.remove(node.identity)
|
val oldValue = registeredNodes.remove(node.legalIdentity)
|
||||||
_changed.onNext(MapChange(node, oldValue, MapChangeType.Removed))
|
_changed.onNext(MapChange(node, oldValue, MapChangeType.Removed))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +48,6 @@ import javax.annotation.concurrent.ThreadSafe
|
|||||||
// a concept of identity changes over time, should that include the node for an identity? If so, that is likely to
|
// a concept of identity changes over time, should that include the node for an identity? If so, that is likely to
|
||||||
// replace this service.
|
// replace this service.
|
||||||
interface NetworkMapService {
|
interface NetworkMapService {
|
||||||
object Type : ServiceType("corda.network_map")
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val DEFAULT_EXPIRATION_PERIOD = Period.ofWeeks(4)
|
val DEFAULT_EXPIRATION_PERIOD = Period.ofWeeks(4)
|
||||||
@ -63,6 +62,8 @@ interface NetworkMapService {
|
|||||||
val PUSH_ACK_PROTOCOL_TOPIC = "platform.network_map.push_ack"
|
val PUSH_ACK_PROTOCOL_TOPIC = "platform.network_map.push_ack"
|
||||||
|
|
||||||
val logger = loggerFor<NetworkMapService>()
|
val logger = loggerFor<NetworkMapService>()
|
||||||
|
|
||||||
|
val type = ServiceType.corda.getSubType("network_map")
|
||||||
}
|
}
|
||||||
|
|
||||||
val nodes: List<NodeInfo>
|
val nodes: List<NodeInfo>
|
||||||
@ -270,7 +271,7 @@ abstract class AbstractNetworkMapService
|
|||||||
// Update the current value atomically, so that if multiple updates come
|
// Update the current value atomically, so that if multiple updates come
|
||||||
// in on different threads, there is no risk of a race condition while checking
|
// in on different threads, there is no risk of a race condition while checking
|
||||||
// sequence numbers.
|
// sequence numbers.
|
||||||
val registrationInfo = registeredNodes.compute(node.identity, { mapKey: Party, existing: NodeRegistrationInfo? ->
|
val registrationInfo = registeredNodes.compute(node.legalIdentity, { mapKey: Party, existing: NodeRegistrationInfo? ->
|
||||||
changed = existing == null || existing.reg.serial < change.serial
|
changed = existing == null || existing.reg.serial < change.serial
|
||||||
if (changed) {
|
if (changed) {
|
||||||
when (change.type) {
|
when (change.type) {
|
||||||
@ -332,7 +333,7 @@ class NodeRegistration(val node: NodeInfo, val serial: Long, val type: AddOrRemo
|
|||||||
*/
|
*/
|
||||||
fun toWire(privateKey: PrivateKey): WireNodeRegistration {
|
fun toWire(privateKey: PrivateKey): WireNodeRegistration {
|
||||||
val regSerialized = this.serialize()
|
val regSerialized = this.serialize()
|
||||||
val regSig = privateKey.signWithECDSA(regSerialized.bits, node.identity.owningKey)
|
val regSig = privateKey.signWithECDSA(regSerialized.bits, node.legalIdentity.owningKey)
|
||||||
|
|
||||||
return WireNodeRegistration(regSerialized, regSig)
|
return WireNodeRegistration(regSerialized, regSig)
|
||||||
}
|
}
|
||||||
@ -346,7 +347,7 @@ class NodeRegistration(val node: NodeInfo, val serial: Long, val type: AddOrRemo
|
|||||||
class WireNodeRegistration(raw: SerializedBytes<NodeRegistration>, sig: DigitalSignature.WithKey) : SignedData<NodeRegistration>(raw, sig) {
|
class WireNodeRegistration(raw: SerializedBytes<NodeRegistration>, sig: DigitalSignature.WithKey) : SignedData<NodeRegistration>(raw, sig) {
|
||||||
@Throws(IllegalArgumentException::class)
|
@Throws(IllegalArgumentException::class)
|
||||||
override fun verifyData(data: NodeRegistration) {
|
override fun verifyData(data: NodeRegistration) {
|
||||||
require(data.node.identity.owningKey == sig.by)
|
require(data.node.legalIdentity.owningKey == sig.by)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,16 +1,12 @@
|
|||||||
package com.r3corda.node.services.persistence
|
package com.r3corda.node.services.persistence
|
||||||
|
|
||||||
import com.r3corda.core.crypto.Party
|
|
||||||
import com.r3corda.core.node.services.AttachmentStorage
|
import com.r3corda.core.node.services.AttachmentStorage
|
||||||
import com.r3corda.core.node.services.StateMachineRecordedTransactionMappingStorage
|
import com.r3corda.core.node.services.StateMachineRecordedTransactionMappingStorage
|
||||||
import com.r3corda.core.node.services.TransactionStorage
|
import com.r3corda.core.node.services.TransactionStorage
|
||||||
import com.r3corda.core.node.services.TxWritableStorageService
|
import com.r3corda.core.node.services.TxWritableStorageService
|
||||||
import com.r3corda.core.serialization.SingletonSerializeAsToken
|
import com.r3corda.core.serialization.SingletonSerializeAsToken
|
||||||
import java.security.KeyPair
|
|
||||||
|
|
||||||
open class StorageServiceImpl(override val attachments: AttachmentStorage,
|
open class StorageServiceImpl(override val attachments: AttachmentStorage,
|
||||||
override val validatedTransactions: TransactionStorage,
|
override val validatedTransactions: TransactionStorage,
|
||||||
override val stateMachineRecordedTransactionMapping: StateMachineRecordedTransactionMappingStorage,
|
override val stateMachineRecordedTransactionMapping: StateMachineRecordedTransactionMappingStorage)
|
||||||
override val myLegalIdentityKey: KeyPair,
|
|
||||||
override val myLegalIdentity: Party = Party("Unit test party", myLegalIdentityKey.public))
|
|
||||||
: SingletonSerializeAsToken(), TxWritableStorageService
|
: SingletonSerializeAsToken(), TxWritableStorageService
|
||||||
|
@ -187,7 +187,7 @@ class ProtocolStateMachineImpl<R>(override val id: StateMachineRunId,
|
|||||||
val session = ProtocolSession(sessionProtocol, otherParty, random63BitValue(), null)
|
val session = ProtocolSession(sessionProtocol, otherParty, random63BitValue(), null)
|
||||||
openSessions[Pair(sessionProtocol, otherParty)] = session
|
openSessions[Pair(sessionProtocol, otherParty)] = session
|
||||||
val counterpartyProtocol = sessionProtocol.getCounterpartyMarker(otherParty).name
|
val counterpartyProtocol = sessionProtocol.getCounterpartyMarker(otherParty).name
|
||||||
val sessionInit = SessionInit(session.ourSessionId, serviceHub.storageService.myLegalIdentity, counterpartyProtocol)
|
val sessionInit = SessionInit(session.ourSessionId, serviceHub.myInfo.legalIdentity, counterpartyProtocol)
|
||||||
val sessionInitResponse = sendAndReceiveInternal(session, sessionInit, SessionInitResponse::class.java)
|
val sessionInitResponse = sendAndReceiveInternal(session, sessionInit, SessionInitResponse::class.java)
|
||||||
if (sessionInitResponse is SessionConfirm) {
|
if (sessionInitResponse is SessionConfirm) {
|
||||||
session.otherPartySessionId = sessionInitResponse.initiatedSessionId
|
session.otherPartySessionId = sessionInitResponse.initiatedSessionId
|
||||||
|
@ -386,7 +386,7 @@ class StateMachineManager(val serviceHub: ServiceHubInternal,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun sendSessionMessage(party: Party, message: SessionMessage, psm: ProtocolStateMachineImpl<*>?) {
|
private fun sendSessionMessage(party: Party, message: SessionMessage, psm: ProtocolStateMachineImpl<*>?) {
|
||||||
val node = serviceHub.networkMapCache.getNodeByLegalName(party.name)
|
val node = serviceHub.networkMapCache.getNodeByPublicKey(party.owningKey)
|
||||||
?: throw IllegalArgumentException("Don't know about party $party")
|
?: throw IllegalArgumentException("Don't know about party $party")
|
||||||
val logger = psm?.logger ?: logger
|
val logger = psm?.logger ?: logger
|
||||||
logger.trace { "${psm?.id} sending $message to party $party" }
|
logger.trace { "${psm?.id} sending $message to party $party" }
|
||||||
|
@ -5,6 +5,7 @@ import com.r3corda.core.node.services.ServiceType
|
|||||||
import com.r3corda.core.serialization.SingletonSerializeAsToken
|
import com.r3corda.core.serialization.SingletonSerializeAsToken
|
||||||
import com.r3corda.node.services.api.ServiceHubInternal
|
import com.r3corda.node.services.api.ServiceHubInternal
|
||||||
import com.r3corda.protocols.NotaryProtocol
|
import com.r3corda.protocols.NotaryProtocol
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Notary service acts as the final signer of a transaction ensuring two things:
|
* A Notary service acts as the final signer of a transaction ensuring two things:
|
||||||
@ -16,9 +17,6 @@ import com.r3corda.protocols.NotaryProtocol
|
|||||||
* This is the base implementation that can be customised with specific Notary transaction commit protocol.
|
* This is the base implementation that can be customised with specific Notary transaction commit protocol.
|
||||||
*/
|
*/
|
||||||
abstract class NotaryService(services: ServiceHubInternal) : SingletonSerializeAsToken() {
|
abstract class NotaryService(services: ServiceHubInternal) : SingletonSerializeAsToken() {
|
||||||
// Do not specify this as an advertised service. Use a concrete implementation.
|
|
||||||
// TODO: We do not want a service type that cannot be used. Fix the type system abuse here.
|
|
||||||
object Type : ServiceType("corda.notary")
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
services.registerProtocolInitiator(NotaryProtocol.Client::class) { createProtocol(it) }
|
services.registerProtocolInitiator(NotaryProtocol.Client::class) { createProtocol(it) }
|
||||||
|
@ -12,7 +12,9 @@ import com.r3corda.protocols.NotaryProtocol
|
|||||||
class SimpleNotaryService(services: ServiceHubInternal,
|
class SimpleNotaryService(services: ServiceHubInternal,
|
||||||
val timestampChecker: TimestampChecker,
|
val timestampChecker: TimestampChecker,
|
||||||
val uniquenessProvider: UniquenessProvider) : NotaryService(services) {
|
val uniquenessProvider: UniquenessProvider) : NotaryService(services) {
|
||||||
object Type : ServiceType("corda.notary.simple")
|
companion object {
|
||||||
|
val type = ServiceType.notary.getSubType("simple")
|
||||||
|
}
|
||||||
|
|
||||||
override fun createProtocol(otherParty: Party): NotaryProtocol.Service {
|
override fun createProtocol(otherParty: Party): NotaryProtocol.Service {
|
||||||
return NotaryProtocol.Service(otherParty, timestampChecker, uniquenessProvider)
|
return NotaryProtocol.Service(otherParty, timestampChecker, uniquenessProvider)
|
||||||
|
@ -11,7 +11,9 @@ import com.r3corda.protocols.ValidatingNotaryProtocol
|
|||||||
class ValidatingNotaryService(services: ServiceHubInternal,
|
class ValidatingNotaryService(services: ServiceHubInternal,
|
||||||
val timestampChecker: TimestampChecker,
|
val timestampChecker: TimestampChecker,
|
||||||
val uniquenessProvider: UniquenessProvider) : NotaryService(services) {
|
val uniquenessProvider: UniquenessProvider) : NotaryService(services) {
|
||||||
object Type : ServiceType("corda.notary.validating")
|
companion object {
|
||||||
|
val type = ServiceType.notary.getSubType("validating")
|
||||||
|
}
|
||||||
|
|
||||||
override fun createProtocol(otherParty: Party): ValidatingNotaryProtocol {
|
override fun createProtocol(otherParty: Party): ValidatingNotaryProtocol {
|
||||||
return ValidatingNotaryProtocol(otherParty, timestampChecker, uniquenessProvider)
|
return ValidatingNotaryProtocol(otherParty, timestampChecker, uniquenessProvider)
|
||||||
|
@ -38,9 +38,9 @@ class ServerRPCTest {
|
|||||||
@Before
|
@Before
|
||||||
fun setup() {
|
fun setup() {
|
||||||
network = MockNetwork()
|
network = MockNetwork()
|
||||||
val networkMap = network.createNode(advertisedServices = ServiceInfo(NetworkMapService.Type))
|
val networkMap = network.createNode(advertisedServices = ServiceInfo(NetworkMapService.type))
|
||||||
aliceNode = network.createNode(networkMapAddress = networkMap.info.address)
|
aliceNode = network.createNode(networkMapAddress = networkMap.info.address)
|
||||||
notaryNode = network.createNode(advertisedServices = ServiceInfo(SimpleNotaryService.Type), networkMapAddress = networkMap.info.address)
|
notaryNode = network.createNode(advertisedServices = ServiceInfo(SimpleNotaryService.type), networkMapAddress = networkMap.info.address)
|
||||||
rpc = ServerRPCOps(aliceNode.services, aliceNode.smm, aliceNode.database)
|
rpc = ServerRPCOps(aliceNode.services, aliceNode.smm, aliceNode.database)
|
||||||
|
|
||||||
stateMachineUpdates = rpc.stateMachinesAndUpdates().second
|
stateMachineUpdates = rpc.stateMachinesAndUpdates().second
|
||||||
@ -57,13 +57,13 @@ class ServerRPCTest {
|
|||||||
assertFalse(aliceNode.services.vaultService.currentVault.states.iterator().hasNext())
|
assertFalse(aliceNode.services.vaultService.currentVault.states.iterator().hasNext())
|
||||||
|
|
||||||
// Tell the monitoring service node to issue some cash
|
// Tell the monitoring service node to issue some cash
|
||||||
val recipient = aliceNode.services.storageService.myLegalIdentity
|
val recipient = aliceNode.info.legalIdentity
|
||||||
val outEvent = ClientToServiceCommand.IssueCash(Amount(quantity, GBP), ref, recipient, DUMMY_NOTARY)
|
val outEvent = ClientToServiceCommand.IssueCash(Amount(quantity, GBP), ref, recipient, notaryNode.info.notaryIdentity)
|
||||||
rpc.executeCommand(outEvent)
|
rpc.executeCommand(outEvent)
|
||||||
network.runNetwork()
|
network.runNetwork()
|
||||||
|
|
||||||
val expectedState = Cash.State(Amount(quantity,
|
val expectedState = Cash.State(Amount(quantity,
|
||||||
Issued(aliceNode.services.storageService.myLegalIdentity.ref(ref), GBP)),
|
Issued(aliceNode.info.legalIdentity.ref(ref), GBP)),
|
||||||
recipient.owningKey)
|
recipient.owningKey)
|
||||||
|
|
||||||
var issueSmId: StateMachineRunId? = null
|
var issueSmId: StateMachineRunId? = null
|
||||||
@ -99,15 +99,15 @@ class ServerRPCTest {
|
|||||||
rpc.executeCommand(ClientToServiceCommand.IssueCash(
|
rpc.executeCommand(ClientToServiceCommand.IssueCash(
|
||||||
amount = Amount(100, USD),
|
amount = Amount(100, USD),
|
||||||
issueRef = OpaqueBytes(ByteArray(1, { 1 })),
|
issueRef = OpaqueBytes(ByteArray(1, { 1 })),
|
||||||
recipient = aliceNode.services.storageService.myLegalIdentity,
|
recipient = aliceNode.info.legalIdentity,
|
||||||
notary = notaryNode.services.storageService.myLegalIdentity
|
notary = notaryNode.info.notaryIdentity
|
||||||
))
|
))
|
||||||
|
|
||||||
network.runNetwork()
|
network.runNetwork()
|
||||||
|
|
||||||
rpc.executeCommand(ClientToServiceCommand.PayCash(
|
rpc.executeCommand(ClientToServiceCommand.PayCash(
|
||||||
amount = Amount(100, Issued(PartyAndReference(aliceNode.services.storageService.myLegalIdentity, OpaqueBytes(ByteArray(1, { 1 }))), USD)),
|
amount = Amount(100, Issued(PartyAndReference(aliceNode.info.legalIdentity, OpaqueBytes(ByteArray(1, { 1 }))), USD)),
|
||||||
recipient = aliceNode.services.storageService.myLegalIdentity
|
recipient = aliceNode.info.legalIdentity
|
||||||
))
|
))
|
||||||
|
|
||||||
network.runNetwork()
|
network.runNetwork()
|
||||||
@ -142,7 +142,7 @@ class ServerRPCTest {
|
|||||||
val signaturePubKeys = tx.sigs.map { it.by }.toSet()
|
val signaturePubKeys = tx.sigs.map { it.by }.toSet()
|
||||||
// Only Alice signed
|
// Only Alice signed
|
||||||
require(signaturePubKeys.size == 1)
|
require(signaturePubKeys.size == 1)
|
||||||
require(signaturePubKeys.contains(aliceNode.services.storageService.myLegalIdentity.owningKey))
|
require(signaturePubKeys.contains(aliceNode.info.legalIdentity.owningKey))
|
||||||
},
|
},
|
||||||
// MOVE
|
// MOVE
|
||||||
expect { tx ->
|
expect { tx ->
|
||||||
@ -151,8 +151,8 @@ class ServerRPCTest {
|
|||||||
val signaturePubKeys = tx.sigs.map { it.by }.toSet()
|
val signaturePubKeys = tx.sigs.map { it.by }.toSet()
|
||||||
// Alice and Notary signed
|
// Alice and Notary signed
|
||||||
require(signaturePubKeys.size == 2)
|
require(signaturePubKeys.size == 2)
|
||||||
require(signaturePubKeys.contains(aliceNode.services.storageService.myLegalIdentity.owningKey))
|
require(signaturePubKeys.contains(aliceNode.info.legalIdentity.owningKey))
|
||||||
require(signaturePubKeys.contains(notaryNode.services.storageService.myLegalIdentity.owningKey))
|
require(signaturePubKeys.contains(notaryNode.info.notaryIdentity.owningKey))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ class AttachmentTests {
|
|||||||
|
|
||||||
// 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.
|
||||||
network.runNetwork()
|
network.runNetwork()
|
||||||
val f1 = n1.services.startProtocol("tests.fetch1", FetchAttachmentsProtocol(setOf(id), n0.info.identity))
|
val f1 = n1.services.startProtocol("tests.fetch1", FetchAttachmentsProtocol(setOf(id), n0.info.legalIdentity))
|
||||||
network.runNetwork()
|
network.runNetwork()
|
||||||
assertEquals(0, f1.get().fromDisk.size)
|
assertEquals(0, f1.get().fromDisk.size)
|
||||||
|
|
||||||
@ -65,7 +65,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.services.startProtocol("tests.fetch1", FetchAttachmentsProtocol(setOf(id), n0.info.identity)).get()
|
val response: FetchDataProtocol.Result<Attachment> = n1.services.startProtocol("tests.fetch1", FetchAttachmentsProtocol(setOf(id), n0.info.legalIdentity)).get()
|
||||||
assertEquals(attachment, response.fromDisk[0])
|
assertEquals(attachment, response.fromDisk[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ 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()
|
||||||
network.runNetwork()
|
network.runNetwork()
|
||||||
val f1 = n1.services.startProtocol("tests.fetch2", FetchAttachmentsProtocol(setOf(hash), n0.info.identity))
|
val f1 = n1.services.startProtocol("tests.fetch2", FetchAttachmentsProtocol(setOf(hash), n0.info.legalIdentity))
|
||||||
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)
|
||||||
@ -96,7 +96,7 @@ class AttachmentTests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, true, null, null, ServiceInfo(NetworkMapService.Type), ServiceInfo(SimpleNotaryService.Type))
|
}, true, null, null, ServiceInfo(NetworkMapService.type), ServiceInfo(SimpleNotaryService.type))
|
||||||
val n1 = network.createNode(n0.info.address)
|
val n1 = network.createNode(n0.info.address)
|
||||||
|
|
||||||
// Insert an attachment into node zero's store directly.
|
// Insert an attachment into node zero's store directly.
|
||||||
@ -109,7 +109,7 @@ class AttachmentTests {
|
|||||||
|
|
||||||
// Get n1 to fetch the attachment. Should receive corrupted bytes.
|
// Get n1 to fetch the attachment. Should receive corrupted bytes.
|
||||||
network.runNetwork()
|
network.runNetwork()
|
||||||
val f1 = n1.services.startProtocol("tests.fetch1", FetchAttachmentsProtocol(setOf(id), n0.info.identity))
|
val f1 = n1.services.startProtocol("tests.fetch1", FetchAttachmentsProtocol(setOf(id), n0.info.legalIdentity))
|
||||||
network.runNetwork()
|
network.runNetwork()
|
||||||
assertFailsWith<FetchDataProtocol.DownloadedVsRequestedDataMismatch> {
|
assertFailsWith<FetchDataProtocol.DownloadedVsRequestedDataMismatch> {
|
||||||
rootCauseExceptions { f1.get() }
|
rootCauseExceptions { f1.get() }
|
||||||
|
@ -41,7 +41,7 @@ class InMemoryMessagingTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun basics() {
|
fun basics() {
|
||||||
val node1 = network.createNode(advertisedServices = ServiceInfo(NetworkMapService.Type))
|
val node1 = network.createNode(advertisedServices = ServiceInfo(NetworkMapService.type))
|
||||||
val node2 = network.createNode(networkMapAddress = node1.info.address)
|
val node2 = network.createNode(networkMapAddress = node1.info.address)
|
||||||
val node3 = network.createNode(networkMapAddress = node1.info.address)
|
val node3 = network.createNode(networkMapAddress = node1.info.address)
|
||||||
|
|
||||||
@ -70,7 +70,7 @@ class InMemoryMessagingTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun broadcast() {
|
fun broadcast() {
|
||||||
val node1 = network.createNode(advertisedServices = ServiceInfo(NetworkMapService.Type))
|
val node1 = network.createNode(advertisedServices = ServiceInfo(NetworkMapService.type))
|
||||||
val node2 = network.createNode(networkMapAddress = node1.info.address)
|
val node2 = network.createNode(networkMapAddress = node1.info.address)
|
||||||
val node3 = network.createNode(networkMapAddress = node1.info.address)
|
val node3 = network.createNode(networkMapAddress = node1.info.address)
|
||||||
|
|
||||||
@ -89,7 +89,7 @@ class InMemoryMessagingTests {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
fun `skip unhandled messages`() {
|
fun `skip unhandled messages`() {
|
||||||
val node1 = network.createNode(advertisedServices = ServiceInfo(NetworkMapService.Type))
|
val node1 = network.createNode(advertisedServices = ServiceInfo(NetworkMapService.type))
|
||||||
val node2 = network.createNode(networkMapAddress = node1.info.address)
|
val node2 = network.createNode(networkMapAddress = node1.info.address)
|
||||||
var received: Int = 0
|
var received: Int = 0
|
||||||
|
|
||||||
|
@ -8,11 +8,11 @@ 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.messaging.SingleMessageRecipient
|
||||||
import com.r3corda.core.node.ServiceHub
|
|
||||||
import com.r3corda.core.node.services.*
|
import com.r3corda.core.node.services.*
|
||||||
import com.r3corda.core.protocols.ProtocolStateMachine
|
import com.r3corda.core.protocols.ProtocolStateMachine
|
||||||
import com.r3corda.core.protocols.StateMachineRunId
|
import com.r3corda.core.protocols.StateMachineRunId
|
||||||
import com.r3corda.core.transactions.SignedTransaction
|
import com.r3corda.core.transactions.SignedTransaction
|
||||||
|
import com.r3corda.core.transactions.TransactionBuilder
|
||||||
import com.r3corda.core.transactions.WireTransaction
|
import com.r3corda.core.transactions.WireTransaction
|
||||||
import com.r3corda.core.utilities.DUMMY_NOTARY
|
import com.r3corda.core.utilities.DUMMY_NOTARY
|
||||||
import com.r3corda.core.utilities.DUMMY_NOTARY_KEY
|
import com.r3corda.core.utilities.DUMMY_NOTARY_KEY
|
||||||
@ -85,16 +85,20 @@ class TwoPartyTradeProtocolTests {
|
|||||||
notaryNode = net.createNotaryNode(DUMMY_NOTARY.name, DUMMY_NOTARY_KEY)
|
notaryNode = net.createNotaryNode(DUMMY_NOTARY.name, DUMMY_NOTARY_KEY)
|
||||||
aliceNode = net.createPartyNode(notaryNode.info.address, ALICE.name, ALICE_KEY)
|
aliceNode = net.createPartyNode(notaryNode.info.address, ALICE.name, ALICE_KEY)
|
||||||
bobNode = net.createPartyNode(notaryNode.info.address, BOB.name, BOB_KEY)
|
bobNode = net.createPartyNode(notaryNode.info.address, BOB.name, BOB_KEY)
|
||||||
|
val aliceKey = aliceNode.services.legalIdentityKey
|
||||||
|
val notaryKey = notaryNode.services.notaryIdentityKey
|
||||||
|
|
||||||
aliceNode.disableDBCloseOnStop()
|
aliceNode.disableDBCloseOnStop()
|
||||||
bobNode.disableDBCloseOnStop()
|
bobNode.disableDBCloseOnStop()
|
||||||
|
|
||||||
databaseTransaction(bobNode.database) {
|
databaseTransaction(bobNode.database) {
|
||||||
bobNode.services.fillWithSomeTestCash(2000.DOLLARS)
|
bobNode.services.fillWithSomeTestCash(2000.DOLLARS, outputNotary = notaryNode.info.notaryIdentity)
|
||||||
}
|
}
|
||||||
val alicesFakePaper = fillUpForSeller(false, aliceNode.storage.myLegalIdentity.owningKey,
|
val alicesFakePaper = fillUpForSeller(false, aliceNode.info.legalIdentity.owningKey,
|
||||||
1200.DOLLARS `issued by` DUMMY_CASH_ISSUER, null).second
|
1200.DOLLARS `issued by` DUMMY_CASH_ISSUER, null, notaryNode.info.notaryIdentity).second
|
||||||
insertFakeTransactions(alicesFakePaper, aliceNode, aliceNode.storage.myLegalIdentityKey, notaryNode.storage.myLegalIdentityKey)
|
|
||||||
|
insertFakeTransactions(alicesFakePaper, aliceNode, aliceKey, notaryKey)
|
||||||
|
|
||||||
val (bobPsm, aliceResult) = runBuyerAndSeller("alice's paper".outputStateAndRef())
|
val (bobPsm, aliceResult) = runBuyerAndSeller("alice's paper".outputStateAndRef())
|
||||||
|
|
||||||
// TODO: Verify that the result was inserted into the transaction database.
|
// TODO: Verify that the result was inserted into the transaction database.
|
||||||
@ -121,6 +125,8 @@ class TwoPartyTradeProtocolTests {
|
|||||||
notaryNode = net.createNotaryNode(DUMMY_NOTARY.name, DUMMY_NOTARY_KEY)
|
notaryNode = net.createNotaryNode(DUMMY_NOTARY.name, DUMMY_NOTARY_KEY)
|
||||||
aliceNode = net.createPartyNode(notaryNode.info.address, ALICE.name, ALICE_KEY)
|
aliceNode = net.createPartyNode(notaryNode.info.address, ALICE.name, ALICE_KEY)
|
||||||
bobNode = net.createPartyNode(notaryNode.info.address, BOB.name, BOB_KEY)
|
bobNode = net.createPartyNode(notaryNode.info.address, BOB.name, BOB_KEY)
|
||||||
|
val aliceKey = aliceNode.services.legalIdentityKey
|
||||||
|
val notaryKey = notaryNode.services.notaryIdentityKey
|
||||||
|
|
||||||
val bobAddr = bobNode.net.myAddress as InMemoryMessagingNetwork.Handle
|
val bobAddr = bobNode.net.myAddress as InMemoryMessagingNetwork.Handle
|
||||||
val networkMapAddr = notaryNode.info.address
|
val networkMapAddr = notaryNode.info.address
|
||||||
@ -128,11 +134,11 @@ class TwoPartyTradeProtocolTests {
|
|||||||
net.runNetwork() // Clear network map registration messages
|
net.runNetwork() // Clear network map registration messages
|
||||||
|
|
||||||
databaseTransaction(bobNode.database) {
|
databaseTransaction(bobNode.database) {
|
||||||
bobNode.services.fillWithSomeTestCash(2000.DOLLARS)
|
bobNode.services.fillWithSomeTestCash(2000.DOLLARS, outputNotary = notaryNode.info.notaryIdentity)
|
||||||
}
|
}
|
||||||
val alicesFakePaper = fillUpForSeller(false, aliceNode.storage.myLegalIdentity.owningKey,
|
val alicesFakePaper = fillUpForSeller(false, aliceNode.info.legalIdentity.owningKey,
|
||||||
1200.DOLLARS `issued by` DUMMY_CASH_ISSUER, null).second
|
1200.DOLLARS `issued by` DUMMY_CASH_ISSUER, null, notaryNode.info.notaryIdentity).second
|
||||||
insertFakeTransactions(alicesFakePaper, aliceNode, aliceNode.storage.myLegalIdentityKey)
|
insertFakeTransactions(alicesFakePaper, aliceNode, aliceKey, notaryKey)
|
||||||
val aliceFuture = runBuyerAndSeller("alice's paper".outputStateAndRef()).sellerResult
|
val aliceFuture = runBuyerAndSeller("alice's paper".outputStateAndRef()).sellerResult
|
||||||
|
|
||||||
// Everything is on this thread so we can now step through the protocol one step at a time.
|
// Everything is on this thread so we can now step through the protocol one step at a time.
|
||||||
@ -200,11 +206,9 @@ class TwoPartyTradeProtocolTests {
|
|||||||
override fun constructStorageService(
|
override fun constructStorageService(
|
||||||
attachments: NodeAttachmentService,
|
attachments: NodeAttachmentService,
|
||||||
transactionStorage: TransactionStorage,
|
transactionStorage: TransactionStorage,
|
||||||
stateMachineRecordedTransactionMappingStorage: StateMachineRecordedTransactionMappingStorage,
|
stateMachineRecordedTransactionMappingStorage: StateMachineRecordedTransactionMappingStorage
|
||||||
keyPair: KeyPair,
|
|
||||||
identity: Party
|
|
||||||
): StorageServiceImpl {
|
): StorageServiceImpl {
|
||||||
return StorageServiceImpl(attachments, RecordingTransactionStorage(transactionStorage), stateMachineRecordedTransactionMappingStorage, keyPair, identity)
|
return StorageServiceImpl(attachments, RecordingTransactionStorage(transactionStorage), stateMachineRecordedTransactionMappingStorage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -216,6 +220,7 @@ class TwoPartyTradeProtocolTests {
|
|||||||
notaryNode = net.createNotaryNode(DUMMY_NOTARY.name, DUMMY_NOTARY_KEY)
|
notaryNode = net.createNotaryNode(DUMMY_NOTARY.name, DUMMY_NOTARY_KEY)
|
||||||
aliceNode = makeNodeWithTracking(notaryNode.info.address, ALICE.name, ALICE_KEY)
|
aliceNode = makeNodeWithTracking(notaryNode.info.address, ALICE.name, ALICE_KEY)
|
||||||
bobNode = makeNodeWithTracking(notaryNode.info.address, BOB.name, BOB_KEY)
|
bobNode = makeNodeWithTracking(notaryNode.info.address, BOB.name, BOB_KEY)
|
||||||
|
val aliceKey = aliceNode.services.legalIdentityKey
|
||||||
|
|
||||||
ledger(aliceNode.services) {
|
ledger(aliceNode.services) {
|
||||||
|
|
||||||
@ -228,11 +233,11 @@ class TwoPartyTradeProtocolTests {
|
|||||||
}
|
}
|
||||||
val attachmentID = attachment(ByteArrayInputStream(stream.toByteArray()))
|
val attachmentID = attachment(ByteArrayInputStream(stream.toByteArray()))
|
||||||
|
|
||||||
val bobsFakeCash = fillUpForBuyer(false, bobNode.keyManagement.freshKey().public).second
|
val bobsFakeCash = fillUpForBuyer(false, bobNode.keyManagement.freshKey().public, notaryNode.info.notaryIdentity).second
|
||||||
val bobsSignedTxns = insertFakeTransactions(bobsFakeCash, bobNode)
|
val bobsSignedTxns = insertFakeTransactions(bobsFakeCash, bobNode)
|
||||||
val alicesFakePaper = fillUpForSeller(false, aliceNode.storage.myLegalIdentity.owningKey,
|
val alicesFakePaper = fillUpForSeller(false, aliceNode.info.legalIdentity.owningKey,
|
||||||
1200.DOLLARS `issued by` DUMMY_CASH_ISSUER, attachmentID).second
|
1200.DOLLARS `issued by` DUMMY_CASH_ISSUER, attachmentID, notaryNode.info.notaryIdentity).second
|
||||||
val alicesSignedTxns = insertFakeTransactions(alicesFakePaper, aliceNode, aliceNode.storage.myLegalIdentityKey)
|
val alicesSignedTxns = insertFakeTransactions(alicesFakePaper, aliceNode, aliceKey)
|
||||||
|
|
||||||
net.runNetwork() // Clear network map registration messages
|
net.runNetwork() // Clear network map registration messages
|
||||||
|
|
||||||
@ -307,6 +312,7 @@ class TwoPartyTradeProtocolTests {
|
|||||||
notaryNode = net.createNotaryNode(DUMMY_NOTARY.name, DUMMY_NOTARY_KEY)
|
notaryNode = net.createNotaryNode(DUMMY_NOTARY.name, DUMMY_NOTARY_KEY)
|
||||||
aliceNode = makeNodeWithTracking(notaryNode.info.address, ALICE.name, ALICE_KEY)
|
aliceNode = makeNodeWithTracking(notaryNode.info.address, ALICE.name, ALICE_KEY)
|
||||||
bobNode = makeNodeWithTracking(notaryNode.info.address, BOB.name, BOB_KEY)
|
bobNode = makeNodeWithTracking(notaryNode.info.address, BOB.name, BOB_KEY)
|
||||||
|
val aliceKey = aliceNode.services.legalIdentityKey
|
||||||
|
|
||||||
ledger(aliceNode.services) {
|
ledger(aliceNode.services) {
|
||||||
|
|
||||||
@ -319,11 +325,11 @@ class TwoPartyTradeProtocolTests {
|
|||||||
}
|
}
|
||||||
val attachmentID = attachment(ByteArrayInputStream(stream.toByteArray()))
|
val attachmentID = attachment(ByteArrayInputStream(stream.toByteArray()))
|
||||||
|
|
||||||
val bobsFakeCash = fillUpForBuyer(false, bobNode.keyManagement.freshKey().public).second
|
val bobsFakeCash = fillUpForBuyer(false, bobNode.keyManagement.freshKey().public, notaryNode.info.notaryIdentity).second
|
||||||
insertFakeTransactions(bobsFakeCash, bobNode)
|
insertFakeTransactions(bobsFakeCash, bobNode)
|
||||||
val alicesFakePaper = fillUpForSeller(false, aliceNode.storage.myLegalIdentity.owningKey,
|
val alicesFakePaper = fillUpForSeller(false, aliceNode.info.legalIdentity.owningKey,
|
||||||
1200.DOLLARS `issued by` DUMMY_CASH_ISSUER, attachmentID).second
|
1200.DOLLARS `issued by` DUMMY_CASH_ISSUER, attachmentID, notaryNode.info.notaryIdentity).second
|
||||||
insertFakeTransactions(alicesFakePaper, aliceNode, aliceNode.storage.myLegalIdentityKey)
|
insertFakeTransactions(alicesFakePaper, aliceNode, aliceKey)
|
||||||
|
|
||||||
net.runNetwork() // Clear network map registration messages
|
net.runNetwork() // Clear network map registration messages
|
||||||
|
|
||||||
@ -387,9 +393,9 @@ class TwoPartyTradeProtocolTests {
|
|||||||
|
|
||||||
private fun runBuyerAndSeller(assetToSell: StateAndRef<OwnableState>) : RunResult {
|
private fun runBuyerAndSeller(assetToSell: StateAndRef<OwnableState>) : RunResult {
|
||||||
val buyerFuture = bobNode.initiateSingleShotProtocol(Seller::class) { otherParty ->
|
val buyerFuture = bobNode.initiateSingleShotProtocol(Seller::class) { otherParty ->
|
||||||
Buyer(otherParty, notaryNode.info.identity, 1000.DOLLARS, CommercialPaper.State::class.java)
|
Buyer(otherParty, notaryNode.info.notaryIdentity, 1000.DOLLARS, CommercialPaper.State::class.java)
|
||||||
}
|
}
|
||||||
val seller = Seller(bobNode.info.identity, notaryNode.info, assetToSell, 1000.DOLLARS, ALICE_KEY)
|
val seller = Seller(bobNode.info.legalIdentity, notaryNode.info, assetToSell, 1000.DOLLARS, ALICE_KEY)
|
||||||
val sellerResultFuture = aliceNode.smm.add("seller", seller).resultFuture
|
val sellerResultFuture = aliceNode.smm.add("seller", seller).resultFuture
|
||||||
return RunResult(buyerFuture, sellerResultFuture, seller.psm.id)
|
return RunResult(buyerFuture, sellerResultFuture, seller.psm.id)
|
||||||
}
|
}
|
||||||
@ -402,15 +408,16 @@ class TwoPartyTradeProtocolTests {
|
|||||||
notaryNode = net.createNotaryNode(DUMMY_NOTARY.name, DUMMY_NOTARY_KEY)
|
notaryNode = net.createNotaryNode(DUMMY_NOTARY.name, DUMMY_NOTARY_KEY)
|
||||||
aliceNode = net.createPartyNode(notaryNode.info.address, ALICE.name, ALICE_KEY)
|
aliceNode = net.createPartyNode(notaryNode.info.address, ALICE.name, ALICE_KEY)
|
||||||
bobNode = net.createPartyNode(notaryNode.info.address, BOB.name, BOB_KEY)
|
bobNode = net.createPartyNode(notaryNode.info.address, BOB.name, BOB_KEY)
|
||||||
|
val aliceKey = aliceNode.services.legalIdentityKey
|
||||||
|
val bobKey = bobNode.services.legalIdentityKey
|
||||||
val issuer = MEGA_CORP.ref(1, 2, 3)
|
val issuer = MEGA_CORP.ref(1, 2, 3)
|
||||||
|
|
||||||
val bobKey = bobNode.keyManagement.freshKey()
|
val bobsBadCash = fillUpForBuyer(bobError, bobKey.public, notaryNode.info.notaryIdentity).second
|
||||||
val bobsBadCash = fillUpForBuyer(bobError, bobKey.public).second
|
val alicesFakePaper = fillUpForSeller(aliceError, aliceNode.info.legalIdentity.owningKey,
|
||||||
val alicesFakePaper = fillUpForSeller(aliceError, aliceNode.storage.myLegalIdentity.owningKey,
|
1200.DOLLARS `issued by` issuer, null, notaryNode.info.notaryIdentity).second
|
||||||
1200.DOLLARS `issued by` issuer, null).second
|
|
||||||
|
|
||||||
insertFakeTransactions(bobsBadCash, bobNode, bobNode.storage.myLegalIdentityKey, bobNode.storage.myLegalIdentityKey)
|
insertFakeTransactions(bobsBadCash, bobNode, bobKey)
|
||||||
insertFakeTransactions(alicesFakePaper, aliceNode, aliceNode.storage.myLegalIdentityKey)
|
insertFakeTransactions(alicesFakePaper, aliceNode, aliceKey)
|
||||||
|
|
||||||
net.runNetwork() // Clear network map registration messages
|
net.runNetwork() // Clear network map registration messages
|
||||||
|
|
||||||
@ -452,14 +459,15 @@ class TwoPartyTradeProtocolTests {
|
|||||||
|
|
||||||
private fun LedgerDSL<TestTransactionDSLInterpreter, TestLedgerDSLInterpreter>.fillUpForBuyer(
|
private fun LedgerDSL<TestTransactionDSLInterpreter, TestLedgerDSLInterpreter>.fillUpForBuyer(
|
||||||
withError: Boolean,
|
withError: Boolean,
|
||||||
owner: PublicKey = BOB_PUBKEY): Pair<Vault, List<WireTransaction>> {
|
owner: PublicKey = BOB_PUBKEY,
|
||||||
|
notary: Party): Pair<Vault, List<WireTransaction>> {
|
||||||
val issuer = DUMMY_CASH_ISSUER
|
val issuer = DUMMY_CASH_ISSUER
|
||||||
// Bob (Buyer) has some cash he got from the Bank of Elbonia, Alice (Seller) has some commercial paper she
|
// Bob (Buyer) has some cash he got from the Bank of Elbonia, Alice (Seller) has some commercial paper she
|
||||||
// wants to sell to Bob.
|
// wants to sell to Bob.
|
||||||
val eb1 = transaction {
|
val eb1 = transaction(transactionBuilder = TransactionBuilder(notary = notary)) {
|
||||||
// Issued money to itself.
|
// Issued money to itself.
|
||||||
output("elbonian money 1") { 800.DOLLARS.CASH `issued by` issuer `owned by` MEGA_CORP_PUBKEY }
|
output("elbonian money 1", notary = notary) { 800.DOLLARS.CASH `issued by` issuer `owned by` MEGA_CORP_PUBKEY }
|
||||||
output("elbonian money 2") { 1000.DOLLARS.CASH `issued by` issuer `owned by` MEGA_CORP_PUBKEY }
|
output("elbonian money 2", notary = notary) { 1000.DOLLARS.CASH `issued by` issuer `owned by` MEGA_CORP_PUBKEY }
|
||||||
if (!withError)
|
if (!withError)
|
||||||
command(DUMMY_CASH_ISSUER_KEY.public) { Cash.Commands.Issue() }
|
command(DUMMY_CASH_ISSUER_KEY.public) { Cash.Commands.Issue() }
|
||||||
else
|
else
|
||||||
@ -474,17 +482,17 @@ class TwoPartyTradeProtocolTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Bob gets some cash onto the ledger from BoE
|
// Bob gets some cash onto the ledger from BoE
|
||||||
val bc1 = transaction {
|
val bc1 = transaction(transactionBuilder = TransactionBuilder(notary = notary)) {
|
||||||
input("elbonian money 1")
|
input("elbonian money 1")
|
||||||
output("bob cash 1") { 800.DOLLARS.CASH `issued by` issuer `owned by` owner }
|
output("bob cash 1", notary = notary) { 800.DOLLARS.CASH `issued by` issuer `owned by` owner }
|
||||||
command(MEGA_CORP_PUBKEY) { Cash.Commands.Move() }
|
command(MEGA_CORP_PUBKEY) { Cash.Commands.Move() }
|
||||||
this.verifies()
|
this.verifies()
|
||||||
}
|
}
|
||||||
|
|
||||||
val bc2 = transaction {
|
val bc2 = transaction(transactionBuilder = TransactionBuilder(notary = notary)) {
|
||||||
input("elbonian money 2")
|
input("elbonian money 2")
|
||||||
output("bob cash 2") { 300.DOLLARS.CASH `issued by` issuer `owned by` owner }
|
output("bob cash 2", notary = notary) { 300.DOLLARS.CASH `issued by` issuer `owned by` owner }
|
||||||
output { 700.DOLLARS.CASH `issued by` issuer `owned by` MEGA_CORP_PUBKEY } // Change output.
|
output(notary = notary) { 700.DOLLARS.CASH `issued by` issuer `owned by` MEGA_CORP_PUBKEY } // Change output.
|
||||||
command(MEGA_CORP_PUBKEY) { Cash.Commands.Move() }
|
command(MEGA_CORP_PUBKEY) { Cash.Commands.Move() }
|
||||||
this.verifies()
|
this.verifies()
|
||||||
}
|
}
|
||||||
@ -497,9 +505,10 @@ class TwoPartyTradeProtocolTests {
|
|||||||
withError: Boolean,
|
withError: Boolean,
|
||||||
owner: PublicKey,
|
owner: PublicKey,
|
||||||
amount: Amount<Issued<Currency>>,
|
amount: Amount<Issued<Currency>>,
|
||||||
attachmentID: SecureHash?): Pair<Vault, List<WireTransaction>> {
|
attachmentID: SecureHash?,
|
||||||
val ap = transaction {
|
notary: Party): Pair<Vault, List<WireTransaction>> {
|
||||||
output("alice's paper") {
|
val ap = transaction(transactionBuilder = TransactionBuilder(notary = notary)) {
|
||||||
|
output("alice's paper", notary = notary) {
|
||||||
CommercialPaper.State(MEGA_CORP.ref(1, 2, 3), owner, amount, TEST_TX_TIME + 7.days)
|
CommercialPaper.State(MEGA_CORP.ref(1, 2, 3), owner, amount, TEST_TX_TIME + 7.days)
|
||||||
}
|
}
|
||||||
command(MEGA_CORP_PUBKEY) { CommercialPaper.Commands.Issue() }
|
command(MEGA_CORP_PUBKEY) { CommercialPaper.Commands.Issue() }
|
||||||
|
@ -41,19 +41,19 @@ abstract class AbstractNetworkMapServiceTest {
|
|||||||
|
|
||||||
// Confirm the service contains no nodes as own node only registered if network is run.
|
// Confirm the service contains no nodes as own node only registered if network is run.
|
||||||
assertEquals(0, service().nodes.count())
|
assertEquals(0, service().nodes.count())
|
||||||
assertNull(service().processQueryRequest(NetworkMapService.QueryIdentityRequest(registerNode.info.identity, mapServiceNode.info.address, Long.MIN_VALUE)).node)
|
assertNull(service().processQueryRequest(NetworkMapService.QueryIdentityRequest(registerNode.info.legalIdentity, mapServiceNode.info.address, Long.MIN_VALUE)).node)
|
||||||
|
|
||||||
// Register the new node
|
// Register the new node
|
||||||
val instant = Instant.now()
|
val instant = Instant.now()
|
||||||
val expires = instant + NetworkMapService.DEFAULT_EXPIRATION_PERIOD
|
val expires = instant + NetworkMapService.DEFAULT_EXPIRATION_PERIOD
|
||||||
val nodeKey = registerNode.storage.myLegalIdentityKey
|
val nodeKey = registerNode.services.legalIdentityKey
|
||||||
val addChange = NodeRegistration(registerNode.info, instant.toEpochMilli(), AddOrRemove.ADD, expires)
|
val addChange = NodeRegistration(registerNode.info, instant.toEpochMilli(), AddOrRemove.ADD, expires)
|
||||||
val addWireChange = addChange.toWire(nodeKey.private)
|
val addWireChange = addChange.toWire(nodeKey.private)
|
||||||
service().processRegistrationChangeRequest(RegistrationRequest(addWireChange, mapServiceNode.info.address, Long.MIN_VALUE))
|
service().processRegistrationChangeRequest(RegistrationRequest(addWireChange, mapServiceNode.info.address, Long.MIN_VALUE))
|
||||||
swizzle()
|
swizzle()
|
||||||
|
|
||||||
assertEquals(1, service().nodes.count())
|
assertEquals(1, service().nodes.count())
|
||||||
assertEquals(registerNode.info, service().processQueryRequest(NetworkMapService.QueryIdentityRequest(registerNode.info.identity, mapServiceNode.info.address, Long.MIN_VALUE)).node)
|
assertEquals(registerNode.info, service().processQueryRequest(NetworkMapService.QueryIdentityRequest(registerNode.info.legalIdentity, mapServiceNode.info.address, Long.MIN_VALUE)).node)
|
||||||
|
|
||||||
// Re-registering should be a no-op
|
// Re-registering should be a no-op
|
||||||
service().processRegistrationChangeRequest(RegistrationRequest(addWireChange, mapServiceNode.info.address, Long.MIN_VALUE))
|
service().processRegistrationChangeRequest(RegistrationRequest(addWireChange, mapServiceNode.info.address, Long.MIN_VALUE))
|
||||||
@ -67,7 +67,7 @@ abstract class AbstractNetworkMapServiceTest {
|
|||||||
assert(service().processRegistrationChangeRequest(RegistrationRequest(removeWireChange, mapServiceNode.info.address, Long.MIN_VALUE)).success)
|
assert(service().processRegistrationChangeRequest(RegistrationRequest(removeWireChange, mapServiceNode.info.address, Long.MIN_VALUE)).success)
|
||||||
swizzle()
|
swizzle()
|
||||||
|
|
||||||
assertNull(service().processQueryRequest(NetworkMapService.QueryIdentityRequest(registerNode.info.identity, mapServiceNode.info.address, Long.MIN_VALUE)).node)
|
assertNull(service().processQueryRequest(NetworkMapService.QueryIdentityRequest(registerNode.info.legalIdentity, mapServiceNode.info.address, Long.MIN_VALUE)).node)
|
||||||
swizzle()
|
swizzle()
|
||||||
|
|
||||||
// Trying to de-register a node that doesn't exist should fail
|
// Trying to de-register a node that doesn't exist should fail
|
||||||
@ -88,7 +88,7 @@ abstract class AbstractNetworkMapServiceTest {
|
|||||||
assertEquals(2, fetchPsm.get()?.count())
|
assertEquals(2, fetchPsm.get()?.count())
|
||||||
|
|
||||||
// Forcibly deregister the second node
|
// Forcibly deregister the second node
|
||||||
val nodeKey = registerNode.storage.myLegalIdentityKey
|
val nodeKey = registerNode.services.legalIdentityKey
|
||||||
val instant = Instant.now()
|
val instant = Instant.now()
|
||||||
val expires = instant + NetworkMapService.DEFAULT_EXPIRATION_PERIOD
|
val expires = instant + NetworkMapService.DEFAULT_EXPIRATION_PERIOD
|
||||||
val reg = NodeRegistration(registerNode.info, instant.toEpochMilli()+1, AddOrRemove.REMOVE, expires)
|
val reg = NodeRegistration(registerNode.info, instant.toEpochMilli()+1, AddOrRemove.REMOVE, expires)
|
||||||
@ -126,7 +126,7 @@ abstract class AbstractNetworkMapServiceTest {
|
|||||||
assertEquals(0, service().getUnacknowledgedCount(registerNode.info.address, startingMapVersion))
|
assertEquals(0, service().getUnacknowledgedCount(registerNode.info.address, startingMapVersion))
|
||||||
|
|
||||||
// Fire off an update
|
// Fire off an update
|
||||||
val nodeKey = registerNode.storage.myLegalIdentityKey
|
val nodeKey = registerNode.services.legalIdentityKey
|
||||||
var seq = 0L
|
var seq = 0L
|
||||||
val expires = Instant.now() + NetworkMapService.DEFAULT_EXPIRATION_PERIOD
|
val expires = Instant.now() + NetworkMapService.DEFAULT_EXPIRATION_PERIOD
|
||||||
var reg = NodeRegistration(registerNode.info, seq++, AddOrRemove.ADD, expires)
|
var reg = NodeRegistration(registerNode.info, seq++, AddOrRemove.ADD, expires)
|
||||||
|
@ -3,6 +3,7 @@ package com.r3corda.node.services
|
|||||||
import com.codahale.metrics.MetricRegistry
|
import com.codahale.metrics.MetricRegistry
|
||||||
import com.google.common.util.concurrent.ListenableFuture
|
import com.google.common.util.concurrent.ListenableFuture
|
||||||
import com.r3corda.core.crypto.Party
|
import com.r3corda.core.crypto.Party
|
||||||
|
import com.r3corda.core.node.NodeInfo
|
||||||
import com.r3corda.core.node.services.*
|
import com.r3corda.core.node.services.*
|
||||||
import com.r3corda.core.protocols.ProtocolLogic
|
import com.r3corda.core.protocols.ProtocolLogic
|
||||||
import com.r3corda.core.protocols.ProtocolLogicRefFactory
|
import com.r3corda.core.protocols.ProtocolLogicRefFactory
|
||||||
@ -51,6 +52,8 @@ open class MockServiceHubInternal(
|
|||||||
get() = scheduler ?: throw UnsupportedOperationException()
|
get() = scheduler ?: throw UnsupportedOperationException()
|
||||||
override val clock: Clock
|
override val clock: Clock
|
||||||
get() = overrideClock ?: throw UnsupportedOperationException()
|
get() = overrideClock ?: throw UnsupportedOperationException()
|
||||||
|
override val myInfo: NodeInfo
|
||||||
|
get() = throw UnsupportedOperationException()
|
||||||
|
|
||||||
override val monitoringService: MonitoringService = MonitoringService(MetricRegistry())
|
override val monitoringService: MonitoringService = MonitoringService(MetricRegistry())
|
||||||
override val protocolLogicRefFactory: ProtocolLogicRefFactory
|
override val protocolLogicRefFactory: ProtocolLogicRefFactory
|
||||||
|
@ -259,7 +259,7 @@ class NodeSchedulerServiceTest : SingletonSerializeAsToken() {
|
|||||||
private fun scheduleTX(instant: Instant, increment: Int = 1): ScheduledStateRef? {
|
private fun scheduleTX(instant: Instant, increment: Int = 1): ScheduledStateRef? {
|
||||||
var scheduledRef: ScheduledStateRef? = null
|
var scheduledRef: ScheduledStateRef? = null
|
||||||
apply {
|
apply {
|
||||||
val freshKey = services.storageService.myLegalIdentityKey
|
val freshKey = services.keyManagementService.freshKey()
|
||||||
val state = TestState(factory.create(TestProtocolLogic::class.java, increment), instant)
|
val state = TestState(factory.create(TestProtocolLogic::class.java, increment), instant)
|
||||||
val usefulTX = TransactionType.General.Builder(null).apply {
|
val usefulTX = TransactionType.General.Builder(null).apply {
|
||||||
addOutputState(state, DUMMY_NOTARY)
|
addOutputState(state, DUMMY_NOTARY)
|
||||||
|
@ -36,18 +36,18 @@ class NotaryChangeTests {
|
|||||||
oldNotaryNode = net.createNode(
|
oldNotaryNode = net.createNode(
|
||||||
legalName = DUMMY_NOTARY.name,
|
legalName = DUMMY_NOTARY.name,
|
||||||
keyPair = DUMMY_NOTARY_KEY,
|
keyPair = DUMMY_NOTARY_KEY,
|
||||||
advertisedServices = *arrayOf(ServiceInfo(NetworkMapService.Type), ServiceInfo(SimpleNotaryService.Type)))
|
advertisedServices = *arrayOf(ServiceInfo(NetworkMapService.type), ServiceInfo(SimpleNotaryService.type)))
|
||||||
clientNodeA = net.createNode(networkMapAddress = oldNotaryNode.info.address)
|
clientNodeA = net.createNode(networkMapAddress = oldNotaryNode.info.address)
|
||||||
clientNodeB = net.createNode(networkMapAddress = oldNotaryNode.info.address)
|
clientNodeB = net.createNode(networkMapAddress = oldNotaryNode.info.address)
|
||||||
newNotaryNode = net.createNode(networkMapAddress = oldNotaryNode.info.address, advertisedServices = ServiceInfo(SimpleNotaryService.Type))
|
newNotaryNode = net.createNode(networkMapAddress = oldNotaryNode.info.address, advertisedServices = ServiceInfo(SimpleNotaryService.type))
|
||||||
|
|
||||||
net.runNetwork() // Clear network map registration messages
|
net.runNetwork() // Clear network map registration messages
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `should change notary for a state with single participant`() {
|
fun `should change notary for a state with single participant`() {
|
||||||
val state = issueState(clientNodeA)
|
val state = issueState(clientNodeA, oldNotaryNode)
|
||||||
val newNotary = newNotaryNode.info.identity
|
val newNotary = newNotaryNode.info.notaryIdentity
|
||||||
val protocol = Instigator(state, newNotary)
|
val protocol = Instigator(state, newNotary)
|
||||||
val future = clientNodeA.services.startProtocol("notary-change", protocol)
|
val future = clientNodeA.services.startProtocol("notary-change", protocol)
|
||||||
|
|
||||||
@ -59,8 +59,8 @@ class NotaryChangeTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `should change notary for a state with multiple participants`() {
|
fun `should change notary for a state with multiple participants`() {
|
||||||
val state = issueMultiPartyState(clientNodeA, clientNodeB)
|
val state = issueMultiPartyState(clientNodeA, clientNodeB, oldNotaryNode)
|
||||||
val newNotary = newNotaryNode.info.identity
|
val newNotary = newNotaryNode.info.notaryIdentity
|
||||||
val protocol = Instigator(state, newNotary)
|
val protocol = Instigator(state, newNotary)
|
||||||
val future = clientNodeA.services.startProtocol("notary-change", protocol)
|
val future = clientNodeA.services.startProtocol("notary-change", protocol)
|
||||||
|
|
||||||
@ -75,7 +75,7 @@ class NotaryChangeTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `should throw when a participant refuses to change Notary`() {
|
fun `should throw when a participant refuses to change Notary`() {
|
||||||
val state = issueMultiPartyState(clientNodeA, clientNodeB)
|
val state = issueMultiPartyState(clientNodeA, clientNodeB, oldNotaryNode)
|
||||||
val newEvilNotary = Party("Evil Notary", generateKeyPair().public)
|
val newEvilNotary = Party("Evil Notary", generateKeyPair().public)
|
||||||
val protocol = Instigator(state, newEvilNotary)
|
val protocol = Instigator(state, newEvilNotary)
|
||||||
val future = clientNodeA.services.startProtocol("notary-change", protocol)
|
val future = clientNodeA.services.startProtocol("notary-change", protocol)
|
||||||
@ -96,22 +96,27 @@ class NotaryChangeTests {
|
|||||||
// - The transaction type is not a notary change transaction at all.
|
// - The transaction type is not a notary change transaction at all.
|
||||||
}
|
}
|
||||||
|
|
||||||
fun issueState(node: AbstractNode): StateAndRef<*> {
|
fun issueState(node: AbstractNode, notaryNode: AbstractNode): StateAndRef<*> {
|
||||||
val tx = DummyContract.generateInitial(node.info.identity.ref(0), Random().nextInt(), DUMMY_NOTARY)
|
val tx = DummyContract.generateInitial(node.info.legalIdentity.ref(0), Random().nextInt(), notaryNode.info.notaryIdentity)
|
||||||
tx.signWith(node.storage.myLegalIdentityKey)
|
val nodeKey = node.services.legalIdentityKey
|
||||||
tx.signWith(DUMMY_NOTARY_KEY)
|
tx.signWith(nodeKey)
|
||||||
|
val notaryKeyPair = notaryNode.services.notaryIdentityKey
|
||||||
|
tx.signWith(notaryKeyPair)
|
||||||
val stx = tx.toSignedTransaction()
|
val stx = tx.toSignedTransaction()
|
||||||
node.services.recordTransactions(listOf(stx))
|
node.services.recordTransactions(listOf(stx))
|
||||||
return StateAndRef(tx.outputStates().first(), StateRef(stx.id, 0))
|
return StateAndRef(tx.outputStates().first(), StateRef(stx.id, 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun issueMultiPartyState(nodeA: AbstractNode, nodeB: AbstractNode): StateAndRef<DummyContract.MultiOwnerState> {
|
fun issueMultiPartyState(nodeA: AbstractNode, nodeB: AbstractNode, notaryNode: AbstractNode): StateAndRef<DummyContract.MultiOwnerState> {
|
||||||
val state = TransactionState(DummyContract.MultiOwnerState(0,
|
val state = TransactionState(DummyContract.MultiOwnerState(0,
|
||||||
listOf(nodeA.info.identity.owningKey, nodeB.info.identity.owningKey)), DUMMY_NOTARY)
|
listOf(nodeA.info.legalIdentity.owningKey, nodeB.info.legalIdentity.owningKey)), notaryNode.info.notaryIdentity)
|
||||||
val tx = TransactionType.NotaryChange.Builder(DUMMY_NOTARY).withItems(state)
|
val tx = TransactionType.NotaryChange.Builder(notaryNode.info.notaryIdentity).withItems(state)
|
||||||
tx.signWith(nodeA.storage.myLegalIdentityKey)
|
val nodeAKey = nodeA.services.legalIdentityKey
|
||||||
tx.signWith(nodeB.storage.myLegalIdentityKey)
|
val nodeBKey = nodeB.services.legalIdentityKey
|
||||||
tx.signWith(DUMMY_NOTARY_KEY)
|
tx.signWith(nodeAKey)
|
||||||
|
tx.signWith(nodeBKey)
|
||||||
|
val notaryKeyPair = notaryNode.services.notaryIdentityKey
|
||||||
|
tx.signWith(notaryKeyPair)
|
||||||
val stx = tx.toSignedTransaction()
|
val stx = tx.toSignedTransaction()
|
||||||
nodeA.services.recordTransactions(listOf(stx))
|
nodeA.services.recordTransactions(listOf(stx))
|
||||||
nodeB.services.recordTransactions(listOf(stx))
|
nodeB.services.recordTransactions(listOf(stx))
|
||||||
@ -119,10 +124,11 @@ fun issueMultiPartyState(nodeA: AbstractNode, nodeB: AbstractNode): StateAndRef<
|
|||||||
return stateAndRef
|
return stateAndRef
|
||||||
}
|
}
|
||||||
|
|
||||||
fun issueInvalidState(node: AbstractNode, notary: Party = DUMMY_NOTARY): StateAndRef<*> {
|
fun issueInvalidState(node: AbstractNode, notary: Party): StateAndRef<*> {
|
||||||
val tx = DummyContract.generateInitial(node.info.identity.ref(0), Random().nextInt(), notary)
|
val tx = DummyContract.generateInitial(node.info.legalIdentity.ref(0), Random().nextInt(), notary)
|
||||||
tx.setTime(Instant.now(), 30.seconds)
|
tx.setTime(Instant.now(), 30.seconds)
|
||||||
tx.signWith(node.storage.myLegalIdentityKey)
|
val nodeKey = node.services.legalIdentityKey
|
||||||
|
tx.signWith(nodeKey)
|
||||||
val stx = tx.toSignedTransaction(false)
|
val stx = tx.toSignedTransaction(false)
|
||||||
node.services.recordTransactions(listOf(stx))
|
node.services.recordTransactions(listOf(stx))
|
||||||
return StateAndRef(tx.outputStates().first(), StateRef(stx.id, 0))
|
return StateAndRef(tx.outputStates().first(), StateRef(stx.id, 0))
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
package com.r3corda.node.services
|
package com.r3corda.node.services
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture
|
import com.google.common.util.concurrent.ListenableFuture
|
||||||
|
import com.r3corda.core.contracts.DummyContract
|
||||||
|
import com.r3corda.core.contracts.StateAndRef
|
||||||
|
import com.r3corda.core.contracts.StateRef
|
||||||
import com.r3corda.core.contracts.TransactionType
|
import com.r3corda.core.contracts.TransactionType
|
||||||
import com.r3corda.core.node.services.ServiceInfo
|
import com.r3corda.core.node.services.ServiceInfo
|
||||||
import com.r3corda.core.crypto.DigitalSignature
|
import com.r3corda.core.crypto.DigitalSignature
|
||||||
@ -8,6 +11,7 @@ import com.r3corda.core.seconds
|
|||||||
import com.r3corda.core.transactions.SignedTransaction
|
import com.r3corda.core.transactions.SignedTransaction
|
||||||
import com.r3corda.core.utilities.DUMMY_NOTARY
|
import com.r3corda.core.utilities.DUMMY_NOTARY
|
||||||
import com.r3corda.core.utilities.DUMMY_NOTARY_KEY
|
import com.r3corda.core.utilities.DUMMY_NOTARY_KEY
|
||||||
|
import com.r3corda.node.internal.AbstractNode
|
||||||
import com.r3corda.node.services.network.NetworkMapService
|
import com.r3corda.node.services.network.NetworkMapService
|
||||||
import com.r3corda.node.services.transactions.SimpleNotaryService
|
import com.r3corda.node.services.transactions.SimpleNotaryService
|
||||||
import com.r3corda.protocols.NotaryError
|
import com.r3corda.protocols.NotaryError
|
||||||
@ -18,6 +22,7 @@ import com.r3corda.testing.node.MockNetwork
|
|||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
import java.util.*
|
||||||
import java.util.concurrent.ExecutionException
|
import java.util.concurrent.ExecutionException
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertFailsWith
|
import kotlin.test.assertFailsWith
|
||||||
@ -33,7 +38,7 @@ class NotaryServiceTests {
|
|||||||
notaryNode = net.createNode(
|
notaryNode = net.createNode(
|
||||||
legalName = DUMMY_NOTARY.name,
|
legalName = DUMMY_NOTARY.name,
|
||||||
keyPair = DUMMY_NOTARY_KEY,
|
keyPair = DUMMY_NOTARY_KEY,
|
||||||
advertisedServices = *arrayOf(ServiceInfo(NetworkMapService.Type), ServiceInfo(SimpleNotaryService.Type)))
|
advertisedServices = *arrayOf(ServiceInfo(NetworkMapService.type), ServiceInfo(SimpleNotaryService.type)))
|
||||||
clientNode = net.createNode(networkMapAddress = notaryNode.info.address, keyPair = MINI_CORP_KEY)
|
clientNode = net.createNode(networkMapAddress = notaryNode.info.address, keyPair = MINI_CORP_KEY)
|
||||||
net.runNetwork() // Clear network map registration messages
|
net.runNetwork() // Clear network map registration messages
|
||||||
}
|
}
|
||||||
@ -41,7 +46,7 @@ class NotaryServiceTests {
|
|||||||
@Test fun `should sign a unique transaction with a valid timestamp`() {
|
@Test fun `should sign a unique transaction with a valid timestamp`() {
|
||||||
val stx = run {
|
val stx = run {
|
||||||
val inputState = issueState(clientNode)
|
val inputState = issueState(clientNode)
|
||||||
val tx = TransactionType.General.Builder(DUMMY_NOTARY).withItems(inputState)
|
val tx = TransactionType.General.Builder(notaryNode.info.notaryIdentity).withItems(inputState)
|
||||||
tx.setTime(Instant.now(), 30.seconds)
|
tx.setTime(Instant.now(), 30.seconds)
|
||||||
tx.signWith(clientNode.keyPair!!)
|
tx.signWith(clientNode.keyPair!!)
|
||||||
tx.toSignedTransaction(false)
|
tx.toSignedTransaction(false)
|
||||||
@ -55,7 +60,7 @@ class NotaryServiceTests {
|
|||||||
@Test fun `should sign a unique transaction without a timestamp`() {
|
@Test fun `should sign a unique transaction without a timestamp`() {
|
||||||
val stx = run {
|
val stx = run {
|
||||||
val inputState = issueState(clientNode)
|
val inputState = issueState(clientNode)
|
||||||
val tx = TransactionType.General.Builder(DUMMY_NOTARY).withItems(inputState)
|
val tx = TransactionType.General.Builder(notaryNode.info.notaryIdentity).withItems(inputState)
|
||||||
tx.signWith(clientNode.keyPair!!)
|
tx.signWith(clientNode.keyPair!!)
|
||||||
tx.toSignedTransaction(false)
|
tx.toSignedTransaction(false)
|
||||||
}
|
}
|
||||||
@ -68,7 +73,7 @@ class NotaryServiceTests {
|
|||||||
@Test fun `should report error for transaction with an invalid timestamp`() {
|
@Test fun `should report error for transaction with an invalid timestamp`() {
|
||||||
val stx = run {
|
val stx = run {
|
||||||
val inputState = issueState(clientNode)
|
val inputState = issueState(clientNode)
|
||||||
val tx = TransactionType.General.Builder(DUMMY_NOTARY).withItems(inputState)
|
val tx = TransactionType.General.Builder(notaryNode.info.notaryIdentity).withItems(inputState)
|
||||||
tx.setTime(Instant.now().plusSeconds(3600), 30.seconds)
|
tx.setTime(Instant.now().plusSeconds(3600), 30.seconds)
|
||||||
tx.signWith(clientNode.keyPair!!)
|
tx.signWith(clientNode.keyPair!!)
|
||||||
tx.toSignedTransaction(false)
|
tx.toSignedTransaction(false)
|
||||||
@ -84,7 +89,7 @@ class NotaryServiceTests {
|
|||||||
@Test fun `should report conflict for a duplicate transaction`() {
|
@Test fun `should report conflict for a duplicate transaction`() {
|
||||||
val stx = run {
|
val stx = run {
|
||||||
val inputState = issueState(clientNode)
|
val inputState = issueState(clientNode)
|
||||||
val tx = TransactionType.General.Builder(DUMMY_NOTARY).withItems(inputState)
|
val tx = TransactionType.General.Builder(notaryNode.info.notaryIdentity).withItems(inputState)
|
||||||
tx.signWith(clientNode.keyPair!!)
|
tx.signWith(clientNode.keyPair!!)
|
||||||
tx.toSignedTransaction(false)
|
tx.toSignedTransaction(false)
|
||||||
}
|
}
|
||||||
@ -109,4 +114,15 @@ class NotaryServiceTests {
|
|||||||
net.runNetwork()
|
net.runNetwork()
|
||||||
return future
|
return future
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun issueState(node: AbstractNode): StateAndRef<*> {
|
||||||
|
val tx = DummyContract.generateInitial(node.info.legalIdentity.ref(0), Random().nextInt(), notaryNode.info.notaryIdentity)
|
||||||
|
val nodeKey = node.services.legalIdentityKey
|
||||||
|
tx.signWith(nodeKey)
|
||||||
|
val notaryKeyPair = notaryNode.services.notaryIdentityKey
|
||||||
|
tx.signWith(notaryKeyPair)
|
||||||
|
val stx = tx.toSignedTransaction()
|
||||||
|
node.services.recordTransactions(listOf(stx))
|
||||||
|
return StateAndRef(tx.outputStates().first(), StateRef(stx.id, 0))
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,14 +1,13 @@
|
|||||||
package com.r3corda.node.services
|
package com.r3corda.node.services
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture
|
import com.google.common.util.concurrent.ListenableFuture
|
||||||
import com.r3corda.core.contracts.Command
|
import com.r3corda.core.contracts.*
|
||||||
import com.r3corda.core.contracts.DummyContract
|
|
||||||
import com.r3corda.core.contracts.TransactionType
|
|
||||||
import com.r3corda.core.crypto.DigitalSignature
|
import com.r3corda.core.crypto.DigitalSignature
|
||||||
import com.r3corda.core.node.services.ServiceInfo
|
import com.r3corda.core.node.services.ServiceInfo
|
||||||
import com.r3corda.core.transactions.SignedTransaction
|
import com.r3corda.core.transactions.SignedTransaction
|
||||||
import com.r3corda.core.utilities.DUMMY_NOTARY
|
import com.r3corda.core.utilities.DUMMY_NOTARY
|
||||||
import com.r3corda.core.utilities.DUMMY_NOTARY_KEY
|
import com.r3corda.core.utilities.DUMMY_NOTARY_KEY
|
||||||
|
import com.r3corda.node.internal.AbstractNode
|
||||||
import com.r3corda.node.services.network.NetworkMapService
|
import com.r3corda.node.services.network.NetworkMapService
|
||||||
import com.r3corda.node.services.transactions.ValidatingNotaryService
|
import com.r3corda.node.services.transactions.ValidatingNotaryService
|
||||||
import com.r3corda.protocols.NotaryError
|
import com.r3corda.protocols.NotaryError
|
||||||
@ -20,6 +19,7 @@ import com.r3corda.testing.node.MockNetwork
|
|||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
import java.util.*
|
||||||
import java.util.concurrent.ExecutionException
|
import java.util.concurrent.ExecutionException
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertFailsWith
|
import kotlin.test.assertFailsWith
|
||||||
@ -34,7 +34,7 @@ class ValidatingNotaryServiceTests {
|
|||||||
notaryNode = net.createNode(
|
notaryNode = net.createNode(
|
||||||
legalName = DUMMY_NOTARY.name,
|
legalName = DUMMY_NOTARY.name,
|
||||||
keyPair = DUMMY_NOTARY_KEY,
|
keyPair = DUMMY_NOTARY_KEY,
|
||||||
advertisedServices = *arrayOf(ServiceInfo(NetworkMapService.Type), ServiceInfo(ValidatingNotaryService.Type))
|
advertisedServices = *arrayOf(ServiceInfo(NetworkMapService.type), ServiceInfo(ValidatingNotaryService.type))
|
||||||
)
|
)
|
||||||
clientNode = net.createNode(networkMapAddress = notaryNode.info.address, keyPair = MINI_CORP_KEY)
|
clientNode = net.createNode(networkMapAddress = notaryNode.info.address, keyPair = MINI_CORP_KEY)
|
||||||
net.runNetwork() // Clear network map registration messages
|
net.runNetwork() // Clear network map registration messages
|
||||||
@ -42,8 +42,8 @@ class ValidatingNotaryServiceTests {
|
|||||||
|
|
||||||
@Test fun `should report error for invalid transaction dependency`() {
|
@Test fun `should report error for invalid transaction dependency`() {
|
||||||
val stx = run {
|
val stx = run {
|
||||||
val inputState = issueInvalidState(clientNode)
|
val inputState = issueInvalidState(clientNode, notaryNode.info.notaryIdentity)
|
||||||
val tx = TransactionType.General.Builder(DUMMY_NOTARY).withItems(inputState)
|
val tx = TransactionType.General.Builder(notaryNode.info.notaryIdentity).withItems(inputState)
|
||||||
tx.signWith(clientNode.keyPair!!)
|
tx.signWith(clientNode.keyPair!!)
|
||||||
tx.toSignedTransaction(false)
|
tx.toSignedTransaction(false)
|
||||||
}
|
}
|
||||||
@ -61,7 +61,7 @@ class ValidatingNotaryServiceTests {
|
|||||||
val inputState = issueState(clientNode)
|
val inputState = issueState(clientNode)
|
||||||
|
|
||||||
val command = Command(DummyContract.Commands.Move(), expectedMissingKey)
|
val command = Command(DummyContract.Commands.Move(), expectedMissingKey)
|
||||||
val tx = TransactionType.General.Builder(DUMMY_NOTARY).withItems(inputState, command)
|
val tx = TransactionType.General.Builder(notaryNode.info.notaryIdentity).withItems(inputState, command)
|
||||||
tx.signWith(clientNode.keyPair!!)
|
tx.signWith(clientNode.keyPair!!)
|
||||||
tx.toSignedTransaction(false)
|
tx.toSignedTransaction(false)
|
||||||
}
|
}
|
||||||
@ -82,4 +82,15 @@ class ValidatingNotaryServiceTests {
|
|||||||
net.runNetwork()
|
net.runNetwork()
|
||||||
return future
|
return future
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun issueState(node: AbstractNode): StateAndRef<*> {
|
||||||
|
val tx = DummyContract.generateInitial(node.info.legalIdentity.ref(0), Random().nextInt(), notaryNode.info.notaryIdentity)
|
||||||
|
val nodeKey = node.services.legalIdentityKey
|
||||||
|
tx.signWith(nodeKey)
|
||||||
|
val notaryKeyPair = notaryNode.services.notaryIdentityKey
|
||||||
|
tx.signWith(notaryKeyPair)
|
||||||
|
val stx = tx.toSignedTransaction()
|
||||||
|
node.services.recordTransactions(listOf(stx))
|
||||||
|
return StateAndRef(tx.outputStates().first(), StateRef(stx.id, 0))
|
||||||
|
}
|
||||||
}
|
}
|
@ -84,7 +84,7 @@ class VaultWithCashTest {
|
|||||||
fun `issue and spend total correctly and irrelevant ignored`() {
|
fun `issue and spend total correctly and irrelevant ignored`() {
|
||||||
databaseTransaction(database) {
|
databaseTransaction(database) {
|
||||||
// A tx that sends us money.
|
// A tx that sends us money.
|
||||||
val freshKey = services.storageService.myLegalIdentityKey
|
val freshKey = services.keyManagementService.freshKey()
|
||||||
val usefulTX = TransactionType.General.Builder(null).apply {
|
val usefulTX = TransactionType.General.Builder(null).apply {
|
||||||
Cash().generateIssue(this, 100.DOLLARS `issued by` MEGA_CORP.ref(1), freshKey.public, DUMMY_NOTARY)
|
Cash().generateIssue(this, 100.DOLLARS `issued by` MEGA_CORP.ref(1), freshKey.public, DUMMY_NOTARY)
|
||||||
signWith(MEGA_CORP_KEY)
|
signWith(MEGA_CORP_KEY)
|
||||||
@ -122,7 +122,7 @@ class VaultWithCashTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `branching LinearStates fails to verify`() {
|
fun `branching LinearStates fails to verify`() {
|
||||||
databaseTransaction(database) {
|
databaseTransaction(database) {
|
||||||
val freshKey = services.storageService.myLegalIdentityKey
|
val freshKey = services.keyManagementService.freshKey()
|
||||||
val linearId = UniqueIdentifier()
|
val linearId = UniqueIdentifier()
|
||||||
|
|
||||||
// Issue a linear state
|
// Issue a linear state
|
||||||
@ -142,7 +142,7 @@ class VaultWithCashTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `sequencing LinearStates works`() {
|
fun `sequencing LinearStates works`() {
|
||||||
databaseTransaction(database) {
|
databaseTransaction(database) {
|
||||||
val freshKey = services.storageService.myLegalIdentityKey
|
val freshKey = services.keyManagementService.freshKey()
|
||||||
|
|
||||||
val linearId = UniqueIdentifier()
|
val linearId = UniqueIdentifier()
|
||||||
|
|
||||||
|
@ -33,8 +33,8 @@ class DataVendingServiceTests {
|
|||||||
@Test
|
@Test
|
||||||
fun `notify of transaction`() {
|
fun `notify of transaction`() {
|
||||||
val (vaultServiceNode, registerNode) = network.createTwoNodes()
|
val (vaultServiceNode, registerNode) = network.createTwoNodes()
|
||||||
val beneficiary = vaultServiceNode.services.storageService.myLegalIdentityKey.public
|
val beneficiary = vaultServiceNode.info.legalIdentity.owningKey
|
||||||
val deposit = registerNode.services.storageService.myLegalIdentity.ref(1)
|
val deposit = registerNode.info.legalIdentity.ref(1)
|
||||||
network.runNetwork()
|
network.runNetwork()
|
||||||
|
|
||||||
// Generate an issuance transaction
|
// Generate an issuance transaction
|
||||||
@ -42,7 +42,8 @@ class DataVendingServiceTests {
|
|||||||
Cash().generateIssue(ptx, Amount(100, Issued(deposit, USD)), beneficiary, DUMMY_NOTARY)
|
Cash().generateIssue(ptx, Amount(100, Issued(deposit, USD)), beneficiary, DUMMY_NOTARY)
|
||||||
|
|
||||||
// Complete the cash transaction, and then manually relay it
|
// Complete the cash transaction, and then manually relay it
|
||||||
ptx.signWith(registerNode.services.storageService.myLegalIdentityKey)
|
val registerKey = registerNode.services.legalIdentityKey
|
||||||
|
ptx.signWith(registerKey)
|
||||||
val tx = ptx.toSignedTransaction()
|
val tx = ptx.toSignedTransaction()
|
||||||
assertEquals(0, vaultServiceNode.services.vaultService.currentVault.states.toList().size)
|
assertEquals(0, vaultServiceNode.services.vaultService.currentVault.states.toList().size)
|
||||||
|
|
||||||
@ -61,7 +62,7 @@ class DataVendingServiceTests {
|
|||||||
@Test
|
@Test
|
||||||
fun `notify failure`() {
|
fun `notify failure`() {
|
||||||
val (vaultServiceNode, registerNode) = network.createTwoNodes()
|
val (vaultServiceNode, registerNode) = network.createTwoNodes()
|
||||||
val beneficiary = vaultServiceNode.services.storageService.myLegalIdentityKey.public
|
val beneficiary = vaultServiceNode.info.legalIdentity.owningKey
|
||||||
val deposit = MEGA_CORP.ref(1)
|
val deposit = MEGA_CORP.ref(1)
|
||||||
network.runNetwork()
|
network.runNetwork()
|
||||||
|
|
||||||
@ -70,7 +71,8 @@ class DataVendingServiceTests {
|
|||||||
Cash().generateIssue(ptx, Amount(100, Issued(deposit, USD)), beneficiary, DUMMY_NOTARY)
|
Cash().generateIssue(ptx, Amount(100, Issued(deposit, USD)), beneficiary, DUMMY_NOTARY)
|
||||||
|
|
||||||
// The transaction tries issuing MEGA_CORP cash, but we aren't the issuer, so it's invalid
|
// The transaction tries issuing MEGA_CORP cash, but we aren't the issuer, so it's invalid
|
||||||
ptx.signWith(registerNode.services.storageService.myLegalIdentityKey)
|
val registerKey = registerNode.services.legalIdentityKey
|
||||||
|
ptx.signWith(registerKey)
|
||||||
val tx = ptx.toSignedTransaction(false)
|
val tx = ptx.toSignedTransaction(false)
|
||||||
assertEquals(0, vaultServiceNode.services.vaultService.currentVault.states.toList().size)
|
assertEquals(0, vaultServiceNode.services.vaultService.currentVault.states.toList().size)
|
||||||
|
|
||||||
@ -82,7 +84,7 @@ class DataVendingServiceTests {
|
|||||||
|
|
||||||
private fun MockNode.sendNotifyTx(tx: SignedTransaction, walletServiceNode: MockNode) {
|
private fun MockNode.sendNotifyTx(tx: SignedTransaction, walletServiceNode: MockNode) {
|
||||||
walletServiceNode.services.registerProtocolInitiator(NotifyTxProtocol::class, ::NotifyTransactionHandler)
|
walletServiceNode.services.registerProtocolInitiator(NotifyTxProtocol::class, ::NotifyTransactionHandler)
|
||||||
services.startProtocol("notify-tx", NotifyTxProtocol(walletServiceNode.info.identity, tx))
|
services.startProtocol("notify-tx", NotifyTxProtocol(walletServiceNode.info.legalIdentity, tx))
|
||||||
network.runNetwork()
|
network.runNetwork()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ class StateMachineManagerTests {
|
|||||||
fun `protocol restarted just after receiving payload`() {
|
fun `protocol restarted just after receiving payload`() {
|
||||||
node2.services.registerProtocolInitiator(SendProtocol::class) { ReceiveThenSuspendProtocol(it) }
|
node2.services.registerProtocolInitiator(SendProtocol::class) { ReceiveThenSuspendProtocol(it) }
|
||||||
val payload = random63BitValue()
|
val payload = random63BitValue()
|
||||||
node1.smm.add("test", SendProtocol(payload, node2.info.identity))
|
node1.smm.add("test", SendProtocol(payload, node2.info.legalIdentity))
|
||||||
|
|
||||||
// We push through just enough messages to get only the SessionData sent
|
// We push through just enough messages to get only the SessionData sent
|
||||||
// TODO We should be able to give runNetwork a predicate for when to stop
|
// TODO We should be able to give runNetwork a predicate for when to stop
|
||||||
@ -108,7 +108,7 @@ class StateMachineManagerTests {
|
|||||||
fun `protocol loaded from checkpoint will respond to messages from before start`() {
|
fun `protocol loaded from checkpoint will respond to messages from before start`() {
|
||||||
val payload = random63BitValue()
|
val payload = random63BitValue()
|
||||||
node1.services.registerProtocolInitiator(ReceiveThenSuspendProtocol::class) { SendProtocol(payload, it) }
|
node1.services.registerProtocolInitiator(ReceiveThenSuspendProtocol::class) { SendProtocol(payload, it) }
|
||||||
val receiveProtocol = ReceiveThenSuspendProtocol(node1.info.identity)
|
val receiveProtocol = ReceiveThenSuspendProtocol(node1.info.legalIdentity)
|
||||||
node2.smm.add("test", receiveProtocol) // Prepare checkpointed receive protocol
|
node2.smm.add("test", receiveProtocol) // Prepare checkpointed receive protocol
|
||||||
node2.stop() // kill receiver
|
node2.stop() // kill receiver
|
||||||
val restoredProtocol = node2.restartAndGetRestoredProtocol<ReceiveThenSuspendProtocol>(node1.info.address)
|
val restoredProtocol = node2.restartAndGetRestoredProtocol<ReceiveThenSuspendProtocol>(node1.info.address)
|
||||||
@ -135,7 +135,7 @@ class StateMachineManagerTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Kick off first send and receive
|
// Kick off first send and receive
|
||||||
node2.smm.add("test", PingPongProtocol(node3.info.identity, payload))
|
node2.smm.add("test", PingPongProtocol(node3.info.legalIdentity, payload))
|
||||||
assertEquals(1, node2.checkpointStorage.checkpoints().count())
|
assertEquals(1, node2.checkpointStorage.checkpoints().count())
|
||||||
// Restart node and thus reload the checkpoint and resend the message with same UUID
|
// Restart node and thus reload the checkpoint and resend the message with same UUID
|
||||||
node2.stop()
|
node2.stop()
|
||||||
@ -165,7 +165,7 @@ class StateMachineManagerTests {
|
|||||||
node2.services.registerProtocolInitiator(SendProtocol::class) { ReceiveThenSuspendProtocol(it) }
|
node2.services.registerProtocolInitiator(SendProtocol::class) { ReceiveThenSuspendProtocol(it) }
|
||||||
node3.services.registerProtocolInitiator(SendProtocol::class) { ReceiveThenSuspendProtocol(it) }
|
node3.services.registerProtocolInitiator(SendProtocol::class) { ReceiveThenSuspendProtocol(it) }
|
||||||
val payload = random63BitValue()
|
val payload = random63BitValue()
|
||||||
node1.smm.add("multiple-send", SendProtocol(payload, node2.info.identity, node3.info.identity))
|
node1.smm.add("multiple-send", SendProtocol(payload, node2.info.legalIdentity, node3.info.legalIdentity))
|
||||||
net.runNetwork()
|
net.runNetwork()
|
||||||
val node2Protocol = node2.getSingleProtocol<ReceiveThenSuspendProtocol>().first
|
val node2Protocol = node2.getSingleProtocol<ReceiveThenSuspendProtocol>().first
|
||||||
val node3Protocol = node3.getSingleProtocol<ReceiveThenSuspendProtocol>().first
|
val node3Protocol = node3.getSingleProtocol<ReceiveThenSuspendProtocol>().first
|
||||||
@ -181,7 +181,7 @@ class StateMachineManagerTests {
|
|||||||
val node3Payload = random63BitValue()
|
val node3Payload = random63BitValue()
|
||||||
node2.services.registerProtocolInitiator(ReceiveThenSuspendProtocol::class) { SendProtocol(node2Payload, it) }
|
node2.services.registerProtocolInitiator(ReceiveThenSuspendProtocol::class) { SendProtocol(node2Payload, it) }
|
||||||
node3.services.registerProtocolInitiator(ReceiveThenSuspendProtocol::class) { SendProtocol(node3Payload, it) }
|
node3.services.registerProtocolInitiator(ReceiveThenSuspendProtocol::class) { SendProtocol(node3Payload, it) }
|
||||||
val multiReceiveProtocol = ReceiveThenSuspendProtocol(node2.info.identity, node3.info.identity)
|
val multiReceiveProtocol = ReceiveThenSuspendProtocol(node2.info.legalIdentity, node3.info.legalIdentity)
|
||||||
node1.smm.add("multiple-receive", multiReceiveProtocol)
|
node1.smm.add("multiple-receive", multiReceiveProtocol)
|
||||||
net.runNetwork(1) // session handshaking
|
net.runNetwork(1) // session handshaking
|
||||||
// have the messages arrive in reverse order of receive
|
// have the messages arrive in reverse order of receive
|
||||||
@ -195,7 +195,7 @@ class StateMachineManagerTests {
|
|||||||
@Test
|
@Test
|
||||||
fun `exception thrown on other side`() {
|
fun `exception thrown on other side`() {
|
||||||
node2.services.registerProtocolInitiator(ReceiveThenSuspendProtocol::class) { ExceptionProtocol }
|
node2.services.registerProtocolInitiator(ReceiveThenSuspendProtocol::class) { ExceptionProtocol }
|
||||||
val future = node1.smm.add("exception", ReceiveThenSuspendProtocol(node2.info.identity)).resultFuture
|
val future = node1.smm.add("exception", ReceiveThenSuspendProtocol(node2.info.legalIdentity)).resultFuture
|
||||||
net.runNetwork()
|
net.runNetwork()
|
||||||
assertThatThrownBy { future.get() }.hasCauseInstanceOf(ProtocolSessionException::class.java)
|
assertThatThrownBy { future.get() }.hasCauseInstanceOf(ProtocolSessionException::class.java)
|
||||||
}
|
}
|
||||||
|
@ -406,11 +406,11 @@ private fun startNode(params: CliParams.RunNode, networkMap: SingleMessageRecipi
|
|||||||
val networkMapId =
|
val networkMapId =
|
||||||
when (params.node) {
|
when (params.node) {
|
||||||
IRSDemoNode.NodeA -> {
|
IRSDemoNode.NodeA -> {
|
||||||
advertisedServices = setOf(ServiceInfo(NetworkMapService.Type), ServiceInfo(SimpleNotaryService.Type))
|
advertisedServices = setOf(ServiceInfo(NetworkMapService.type), ServiceInfo(SimpleNotaryService.type))
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
IRSDemoNode.NodeB -> {
|
IRSDemoNode.NodeB -> {
|
||||||
advertisedServices = setOf(ServiceInfo(NodeInterestRates.Type))
|
advertisedServices = setOf(ServiceInfo(NodeInterestRates.type))
|
||||||
networkMap
|
networkMap
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -475,7 +475,7 @@ private fun loadConfigFile(baseDir: Path, configFile: Path, configOverrides: Map
|
|||||||
|
|
||||||
private fun createIdentities(nodeConf: NodeConfiguration) {
|
private fun createIdentities(nodeConf: NodeConfiguration) {
|
||||||
val mockNetwork = MockNetwork(false)
|
val mockNetwork = MockNetwork(false)
|
||||||
val node = MockNetwork.MockNode(nodeConf, mockNetwork, null, setOf(ServiceInfo(NetworkMapService.Type), ServiceInfo(SimpleNotaryService.Type)), 0, null)
|
val node = MockNetwork.MockNode(nodeConf, mockNetwork, null, setOf(ServiceInfo(NetworkMapService.type), ServiceInfo(SimpleNotaryService.type)), 0, null)
|
||||||
node.start()
|
node.start()
|
||||||
node.stop()
|
node.stop()
|
||||||
}
|
}
|
||||||
|
@ -78,12 +78,12 @@ fun main(args: Array<String>) {
|
|||||||
}
|
}
|
||||||
node.networkMapRegistrationFuture.get()
|
node.networkMapRegistrationFuture.get()
|
||||||
val notaryNode = node.services.networkMapCache.notaryNodes[0]
|
val notaryNode = node.services.networkMapCache.notaryNodes[0]
|
||||||
val rateOracle = node.services.networkMapCache.get(InterestRateSwap.OracleType).first()
|
val rateOracle = node.services.networkMapCache.get(InterestRateSwap.oracleType).first()
|
||||||
|
|
||||||
// Make a garbage transaction that includes a rate fix.
|
// Make a garbage transaction that includes a rate fix.
|
||||||
val tx = TransactionType.General.Builder(notaryNode.identity)
|
val tx = TransactionType.General.Builder(notaryNode.notaryIdentity)
|
||||||
tx.addOutputState(TransactionState(Cash.State(1500.DOLLARS `issued by` node.storage.myLegalIdentity.ref(1), node.storage.myLegalIdentityKey.public), notaryNode.identity))
|
tx.addOutputState(TransactionState(Cash.State(1500.DOLLARS `issued by` node.info.legalIdentity.ref(1), node.info.legalIdentity.owningKey), notaryNode.notaryIdentity))
|
||||||
val protocol = RatesFixProtocol(tx, rateOracle.identity, fixOf, expectedRate, rateTolerance)
|
val protocol = RatesFixProtocol(tx, rateOracle.serviceIdentities(InterestRateSwap.oracleType).first(), fixOf, expectedRate, rateTolerance)
|
||||||
node.services.startProtocol("demo.ratefix", protocol).get()
|
node.services.startProtocol("demo.ratefix", protocol).get()
|
||||||
node.stop()
|
node.stop()
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ fun main(args: Array<String>) {
|
|||||||
// the map is not very helpful, but we need one anyway. So just make the buyer side run the network map as it's
|
// the map is not very helpful, but we need one anyway. So just make the buyer side run the network map as it's
|
||||||
// the side that sticks around waiting for the seller.
|
// the side that sticks around waiting for the seller.
|
||||||
val networkMapId = if (role == Role.BUYER) {
|
val networkMapId = if (role == Role.BUYER) {
|
||||||
advertisedServices = setOf(ServiceInfo(NetworkMapService.Type), ServiceInfo(SimpleNotaryService.Type))
|
advertisedServices = setOf(ServiceInfo(NetworkMapService.type), ServiceInfo(SimpleNotaryService.type))
|
||||||
null
|
null
|
||||||
} else {
|
} else {
|
||||||
advertisedServices = emptySet()
|
advertisedServices = emptySet()
|
||||||
@ -160,7 +160,7 @@ fun main(args: Array<String>) {
|
|||||||
runBuyer(node, amount)
|
runBuyer(node, amount)
|
||||||
} else {
|
} else {
|
||||||
node.networkMapRegistrationFuture.success {
|
node.networkMapRegistrationFuture.success {
|
||||||
val party = node.netMapCache.getNodeByLegalName("Bank A")?.identity ?: throw IllegalStateException("Cannot find other node?!")
|
val party = node.netMapCache.getNodeByLegalName("Bank A")?.legalIdentity ?: throw IllegalStateException("Cannot find other node?!")
|
||||||
runSeller(node, amount, party)
|
runSeller(node, amount, party)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -211,8 +211,8 @@ private fun runBuyer(node: Node, amount: Amount<Currency>) {
|
|||||||
// TODO: At some point this demo should be extended to have a central bank node.
|
// TODO: At some point this demo should be extended to have a central bank node.
|
||||||
databaseTransaction(node.database) {
|
databaseTransaction(node.database) {
|
||||||
node.services.fillWithSomeTestCash(300000.DOLLARS,
|
node.services.fillWithSomeTestCash(300000.DOLLARS,
|
||||||
outputNotary = node.info.identity, // In this demo, the buyer and notary are the same.
|
outputNotary = node.info.notaryIdentity, // In this demo, the buyer and notary are on the same node, but need to use right key.
|
||||||
ownedBy = node.storage.myLegalIdentityKey.public)
|
ownedBy = node.info.legalIdentity.owningKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait around until a node asks to start a trade with us. In a real system, this part would happen out of band
|
// Wait around until a node asks to start a trade with us. In a real system, this part would happen out of band
|
||||||
@ -241,7 +241,7 @@ private class TraderDemoProtocolBuyer(val otherSide: Party,
|
|||||||
val notary: NodeInfo = serviceHub.networkMapCache.notaryNodes[0]
|
val notary: NodeInfo = serviceHub.networkMapCache.notaryNodes[0]
|
||||||
val buyer = TwoPartyTradeProtocol.Buyer(
|
val buyer = TwoPartyTradeProtocol.Buyer(
|
||||||
otherSide,
|
otherSide,
|
||||||
notary.identity,
|
notary.notaryIdentity,
|
||||||
amount,
|
amount,
|
||||||
CommercialPaper.State::class.java)
|
CommercialPaper.State::class.java)
|
||||||
|
|
||||||
@ -304,7 +304,7 @@ private class TraderDemoProtocolSeller(val otherSide: Party,
|
|||||||
progressTracker.currentStep = SELF_ISSUING
|
progressTracker.currentStep = SELF_ISSUING
|
||||||
|
|
||||||
val notary: NodeInfo = serviceHub.networkMapCache.notaryNodes[0]
|
val notary: NodeInfo = serviceHub.networkMapCache.notaryNodes[0]
|
||||||
val cpOwnerKey = serviceHub.storageService.myLegalIdentityKey
|
val cpOwnerKey = serviceHub.legalIdentityKey
|
||||||
val commercialPaper = selfIssueSomeCommercialPaper(cpOwnerKey.public, notary)
|
val commercialPaper = selfIssueSomeCommercialPaper(cpOwnerKey.public, notary)
|
||||||
|
|
||||||
progressTracker.currentStep = TRADING
|
progressTracker.currentStep = TRADING
|
||||||
@ -330,7 +330,7 @@ private class TraderDemoProtocolSeller(val otherSide: Party,
|
|||||||
|
|
||||||
val issuance: SignedTransaction = run {
|
val issuance: SignedTransaction = run {
|
||||||
val tx = CommercialPaper().generateIssue(party.ref(1, 2, 3), 1100.DOLLARS `issued by` DUMMY_CASH_ISSUER,
|
val tx = CommercialPaper().generateIssue(party.ref(1, 2, 3), 1100.DOLLARS `issued by` DUMMY_CASH_ISSUER,
|
||||||
Instant.now() + 10.days, notaryNode.identity)
|
Instant.now() + 10.days, notaryNode.notaryIdentity)
|
||||||
|
|
||||||
// TODO: Consider moving these two steps below into generateIssue.
|
// TODO: Consider moving these two steps below into generateIssue.
|
||||||
|
|
||||||
@ -356,7 +356,7 @@ private class TraderDemoProtocolSeller(val otherSide: Party,
|
|||||||
|
|
||||||
// Now make a dummy transaction that moves it to a new key, just to show that resolving dependencies works.
|
// Now make a dummy transaction that moves it to a new key, just to show that resolving dependencies works.
|
||||||
val move: SignedTransaction = run {
|
val move: SignedTransaction = run {
|
||||||
val builder = TransactionType.General.Builder(notaryNode.identity)
|
val builder = TransactionType.General.Builder(notaryNode.notaryIdentity)
|
||||||
CommercialPaper().generateMove(builder, issuance.tx.outRef(0), ownedBy)
|
CommercialPaper().generateMove(builder, issuance.tx.outRef(0), ownedBy)
|
||||||
builder.signWith(keyPair)
|
builder.signWith(keyPair)
|
||||||
val notarySignature = subProtocol(NotaryProtocol.Client(builder.toSignedTransaction(false)))
|
val notarySignature = subProtocol(NotaryProtocol.Client(builder.toSignedTransaction(false)))
|
||||||
|
@ -42,7 +42,7 @@ import javax.annotation.concurrent.ThreadSafe
|
|||||||
* for signing.
|
* for signing.
|
||||||
*/
|
*/
|
||||||
object NodeInterestRates {
|
object NodeInterestRates {
|
||||||
object Type : ServiceType("corda.interest_rates")
|
val type = ServiceType.corda.getSubType("interest_rates")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register the protocol that is used with the Fixing integration tests.
|
* Register the protocol that is used with the Fixing integration tests.
|
||||||
@ -55,25 +55,31 @@ 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(services: ServiceHubInternal) : AcceptsFileUpload, SingletonSerializeAsToken() {
|
class Service(val services: ServiceHubInternal) : AcceptsFileUpload, SingletonSerializeAsToken() {
|
||||||
val ss = services.storageService
|
val oracle: Oracle by lazy {
|
||||||
val oracle = Oracle(ss.myLegalIdentity, ss.myLegalIdentityKey, services.clock)
|
val myNodeInfo = services.myInfo
|
||||||
|
val myIdentity = myNodeInfo.serviceIdentities(type).first()
|
||||||
init {
|
val mySigningKey = services.keyManagementService.toKeyPair(myIdentity.owningKey)
|
||||||
services.registerProtocolInitiator(FixSignProtocol::class) { FixSignHandler(it, oracle) }
|
Oracle(myIdentity, mySigningKey, services.clock)
|
||||||
services.registerProtocolInitiator(FixQueryProtocol::class) { FixQueryHandler(it, oracle) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
// Note access to the singleton oracle property is via the registered SingletonSerializeAsToken Service.
|
||||||
|
// Otherwise the Kryo serialisation of the call stack in the Quasar Fiber extends to include
|
||||||
|
// the framework Oracle and the protocol will crash.
|
||||||
|
services.registerProtocolInitiator(FixSignProtocol::class) { FixSignHandler(it, this) }
|
||||||
|
services.registerProtocolInitiator(FixQueryProtocol::class) { FixQueryHandler(it, this) }
|
||||||
|
}
|
||||||
|
|
||||||
private class FixSignHandler(val otherParty: Party, val oracle: Oracle) : ProtocolLogic<Unit>() {
|
private class FixSignHandler(val otherParty: Party, val service: Service) : ProtocolLogic<Unit>() {
|
||||||
@Suspendable
|
@Suspendable
|
||||||
override fun call() {
|
override fun call() {
|
||||||
val request = receive<SignRequest>(otherParty).unwrap { it }
|
val request = receive<SignRequest>(otherParty).unwrap { it }
|
||||||
send(otherParty, oracle.sign(request.tx))
|
send(otherParty, service.oracle.sign(request.tx))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class FixQueryHandler(val otherParty: Party, val oracle: Oracle) : ProtocolLogic<Unit>() {
|
private class FixQueryHandler(val otherParty: Party, val service: Service) : ProtocolLogic<Unit>() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
object RECEIVED : ProgressTracker.Step("Received fix request")
|
object RECEIVED : ProgressTracker.Step("Received fix request")
|
||||||
@ -89,7 +95,7 @@ object NodeInterestRates {
|
|||||||
@Suspendable
|
@Suspendable
|
||||||
override fun call(): Unit {
|
override fun call(): Unit {
|
||||||
val request = receive<QueryRequest>(otherParty).unwrap { it }
|
val request = receive<QueryRequest>(otherParty).unwrap { it }
|
||||||
val answers = oracle.query(request.queries, request.deadline)
|
val answers = service.oracle.query(request.queries, request.deadline)
|
||||||
progressTracker.currentStep = SENDING
|
progressTracker.currentStep = SENDING
|
||||||
send(otherParty, answers)
|
send(otherParty, answers)
|
||||||
}
|
}
|
||||||
|
@ -111,7 +111,7 @@ fun main(args: Array<String>) {
|
|||||||
// the map is not very helpful, but we need one anyway. So just make the recipient side run the network map as it's
|
// the map is not very helpful, but we need one anyway. So just make the recipient side run the network map as it's
|
||||||
// the side that sticks around waiting for the sender.
|
// the side that sticks around waiting for the sender.
|
||||||
val networkMapId = if (role == Role.SENDER) {
|
val networkMapId = if (role == Role.SENDER) {
|
||||||
advertisedServices = setOf(ServiceInfo(NetworkMapService.Type), ServiceInfo(SimpleNotaryService.Type))
|
advertisedServices = setOf(ServiceInfo(NetworkMapService.type), ServiceInfo(SimpleNotaryService.type))
|
||||||
null
|
null
|
||||||
} else {
|
} else {
|
||||||
advertisedServices = emptySet()
|
advertisedServices = emptySet()
|
||||||
@ -131,7 +131,7 @@ fun main(args: Array<String>) {
|
|||||||
node.networkMapRegistrationFuture.success {
|
node.networkMapRegistrationFuture.success {
|
||||||
// Pause a moment to give the network map time to update
|
// Pause a moment to give the network map time to update
|
||||||
Thread.sleep(100L)
|
Thread.sleep(100L)
|
||||||
val party = node.netMapCache.getNodeByLegalName(Role.RECIPIENT.legalName)?.identity ?: throw IllegalStateException("Cannot find other node?!")
|
val party = node.netMapCache.getNodeByLegalName(Role.RECIPIENT.legalName)?.legalIdentity ?: throw IllegalStateException("Cannot find other node?!")
|
||||||
runSender(node, party)
|
runSender(node, party)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,14 +62,15 @@ object AutoOfferProtocol {
|
|||||||
@Suspendable
|
@Suspendable
|
||||||
override fun call(): SignedTransaction {
|
override fun call(): SignedTransaction {
|
||||||
require(serviceHub.networkMapCache.notaryNodes.isNotEmpty()) { "No notary nodes registered" }
|
require(serviceHub.networkMapCache.notaryNodes.isNotEmpty()) { "No notary nodes registered" }
|
||||||
val notary = serviceHub.networkMapCache.notaryNodes.first().identity
|
val notary = serviceHub.networkMapCache.notaryNodes.first().notaryIdentity
|
||||||
// need to pick which ever party is not us
|
// need to pick which ever party is not us
|
||||||
val otherParty = notUs(dealToBeOffered.parties).single()
|
val otherParty = notUs(dealToBeOffered.parties).single()
|
||||||
progressTracker.currentStep = DEALING
|
progressTracker.currentStep = DEALING
|
||||||
|
val myKey = serviceHub.legalIdentityKey
|
||||||
val instigator = Instigator(
|
val instigator = Instigator(
|
||||||
otherParty,
|
otherParty,
|
||||||
AutoOffer(notary, dealToBeOffered),
|
AutoOffer(notary, dealToBeOffered),
|
||||||
serviceHub.storageService.myLegalIdentityKey,
|
myKey,
|
||||||
progressTracker.getChildProgressTracker(DEALING)!!
|
progressTracker.getChildProgressTracker(DEALING)!!
|
||||||
)
|
)
|
||||||
val stx = subProtocol(instigator)
|
val stx = subProtocol(instigator)
|
||||||
@ -79,7 +80,7 @@ object AutoOfferProtocol {
|
|||||||
private fun notUs(parties: List<Party>): List<Party> {
|
private fun notUs(parties: List<Party>): List<Party> {
|
||||||
val notUsParties: MutableList<Party> = arrayListOf()
|
val notUsParties: MutableList<Party> = arrayListOf()
|
||||||
for (party in parties) {
|
for (party in parties) {
|
||||||
if (serviceHub.storageService.myLegalIdentity != party) {
|
if (serviceHub.myInfo.legalIdentity != party) {
|
||||||
notUsParties.add(party)
|
notUsParties.add(party)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ object ExitServerProtocol {
|
|||||||
if (recipient.address is MockNetworkMapCache.MockAddress) {
|
if (recipient.address is MockNetworkMapCache.MockAddress) {
|
||||||
// Ignore
|
// Ignore
|
||||||
} else {
|
} else {
|
||||||
send(recipient.identity, ExitMessage(exitCode))
|
send(recipient.legalIdentity, ExitMessage(exitCode))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ object UpdateBusinessDayProtocol {
|
|||||||
if (recipient.address is MockNetworkMapCache.MockAddress) {
|
if (recipient.address is MockNetworkMapCache.MockAddress) {
|
||||||
// Ignore
|
// Ignore
|
||||||
} else {
|
} else {
|
||||||
send(recipient.identity, UpdateBusinessDayMessage(date))
|
send(recipient.legalIdentity, UpdateBusinessDayMessage(date))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -108,15 +108,15 @@ class IRSSimulation(networkSendManuallyPumped: Boolean, runAsync: Boolean, laten
|
|||||||
// have the convenient copy() method that'd let us make small adjustments. Instead they're partly mutable.
|
// have the convenient copy() method that'd let us make small adjustments. Instead they're partly mutable.
|
||||||
// TODO: We should revisit this in post-Excalibur cleanup and fix, e.g. by introducing an interface.
|
// TODO: We should revisit this in post-Excalibur cleanup and fix, e.g. by introducing an interface.
|
||||||
val irs = om.readValue<InterestRateSwap.State>(javaClass.getResource("trade.json"))
|
val irs = om.readValue<InterestRateSwap.State>(javaClass.getResource("trade.json"))
|
||||||
irs.fixedLeg.fixedRatePayer = node1.info.identity
|
irs.fixedLeg.fixedRatePayer = node1.info.legalIdentity
|
||||||
irs.floatingLeg.floatingRatePayer = node2.info.identity
|
irs.floatingLeg.floatingRatePayer = node2.info.legalIdentity
|
||||||
|
|
||||||
val acceptorTx = node2.initiateSingleShotProtocol(Instigator::class) { Acceptor(it) }.flatMap { it.resultFuture }
|
val acceptorTx = node2.initiateSingleShotProtocol(Instigator::class) { Acceptor(it) }.flatMap { it.resultFuture }
|
||||||
|
|
||||||
showProgressFor(listOf(node1, node2))
|
showProgressFor(listOf(node1, node2))
|
||||||
showConsensusFor(listOf(node1, node2, regulators[0]))
|
showConsensusFor(listOf(node1, node2, regulators[0]))
|
||||||
|
|
||||||
val instigator = Instigator(node2.info.identity, AutoOffer(notary.info.identity, irs), node1.keyPair!!)
|
val instigator = Instigator(node2.info.legalIdentity, AutoOffer(notary.info.notaryIdentity, irs), node1.keyPair!!)
|
||||||
val instigatorTx = node1.services.startProtocol("instigator", instigator)
|
val instigatorTx = node1.services.startProtocol("instigator", instigator)
|
||||||
|
|
||||||
return Futures.allAsList(instigatorTx, acceptorTx).flatMap { instigatorTx }
|
return Futures.allAsList(instigatorTx, acceptorTx).flatMap { instigatorTx }
|
||||||
|
@ -87,7 +87,7 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
|
|||||||
object NetworkMapNodeFactory : MockNetwork.Factory {
|
object NetworkMapNodeFactory : MockNetwork.Factory {
|
||||||
override fun create(config: NodeConfiguration, network: MockNetwork,
|
override fun create(config: NodeConfiguration, network: MockNetwork,
|
||||||
networkMapAddr: SingleMessageRecipient?, advertisedServices: Set<ServiceInfo>, id: Int, keyPair: KeyPair?): MockNetwork.MockNode {
|
networkMapAddr: SingleMessageRecipient?, advertisedServices: Set<ServiceInfo>, id: Int, keyPair: KeyPair?): MockNetwork.MockNode {
|
||||||
require(advertisedServices.containsType(NetworkMapService.Type))
|
require(advertisedServices.containsType(NetworkMapService.type))
|
||||||
|
|
||||||
// TODO: create a base class that provides a default implementation
|
// TODO: create a base class that provides a default implementation
|
||||||
val cfg = object : NodeConfiguration {
|
val cfg = object : NodeConfiguration {
|
||||||
@ -109,7 +109,7 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
|
|||||||
object NotaryNodeFactory : MockNetwork.Factory {
|
object NotaryNodeFactory : MockNetwork.Factory {
|
||||||
override fun create(config: NodeConfiguration, network: MockNetwork, networkMapAddr: SingleMessageRecipient?,
|
override fun create(config: NodeConfiguration, network: MockNetwork, networkMapAddr: SingleMessageRecipient?,
|
||||||
advertisedServices: Set<ServiceInfo>, id: Int, keyPair: KeyPair?): MockNetwork.MockNode {
|
advertisedServices: Set<ServiceInfo>, id: Int, keyPair: KeyPair?): MockNetwork.MockNode {
|
||||||
require(advertisedServices.containsType(SimpleNotaryService.Type))
|
require(advertisedServices.containsType(SimpleNotaryService.type))
|
||||||
|
|
||||||
// TODO: create a base class that provides a default implementation
|
// TODO: create a base class that provides a default implementation
|
||||||
val cfg = object : NodeConfiguration {
|
val cfg = object : NodeConfiguration {
|
||||||
@ -130,7 +130,7 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
|
|||||||
object RatesOracleFactory : MockNetwork.Factory {
|
object RatesOracleFactory : MockNetwork.Factory {
|
||||||
override fun create(config: NodeConfiguration, network: MockNetwork, networkMapAddr: SingleMessageRecipient?,
|
override fun create(config: NodeConfiguration, network: MockNetwork, networkMapAddr: SingleMessageRecipient?,
|
||||||
advertisedServices: Set<ServiceInfo>, id: Int, keyPair: KeyPair?): MockNetwork.MockNode {
|
advertisedServices: Set<ServiceInfo>, id: Int, keyPair: KeyPair?): MockNetwork.MockNode {
|
||||||
require(advertisedServices.containsType(NodeInterestRates.Type))
|
require(advertisedServices.containsType(NodeInterestRates.type))
|
||||||
|
|
||||||
// TODO: create a base class that provides a default implementation
|
// TODO: create a base class that provides a default implementation
|
||||||
val cfg = object : NodeConfiguration {
|
val cfg = object : NodeConfiguration {
|
||||||
@ -188,12 +188,12 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
|
|||||||
val network = MockNetwork(networkSendManuallyPumped, runAsync)
|
val network = MockNetwork(networkSendManuallyPumped, runAsync)
|
||||||
// This one must come first.
|
// This one must come first.
|
||||||
val networkMap: SimulatedNode
|
val networkMap: SimulatedNode
|
||||||
= network.createNode(null, nodeFactory = NetworkMapNodeFactory, advertisedServices = ServiceInfo(NetworkMapService.Type)) as SimulatedNode
|
= network.createNode(null, nodeFactory = NetworkMapNodeFactory, advertisedServices = ServiceInfo(NetworkMapService.type)) as SimulatedNode
|
||||||
val notary: SimulatedNode
|
val notary: SimulatedNode
|
||||||
= network.createNode(networkMap.info.address, nodeFactory = NotaryNodeFactory, advertisedServices = ServiceInfo(SimpleNotaryService.Type)) as SimulatedNode
|
= network.createNode(networkMap.info.address, nodeFactory = NotaryNodeFactory, advertisedServices = ServiceInfo(SimpleNotaryService.type)) as SimulatedNode
|
||||||
val regulators: List<SimulatedNode> = listOf(network.createNode(networkMap.info.address, start = false, nodeFactory = RegulatorFactory) as SimulatedNode)
|
val regulators: List<SimulatedNode> = listOf(network.createNode(networkMap.info.address, start = false, nodeFactory = RegulatorFactory) as SimulatedNode)
|
||||||
val ratesOracle: SimulatedNode
|
val ratesOracle: SimulatedNode
|
||||||
= network.createNode(networkMap.info.address, start = false, nodeFactory = RatesOracleFactory, advertisedServices = ServiceInfo(NodeInterestRates.Type)) as SimulatedNode
|
= network.createNode(networkMap.info.address, start = false, nodeFactory = RatesOracleFactory, advertisedServices = ServiceInfo(NodeInterestRates.type)) as SimulatedNode
|
||||||
|
|
||||||
// All nodes must be in one of these two lists for the purposes of the visualiser tool.
|
// All nodes must be in one of these two lists for the purposes of the visualiser tool.
|
||||||
val serviceProviders: List<SimulatedNode> = listOf(notary, ratesOracle, networkMap)
|
val serviceProviders: List<SimulatedNode> = listOf(notary, ratesOracle, networkMap)
|
||||||
|
@ -33,14 +33,16 @@ class TradeSimulation(runAsync: Boolean, latencyInjector: InMemoryMessagingNetwo
|
|||||||
val buyer = banks[buyerBankIndex]
|
val buyer = banks[buyerBankIndex]
|
||||||
val seller = banks[sellerBankIndex]
|
val seller = banks[sellerBankIndex]
|
||||||
|
|
||||||
buyer.services.fillWithSomeTestCash(1500.DOLLARS, notary.info.identity)
|
buyer.services.fillWithSomeTestCash(1500.DOLLARS, notary.info.notaryIdentity)
|
||||||
|
|
||||||
val issuance = run {
|
val issuance = run {
|
||||||
val tx = CommercialPaper().generateIssue(seller.info.identity.ref(1, 2, 3), 1100.DOLLARS `issued by` DUMMY_CASH_ISSUER,
|
val tx = CommercialPaper().generateIssue(seller.info.legalIdentity.ref(1, 2, 3), 1100.DOLLARS `issued by` DUMMY_CASH_ISSUER,
|
||||||
Instant.now() + 10.days, notary.info.identity)
|
Instant.now() + 10.days, notary.info.notaryIdentity)
|
||||||
tx.setTime(Instant.now(), 30.seconds)
|
tx.setTime(Instant.now(), 30.seconds)
|
||||||
tx.signWith(notary.storage.myLegalIdentityKey)
|
val notaryKey = notary.services.notaryIdentityKey
|
||||||
tx.signWith(seller.storage.myLegalIdentityKey)
|
val sellerKey = seller.services.legalIdentityKey
|
||||||
|
tx.signWith(notaryKey)
|
||||||
|
tx.signWith(sellerKey)
|
||||||
tx.toSignedTransaction(true)
|
tx.toSignedTransaction(true)
|
||||||
}
|
}
|
||||||
seller.services.recordTransactions(issuance)
|
seller.services.recordTransactions(issuance)
|
||||||
@ -48,15 +50,16 @@ class TradeSimulation(runAsync: Boolean, latencyInjector: InMemoryMessagingNetwo
|
|||||||
val amount = 1000.DOLLARS
|
val amount = 1000.DOLLARS
|
||||||
|
|
||||||
val buyerFuture = buyer.initiateSingleShotProtocol(Seller::class) {
|
val buyerFuture = buyer.initiateSingleShotProtocol(Seller::class) {
|
||||||
Buyer(it, notary.info.identity, amount, CommercialPaper.State::class.java)
|
Buyer(it, notary.info.notaryIdentity, amount, CommercialPaper.State::class.java)
|
||||||
}.flatMap { it.resultFuture }
|
}.flatMap { it.resultFuture }
|
||||||
|
|
||||||
|
val sellerKey = seller.services.legalIdentityKey
|
||||||
val sellerProtocol = Seller(
|
val sellerProtocol = Seller(
|
||||||
buyer.info.identity,
|
buyer.info.legalIdentity,
|
||||||
notary.info,
|
notary.info,
|
||||||
issuance.tx.outRef<OwnableState>(0),
|
issuance.tx.outRef<OwnableState>(0),
|
||||||
amount,
|
amount,
|
||||||
seller.storage.myLegalIdentityKey)
|
sellerKey)
|
||||||
|
|
||||||
showConsensusFor(listOf(buyer, seller, notary))
|
showConsensusFor(listOf(buyer, seller, notary))
|
||||||
showProgressFor(listOf(buyer, seller))
|
showProgressFor(listOf(buyer, seller))
|
||||||
|
@ -11,6 +11,7 @@ import com.r3corda.core.contracts.TransactionType
|
|||||||
import com.r3corda.core.contracts.`with notary`
|
import com.r3corda.core.contracts.`with notary`
|
||||||
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.node.services.ServiceInfo
|
||||||
import com.r3corda.core.utilities.DUMMY_NOTARY
|
import com.r3corda.core.utilities.DUMMY_NOTARY
|
||||||
import com.r3corda.core.utilities.LogHelper
|
import com.r3corda.core.utilities.LogHelper
|
||||||
import com.r3corda.testing.node.MockNetwork
|
import com.r3corda.testing.node.MockNetwork
|
||||||
@ -141,13 +142,14 @@ class NodeInterestRatesTest {
|
|||||||
@Test
|
@Test
|
||||||
fun network() {
|
fun network() {
|
||||||
val net = MockNetwork()
|
val net = MockNetwork()
|
||||||
val (n1, n2) = net.createTwoNodes()
|
val n1 = net.createNotaryNode()
|
||||||
|
val n2 = net.createNode(n1.info.address, advertisedServices = ServiceInfo(NodeInterestRates.type))
|
||||||
databaseTransaction(n2.database) {
|
databaseTransaction(n2.database) {
|
||||||
n2.findService<NodeInterestRates.Service>().oracle.knownFixes = TEST_DATA
|
n2.findService<NodeInterestRates.Service>().oracle.knownFixes = TEST_DATA
|
||||||
}
|
}
|
||||||
val tx = TransactionType.General.Builder(null)
|
val tx = TransactionType.General.Builder(null)
|
||||||
val fixOf = NodeInterestRates.parseFixOf("LIBOR 2016-03-16 1M")
|
val fixOf = NodeInterestRates.parseFixOf("LIBOR 2016-03-16 1M")
|
||||||
val protocol = RatesFixProtocol(tx, n2.info.identity, fixOf, "0.675".bd, "0.1".bd)
|
val protocol = RatesFixProtocol(tx, n2.info.serviceIdentities(NodeInterestRates.type).first(), fixOf, "0.675".bd, "0.1".bd)
|
||||||
LogHelper.setLevel("rates")
|
LogHelper.setLevel("rates")
|
||||||
net.runNetwork()
|
net.runNetwork()
|
||||||
val future = n1.services.startProtocol("rates", protocol)
|
val future = n1.services.startProtocol("rates", protocol)
|
||||||
|
@ -20,8 +20,8 @@ class MockNetworkMapCache() : com.r3corda.node.services.network.InMemoryNetworkM
|
|||||||
init {
|
init {
|
||||||
val mockNodeA = NodeInfo(MockAddress("bankC:8080"), Party("Bank C", DummyPublicKey("Bank C")))
|
val mockNodeA = NodeInfo(MockAddress("bankC:8080"), Party("Bank C", DummyPublicKey("Bank C")))
|
||||||
val mockNodeB = NodeInfo(MockAddress("bankD:8080"), Party("Bank D", DummyPublicKey("Bank D")))
|
val mockNodeB = NodeInfo(MockAddress("bankD:8080"), Party("Bank D", DummyPublicKey("Bank D")))
|
||||||
registeredNodes[mockNodeA.identity] = mockNodeA
|
registeredNodes[mockNodeA.legalIdentity] = mockNodeA
|
||||||
registeredNodes[mockNodeB.identity] = mockNodeB
|
registeredNodes[mockNodeB.legalIdentity] = mockNodeB
|
||||||
runWithoutMapService()
|
runWithoutMapService()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ class MockNetworkMapCache() : com.r3corda.node.services.network.InMemoryNetworkM
|
|||||||
*/
|
*/
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
fun addRegistration(node: NodeInfo) {
|
fun addRegistration(node: NodeInfo) {
|
||||||
registeredNodes[node.identity] = node
|
registeredNodes[node.legalIdentity] = node
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -39,7 +39,7 @@ class MockNetworkMapCache() : com.r3corda.node.services.network.InMemoryNetworkM
|
|||||||
* not a change being received.
|
* not a change being received.
|
||||||
*/
|
*/
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
fun deleteRegistration(identity: Party) : Boolean {
|
fun deleteRegistration(legalIdentity: Party) : Boolean {
|
||||||
return registeredNodes.remove(identity) != null
|
return registeredNodes.remove(legalIdentity) != null
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -107,7 +107,7 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false,
|
|||||||
|
|
||||||
override fun makeVaultService(): VaultService = InMemoryVaultService(services)
|
override fun makeVaultService(): VaultService = InMemoryVaultService(services)
|
||||||
|
|
||||||
override fun makeKeyManagementService(): KeyManagementService = E2ETestKeyManagementService(setOf(storage.myLegalIdentityKey))
|
override fun makeKeyManagementService(): KeyManagementService = E2ETestKeyManagementService(partyKeys)
|
||||||
|
|
||||||
override fun startMessagingService(cordaRPCOps: CordaRPCOps?) {
|
override fun startMessagingService(cordaRPCOps: CordaRPCOps?) {
|
||||||
// Nothing to do
|
// Nothing to do
|
||||||
@ -129,7 +129,7 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false,
|
|||||||
|
|
||||||
override fun start(): MockNode {
|
override fun start(): MockNode {
|
||||||
super.start()
|
super.start()
|
||||||
mockNet.identities.add(storage.myLegalIdentity)
|
mockNet.identities.add(info.legalIdentity)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,7 +212,7 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false,
|
|||||||
fun createTwoNodes(nodeFactory: Factory = defaultFactory, notaryKeyPair: KeyPair? = null): Pair<MockNode, MockNode> {
|
fun createTwoNodes(nodeFactory: Factory = defaultFactory, notaryKeyPair: KeyPair? = null): Pair<MockNode, MockNode> {
|
||||||
require(nodes.isEmpty())
|
require(nodes.isEmpty())
|
||||||
return Pair(
|
return Pair(
|
||||||
createNode(null, -1, nodeFactory, true, null, notaryKeyPair, ServiceInfo(NetworkMapService.Type), ServiceInfo(SimpleNotaryService.Type)),
|
createNode(null, -1, nodeFactory, true, null, notaryKeyPair, ServiceInfo(NetworkMapService.type), ServiceInfo(SimpleNotaryService.type)),
|
||||||
createNode(nodes[0].info.address, -1, nodeFactory, true, null)
|
createNode(nodes[0].info.address, -1, nodeFactory, true, null)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -229,9 +229,9 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false,
|
|||||||
*/
|
*/
|
||||||
fun createSomeNodes(numPartyNodes: Int = 2, nodeFactory: Factory = defaultFactory, notaryKeyPair: KeyPair? = DUMMY_NOTARY_KEY): BasketOfNodes {
|
fun createSomeNodes(numPartyNodes: Int = 2, nodeFactory: Factory = defaultFactory, notaryKeyPair: KeyPair? = DUMMY_NOTARY_KEY): BasketOfNodes {
|
||||||
require(nodes.isEmpty())
|
require(nodes.isEmpty())
|
||||||
val mapNode = createNode(null, nodeFactory = nodeFactory, advertisedServices = ServiceInfo(NetworkMapService.Type))
|
val mapNode = createNode(null, nodeFactory = nodeFactory, advertisedServices = ServiceInfo(NetworkMapService.type))
|
||||||
val notaryNode = createNode(mapNode.info.address, nodeFactory = nodeFactory, keyPair = notaryKeyPair,
|
val notaryNode = createNode(mapNode.info.address, nodeFactory = nodeFactory, keyPair = notaryKeyPair,
|
||||||
advertisedServices = ServiceInfo(SimpleNotaryService.Type))
|
advertisedServices = ServiceInfo(SimpleNotaryService.type))
|
||||||
val nodes = ArrayList<MockNode>()
|
val nodes = ArrayList<MockNode>()
|
||||||
repeat(numPartyNodes) {
|
repeat(numPartyNodes) {
|
||||||
nodes += createPartyNode(mapNode.info.address)
|
nodes += createPartyNode(mapNode.info.address)
|
||||||
@ -240,7 +240,7 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false,
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun createNotaryNode(legalName: String? = null, keyPair: KeyPair? = null): MockNode {
|
fun createNotaryNode(legalName: String? = null, keyPair: KeyPair? = null): MockNode {
|
||||||
return createNode(null, -1, defaultFactory, true, legalName, keyPair, ServiceInfo(NetworkMapService.Type), ServiceInfo(SimpleNotaryService.Type))
|
return createNode(null, -1, defaultFactory, true, legalName, keyPair, ServiceInfo(NetworkMapService.type), ServiceInfo(SimpleNotaryService.type))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createPartyNode(networkMapAddr: SingleMessageRecipient, legalName: String? = null, keyPair: KeyPair? = null): MockNode {
|
fun createPartyNode(networkMapAddr: SingleMessageRecipient, legalName: String? = null, keyPair: KeyPair? = null): MockNode {
|
||||||
|
@ -7,6 +7,8 @@ import com.r3corda.core.crypto.SecureHash
|
|||||||
import com.r3corda.core.crypto.generateKeyPair
|
import com.r3corda.core.crypto.generateKeyPair
|
||||||
import com.r3corda.core.crypto.sha256
|
import com.r3corda.core.crypto.sha256
|
||||||
import com.r3corda.core.messaging.MessagingService
|
import com.r3corda.core.messaging.MessagingService
|
||||||
|
import com.r3corda.core.messaging.SingleMessageRecipient
|
||||||
|
import com.r3corda.core.node.NodeInfo
|
||||||
import com.r3corda.core.node.ServiceHub
|
import com.r3corda.core.node.ServiceHub
|
||||||
import com.r3corda.core.node.services.*
|
import com.r3corda.core.node.services.*
|
||||||
import com.r3corda.core.protocols.ProtocolLogic
|
import com.r3corda.core.protocols.ProtocolLogic
|
||||||
@ -52,7 +54,7 @@ open class MockServices(val key: KeyPair = generateKeyPair()) : ServiceHub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override val storageService: TxWritableStorageService = MockStorageService(myLegalIdentityKey = key)
|
override val storageService: TxWritableStorageService = MockStorageService()
|
||||||
override val identityService: MockIdentityService = MockIdentityService(listOf(MEGA_CORP, MINI_CORP, DUMMY_NOTARY))
|
override val identityService: MockIdentityService = MockIdentityService(listOf(MEGA_CORP, MINI_CORP, DUMMY_NOTARY))
|
||||||
override val keyManagementService: MockKeyManagementService = MockKeyManagementService(key)
|
override val keyManagementService: MockKeyManagementService = MockKeyManagementService(key)
|
||||||
|
|
||||||
@ -61,6 +63,7 @@ open class MockServices(val key: KeyPair = generateKeyPair()) : ServiceHub {
|
|||||||
override val networkMapCache: NetworkMapCache get() = throw UnsupportedOperationException()
|
override val networkMapCache: NetworkMapCache get() = throw UnsupportedOperationException()
|
||||||
override val clock: Clock get() = throw UnsupportedOperationException()
|
override val clock: Clock get() = throw UnsupportedOperationException()
|
||||||
override val schedulerService: SchedulerService get() = throw UnsupportedOperationException()
|
override val schedulerService: SchedulerService get() = throw UnsupportedOperationException()
|
||||||
|
override val myInfo: NodeInfo get() = NodeInfo(object : SingleMessageRecipient {} , Party("MegaCorp", key.public))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ThreadSafe
|
@ThreadSafe
|
||||||
@ -150,8 +153,6 @@ open class MockTransactionStorage : TransactionStorage {
|
|||||||
@ThreadSafe
|
@ThreadSafe
|
||||||
class MockStorageService(override val attachments: AttachmentStorage = MockAttachmentStorage(),
|
class MockStorageService(override val attachments: AttachmentStorage = MockAttachmentStorage(),
|
||||||
override val validatedTransactions: TransactionStorage = MockTransactionStorage(),
|
override val validatedTransactions: TransactionStorage = MockTransactionStorage(),
|
||||||
override val myLegalIdentityKey: KeyPair = generateKeyPair(),
|
|
||||||
override val myLegalIdentity: Party = Party("Unit test party", myLegalIdentityKey.public),
|
|
||||||
override val stateMachineRecordedTransactionMapping: StateMachineRecordedTransactionMappingStorage = MockStateMachineRecordedTransactionMappingStorage())
|
override val stateMachineRecordedTransactionMapping: StateMachineRecordedTransactionMappingStorage = MockStateMachineRecordedTransactionMappingStorage())
|
||||||
: SingletonSerializeAsToken(), TxWritableStorageService
|
: SingletonSerializeAsToken(), TxWritableStorageService
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user