mirror of
https://github.com/corda/corda.git
synced 2025-06-15 13:48:14 +00:00
Replace X500Name with CordaX500Name (#1447)
Replace X500Name with CordaX500Name, which enforces the specific constraints Corda expects on legal/service identity names.
This commit is contained in:
@ -15,6 +15,7 @@ import net.corda.core.crypto.*
|
|||||||
import net.corda.core.crypto.CompositeKey
|
import net.corda.core.crypto.CompositeKey
|
||||||
import net.corda.core.identity.AbstractParty
|
import net.corda.core.identity.AbstractParty
|
||||||
import net.corda.core.identity.AnonymousParty
|
import net.corda.core.identity.AnonymousParty
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.messaging.CordaRPCOps
|
import net.corda.core.messaging.CordaRPCOps
|
||||||
import net.corda.core.node.NodeInfo
|
import net.corda.core.node.NodeInfo
|
||||||
@ -30,7 +31,6 @@ import net.corda.core.utilities.OpaqueBytes
|
|||||||
import net.corda.core.utilities.parsePublicKeyBase58
|
import net.corda.core.utilities.parsePublicKeyBase58
|
||||||
import net.corda.core.utilities.toBase58String
|
import net.corda.core.utilities.toBase58String
|
||||||
import net.i2p.crypto.eddsa.EdDSAPublicKey
|
import net.i2p.crypto.eddsa.EdDSAPublicKey
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@ -46,25 +46,25 @@ object JacksonSupport {
|
|||||||
// If you change this API please update the docs in the docsite (json.rst)
|
// If you change this API please update the docs in the docsite (json.rst)
|
||||||
|
|
||||||
interface PartyObjectMapper {
|
interface PartyObjectMapper {
|
||||||
fun partyFromX500Name(name: X500Name): Party?
|
fun partyFromX500Name(name: CordaX500Name): Party?
|
||||||
fun partyFromKey(owningKey: PublicKey): Party?
|
fun partyFromKey(owningKey: PublicKey): Party?
|
||||||
fun partiesFromName(query: String): Set<Party>
|
fun partiesFromName(query: String): Set<Party>
|
||||||
}
|
}
|
||||||
|
|
||||||
class RpcObjectMapper(val rpc: CordaRPCOps, factory: JsonFactory, val fuzzyIdentityMatch: Boolean) : PartyObjectMapper, ObjectMapper(factory) {
|
class RpcObjectMapper(val rpc: CordaRPCOps, factory: JsonFactory, val fuzzyIdentityMatch: Boolean) : PartyObjectMapper, ObjectMapper(factory) {
|
||||||
override fun partyFromX500Name(name: X500Name): Party? = rpc.partyFromX500Name(name)
|
override fun partyFromX500Name(name: CordaX500Name): Party? = rpc.partyFromX500Name(name)
|
||||||
override fun partyFromKey(owningKey: PublicKey): Party? = rpc.partyFromKey(owningKey)
|
override fun partyFromKey(owningKey: PublicKey): Party? = rpc.partyFromKey(owningKey)
|
||||||
override fun partiesFromName(query: String) = rpc.partiesFromName(query, fuzzyIdentityMatch)
|
override fun partiesFromName(query: String) = rpc.partiesFromName(query, fuzzyIdentityMatch)
|
||||||
}
|
}
|
||||||
|
|
||||||
class IdentityObjectMapper(val identityService: IdentityService, factory: JsonFactory, val fuzzyIdentityMatch: Boolean) : PartyObjectMapper, ObjectMapper(factory) {
|
class IdentityObjectMapper(val identityService: IdentityService, factory: JsonFactory, val fuzzyIdentityMatch: Boolean) : PartyObjectMapper, ObjectMapper(factory) {
|
||||||
override fun partyFromX500Name(name: X500Name): Party? = identityService.partyFromX500Name(name)
|
override fun partyFromX500Name(name: CordaX500Name): Party? = identityService.partyFromX500Name(name)
|
||||||
override fun partyFromKey(owningKey: PublicKey): Party? = identityService.partyFromKey(owningKey)
|
override fun partyFromKey(owningKey: PublicKey): Party? = identityService.partyFromKey(owningKey)
|
||||||
override fun partiesFromName(query: String) = identityService.partiesFromName(query, fuzzyIdentityMatch)
|
override fun partiesFromName(query: String) = identityService.partiesFromName(query, fuzzyIdentityMatch)
|
||||||
}
|
}
|
||||||
|
|
||||||
class NoPartyObjectMapper(factory: JsonFactory) : PartyObjectMapper, ObjectMapper(factory) {
|
class NoPartyObjectMapper(factory: JsonFactory) : PartyObjectMapper, ObjectMapper(factory) {
|
||||||
override fun partyFromX500Name(name: X500Name): Party? = throw UnsupportedOperationException()
|
override fun partyFromX500Name(name: CordaX500Name): Party? = throw UnsupportedOperationException()
|
||||||
override fun partyFromKey(owningKey: PublicKey): Party? = throw UnsupportedOperationException()
|
override fun partyFromKey(owningKey: PublicKey): Party? = throw UnsupportedOperationException()
|
||||||
override fun partiesFromName(query: String) = throw UnsupportedOperationException()
|
override fun partiesFromName(query: String) = throw UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
@ -105,8 +105,8 @@ object JacksonSupport {
|
|||||||
addSerializer(OpaqueBytes::class.java, OpaqueBytesSerializer)
|
addSerializer(OpaqueBytes::class.java, OpaqueBytesSerializer)
|
||||||
|
|
||||||
// For X.500 distinguished names
|
// For X.500 distinguished names
|
||||||
addDeserializer(X500Name::class.java, X500NameDeserializer)
|
addDeserializer(CordaX500Name::class.java, CordaX500NameDeserializer)
|
||||||
addSerializer(X500Name::class.java, X500NameSerializer)
|
addSerializer(CordaX500Name::class.java, CordaX500NameSerializer)
|
||||||
|
|
||||||
// Mixins for transaction types to prevent some properties from being serialized
|
// Mixins for transaction types to prevent some properties from being serialized
|
||||||
setMixInAnnotation(SignedTransaction::class.java, SignedTransactionMixin::class.java)
|
setMixInAnnotation(SignedTransaction::class.java, SignedTransactionMixin::class.java)
|
||||||
@ -191,7 +191,7 @@ object JacksonSupport {
|
|||||||
// Base58 keys never include an equals character, while X.500 names always will, so we use that to determine
|
// Base58 keys never include an equals character, while X.500 names always will, so we use that to determine
|
||||||
// how to parse the content
|
// how to parse the content
|
||||||
return if (parser.text.contains("=")) {
|
return if (parser.text.contains("=")) {
|
||||||
val principal = X500Name(parser.text)
|
val principal = CordaX500Name.parse(parser.text)
|
||||||
mapper.partyFromX500Name(principal) ?: throw JsonParseException(parser, "Could not find a Party with name $principal")
|
mapper.partyFromX500Name(principal) ?: throw JsonParseException(parser, "Could not find a Party with name $principal")
|
||||||
} else {
|
} else {
|
||||||
val nameMatches = mapper.partiesFromName(parser.text)
|
val nameMatches = mapper.partiesFromName(parser.text)
|
||||||
@ -211,22 +211,22 @@ object JacksonSupport {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object X500NameSerializer : JsonSerializer<X500Name>() {
|
object CordaX500NameSerializer : JsonSerializer<CordaX500Name>() {
|
||||||
override fun serialize(obj: X500Name, generator: JsonGenerator, provider: SerializerProvider) {
|
override fun serialize(obj: CordaX500Name, generator: JsonGenerator, provider: SerializerProvider) {
|
||||||
generator.writeString(obj.toString())
|
generator.writeString(obj.toString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object X500NameDeserializer : JsonDeserializer<X500Name>() {
|
object CordaX500NameDeserializer : JsonDeserializer<CordaX500Name>() {
|
||||||
override fun deserialize(parser: JsonParser, context: DeserializationContext): X500Name {
|
override fun deserialize(parser: JsonParser, context: DeserializationContext): CordaX500Name {
|
||||||
if (parser.currentToken == JsonToken.FIELD_NAME) {
|
if (parser.currentToken == JsonToken.FIELD_NAME) {
|
||||||
parser.nextToken()
|
parser.nextToken()
|
||||||
}
|
}
|
||||||
|
|
||||||
return try {
|
return try {
|
||||||
X500Name(parser.text)
|
CordaX500Name.parse(parser.text)
|
||||||
} catch(ex: IllegalArgumentException) {
|
} catch(ex: IllegalArgumentException) {
|
||||||
throw JsonParseException(parser, "Invalid X.500 name ${parser.text}: ${ex.message}", ex)
|
throw JsonParseException(parser, "Invalid Corda X.500 name ${parser.text}: ${ex.message}", ex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import net.corda.core.crypto.isFulfilledBy
|
|||||||
import net.corda.core.crypto.keys
|
import net.corda.core.crypto.keys
|
||||||
import net.corda.core.flows.FlowInitiator
|
import net.corda.core.flows.FlowInitiator
|
||||||
import net.corda.core.flows.StateMachineRunId
|
import net.corda.core.flows.StateMachineRunId
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.internal.bufferUntilSubscribed
|
import net.corda.core.internal.bufferUntilSubscribed
|
||||||
import net.corda.core.messaging.CordaRPCOps
|
import net.corda.core.messaging.CordaRPCOps
|
||||||
import net.corda.core.messaging.StateMachineTransactionMapping
|
import net.corda.core.messaging.StateMachineTransactionMapping
|
||||||
@ -25,14 +26,13 @@ import net.corda.finance.USD
|
|||||||
import net.corda.finance.flows.CashExitFlow
|
import net.corda.finance.flows.CashExitFlow
|
||||||
import net.corda.finance.flows.CashIssueFlow
|
import net.corda.finance.flows.CashIssueFlow
|
||||||
import net.corda.finance.flows.CashPaymentFlow
|
import net.corda.finance.flows.CashPaymentFlow
|
||||||
import net.corda.node.services.network.NetworkMapService
|
|
||||||
import net.corda.node.services.FlowPermissions.Companion.startFlowPermission
|
import net.corda.node.services.FlowPermissions.Companion.startFlowPermission
|
||||||
|
import net.corda.node.services.network.NetworkMapService
|
||||||
import net.corda.node.services.transactions.SimpleNotaryService
|
import net.corda.node.services.transactions.SimpleNotaryService
|
||||||
import net.corda.nodeapi.User
|
import net.corda.nodeapi.User
|
||||||
import net.corda.testing.*
|
import net.corda.testing.*
|
||||||
import net.corda.testing.driver.driver
|
import net.corda.testing.driver.driver
|
||||||
import net.corda.testing.node.DriverBasedTest
|
import net.corda.testing.node.DriverBasedTest
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ class NodeMonitorModelTest : DriverBasedTest() {
|
|||||||
lateinit var transactions: Observable<SignedTransaction>
|
lateinit var transactions: Observable<SignedTransaction>
|
||||||
lateinit var vaultUpdates: Observable<Vault.Update<ContractState>>
|
lateinit var vaultUpdates: Observable<Vault.Update<ContractState>>
|
||||||
lateinit var networkMapUpdates: Observable<NetworkMapCache.MapChange>
|
lateinit var networkMapUpdates: Observable<NetworkMapCache.MapChange>
|
||||||
lateinit var newNode: (X500Name) -> NodeInfo
|
lateinit var newNode: (CordaX500Name) -> NodeInfo
|
||||||
|
|
||||||
override fun setup() = driver {
|
override fun setup() = driver {
|
||||||
val cashUser = User("user1", "test", permissions = setOf(
|
val cashUser = User("user1", "test", permissions = setOf(
|
||||||
|
@ -2,6 +2,7 @@ package net.corda.java.rpc;
|
|||||||
|
|
||||||
import net.corda.client.rpc.CordaRPCConnection;
|
import net.corda.client.rpc.CordaRPCConnection;
|
||||||
import net.corda.core.contracts.Amount;
|
import net.corda.core.contracts.Amount;
|
||||||
|
import net.corda.core.identity.CordaX500Name;
|
||||||
import net.corda.core.messaging.CordaRPCOps;
|
import net.corda.core.messaging.CordaRPCOps;
|
||||||
import net.corda.core.messaging.FlowHandle;
|
import net.corda.core.messaging.FlowHandle;
|
||||||
import net.corda.core.node.NodeInfo;
|
import net.corda.core.node.NodeInfo;
|
||||||
@ -43,7 +44,7 @@ public class StandaloneCordaRPCJavaClientTest {
|
|||||||
private NodeInfo notaryNode;
|
private NodeInfo notaryNode;
|
||||||
|
|
||||||
private NodeConfig notaryConfig = new NodeConfig(
|
private NodeConfig notaryConfig = new NodeConfig(
|
||||||
X500NameUtils.getX500Name("Notary Service", "Zurich", "CH"),
|
new CordaX500Name("Notary Service", "Zurich", "CH"),
|
||||||
port.getAndIncrement(),
|
port.getAndIncrement(),
|
||||||
port.getAndIncrement(),
|
port.getAndIncrement(),
|
||||||
port.getAndIncrement(),
|
port.getAndIncrement(),
|
||||||
|
@ -4,12 +4,16 @@ import com.google.common.hash.Hashing
|
|||||||
import com.google.common.hash.HashingInputStream
|
import com.google.common.hash.HashingInputStream
|
||||||
import net.corda.client.rpc.CordaRPCConnection
|
import net.corda.client.rpc.CordaRPCConnection
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.internal.*
|
import net.corda.core.internal.*
|
||||||
import net.corda.core.messaging.*
|
import net.corda.core.messaging.*
|
||||||
import net.corda.core.node.NodeInfo
|
import net.corda.core.node.NodeInfo
|
||||||
import net.corda.core.node.services.Vault
|
import net.corda.core.node.services.Vault
|
||||||
import net.corda.core.node.services.vault.*
|
import net.corda.core.node.services.vault.*
|
||||||
import net.corda.core.utilities.*
|
import net.corda.core.utilities.OpaqueBytes
|
||||||
|
import net.corda.core.utilities.getOrThrow
|
||||||
|
import net.corda.core.utilities.loggerFor
|
||||||
|
import net.corda.core.utilities.seconds
|
||||||
import net.corda.finance.DOLLARS
|
import net.corda.finance.DOLLARS
|
||||||
import net.corda.finance.POUNDS
|
import net.corda.finance.POUNDS
|
||||||
import net.corda.finance.SWISS_FRANCS
|
import net.corda.finance.SWISS_FRANCS
|
||||||
@ -54,7 +58,7 @@ class StandaloneCordaRPClientTest {
|
|||||||
private lateinit var notaryNode: NodeInfo
|
private lateinit var notaryNode: NodeInfo
|
||||||
|
|
||||||
private val notaryConfig = NodeConfig(
|
private val notaryConfig = NodeConfig(
|
||||||
legalName = getX500Name(O = "Notary Service", OU = "corda", L = "Zurich", C = "CH"),
|
legalName = CordaX500Name(organisation = "Notary Service", locality = "Zurich", country = "CH"),
|
||||||
p2pPort = port.andIncrement,
|
p2pPort = port.andIncrement,
|
||||||
rpcPort = port.andIncrement,
|
rpcPort = port.andIncrement,
|
||||||
webPort = port.andIncrement,
|
webPort = port.andIncrement,
|
||||||
|
@ -3,7 +3,6 @@ package net.corda.core.identity
|
|||||||
import net.corda.core.contracts.PartyAndReference
|
import net.corda.core.contracts.PartyAndReference
|
||||||
import net.corda.core.serialization.CordaSerializable
|
import net.corda.core.serialization.CordaSerializable
|
||||||
import net.corda.core.utilities.OpaqueBytes
|
import net.corda.core.utilities.OpaqueBytes
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -15,7 +14,7 @@ abstract class AbstractParty(val owningKey: PublicKey) {
|
|||||||
/** Anonymised parties do not include any detail apart from owning key, so equality is dependent solely on the key */
|
/** Anonymised parties do not include any detail apart from owning key, so equality is dependent solely on the key */
|
||||||
override fun equals(other: Any?): Boolean = other === this || other is AbstractParty && other.owningKey == owningKey
|
override fun equals(other: Any?): Boolean = other === this || other is AbstractParty && other.owningKey == owningKey
|
||||||
override fun hashCode(): Int = owningKey.hashCode()
|
override fun hashCode(): Int = owningKey.hashCode()
|
||||||
abstract fun nameOrNull(): X500Name?
|
abstract fun nameOrNull(): CordaX500Name?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build a reference to something being stored or issued by a party e.g. in a vault or (more likely) on their normal
|
* Build a reference to something being stored or issued by a party e.g. in a vault or (more likely) on their normal
|
||||||
|
@ -3,7 +3,6 @@ package net.corda.core.identity
|
|||||||
import net.corda.core.contracts.PartyAndReference
|
import net.corda.core.contracts.PartyAndReference
|
||||||
import net.corda.core.crypto.toStringShort
|
import net.corda.core.crypto.toStringShort
|
||||||
import net.corda.core.utilities.OpaqueBytes
|
import net.corda.core.utilities.OpaqueBytes
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -11,7 +10,7 @@ import java.security.PublicKey
|
|||||||
* information such as name. It is intended to represent a party on the distributed ledger.
|
* information such as name. It is intended to represent a party on the distributed ledger.
|
||||||
*/
|
*/
|
||||||
class AnonymousParty(owningKey: PublicKey) : AbstractParty(owningKey) {
|
class AnonymousParty(owningKey: PublicKey) : AbstractParty(owningKey) {
|
||||||
override fun nameOrNull(): X500Name? = null
|
override fun nameOrNull(): CordaX500Name? = null
|
||||||
override fun ref(bytes: OpaqueBytes): PartyAndReference = PartyAndReference(this, bytes)
|
override fun ref(bytes: OpaqueBytes): PartyAndReference = PartyAndReference(this, bytes)
|
||||||
override fun toString() = "Anonymous(${owningKey.toStringShort()})"
|
override fun toString() = "Anonymous(${owningKey.toStringShort()})"
|
||||||
}
|
}
|
126
core/src/main/kotlin/net/corda/core/identity/CordaX500Name.kt
Normal file
126
core/src/main/kotlin/net/corda/core/identity/CordaX500Name.kt
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
package net.corda.core.identity
|
||||||
|
|
||||||
|
import net.corda.core.internal.LegalNameValidator
|
||||||
|
import net.corda.core.serialization.CordaSerializable
|
||||||
|
import net.corda.core.utilities.countryCodes
|
||||||
|
import org.bouncycastle.asn1.ASN1Encodable
|
||||||
|
import org.bouncycastle.asn1.ASN1ObjectIdentifier
|
||||||
|
import org.bouncycastle.asn1.x500.AttributeTypeAndValue
|
||||||
|
import org.bouncycastle.asn1.x500.X500Name
|
||||||
|
import org.bouncycastle.asn1.x500.X500NameBuilder
|
||||||
|
import org.bouncycastle.asn1.x500.style.BCStyle
|
||||||
|
|
||||||
|
/**
|
||||||
|
* X.500 distinguished name data type customised to how Corda uses names. This restricts the attributes to those Corda
|
||||||
|
* supports, and requires that organsation, locality and country attributes are specified. See also RFC 4519 for
|
||||||
|
* the underlying attribute type definitions
|
||||||
|
*
|
||||||
|
* @property commonName optional name by the which the entity is usually known. Used only for services (for
|
||||||
|
* organisations, the [organisation] property is the name). Corresponds to the "CN" attribute type.
|
||||||
|
* @property organisationUnit optional name of a unit within the [organisation]. Corresponds to the "OU" attribute type.
|
||||||
|
* @property organisation name of the organisation. Corresponds to the "O" attribute type.
|
||||||
|
* @property locality locality of the organisation, typically nearest major city. For distributed services this would be
|
||||||
|
* where one of the organisations is based. Corresponds to the "L" attribute type.
|
||||||
|
* @property state the full name of the state or province the organisation is based in. Corresponds to the "ST"
|
||||||
|
* attribute type.
|
||||||
|
* @property country country the organisation is in, as an ISO 3166-1 2-letter country code. Corresponds to the "C"
|
||||||
|
* attribute type.
|
||||||
|
*/
|
||||||
|
@CordaSerializable
|
||||||
|
data class CordaX500Name(val commonName: String?,
|
||||||
|
val organisationUnit: String?,
|
||||||
|
val organisation: String,
|
||||||
|
val locality: String,
|
||||||
|
val state: String?,
|
||||||
|
val country: String) {
|
||||||
|
init {
|
||||||
|
// Legal name checks.
|
||||||
|
LegalNameValidator.validateLegalName(organisation)
|
||||||
|
|
||||||
|
// Attribute data width checks.
|
||||||
|
require(country.length == LENGTH_COUNTRY) { "Invalid country '$country' Country code must be 2 letters ISO code " }
|
||||||
|
require(country.toUpperCase() == country) { "Country code should be in upper case." }
|
||||||
|
require(countryCodes.contains(country)) { "Invalid country code '${country}'" }
|
||||||
|
|
||||||
|
require(organisation.length < MAX_LENGTH_ORGANISATION) { "Organisation attribute (O) must contain less then $MAX_LENGTH_ORGANISATION characters." }
|
||||||
|
require(locality.length < MAX_LENGTH_LOCALITY) { "Locality attribute (L) must contain less then $MAX_LENGTH_LOCALITY characters." }
|
||||||
|
|
||||||
|
state?.let { require(it.length < MAX_LENGTH_STATE) { "State attribute (ST) must contain less then $MAX_LENGTH_STATE characters." } }
|
||||||
|
organisationUnit?.let { require(it.length < MAX_LENGTH_ORGANISATION_UNIT) { "Organisation Unit attribute (OU) must contain less then $MAX_LENGTH_ORGANISATION_UNIT characters." } }
|
||||||
|
commonName?.let { require(it.length < MAX_LENGTH_COMMON_NAME) { "Common Name attribute (CN) must contain less then $MAX_LENGTH_COMMON_NAME characters." } }
|
||||||
|
}
|
||||||
|
constructor(commonName: String, organisation: String, locality: String, country: String) : this(null, commonName, organisation, locality, null, country)
|
||||||
|
/**
|
||||||
|
* @param organisation name of the organisation.
|
||||||
|
* @param locality locality of the organisation, typically nearest major city.
|
||||||
|
* @param country country the organisation is in, as an ISO 3166-1 2-letter country code.
|
||||||
|
*/
|
||||||
|
constructor(organisation: String, locality: String, country: String) : this(null, null, organisation, locality, null, country)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val LENGTH_COUNTRY = 2
|
||||||
|
const val MAX_LENGTH_ORGANISATION = 128
|
||||||
|
const val MAX_LENGTH_LOCALITY = 64
|
||||||
|
const val MAX_LENGTH_STATE = 64
|
||||||
|
const val MAX_LENGTH_ORGANISATION_UNIT = 64
|
||||||
|
const val MAX_LENGTH_COMMON_NAME = 64
|
||||||
|
private val mandatoryAttributes = setOf(BCStyle.O, BCStyle.C, BCStyle.L)
|
||||||
|
private val supportedAttributes = mandatoryAttributes + setOf(BCStyle.CN, BCStyle.ST, BCStyle.OU)
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun build(x500Name: X500Name) : CordaX500Name {
|
||||||
|
val rDNs = x500Name.rdNs.flatMap { it.typesAndValues.toList() }
|
||||||
|
val attrsMap: Map<ASN1ObjectIdentifier, ASN1Encodable> = rDNs.associateBy(AttributeTypeAndValue::getType, AttributeTypeAndValue::getValue)
|
||||||
|
val attributes = attrsMap.keys
|
||||||
|
|
||||||
|
// Duplicate attribute value checks.
|
||||||
|
require(attributes.size == attributes.toSet().size) { "X500Name contain duplicate attribute." }
|
||||||
|
|
||||||
|
// Mandatory attribute checks.
|
||||||
|
require(attributes.containsAll(mandatoryAttributes)) {
|
||||||
|
val missingAttributes = mandatoryAttributes.subtract(attributes).map { BCStyle.INSTANCE.oidToDisplayName(it) }
|
||||||
|
"The following attribute${if (missingAttributes.size > 1) "s are" else " is"} missing from the legal name : $missingAttributes"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Supported attribute checks.
|
||||||
|
require(attributes.subtract(supportedAttributes).isEmpty()) {
|
||||||
|
val unsupportedAttributes = attributes.subtract(supportedAttributes).map { BCStyle.INSTANCE.oidToDisplayName(it) }
|
||||||
|
"The following attribute${if (unsupportedAttributes.size > 1) "s are" else " is"} not supported in Corda :$unsupportedAttributes"
|
||||||
|
}
|
||||||
|
|
||||||
|
val CN = attrsMap[BCStyle.CN]?.toString()
|
||||||
|
val OU = attrsMap[BCStyle.OU]?.toString()
|
||||||
|
val O = attrsMap[BCStyle.O]?.toString() ?: throw IllegalArgumentException("Corda X.500 names must include an O attribute")
|
||||||
|
val L = attrsMap[BCStyle.L]?.toString() ?: throw IllegalArgumentException("Corda X.500 names must include an L attribute")
|
||||||
|
val ST = attrsMap[BCStyle.ST]?.toString()
|
||||||
|
val C = attrsMap[BCStyle.C]?.toString() ?: throw IllegalArgumentException("Corda X.500 names must include an C attribute")
|
||||||
|
return CordaX500Name(CN, OU, O, L, ST, C)
|
||||||
|
}
|
||||||
|
@JvmStatic
|
||||||
|
fun parse(name: String) : CordaX500Name = build(X500Name(name))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transient
|
||||||
|
private var x500Cache: X500Name? = null
|
||||||
|
|
||||||
|
override fun toString(): String = x500Name.toString()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the underlying X.500 name from this Corda-safe X.500 name. These are guaranteed to have a consistent
|
||||||
|
* ordering, such that their `toString()` function returns the same value every time for the same [CordaX500Name].
|
||||||
|
*/
|
||||||
|
val x500Name: X500Name
|
||||||
|
get() {
|
||||||
|
if (x500Cache == null) {
|
||||||
|
x500Cache = X500NameBuilder(BCStyle.INSTANCE).apply {
|
||||||
|
addRDN(BCStyle.C, country)
|
||||||
|
state?.let { addRDN(BCStyle.ST, it) }
|
||||||
|
addRDN(BCStyle.L, locality)
|
||||||
|
addRDN(BCStyle.O, organisation)
|
||||||
|
organisationUnit?.let { addRDN(BCStyle.OU, it) }
|
||||||
|
commonName?.let { addRDN(BCStyle.CN, it) }
|
||||||
|
}.build()
|
||||||
|
}
|
||||||
|
return x500Cache!!
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +1,9 @@
|
|||||||
package net.corda.core.identity
|
package net.corda.core.identity
|
||||||
|
|
||||||
import net.corda.core.contracts.PartyAndReference
|
import net.corda.core.contracts.PartyAndReference
|
||||||
import net.corda.core.crypto.Crypto
|
|
||||||
import net.corda.core.crypto.CompositeKey
|
import net.corda.core.crypto.CompositeKey
|
||||||
|
import net.corda.core.crypto.Crypto
|
||||||
import net.corda.core.utilities.OpaqueBytes
|
import net.corda.core.utilities.OpaqueBytes
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import org.bouncycastle.cert.X509CertificateHolder
|
import org.bouncycastle.cert.X509CertificateHolder
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
|
|
||||||
@ -27,9 +26,9 @@ import java.security.PublicKey
|
|||||||
*
|
*
|
||||||
* @see CompositeKey
|
* @see CompositeKey
|
||||||
*/
|
*/
|
||||||
class Party(val name: X500Name, owningKey: PublicKey) : AbstractParty(owningKey) {
|
class Party(val name: CordaX500Name, owningKey: PublicKey) : AbstractParty(owningKey) {
|
||||||
constructor(certificate: X509CertificateHolder) : this(certificate.subject, Crypto.toSupportedPublicKey(certificate.subjectPublicKeyInfo))
|
constructor(certificate: X509CertificateHolder) : this(CordaX500Name.build(certificate.subject), Crypto.toSupportedPublicKey(certificate.subjectPublicKeyInfo))
|
||||||
override fun nameOrNull(): X500Name = name
|
override fun nameOrNull(): CordaX500Name = name
|
||||||
fun anonymise(): AnonymousParty = AnonymousParty(owningKey)
|
fun anonymise(): AnonymousParty = AnonymousParty(owningKey)
|
||||||
override fun ref(bytes: OpaqueBytes): PartyAndReference = PartyAndReference(this, bytes)
|
override fun ref(bytes: OpaqueBytes): PartyAndReference = PartyAndReference(this, bytes)
|
||||||
override fun toString() = name.toString()
|
override fun toString() = name.toString()
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package net.corda.core.identity
|
package net.corda.core.identity
|
||||||
|
|
||||||
import net.corda.core.internal.toX509CertHolder
|
import net.corda.core.internal.toX509CertHolder
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import org.bouncycastle.cert.X509CertificateHolder
|
import org.bouncycastle.cert.X509CertificateHolder
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
import java.security.cert.*
|
import java.security.cert.*
|
||||||
@ -24,7 +23,7 @@ class PartyAndCertificate(val certPath: CertPath) {
|
|||||||
@Transient val party: Party = Party(certificate)
|
@Transient val party: Party = Party(certificate)
|
||||||
|
|
||||||
val owningKey: PublicKey get() = party.owningKey
|
val owningKey: PublicKey get() = party.owningKey
|
||||||
val name: X500Name get() = party.name
|
val name: CordaX500Name get() = party.name
|
||||||
|
|
||||||
operator fun component1(): Party = party
|
operator fun component1(): Party = party
|
||||||
operator fun component2(): X509CertificateHolder = certificate
|
operator fun component2(): X509CertificateHolder = certificate
|
||||||
|
@ -0,0 +1,117 @@
|
|||||||
|
package net.corda.core.internal
|
||||||
|
|
||||||
|
import java.lang.Character.UnicodeScript.*
|
||||||
|
import java.text.Normalizer
|
||||||
|
import java.util.regex.Pattern
|
||||||
|
import javax.security.auth.x500.X500Principal
|
||||||
|
|
||||||
|
object LegalNameValidator {
|
||||||
|
/**
|
||||||
|
* The validation function will validate the input string using the following rules:
|
||||||
|
*
|
||||||
|
* - No blacklisted words like "node", "server".
|
||||||
|
* - Restrict names to Latin scripts for now to avoid right-to-left issues, debugging issues when we can't pronounce
|
||||||
|
* names over the phone, and character confusability attacks.
|
||||||
|
* - Must consist of at least three letters and should start with a capital letter.
|
||||||
|
* - No commas or equals signs.
|
||||||
|
* - No dollars or quote marks, we might need to relax the quote mark constraint in future to handle Irish company names.
|
||||||
|
*
|
||||||
|
* @throws IllegalArgumentException if the name does not meet the required rules. The message indicates why not.
|
||||||
|
*/
|
||||||
|
fun validateLegalName(normalizedLegalName: String) {
|
||||||
|
Rule.legalNameRules.forEach { it.validate(normalizedLegalName) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The normalize function will trim the input string, replace any multiple spaces with a single space,
|
||||||
|
* and normalize the string according to NFKC normalization form.
|
||||||
|
*/
|
||||||
|
fun normaliseLegalName(legalName: String): String {
|
||||||
|
val trimmedLegalName = legalName.trim().replace(WHITESPACE, " ")
|
||||||
|
return Normalizer.normalize(trimmedLegalName, Normalizer.Form.NFKC)
|
||||||
|
}
|
||||||
|
|
||||||
|
val WHITESPACE = "\\s++".toRegex()
|
||||||
|
|
||||||
|
sealed class Rule<in T> {
|
||||||
|
companion object {
|
||||||
|
val legalNameRules: List<Rule<String>> = listOf(
|
||||||
|
UnicodeNormalizationRule(),
|
||||||
|
CharacterRule(',', '=', '$', '"', '\'', '\\'),
|
||||||
|
WordRule("node", "server"),
|
||||||
|
LengthRule(maxLength = 255),
|
||||||
|
// TODO: Implement confusable character detection if we add more scripts.
|
||||||
|
UnicodeRangeRule(LATIN, COMMON, INHERITED),
|
||||||
|
CapitalLetterRule(),
|
||||||
|
X500NameRule(),
|
||||||
|
MustHaveAtLeastTwoLettersRule()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract fun validate(legalName: T)
|
||||||
|
|
||||||
|
private class UnicodeNormalizationRule : Rule<String>() {
|
||||||
|
override fun validate(legalName: String) {
|
||||||
|
require(legalName == normaliseLegalName(legalName)) { "Legal name must be normalized. Please use 'normaliseLegalName' to normalize the legal name before validation." }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class UnicodeRangeRule(vararg supportScripts: Character.UnicodeScript) : Rule<String>() {
|
||||||
|
private val pattern = supportScripts.map { "\\p{Is$it}" }.joinToString(separator = "", prefix = "[", postfix = "]*").let { Pattern.compile(it) }
|
||||||
|
|
||||||
|
override fun validate(legalName: String) {
|
||||||
|
require(pattern.matcher(legalName).matches()) {
|
||||||
|
val illegalChars = legalName.replace(pattern.toRegex(), "").toSet()
|
||||||
|
if (illegalChars.size > 1) {
|
||||||
|
"Forbidden characters $illegalChars in \"$legalName\"."
|
||||||
|
} else {
|
||||||
|
"Forbidden character $illegalChars in \"$legalName\"."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class CharacterRule(vararg val bannedChars: Char) : Rule<String>() {
|
||||||
|
override fun validate(legalName: String) {
|
||||||
|
bannedChars.forEach {
|
||||||
|
require(!legalName.contains(it, true)) { "Character not allowed in legal names: $it" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class WordRule(vararg val bannedWords: String) : Rule<String>() {
|
||||||
|
override fun validate(legalName: String) {
|
||||||
|
bannedWords.forEach {
|
||||||
|
require(!legalName.contains(it, ignoreCase = true)) { "Word not allowed in legal names: $it" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class LengthRule(val maxLength: Int) : Rule<String>() {
|
||||||
|
override fun validate(legalName: String) {
|
||||||
|
require(legalName.length <= maxLength) { "Legal name longer then $maxLength characters." }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class CapitalLetterRule : Rule<String>() {
|
||||||
|
override fun validate(legalName: String) {
|
||||||
|
val capitalizedLegalName = legalName.capitalize()
|
||||||
|
require(legalName == capitalizedLegalName) { "Legal name should be capitalized. i.e. '$capitalizedLegalName'" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class X500NameRule : Rule<String>() {
|
||||||
|
override fun validate(legalName: String) {
|
||||||
|
// This will throw IllegalArgumentException if the name does not comply with X500 name format.
|
||||||
|
X500Principal("CN=$legalName")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class MustHaveAtLeastTwoLettersRule : Rule<String>() {
|
||||||
|
override fun validate(legalName: String) {
|
||||||
|
// Try to exclude names like "/", "£", "X" etc.
|
||||||
|
require(legalName.count { it.isLetter() } >= 2) { "Illegal input legal name '$legalName'. Legal name must have at least two letters" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,13 +2,12 @@ package net.corda.core.messaging
|
|||||||
|
|
||||||
import net.corda.core.concurrent.CordaFuture
|
import net.corda.core.concurrent.CordaFuture
|
||||||
import net.corda.core.contracts.ContractState
|
import net.corda.core.contracts.ContractState
|
||||||
import net.corda.core.contracts.StateAndRef
|
|
||||||
import net.corda.core.contracts.UpgradedContract
|
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
import net.corda.core.flows.FlowInitiator
|
import net.corda.core.flows.FlowInitiator
|
||||||
import net.corda.core.flows.FlowLogic
|
import net.corda.core.flows.FlowLogic
|
||||||
import net.corda.core.flows.StateMachineRunId
|
import net.corda.core.flows.StateMachineRunId
|
||||||
import net.corda.core.identity.AbstractParty
|
import net.corda.core.identity.AbstractParty
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.node.NodeInfo
|
import net.corda.core.node.NodeInfo
|
||||||
import net.corda.core.node.services.NetworkMapCache
|
import net.corda.core.node.services.NetworkMapCache
|
||||||
@ -21,7 +20,6 @@ import net.corda.core.node.services.vault.Sort
|
|||||||
import net.corda.core.serialization.CordaSerializable
|
import net.corda.core.serialization.CordaSerializable
|
||||||
import net.corda.core.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
import net.corda.core.utilities.Try
|
import net.corda.core.utilities.Try
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
@ -270,7 +268,7 @@ interface CordaRPCOps : RPCOps {
|
|||||||
/**
|
/**
|
||||||
* Returns the [Party] with the X.500 principal as it's [Party.name]
|
* Returns the [Party] with the X.500 principal as it's [Party.name]
|
||||||
*/
|
*/
|
||||||
fun partyFromX500Name(x500Name: X500Name): Party?
|
fun partyFromX500Name(x500Name: CordaX500Name): Party?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of candidate matches for a given string, with optional fuzzy(ish) matching. Fuzzy matching may
|
* Returns a list of candidate matches for a given string, with optional fuzzy(ish) matching. Fuzzy matching may
|
||||||
|
@ -2,7 +2,6 @@ package net.corda.core.messaging
|
|||||||
|
|
||||||
import net.corda.core.serialization.CordaSerializable
|
import net.corda.core.serialization.CordaSerializable
|
||||||
|
|
||||||
|
|
||||||
/** The interface for a group of message recipients (which may contain only one recipient) */
|
/** The interface for a group of message recipients (which may contain only one recipient) */
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
interface MessageRecipients
|
interface MessageRecipients
|
||||||
|
@ -6,7 +6,6 @@ import net.corda.core.node.services.ServiceInfo
|
|||||||
import net.corda.core.node.services.ServiceType
|
import net.corda.core.node.services.ServiceType
|
||||||
import net.corda.core.serialization.CordaSerializable
|
import net.corda.core.serialization.CordaSerializable
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
import net.corda.core.utilities.locality
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Information for an advertised service including the service specific identity information.
|
* Information for an advertised service including the service specific identity information.
|
||||||
|
@ -1,11 +1,7 @@
|
|||||||
package net.corda.core.node.services
|
package net.corda.core.node.services
|
||||||
|
|
||||||
import net.corda.core.contracts.PartyAndReference
|
import net.corda.core.contracts.PartyAndReference
|
||||||
import net.corda.core.identity.AbstractParty
|
import net.corda.core.identity.*
|
||||||
import net.corda.core.identity.AnonymousParty
|
|
||||||
import net.corda.core.identity.Party
|
|
||||||
import net.corda.core.identity.PartyAndCertificate
|
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import org.bouncycastle.cert.X509CertificateHolder
|
import org.bouncycastle.cert.X509CertificateHolder
|
||||||
import java.security.InvalidAlgorithmParameterException
|
import java.security.InvalidAlgorithmParameterException
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
@ -79,7 +75,7 @@ interface IdentityService {
|
|||||||
|
|
||||||
fun partyFromKey(key: PublicKey): Party?
|
fun partyFromKey(key: PublicKey): Party?
|
||||||
|
|
||||||
fun partyFromX500Name(principal: X500Name): Party?
|
fun partyFromX500Name(name: CordaX500Name): Party?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the well known identity from an abstract party. This is intended to resolve the well known identity
|
* Returns the well known identity from an abstract party. This is intended to resolve the well known identity
|
||||||
|
@ -3,13 +3,13 @@ package net.corda.core.node.services
|
|||||||
import net.corda.core.concurrent.CordaFuture
|
import net.corda.core.concurrent.CordaFuture
|
||||||
import net.corda.core.contracts.Contract
|
import net.corda.core.contracts.Contract
|
||||||
import net.corda.core.identity.AbstractParty
|
import net.corda.core.identity.AbstractParty
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.internal.randomOrNull
|
import net.corda.core.internal.randomOrNull
|
||||||
import net.corda.core.messaging.DataFeed
|
import net.corda.core.messaging.DataFeed
|
||||||
import net.corda.core.node.NodeInfo
|
import net.corda.core.node.NodeInfo
|
||||||
import net.corda.core.serialization.CordaSerializable
|
import net.corda.core.serialization.CordaSerializable
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
|
|
||||||
@ -77,7 +77,7 @@ interface NetworkMapCache {
|
|||||||
fun getNodeByLegalIdentity(party: AbstractParty): NodeInfo?
|
fun getNodeByLegalIdentity(party: AbstractParty): NodeInfo?
|
||||||
|
|
||||||
/** Look up the node info for a legal name. */
|
/** Look up the node info for a legal name. */
|
||||||
fun getNodeByLegalName(principal: X500Name): NodeInfo?
|
fun getNodeByLegalName(principal: CordaX500Name): NodeInfo?
|
||||||
|
|
||||||
/** Look up the node info for a host and port. */
|
/** Look up the node info for a host and port. */
|
||||||
fun getNodeByAddress(address: NetworkHostAndPort): NodeInfo?
|
fun getNodeByAddress(address: NetworkHostAndPort): NodeInfo?
|
||||||
@ -100,7 +100,7 @@ interface NetworkMapCache {
|
|||||||
fun getPartyInfo(party: Party): PartyInfo?
|
fun getPartyInfo(party: Party): PartyInfo?
|
||||||
|
|
||||||
/** Gets a notary identity by the given name. */
|
/** Gets a notary identity by the given name. */
|
||||||
fun getNotary(principal: X500Name): Party? {
|
fun getNotary(principal: CordaX500Name): Party? {
|
||||||
val notaryNode = notaryNodes.filter {
|
val notaryNode = notaryNodes.filter {
|
||||||
it.advertisedServices.any { it.info.type.isSubTypeOf(ServiceType.notary) && it.info.name == principal }
|
it.advertisedServices.any { it.info.type.isSubTypeOf(ServiceType.notary) && it.info.name == principal }
|
||||||
}.randomOrNull()
|
}.randomOrNull()
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package net.corda.core.node.services
|
package net.corda.core.node.services
|
||||||
|
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.serialization.CordaSerializable
|
import net.corda.core.serialization.CordaSerializable
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A container for additional information for an advertised service.
|
* A container for additional information for an advertised service.
|
||||||
@ -11,14 +11,14 @@ import org.bouncycastle.asn1.x500.X500Name
|
|||||||
* grouping identifier for nodes collectively running a distributed service.
|
* grouping identifier for nodes collectively running a distributed service.
|
||||||
*/
|
*/
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
data class ServiceInfo(val type: ServiceType, val name: X500Name? = null) {
|
data class ServiceInfo(val type: ServiceType, val name: CordaX500Name? = null) {
|
||||||
companion object {
|
companion object {
|
||||||
fun parse(encoded: String): ServiceInfo {
|
fun parse(encoded: String): ServiceInfo {
|
||||||
val parts = encoded.split("|")
|
val parts = encoded.split("|")
|
||||||
require(parts.size in 1..2) { "Invalid number of elements found" }
|
require(parts.size in 1..2) { "Invalid number of elements found" }
|
||||||
val type = ServiceType.parse(parts[0])
|
val type = ServiceType.parse(parts[0])
|
||||||
val name = parts.getOrNull(1)
|
val name = parts.getOrNull(1)
|
||||||
val principal = name?.let { X500Name(it) }
|
val principal = name?.let { CordaX500Name.parse(it) }
|
||||||
return ServiceInfo(type, principal)
|
return ServiceInfo(type, principal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,170 +0,0 @@
|
|||||||
@file:JvmName("LegalNameValidator")
|
|
||||||
|
|
||||||
package net.corda.core.utilities
|
|
||||||
|
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import org.bouncycastle.asn1.x500.style.BCStyle
|
|
||||||
import java.lang.Character.UnicodeScript.*
|
|
||||||
import java.text.Normalizer
|
|
||||||
import java.util.regex.Pattern
|
|
||||||
import javax.security.auth.x500.X500Principal
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The validation function will validate the input string using the following rules:
|
|
||||||
*
|
|
||||||
* - No blacklisted words like "node", "server".
|
|
||||||
* - Restrict names to Latin scripts for now to avoid right-to-left issues, debugging issues when we can't pronounce
|
|
||||||
* names over the phone, and character confusability attacks.
|
|
||||||
* - Must consist of at least three letters and should start with a capital letter.
|
|
||||||
* - No commas or equals signs.
|
|
||||||
* - No dollars or quote marks, we might need to relax the quote mark constraint in future to handle Irish company names.
|
|
||||||
*
|
|
||||||
* @throws IllegalArgumentException if the name does not meet the required rules. The message indicates why not.
|
|
||||||
*/
|
|
||||||
fun validateLegalName(normalizedLegalName: String) {
|
|
||||||
Rule.legalNameRules.forEach { it.validate(normalizedLegalName) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The normalize function will trim the input string, replace any multiple spaces with a single space,
|
|
||||||
* and normalize the string according to NFKC normalization form.
|
|
||||||
*/
|
|
||||||
fun normaliseLegalName(legalName: String): String {
|
|
||||||
val trimmedLegalName = legalName.trim().replace(WHITESPACE, " ")
|
|
||||||
return Normalizer.normalize(trimmedLegalName, Normalizer.Form.NFKC)
|
|
||||||
}
|
|
||||||
|
|
||||||
val WHITESPACE = "\\s++".toRegex()
|
|
||||||
|
|
||||||
private val mandatoryAttributes = setOf(BCStyle.O, BCStyle.C, BCStyle.L)
|
|
||||||
private val supportedAttributes = mandatoryAttributes + setOf(BCStyle.CN, BCStyle.ST, BCStyle.OU)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validate X500Name according to Corda X500Name specification
|
|
||||||
*
|
|
||||||
* Supported attributes:
|
|
||||||
* - organisation (O) – VARCHAR(127)
|
|
||||||
* - state (ST) – VARCHAR(64) nullable
|
|
||||||
* - locality (L) – VARCHAR(64)
|
|
||||||
* - country (C) – VARCHAR(2) - ISO code of the country in which it is registered
|
|
||||||
* - organizational-unit (OU) – VARCHAR(64) nullable
|
|
||||||
* - common name (CN) – VARCHAR(64)
|
|
||||||
*
|
|
||||||
* @throws IllegalArgumentException if the name does not meet the required rules. The message indicates why not.
|
|
||||||
* @see <a href="https://r3-cev.atlassian.net/wiki/spaces/AWG/pages/129206341/Distinguished+name+structure">Design Doc</a>.
|
|
||||||
*/
|
|
||||||
fun validateX500Name(x500Name: X500Name) {
|
|
||||||
val rDNs = x500Name.rdNs.flatMap { it.typesAndValues.asList() }
|
|
||||||
val attributes = rDNs.map { it.type }
|
|
||||||
|
|
||||||
// Duplicate attribute value checks.
|
|
||||||
require(attributes.size == attributes.toSet().size) { "X500Name contain duplicate attribute." }
|
|
||||||
|
|
||||||
// Mandatory attribute checks.
|
|
||||||
require(attributes.containsAll(mandatoryAttributes)) {
|
|
||||||
val missingAttributes = mandatoryAttributes.subtract(attributes).map { BCStyle.INSTANCE.oidToDisplayName(it) }
|
|
||||||
"The following attribute${if (missingAttributes.size > 1) "s are" else " is"} missing from the legal name : $missingAttributes"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Supported attribute checks.
|
|
||||||
require(attributes.subtract(supportedAttributes).isEmpty()) {
|
|
||||||
val unsupportedAttributes = attributes.subtract(supportedAttributes).map { BCStyle.INSTANCE.oidToDisplayName(it) }
|
|
||||||
"The following attribute${if (unsupportedAttributes.size > 1) "s are" else " is"} not supported in Corda :$unsupportedAttributes"
|
|
||||||
}
|
|
||||||
// Legal name checks.
|
|
||||||
validateLegalName(x500Name.organisation)
|
|
||||||
|
|
||||||
// Attribute data width checks.
|
|
||||||
require(x500Name.country.length == 2) { "Invalid country '${x500Name.country}' Country code must be 2 letters ISO code " }
|
|
||||||
require(x500Name.country.toUpperCase() == x500Name.country) { "Country code should be in upper case." }
|
|
||||||
require(countryCodes.contains(x500Name.country)) { "Invalid country code '${x500Name.country}'" }
|
|
||||||
|
|
||||||
require(x500Name.organisation.length < 128) { "Organisation attribute (O) must contain less then 128 characters." }
|
|
||||||
require(x500Name.locality.length < 64) { "Locality attribute (L) must contain less then 64 characters." }
|
|
||||||
|
|
||||||
x500Name.state?.let { require(it.length < 64) { "State attribute (ST) must contain less then 64 characters." } }
|
|
||||||
x500Name.organisationUnit?.let { require(it.length < 64) { "Organisation Unit attribute (OU) must contain less then 64 characters." } }
|
|
||||||
x500Name.commonName?.let { require(it.length < 64) { "Common Name attribute (CN) must contain less then 64 characters." } }
|
|
||||||
}
|
|
||||||
|
|
||||||
private sealed class Rule<in T> {
|
|
||||||
companion object {
|
|
||||||
val legalNameRules: List<Rule<String>> = listOf(
|
|
||||||
UnicodeNormalizationRule(),
|
|
||||||
CharacterRule(',', '=', '$', '"', '\'', '\\'),
|
|
||||||
WordRule("node", "server"),
|
|
||||||
LengthRule(maxLength = 255),
|
|
||||||
// TODO: Implement confusable character detection if we add more scripts.
|
|
||||||
UnicodeRangeRule(LATIN, COMMON, INHERITED),
|
|
||||||
CapitalLetterRule(),
|
|
||||||
X500NameRule(),
|
|
||||||
MustHaveAtLeastTwoLettersRule()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract fun validate(legalName: T)
|
|
||||||
|
|
||||||
private class UnicodeNormalizationRule : Rule<String>() {
|
|
||||||
override fun validate(legalName: String) {
|
|
||||||
require(legalName == normaliseLegalName(legalName)) { "Legal name must be normalized. Please use 'normaliseLegalName' to normalize the legal name before validation." }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class UnicodeRangeRule(vararg supportScripts: Character.UnicodeScript) : Rule<String>() {
|
|
||||||
private val pattern = supportScripts.map { "\\p{Is$it}" }.joinToString(separator = "", prefix = "[", postfix = "]*").let { Pattern.compile(it) }
|
|
||||||
|
|
||||||
override fun validate(legalName: String) {
|
|
||||||
require(pattern.matcher(legalName).matches()) {
|
|
||||||
val illegalChars = legalName.replace(pattern.toRegex(), "").toSet()
|
|
||||||
if (illegalChars.size > 1) {
|
|
||||||
"Forbidden characters $illegalChars in \"$legalName\"."
|
|
||||||
} else {
|
|
||||||
"Forbidden character $illegalChars in \"$legalName\"."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class CharacterRule(vararg val bannedChars: Char) : Rule<String>() {
|
|
||||||
override fun validate(legalName: String) {
|
|
||||||
bannedChars.forEach {
|
|
||||||
require(!legalName.contains(it, true)) { "Character not allowed in legal names: $it" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class WordRule(vararg val bannedWords: String) : Rule<String>() {
|
|
||||||
override fun validate(legalName: String) {
|
|
||||||
bannedWords.forEach {
|
|
||||||
require(!legalName.contains(it, ignoreCase = true)) { "Word not allowed in legal names: $it" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class LengthRule(val maxLength: Int) : Rule<String>() {
|
|
||||||
override fun validate(legalName: String) {
|
|
||||||
require(legalName.length <= maxLength) { "Legal name longer then $maxLength characters." }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class CapitalLetterRule : Rule<String>() {
|
|
||||||
override fun validate(legalName: String) {
|
|
||||||
val capitalizedLegalName = legalName.capitalize()
|
|
||||||
require(legalName == capitalizedLegalName) { "Legal name should be capitalized. i.e. '$capitalizedLegalName'" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class X500NameRule : Rule<String>() {
|
|
||||||
override fun validate(legalName: String) {
|
|
||||||
// This will throw IllegalArgumentException if the name does not comply with X500 name format.
|
|
||||||
X500Principal("CN=$legalName")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class MustHaveAtLeastTwoLettersRule : Rule<String>() {
|
|
||||||
override fun validate(legalName: String) {
|
|
||||||
// Try to exclude names like "/", "£", "X" etc.
|
|
||||||
require(legalName.count { it.isLetter() } >= 2) { "Illegal input legal name '$legalName'. Legal name must have at least two letters" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -8,7 +8,6 @@ import org.bouncycastle.asn1.x500.X500NameBuilder
|
|||||||
import org.bouncycastle.asn1.x500.style.BCStyle
|
import org.bouncycastle.asn1.x500.style.BCStyle
|
||||||
|
|
||||||
val X500Name.commonName: String? get() = getRDNValueString(BCStyle.CN)
|
val X500Name.commonName: String? get() = getRDNValueString(BCStyle.CN)
|
||||||
val X500Name.organisationUnit: String? get() = getRDNValueString(BCStyle.OU)
|
|
||||||
val X500Name.state: String? get() = getRDNValueString(BCStyle.ST)
|
val X500Name.state: String? get() = getRDNValueString(BCStyle.ST)
|
||||||
val X500Name.organisation: String get() = getRDNValueString(BCStyle.O) ?: throw IllegalArgumentException("Malformed X500 name, organisation attribute (O) cannot be empty.")
|
val X500Name.organisation: String get() = getRDNValueString(BCStyle.O) ?: throw IllegalArgumentException("Malformed X500 name, organisation attribute (O) cannot be empty.")
|
||||||
val X500Name.locality: String get() = getRDNValueString(BCStyle.L) ?: throw IllegalArgumentException("Malformed X500 name, locality attribute (L) cannot be empty.")
|
val X500Name.locality: String get() = getRDNValueString(BCStyle.L) ?: throw IllegalArgumentException("Malformed X500 name, locality attribute (L) cannot be empty.")
|
||||||
@ -36,13 +35,4 @@ fun getX500Name(O: String, L: String, C: String, CN: String? = null, OU: String?
|
|||||||
OU?.let { addRDN(BCStyle.OU, it) }
|
OU?.let { addRDN(BCStyle.OU, it) }
|
||||||
CN?.let { addRDN(BCStyle.CN, it) }
|
CN?.let { addRDN(BCStyle.CN, it) }
|
||||||
}.build()
|
}.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun X500Name.withCommonName(commonName: String?): X500Name {
|
|
||||||
return getX500Name(organisation, locality, country, commonName, organisationUnit, state)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun X500Name.toWellFormattedName(): X500Name {
|
|
||||||
validateX500Name(this)
|
|
||||||
return getX500Name(organisation, locality, country, commonName, organisationUnit, state)
|
|
||||||
}
|
|
@ -331,10 +331,10 @@ class CompositeKeyTests : TestDependencyInjectionBase() {
|
|||||||
|
|
||||||
// Create self sign CA.
|
// Create self sign CA.
|
||||||
val caKeyPair = Crypto.generateKeyPair()
|
val caKeyPair = Crypto.generateKeyPair()
|
||||||
val ca = X509Utilities.createSelfSignedCACertificate(getX500Name(CN = "Test CA", O = "R3", L = "London", C = "GB"), caKeyPair)
|
val ca = X509Utilities.createSelfSignedCACertificate(getX500Name(CN = "Test CA", O = "R3 Ltd", L = "London", C = "GB"), caKeyPair)
|
||||||
|
|
||||||
// Sign the composite key with the self sign CA.
|
// Sign the composite key with the self sign CA.
|
||||||
val compositeKeyCert = X509Utilities.createCertificate(CertificateType.IDENTITY, ca, caKeyPair, getX500Name(CN = "CompositeKey", O = "R3", L = "London", C = "GB"), compositeKey)
|
val compositeKeyCert = X509Utilities.createCertificate(CertificateType.IDENTITY, ca, caKeyPair, getX500Name(CN = "CompositeKey", O = "R3 Ltd", L = "London", C = "GB"), compositeKey)
|
||||||
|
|
||||||
// Store certificate to keystore.
|
// Store certificate to keystore.
|
||||||
val keystorePath = tempFolder.root.toPath() / "keystore.jks"
|
val keystorePath = tempFolder.root.toPath() / "keystore.jks"
|
||||||
|
@ -0,0 +1,63 @@
|
|||||||
|
package net.corda.core.identity
|
||||||
|
|
||||||
|
import org.junit.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.test.assertFailsWith
|
||||||
|
import kotlin.test.assertNull
|
||||||
|
|
||||||
|
class CordaX500NameTest {
|
||||||
|
@Test
|
||||||
|
fun `parse service name with organisational unit`() {
|
||||||
|
val name = CordaX500Name.parse("O=Bank A, L=New York, C=US, OU=Org Unit, CN=Service Name")
|
||||||
|
assertEquals("Service Name", name.commonName)
|
||||||
|
assertEquals("Org Unit", name.organisationUnit)
|
||||||
|
assertEquals("Bank A", name.organisation)
|
||||||
|
assertEquals("New York", name.locality)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `parse service name`() {
|
||||||
|
val name = CordaX500Name.parse("O=Bank A, L=New York, C=US, CN=Service Name")
|
||||||
|
assertEquals("Service Name", name.commonName)
|
||||||
|
assertNull(name.organisationUnit)
|
||||||
|
assertEquals("Bank A", name.organisation)
|
||||||
|
assertEquals("New York", name.locality)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `parse legal entity name`() {
|
||||||
|
val name = CordaX500Name.parse("O=Bank A, L=New York, C=US")
|
||||||
|
assertNull(name.commonName)
|
||||||
|
assertNull(name.organisationUnit)
|
||||||
|
assertEquals("Bank A", name.organisation)
|
||||||
|
assertEquals("New York", name.locality)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `rejects name with no organisation`() {
|
||||||
|
assertFailsWith(IllegalArgumentException::class) {
|
||||||
|
CordaX500Name.parse("L=New York, C=US, OU=Org Unit, CN=Service Name")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `rejects name with no locality`() {
|
||||||
|
assertFailsWith(IllegalArgumentException::class) {
|
||||||
|
CordaX500Name.parse("O=Bank A, C=US, OU=Org Unit, CN=Service Name")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `rejects name with no country`() {
|
||||||
|
assertFailsWith(IllegalArgumentException::class) {
|
||||||
|
CordaX500Name.parse("O=Bank A, L=New York, OU=Org Unit, CN=Service Name")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `rejects name with wrong organisation name format`() {
|
||||||
|
assertFailsWith(IllegalArgumentException::class) {
|
||||||
|
CordaX500Name.parse("O=B, L=New York, C=US, OU=Org Unit, CN=Service Name")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,7 +3,6 @@ package net.corda.core.identity
|
|||||||
import net.corda.core.crypto.entropyToKeyPair
|
import net.corda.core.crypto.entropyToKeyPair
|
||||||
import net.corda.core.serialization.deserialize
|
import net.corda.core.serialization.deserialize
|
||||||
import net.corda.core.serialization.serialize
|
import net.corda.core.serialization.serialize
|
||||||
import net.corda.core.utilities.getX500Name
|
|
||||||
import net.corda.testing.getTestPartyAndCertificate
|
import net.corda.testing.getTestPartyAndCertificate
|
||||||
import net.corda.testing.withTestSerialization
|
import net.corda.testing.withTestSerialization
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
@ -15,7 +14,7 @@ class PartyAndCertificateTest {
|
|||||||
fun `kryo serialisation`() {
|
fun `kryo serialisation`() {
|
||||||
withTestSerialization {
|
withTestSerialization {
|
||||||
val original = getTestPartyAndCertificate(Party(
|
val original = getTestPartyAndCertificate(Party(
|
||||||
getX500Name(O = "Test Corp", L = "Madrid", C = "ES"),
|
CordaX500Name(organisation = "Test Corp", locality = "Madrid", country = "ES"),
|
||||||
entropyToKeyPair(BigInteger.valueOf(83)).public))
|
entropyToKeyPair(BigInteger.valueOf(83)).public))
|
||||||
val copy = original.serialize().deserialize()
|
val copy = original.serialize().deserialize()
|
||||||
assertThat(copy).isEqualTo(original).isNotSameAs(original)
|
assertThat(copy).isEqualTo(original).isNotSameAs(original)
|
||||||
|
@ -0,0 +1,102 @@
|
|||||||
|
package net.corda.core.internal
|
||||||
|
|
||||||
|
import org.junit.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.test.assertFailsWith
|
||||||
|
|
||||||
|
class LegalNameValidatorTest {
|
||||||
|
@Test
|
||||||
|
fun `no double spaces`() {
|
||||||
|
assertFailsWith(IllegalArgumentException::class) {
|
||||||
|
LegalNameValidator.validateLegalName("Test Legal Name")
|
||||||
|
}
|
||||||
|
LegalNameValidator.validateLegalName(LegalNameValidator.normaliseLegalName("Test Legal Name"))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `no trailing white space`() {
|
||||||
|
assertFailsWith(IllegalArgumentException::class) {
|
||||||
|
LegalNameValidator.validateLegalName("Test ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `no prefixed white space`() {
|
||||||
|
assertFailsWith(IllegalArgumentException::class) {
|
||||||
|
LegalNameValidator.validateLegalName(" Test")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `blacklisted words`() {
|
||||||
|
assertFailsWith(IllegalArgumentException::class) {
|
||||||
|
LegalNameValidator.validateLegalName("Test Server")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `blacklisted characters`() {
|
||||||
|
LegalNameValidator.validateLegalName("Test")
|
||||||
|
assertFailsWith(IllegalArgumentException::class) {
|
||||||
|
LegalNameValidator.validateLegalName("\$Test")
|
||||||
|
}
|
||||||
|
assertFailsWith(IllegalArgumentException::class) {
|
||||||
|
LegalNameValidator.validateLegalName("\"Test")
|
||||||
|
}
|
||||||
|
assertFailsWith(IllegalArgumentException::class) {
|
||||||
|
LegalNameValidator.validateLegalName("\'Test")
|
||||||
|
}
|
||||||
|
assertFailsWith(IllegalArgumentException::class) {
|
||||||
|
LegalNameValidator.validateLegalName("=Test")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `unicode range`() {
|
||||||
|
LegalNameValidator.validateLegalName("Test A")
|
||||||
|
assertFailsWith(IllegalArgumentException::class) {
|
||||||
|
// Greek letter A.
|
||||||
|
LegalNameValidator.validateLegalName("Test Α")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `legal name length less then 256 characters`() {
|
||||||
|
val longLegalName = StringBuilder()
|
||||||
|
while (longLegalName.length < 255) {
|
||||||
|
longLegalName.append("A")
|
||||||
|
}
|
||||||
|
LegalNameValidator.validateLegalName(longLegalName.toString())
|
||||||
|
|
||||||
|
assertFailsWith(IllegalArgumentException::class) {
|
||||||
|
LegalNameValidator.validateLegalName(longLegalName.append("A").toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `legal name should be capitalized`() {
|
||||||
|
LegalNameValidator.validateLegalName("Good legal name")
|
||||||
|
assertFailsWith(IllegalArgumentException::class) {
|
||||||
|
LegalNameValidator.validateLegalName("bad name")
|
||||||
|
}
|
||||||
|
assertFailsWith(IllegalArgumentException::class) {
|
||||||
|
LegalNameValidator.validateLegalName("bad Name")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `correctly handle whitespaces`() {
|
||||||
|
assertEquals("Legal Name With Tab", LegalNameValidator.normaliseLegalName("Legal Name With\tTab"))
|
||||||
|
assertEquals("Legal Name With Unicode Whitespaces", LegalNameValidator.normaliseLegalName("Legal Name\u2004With\u0009Unicode\u0020Whitespaces"))
|
||||||
|
assertEquals("Legal Name With Line Breaks", LegalNameValidator.normaliseLegalName("Legal Name With\n\rLine\nBreaks"))
|
||||||
|
assertFailsWith(IllegalArgumentException::class) {
|
||||||
|
LegalNameValidator.validateLegalName("Legal Name With\tTab")
|
||||||
|
}
|
||||||
|
assertFailsWith(IllegalArgumentException::class) {
|
||||||
|
LegalNameValidator.validateLegalName("Legal Name\u2004With\u0009Unicode\u0020Whitespaces")
|
||||||
|
}
|
||||||
|
assertFailsWith(IllegalArgumentException::class) {
|
||||||
|
LegalNameValidator.validateLegalName("Legal Name With\n\rLine\nBreaks")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,15 +1,15 @@
|
|||||||
package net.corda.core.node
|
package net.corda.core.node
|
||||||
|
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.node.services.ServiceInfo
|
import net.corda.core.node.services.ServiceInfo
|
||||||
import net.corda.core.node.services.ServiceType
|
import net.corda.core.node.services.ServiceType
|
||||||
import net.corda.core.utilities.getX500Name
|
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertFailsWith
|
import kotlin.test.assertFailsWith
|
||||||
|
|
||||||
class ServiceInfoTests {
|
class ServiceInfoTests {
|
||||||
val serviceType = ServiceType.getServiceType("test", "service").getSubType("subservice")
|
val serviceType = ServiceType.getServiceType("test", "service").getSubType("subservice")
|
||||||
val name = getX500Name(O = "service.name", L = "London", C = "GB")
|
val name = CordaX500Name(organisation = "Service.name", locality = "London", country = "GB")
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `type and name encodes correctly`() {
|
fun `type and name encodes correctly`() {
|
||||||
|
@ -1,132 +0,0 @@
|
|||||||
package net.corda.core.utilities
|
|
||||||
|
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import org.junit.Test
|
|
||||||
import kotlin.test.assertEquals
|
|
||||||
import kotlin.test.assertFailsWith
|
|
||||||
|
|
||||||
class LegalNameValidatorTest {
|
|
||||||
@Test
|
|
||||||
fun `no double spaces`() {
|
|
||||||
assertFailsWith(IllegalArgumentException::class) {
|
|
||||||
validateLegalName("Test Legal Name")
|
|
||||||
}
|
|
||||||
validateLegalName(normaliseLegalName("Test Legal Name"))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `no trailing white space`() {
|
|
||||||
assertFailsWith(IllegalArgumentException::class) {
|
|
||||||
validateLegalName("Test ")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `no prefixed white space`() {
|
|
||||||
assertFailsWith(IllegalArgumentException::class) {
|
|
||||||
validateLegalName(" Test")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `blacklisted words`() {
|
|
||||||
assertFailsWith(IllegalArgumentException::class) {
|
|
||||||
validateLegalName("Test Server")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `blacklisted characters`() {
|
|
||||||
validateLegalName("Test")
|
|
||||||
assertFailsWith(IllegalArgumentException::class) {
|
|
||||||
validateLegalName("\$Test")
|
|
||||||
}
|
|
||||||
assertFailsWith(IllegalArgumentException::class) {
|
|
||||||
validateLegalName("\"Test")
|
|
||||||
}
|
|
||||||
assertFailsWith(IllegalArgumentException::class) {
|
|
||||||
validateLegalName("\'Test")
|
|
||||||
}
|
|
||||||
assertFailsWith(IllegalArgumentException::class) {
|
|
||||||
validateLegalName("=Test")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `unicode range`() {
|
|
||||||
validateLegalName("Test A")
|
|
||||||
assertFailsWith(IllegalArgumentException::class) {
|
|
||||||
// Greek letter A.
|
|
||||||
validateLegalName("Test Α")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `legal name length less then 256 characters`() {
|
|
||||||
val longLegalName = StringBuilder()
|
|
||||||
while (longLegalName.length < 255) {
|
|
||||||
longLegalName.append("A")
|
|
||||||
}
|
|
||||||
validateLegalName(longLegalName.toString())
|
|
||||||
|
|
||||||
assertFailsWith(IllegalArgumentException::class) {
|
|
||||||
validateLegalName(longLegalName.append("A").toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `legal name should be capitalized`() {
|
|
||||||
validateLegalName("Good legal name")
|
|
||||||
assertFailsWith(IllegalArgumentException::class) {
|
|
||||||
validateLegalName("bad name")
|
|
||||||
}
|
|
||||||
assertFailsWith(IllegalArgumentException::class) {
|
|
||||||
validateLegalName("bad Name")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `correctly handle whitespaces`() {
|
|
||||||
assertEquals("Legal Name With Tab", normaliseLegalName("Legal Name With\tTab"))
|
|
||||||
assertEquals("Legal Name With Unicode Whitespaces", normaliseLegalName("Legal Name\u2004With\u0009Unicode\u0020Whitespaces"))
|
|
||||||
assertEquals("Legal Name With Line Breaks", normaliseLegalName("Legal Name With\n\rLine\nBreaks"))
|
|
||||||
assertFailsWith(IllegalArgumentException::class) {
|
|
||||||
validateLegalName("Legal Name With\tTab")
|
|
||||||
}
|
|
||||||
assertFailsWith(IllegalArgumentException::class) {
|
|
||||||
validateLegalName("Legal Name\u2004With\u0009Unicode\u0020Whitespaces")
|
|
||||||
}
|
|
||||||
assertFailsWith(IllegalArgumentException::class) {
|
|
||||||
validateLegalName("Legal Name With\n\rLine\nBreaks")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `validate x500Name`() {
|
|
||||||
validateX500Name(X500Name("O=Bank A, L=New York, C=US, OU=Org Unit, CN=Service Name"))
|
|
||||||
validateX500Name(X500Name("O=Bank A, L=New York, C=US, CN=Service Name"))
|
|
||||||
validateX500Name(X500Name("O=Bank A, L=New York, C=US"))
|
|
||||||
validateX500Name(X500Name("O=Bank A, L=New York, C=US"))
|
|
||||||
|
|
||||||
// Missing Organisation
|
|
||||||
assertFailsWith(IllegalArgumentException::class) {
|
|
||||||
validateX500Name(X500Name("L=New York, C=US, OU=Org Unit, CN=Service Name"))
|
|
||||||
}
|
|
||||||
// Missing Locality
|
|
||||||
assertFailsWith(IllegalArgumentException::class) {
|
|
||||||
validateX500Name(X500Name("O=Bank A, C=US, OU=Org Unit, CN=Service Name"))
|
|
||||||
}
|
|
||||||
// Missing Country
|
|
||||||
assertFailsWith(IllegalArgumentException::class) {
|
|
||||||
validateX500Name(X500Name("O=Bank A, L=New York, OU=Org Unit, CN=Service Name"))
|
|
||||||
}
|
|
||||||
// Wrong organisation name format
|
|
||||||
assertFailsWith(IllegalArgumentException::class) {
|
|
||||||
validateX500Name(X500Name("O=B, L=New York, C=US, OU=Org Unit, CN=Service Name"))
|
|
||||||
}
|
|
||||||
// Wrong organisation name format
|
|
||||||
assertFailsWith(IllegalArgumentException::class) {
|
|
||||||
validateX500Name(X500Name("O=B, L=New York, C=US, OU=Org Unit, CN=Service Name"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -7,6 +7,7 @@ import net.corda.core.contracts.*;
|
|||||||
import net.corda.core.crypto.SecureHash;
|
import net.corda.core.crypto.SecureHash;
|
||||||
import net.corda.core.crypto.TransactionSignature;
|
import net.corda.core.crypto.TransactionSignature;
|
||||||
import net.corda.core.flows.*;
|
import net.corda.core.flows.*;
|
||||||
|
import net.corda.core.identity.CordaX500Name;
|
||||||
import net.corda.core.identity.Party;
|
import net.corda.core.identity.Party;
|
||||||
import net.corda.core.internal.FetchDataFlow;
|
import net.corda.core.internal.FetchDataFlow;
|
||||||
import net.corda.core.node.services.ServiceType;
|
import net.corda.core.node.services.ServiceType;
|
||||||
@ -19,7 +20,6 @@ import net.corda.core.transactions.TransactionBuilder;
|
|||||||
import net.corda.core.utilities.ProgressTracker;
|
import net.corda.core.utilities.ProgressTracker;
|
||||||
import net.corda.core.utilities.ProgressTracker.Step;
|
import net.corda.core.utilities.ProgressTracker.Step;
|
||||||
import net.corda.core.utilities.UntrustworthyData;
|
import net.corda.core.utilities.UntrustworthyData;
|
||||||
import net.corda.core.utilities.X500NameUtils;
|
|
||||||
import net.corda.finance.contracts.asset.Cash;
|
import net.corda.finance.contracts.asset.Cash;
|
||||||
import net.corda.testing.contracts.DummyContract;
|
import net.corda.testing.contracts.DummyContract;
|
||||||
import net.corda.testing.contracts.DummyContractKt;
|
import net.corda.testing.contracts.DummyContractKt;
|
||||||
@ -123,7 +123,7 @@ public class FlowCookbookJava {
|
|||||||
// - To serve as a timestamping authority if the transaction has a time-window
|
// - To serve as a timestamping authority if the transaction has a time-window
|
||||||
// We retrieve a notary from the network map.
|
// We retrieve a notary from the network map.
|
||||||
// DOCSTART 1
|
// DOCSTART 1
|
||||||
Party specificNotary = getServiceHub().getNetworkMapCache().getNotary(X500NameUtils.getX500Name("Notary Service", "London", "UK"));
|
Party specificNotary = getServiceHub().getNetworkMapCache().getNotary(new CordaX500Name("Notary Service", "London", "UK"));
|
||||||
Party anyNotary = getServiceHub().getNetworkMapCache().getAnyNotary(null);
|
Party anyNotary = getServiceHub().getNetworkMapCache().getAnyNotary(null);
|
||||||
// Unlike the first two methods, ``getNotaryNodes`` returns a
|
// Unlike the first two methods, ``getNotaryNodes`` returns a
|
||||||
// ``List<NodeInfo>``. We have to extract the notary identity of
|
// ``List<NodeInfo>``. We have to extract the notary identity of
|
||||||
@ -134,7 +134,7 @@ public class FlowCookbookJava {
|
|||||||
// We may also need to identify a specific counterparty.
|
// We may also need to identify a specific counterparty.
|
||||||
// Again, we do so using the network map.
|
// Again, we do so using the network map.
|
||||||
// DOCSTART 2
|
// DOCSTART 2
|
||||||
Party namedCounterparty = getServiceHub().getNetworkMapCache().getNodeByLegalName(X500NameUtils.getX500Name("NodeA", "London", "UK")).getLegalIdentity();
|
Party namedCounterparty = getServiceHub().getNetworkMapCache().getNodeByLegalName(new CordaX500Name("NodeA", "London", "UK")).getLegalIdentity();
|
||||||
Party keyedCounterparty = getServiceHub().getNetworkMapCache().getNodeByLegalIdentityKey(dummyPubKey).getLegalIdentity();
|
Party keyedCounterparty = getServiceHub().getNetworkMapCache().getNodeByLegalIdentityKey(dummyPubKey).getLegalIdentity();
|
||||||
Party firstCounterparty = getServiceHub().getNetworkMapCache().getPartyNodes().get(0).getLegalIdentity();
|
Party firstCounterparty = getServiceHub().getNetworkMapCache().getPartyNodes().get(0).getLegalIdentity();
|
||||||
// DOCEND 2
|
// DOCEND 2
|
||||||
|
@ -7,6 +7,7 @@ import net.corda.core.contracts.*
|
|||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
import net.corda.core.crypto.TransactionSignature
|
import net.corda.core.crypto.TransactionSignature
|
||||||
import net.corda.core.flows.*
|
import net.corda.core.flows.*
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.internal.FetchDataFlow
|
import net.corda.core.internal.FetchDataFlow
|
||||||
import net.corda.core.node.services.ServiceType
|
import net.corda.core.node.services.ServiceType
|
||||||
@ -103,7 +104,7 @@ object FlowCookbook {
|
|||||||
// - To serve as a timestamping authority if the transaction has a time-window
|
// - To serve as a timestamping authority if the transaction has a time-window
|
||||||
// We retrieve the notary from the network map.
|
// We retrieve the notary from the network map.
|
||||||
// DOCSTART 1
|
// DOCSTART 1
|
||||||
val specificNotary: Party? = serviceHub.networkMapCache.getNotary(getX500Name(O = "Notary Service", OU = "corda", L = "London", C = "UK"))
|
val specificNotary: Party? = serviceHub.networkMapCache.getNotary(CordaX500Name(organisation = "Notary Service", locality = "London", country = "UK"))
|
||||||
val anyNotary: Party? = serviceHub.networkMapCache.getAnyNotary()
|
val anyNotary: Party? = serviceHub.networkMapCache.getAnyNotary()
|
||||||
// Unlike the first two methods, ``getNotaryNodes`` returns a
|
// Unlike the first two methods, ``getNotaryNodes`` returns a
|
||||||
// ``List<NodeInfo>``. We have to extract the notary identity of
|
// ``List<NodeInfo>``. We have to extract the notary identity of
|
||||||
@ -114,7 +115,7 @@ object FlowCookbook {
|
|||||||
// We may also need to identify a specific counterparty. Again, we
|
// We may also need to identify a specific counterparty. Again, we
|
||||||
// do so using the network map.
|
// do so using the network map.
|
||||||
// DOCSTART 2
|
// DOCSTART 2
|
||||||
val namedCounterparty: Party? = serviceHub.networkMapCache.getNodeByLegalName(getX500Name(O = "NodeA", L = "London", C = "UK"))?.legalIdentity
|
val namedCounterparty: Party? = serviceHub.networkMapCache.getNodeByLegalName(CordaX500Name(organisation = "NodeA", locality = "London", country = "UK"))?.legalIdentity
|
||||||
val keyedCounterparty: Party? = serviceHub.networkMapCache.getNodeByLegalIdentityKey(dummyPubKey)?.legalIdentity
|
val keyedCounterparty: Party? = serviceHub.networkMapCache.getNodeByLegalIdentityKey(dummyPubKey)?.legalIdentity
|
||||||
val firstCounterparty: Party = serviceHub.networkMapCache.partyNodes[0].legalIdentity
|
val firstCounterparty: Party = serviceHub.networkMapCache.partyNodes[0].legalIdentity
|
||||||
// DOCEND 2
|
// DOCEND 2
|
||||||
|
@ -9,6 +9,7 @@ import net.corda.core.contracts.Amount.Companion.sumOrThrow
|
|||||||
import net.corda.core.crypto.NullKeys.NULL_PARTY
|
import net.corda.core.crypto.NullKeys.NULL_PARTY
|
||||||
import net.corda.core.crypto.entropyToKeyPair
|
import net.corda.core.crypto.entropyToKeyPair
|
||||||
import net.corda.core.identity.AbstractParty
|
import net.corda.core.identity.AbstractParty
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.internal.Emoji
|
import net.corda.core.internal.Emoji
|
||||||
import net.corda.core.node.ServiceHub
|
import net.corda.core.node.ServiceHub
|
||||||
@ -18,7 +19,6 @@ import net.corda.core.schemas.QueryableState
|
|||||||
import net.corda.core.transactions.LedgerTransaction
|
import net.corda.core.transactions.LedgerTransaction
|
||||||
import net.corda.core.transactions.TransactionBuilder
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
import net.corda.core.utilities.OpaqueBytes
|
import net.corda.core.utilities.OpaqueBytes
|
||||||
import net.corda.core.utilities.getX500Name
|
|
||||||
import net.corda.core.utilities.toBase58String
|
import net.corda.core.utilities.toBase58String
|
||||||
import net.corda.finance.contracts.asset.cash.selection.CashSelectionH2Impl
|
import net.corda.finance.contracts.asset.cash.selection.CashSelectionH2Impl
|
||||||
import net.corda.finance.schemas.CashSchemaV1
|
import net.corda.finance.schemas.CashSchemaV1
|
||||||
@ -346,7 +346,7 @@ class Cash : OnLedgerAsset<Currency, Cash.Commands, Cash.State>() {
|
|||||||
/** A randomly generated key. */
|
/** A randomly generated key. */
|
||||||
val DUMMY_CASH_ISSUER_KEY by lazy { entropyToKeyPair(BigInteger.valueOf(10)) }
|
val DUMMY_CASH_ISSUER_KEY by lazy { entropyToKeyPair(BigInteger.valueOf(10)) }
|
||||||
/** A dummy, randomly generated issuer party by the name of "Snake Oil Issuer" */
|
/** A dummy, randomly generated issuer party by the name of "Snake Oil Issuer" */
|
||||||
val DUMMY_CASH_ISSUER by lazy { Party(getX500Name(O = "Snake Oil Issuer", OU = "corda", L = "London", C = "GB"), DUMMY_CASH_ISSUER_KEY.public).ref(1) }
|
val DUMMY_CASH_ISSUER by lazy { Party(CordaX500Name(organisation = "Snake Oil Issuer", locality = "London", country = "GB"), DUMMY_CASH_ISSUER_KEY.public).ref(1) }
|
||||||
/** An extension property that lets you write 100.DOLLARS.CASH */
|
/** An extension property that lets you write 100.DOLLARS.CASH */
|
||||||
val Amount<Currency>.CASH: Cash.State get() = Cash.State(Amount(quantity, Issued(DUMMY_CASH_ISSUER, token)), NULL_PARTY)
|
val Amount<Currency>.CASH: Cash.State get() = Cash.State(Amount(quantity, Issued(DUMMY_CASH_ISSUER, token)), NULL_PARTY)
|
||||||
/** An extension property that lets you get a cash state from an issued token, under the [NULL_PARTY] */
|
/** An extension property that lets you get a cash state from an issued token, under the [NULL_PARTY] */
|
||||||
|
@ -9,6 +9,7 @@ import net.corda.core.crypto.SecureHash
|
|||||||
import net.corda.core.crypto.entropyToKeyPair
|
import net.corda.core.crypto.entropyToKeyPair
|
||||||
import net.corda.core.identity.AbstractParty
|
import net.corda.core.identity.AbstractParty
|
||||||
import net.corda.core.identity.AnonymousParty
|
import net.corda.core.identity.AnonymousParty
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.internal.Emoji
|
import net.corda.core.internal.Emoji
|
||||||
import net.corda.core.internal.VisibleForTesting
|
import net.corda.core.internal.VisibleForTesting
|
||||||
@ -16,7 +17,6 @@ import net.corda.core.serialization.CordaSerializable
|
|||||||
import net.corda.core.transactions.LedgerTransaction
|
import net.corda.core.transactions.LedgerTransaction
|
||||||
import net.corda.core.transactions.TransactionBuilder
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
import net.corda.core.utilities.NonEmptySet
|
import net.corda.core.utilities.NonEmptySet
|
||||||
import net.corda.core.utilities.getX500Name
|
|
||||||
import net.corda.core.utilities.seconds
|
import net.corda.core.utilities.seconds
|
||||||
import net.corda.finance.utils.sumFungibleOrNull
|
import net.corda.finance.utils.sumFungibleOrNull
|
||||||
import net.corda.finance.utils.sumObligations
|
import net.corda.finance.utils.sumObligations
|
||||||
@ -792,4 +792,4 @@ infix fun <T : Any> Obligation.State<T>.`issued by`(party: AbstractParty) = copy
|
|||||||
/** A randomly generated key. */
|
/** A randomly generated key. */
|
||||||
val DUMMY_OBLIGATION_ISSUER_KEY by lazy { entropyToKeyPair(BigInteger.valueOf(10)) }
|
val DUMMY_OBLIGATION_ISSUER_KEY by lazy { entropyToKeyPair(BigInteger.valueOf(10)) }
|
||||||
/** A dummy, randomly generated issuer party by the name of "Snake Oil Issuer" */
|
/** A dummy, randomly generated issuer party by the name of "Snake Oil Issuer" */
|
||||||
val DUMMY_OBLIGATION_ISSUER by lazy { Party(getX500Name(O = "Snake Oil Issuer", OU = "corda", L = "London", C = "GB"), DUMMY_OBLIGATION_ISSUER_KEY.public) }
|
val DUMMY_OBLIGATION_ISSUER by lazy { Party(CordaX500Name(organisation = "Snake Oil Issuer", locality = "London", country = "GB"), DUMMY_OBLIGATION_ISSUER_KEY.public) }
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package net.corda.nodeapi
|
package net.corda.nodeapi
|
||||||
|
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
import net.corda.nodeapi.config.SSLConfiguration
|
import net.corda.nodeapi.config.SSLConfiguration
|
||||||
import org.apache.activemq.artemis.api.core.TransportConfiguration
|
import org.apache.activemq.artemis.api.core.TransportConfiguration
|
||||||
@ -12,7 +13,7 @@ import java.nio.file.Path
|
|||||||
sealed class ConnectionDirection {
|
sealed class ConnectionDirection {
|
||||||
data class Inbound(val acceptorFactoryClassName: String) : ConnectionDirection()
|
data class Inbound(val acceptorFactoryClassName: String) : ConnectionDirection()
|
||||||
data class Outbound(
|
data class Outbound(
|
||||||
val expectedCommonName: X500Name? = null,
|
val expectedCommonName: CordaX500Name? = null,
|
||||||
val connectorFactoryClassName: String = NettyConnectorFactory::class.java.name
|
val connectorFactoryClassName: String = NettyConnectorFactory::class.java.name
|
||||||
) : ConnectionDirection()
|
) : ConnectionDirection()
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,10 @@ package net.corda.nodeapi.config
|
|||||||
|
|
||||||
import com.typesafe.config.Config
|
import com.typesafe.config.Config
|
||||||
import com.typesafe.config.ConfigUtil
|
import com.typesafe.config.ConfigUtil
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.internal.noneOrSingle
|
import net.corda.core.internal.noneOrSingle
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
import net.corda.core.utilities.parseNetworkHostAndPort
|
import net.corda.core.utilities.parseNetworkHostAndPort
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import java.net.Proxy
|
import java.net.Proxy
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
@ -72,7 +72,7 @@ private fun Config.getSingleValue(path: String, type: KType): Any? {
|
|||||||
Path::class -> Paths.get(getString(path))
|
Path::class -> Paths.get(getString(path))
|
||||||
URL::class -> URL(getString(path))
|
URL::class -> URL(getString(path))
|
||||||
Properties::class -> getConfig(path).toProperties()
|
Properties::class -> getConfig(path).toProperties()
|
||||||
X500Name::class -> X500Name(getString(path))
|
CordaX500Name::class -> CordaX500Name.parse(getString(path))
|
||||||
else -> if (typeClass.java.isEnum) {
|
else -> if (typeClass.java.isEnum) {
|
||||||
parseEnum(typeClass.java, getString(path))
|
parseEnum(typeClass.java, getString(path))
|
||||||
} else {
|
} else {
|
||||||
@ -99,7 +99,7 @@ private fun Config.getCollectionValue(path: String, type: KType): Collection<Any
|
|||||||
NetworkHostAndPort::class -> getStringList(path).map { it.parseNetworkHostAndPort() }
|
NetworkHostAndPort::class -> getStringList(path).map { it.parseNetworkHostAndPort() }
|
||||||
Path::class -> getStringList(path).map { Paths.get(it) }
|
Path::class -> getStringList(path).map { Paths.get(it) }
|
||||||
URL::class -> getStringList(path).map(::URL)
|
URL::class -> getStringList(path).map(::URL)
|
||||||
X500Name::class -> getStringList(path).map(::X500Name)
|
CordaX500Name::class -> getStringList(path).map(CordaX500Name.Companion::parse)
|
||||||
Properties::class -> getConfigList(path).map(Config::toProperties)
|
Properties::class -> getConfigList(path).map(Config::toProperties)
|
||||||
else -> if (elementClass.java.isEnum) {
|
else -> if (elementClass.java.isEnum) {
|
||||||
getStringList(path).map { parseEnum(elementClass.java, it) }
|
getStringList(path).map { parseEnum(elementClass.java, it) }
|
||||||
|
@ -4,11 +4,10 @@ import com.typesafe.config.Config
|
|||||||
import com.typesafe.config.ConfigFactory.empty
|
import com.typesafe.config.ConfigFactory.empty
|
||||||
import com.typesafe.config.ConfigRenderOptions.defaults
|
import com.typesafe.config.ConfigRenderOptions.defaults
|
||||||
import com.typesafe.config.ConfigValueFactory
|
import com.typesafe.config.ConfigValueFactory
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
import net.corda.core.utilities.getX500Name
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
@ -112,7 +111,7 @@ class ConfigParsingTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun x500Name() {
|
fun x500Name() {
|
||||||
testPropertyType<X500NameData, X500NameListData, X500Name>(getX500Name(O = "Mock Party", L = "London", C = "GB"), getX500Name(O = "Mock Party 2", L = "London", C = "GB"), valuesToString = true)
|
testPropertyType<X500NameData, X500NameListData, CordaX500Name>(CordaX500Name(organisation = "Mock Party", locality = "London", country = "GB"), CordaX500Name(organisation = "Mock Party 2", locality = "London", country = "GB"), valuesToString = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -229,8 +228,8 @@ class ConfigParsingTest {
|
|||||||
data class PathListData(override val values: List<Path>) : ListData<Path>
|
data class PathListData(override val values: List<Path>) : ListData<Path>
|
||||||
data class URLData(override val value: URL) : SingleData<URL>
|
data class URLData(override val value: URL) : SingleData<URL>
|
||||||
data class URLListData(override val values: List<URL>) : ListData<URL>
|
data class URLListData(override val values: List<URL>) : ListData<URL>
|
||||||
data class X500NameData(override val value: X500Name) : SingleData<X500Name>
|
data class X500NameData(override val value: CordaX500Name) : SingleData<CordaX500Name>
|
||||||
data class X500NameListData(override val values: List<X500Name>) : ListData<X500Name>
|
data class X500NameListData(override val values: List<CordaX500Name>) : ListData<CordaX500Name>
|
||||||
data class PropertiesData(override val value: Properties) : SingleData<Properties>
|
data class PropertiesData(override val value: Properties) : SingleData<Properties>
|
||||||
data class PropertiesListData(override val values: List<Properties>) : ListData<Properties>
|
data class PropertiesListData(override val values: List<Properties>) : ListData<Properties>
|
||||||
data class MultiPropertyData(val i: Int, val b: Boolean, val l: List<String>)
|
data class MultiPropertyData(val i: Int, val b: Boolean, val l: List<String>)
|
||||||
|
@ -3,10 +3,10 @@ package net.corda.node.services
|
|||||||
import co.paralleluniverse.fibers.Suspendable
|
import co.paralleluniverse.fibers.Suspendable
|
||||||
import net.corda.core.flows.FlowLogic
|
import net.corda.core.flows.FlowLogic
|
||||||
import net.corda.core.flows.StartableByRPC
|
import net.corda.core.flows.StartableByRPC
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.messaging.startFlow
|
import net.corda.core.messaging.startFlow
|
||||||
import net.corda.core.node.services.ServiceInfo
|
import net.corda.core.node.services.ServiceInfo
|
||||||
import net.corda.core.node.services.ServiceType
|
import net.corda.core.node.services.ServiceType
|
||||||
import net.corda.core.utilities.getX500Name
|
|
||||||
import net.corda.node.services.FlowPermissions.Companion.startFlowPermission
|
import net.corda.node.services.FlowPermissions.Companion.startFlowPermission
|
||||||
import net.corda.nodeapi.User
|
import net.corda.nodeapi.User
|
||||||
import net.corda.testing.driver.driver
|
import net.corda.testing.driver.driver
|
||||||
@ -14,7 +14,7 @@ import org.junit.Test
|
|||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
class AdvertisedServiceTests {
|
class AdvertisedServiceTests {
|
||||||
private val serviceName = getX500Name(O = "Custom Service", OU = "corda", L = "London", C = "GB")
|
private val serviceName = CordaX500Name(organisation = "Custom Service", locality = "London", country = "GB")
|
||||||
private val serviceType = ServiceType.corda.getSubType("custom")
|
private val serviceType = ServiceType.corda.getSubType("custom")
|
||||||
private val user = "bankA"
|
private val user = "bankA"
|
||||||
private val pass = "passA"
|
private val pass = "passA"
|
||||||
|
@ -7,6 +7,7 @@ import net.corda.core.crypto.CompositeKey
|
|||||||
import net.corda.core.flows.NotaryError
|
import net.corda.core.flows.NotaryError
|
||||||
import net.corda.core.flows.NotaryException
|
import net.corda.core.flows.NotaryException
|
||||||
import net.corda.core.flows.NotaryFlow
|
import net.corda.core.flows.NotaryFlow
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
import net.corda.core.node.services.ServiceInfo
|
import net.corda.core.node.services.ServiceInfo
|
||||||
@ -15,7 +16,6 @@ import net.corda.core.transactions.TransactionBuilder
|
|||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
import net.corda.core.utilities.Try
|
import net.corda.core.utilities.Try
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.core.utilities.getX500Name
|
|
||||||
import net.corda.node.internal.AbstractNode
|
import net.corda.node.internal.AbstractNode
|
||||||
import net.corda.node.services.config.BFTSMaRtConfiguration
|
import net.corda.node.services.config.BFTSMaRtConfiguration
|
||||||
import net.corda.node.services.network.NetworkMapService
|
import net.corda.node.services.network.NetworkMapService
|
||||||
@ -35,7 +35,7 @@ import kotlin.test.assertTrue
|
|||||||
|
|
||||||
class BFTNotaryServiceTests {
|
class BFTNotaryServiceTests {
|
||||||
companion object {
|
companion object {
|
||||||
private val clusterName = getX500Name(O = "BFT", OU = "corda", L = "Zurich", C = "CH")
|
private val clusterName = CordaX500Name(organisation = "BFT", locality = "Zurich", country = "CH")
|
||||||
private val serviceType = BFTNonValidatingNotaryService.type
|
private val serviceType = BFTNonValidatingNotaryService.type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,12 +5,12 @@ import net.corda.core.contracts.StateRef
|
|||||||
import net.corda.core.flows.NotaryError
|
import net.corda.core.flows.NotaryError
|
||||||
import net.corda.core.flows.NotaryException
|
import net.corda.core.flows.NotaryException
|
||||||
import net.corda.core.flows.NotaryFlow
|
import net.corda.core.flows.NotaryFlow
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.internal.concurrent.map
|
import net.corda.core.internal.concurrent.map
|
||||||
import net.corda.core.internal.concurrent.transpose
|
import net.corda.core.internal.concurrent.transpose
|
||||||
import net.corda.core.transactions.TransactionBuilder
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.core.utilities.getX500Name
|
|
||||||
import net.corda.node.internal.AbstractNode
|
import net.corda.node.internal.AbstractNode
|
||||||
import net.corda.testing.DUMMY_BANK_A
|
import net.corda.testing.DUMMY_BANK_A
|
||||||
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
|
import net.corda.testing.contracts.DUMMY_PROGRAM_ID
|
||||||
@ -23,7 +23,7 @@ import kotlin.test.assertEquals
|
|||||||
import kotlin.test.assertFailsWith
|
import kotlin.test.assertFailsWith
|
||||||
|
|
||||||
class RaftNotaryServiceTests : NodeBasedTest() {
|
class RaftNotaryServiceTests : NodeBasedTest() {
|
||||||
private val notaryName = getX500Name(O = "RAFT Notary Service", OU = "corda", L = "London", C = "GB")
|
private val notaryName = CordaX500Name(organisation = "RAFT Notary Service", locality = "London", country = "GB")
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `detect double spend`() {
|
fun `detect double spend`() {
|
||||||
|
@ -103,7 +103,7 @@ class MQSecurityAsNodeTest : MQSecurityTest() {
|
|||||||
val clientKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
val clientKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||||
|
|
||||||
// Set name constrain to the legal name.
|
// Set name constrain to the legal name.
|
||||||
val nameConstraints = NameConstraints(arrayOf(GeneralSubtree(GeneralName(GeneralName.directoryName, legalName))), arrayOf())
|
val nameConstraints = NameConstraints(arrayOf(GeneralSubtree(GeneralName(GeneralName.directoryName, legalName.x500Name))), arrayOf())
|
||||||
val clientCACert = X509Utilities.createCertificate(CertificateType.INTERMEDIATE_CA, intermediateCA.certificate,
|
val clientCACert = X509Utilities.createCertificate(CertificateType.INTERMEDIATE_CA, intermediateCA.certificate,
|
||||||
intermediateCA.keyPair, legalName, clientKey.public, nameConstraints = nameConstraints)
|
intermediateCA.keyPair, legalName, clientKey.public, nameConstraints = nameConstraints)
|
||||||
val tlsKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
val tlsKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||||
|
@ -2,6 +2,7 @@ package net.corda.services.messaging
|
|||||||
|
|
||||||
import net.corda.core.concurrent.CordaFuture
|
import net.corda.core.concurrent.CordaFuture
|
||||||
import net.corda.core.crypto.random63BitValue
|
import net.corda.core.crypto.random63BitValue
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.internal.concurrent.transpose
|
import net.corda.core.internal.concurrent.transpose
|
||||||
import net.corda.core.internal.elapsedTime
|
import net.corda.core.internal.elapsedTime
|
||||||
import net.corda.core.internal.times
|
import net.corda.core.internal.times
|
||||||
@ -12,7 +13,6 @@ import net.corda.core.serialization.CordaSerializable
|
|||||||
import net.corda.core.serialization.deserialize
|
import net.corda.core.serialization.deserialize
|
||||||
import net.corda.core.serialization.serialize
|
import net.corda.core.serialization.serialize
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.core.utilities.getX500Name
|
|
||||||
import net.corda.core.utilities.seconds
|
import net.corda.core.utilities.seconds
|
||||||
import net.corda.node.internal.Node
|
import net.corda.node.internal.Node
|
||||||
import net.corda.node.services.messaging.*
|
import net.corda.node.services.messaging.*
|
||||||
@ -22,7 +22,6 @@ import net.corda.node.utilities.ServiceIdentityGenerator
|
|||||||
import net.corda.testing.*
|
import net.corda.testing.*
|
||||||
import net.corda.testing.node.NodeBasedTest
|
import net.corda.testing.node.NodeBasedTest
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.CountDownLatch
|
import java.util.concurrent.CountDownLatch
|
||||||
@ -31,8 +30,8 @@ import java.util.concurrent.atomic.AtomicInteger
|
|||||||
|
|
||||||
class P2PMessagingTest : NodeBasedTest() {
|
class P2PMessagingTest : NodeBasedTest() {
|
||||||
private companion object {
|
private companion object {
|
||||||
val DISTRIBUTED_SERVICE_NAME = getX500Name(O = "DistributedService", L = "London", C = "GB")
|
val DISTRIBUTED_SERVICE_NAME = CordaX500Name(organisation = "DistributedService", locality = "London", country = "GB")
|
||||||
val SERVICE_2_NAME = getX500Name(O = "Service 2", L = "London", C = "GB")
|
val SERVICE_2_NAME = CordaX500Name(organisation = "Service 2", locality = "London", country = "GB")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -65,7 +64,7 @@ class P2PMessagingTest : NodeBasedTest() {
|
|||||||
@Test
|
@Test
|
||||||
fun `communicating with a distributed service which the network map node is part of`() {
|
fun `communicating with a distributed service which the network map node is part of`() {
|
||||||
ServiceIdentityGenerator.generateToDisk(
|
ServiceIdentityGenerator.generateToDisk(
|
||||||
listOf(DUMMY_MAP.name, SERVICE_2_NAME).map { baseDirectory(it) },
|
listOf(DUMMY_MAP.name, SERVICE_2_NAME).map { baseDirectory(it.x500Name) },
|
||||||
RaftValidatingNotaryService.type.id,
|
RaftValidatingNotaryService.type.id,
|
||||||
DISTRIBUTED_SERVICE_NAME)
|
DISTRIBUTED_SERVICE_NAME)
|
||||||
|
|
||||||
@ -204,7 +203,7 @@ class P2PMessagingTest : NodeBasedTest() {
|
|||||||
return crashingNodes
|
return crashingNodes
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun assertAllNodesAreUsed(participatingServiceNodes: List<Node>, serviceName: X500Name, originatingNode: Node) {
|
private fun assertAllNodesAreUsed(participatingServiceNodes: List<Node>, serviceName: CordaX500Name, originatingNode: Node) {
|
||||||
// Setup each node in the distributed service to return back it's NodeInfo so that we can know which node is being used
|
// Setup each node in the distributed service to return back it's NodeInfo so that we can know which node is being used
|
||||||
participatingServiceNodes.forEach { node ->
|
participatingServiceNodes.forEach { node ->
|
||||||
node.respondWith(node.info)
|
node.respondWith(node.info)
|
||||||
|
@ -3,6 +3,7 @@ package net.corda.services.messaging
|
|||||||
import com.nhaarman.mockito_kotlin.whenever
|
import com.nhaarman.mockito_kotlin.whenever
|
||||||
import net.corda.core.concurrent.CordaFuture
|
import net.corda.core.concurrent.CordaFuture
|
||||||
import net.corda.core.crypto.random63BitValue
|
import net.corda.core.crypto.random63BitValue
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.node.NodeInfo
|
import net.corda.core.node.NodeInfo
|
||||||
import net.corda.core.utilities.*
|
import net.corda.core.utilities.*
|
||||||
import net.corda.node.internal.NetworkMapInfo
|
import net.corda.node.internal.NetworkMapInfo
|
||||||
@ -17,7 +18,6 @@ import net.corda.testing.node.NodeBasedTest
|
|||||||
import net.corda.testing.node.SimpleNode
|
import net.corda.testing.node.SimpleNode
|
||||||
import org.assertj.core.api.Assertions.assertThatExceptionOfType
|
import org.assertj.core.api.Assertions.assertThatExceptionOfType
|
||||||
import org.assertj.core.api.Assertions.assertThatThrownBy
|
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.security.cert.X509Certificate
|
import java.security.cert.X509Certificate
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
@ -51,10 +51,10 @@ class P2PSecurityTest : NodeBasedTest() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun startSimpleNode(legalName: X500Name,
|
private fun startSimpleNode(legalName: CordaX500Name,
|
||||||
trustRoot: X509Certificate): SimpleNode {
|
trustRoot: X509Certificate): SimpleNode {
|
||||||
val config = testNodeConfiguration(
|
val config = testNodeConfiguration(
|
||||||
baseDirectory = baseDirectory(legalName),
|
baseDirectory = baseDirectory(legalName.x500Name),
|
||||||
myLegalName = legalName).also {
|
myLegalName = legalName).also {
|
||||||
whenever(it.networkMapService).thenReturn(NetworkMapInfo(networkMapNode.configuration.p2pAddress, networkMapNode.info.legalIdentity.name))
|
whenever(it.networkMapService).thenReturn(NetworkMapInfo(networkMapNode.configuration.p2pAddress, networkMapNode.info.legalIdentity.name))
|
||||||
}
|
}
|
||||||
@ -62,7 +62,7 @@ class P2PSecurityTest : NodeBasedTest() {
|
|||||||
return SimpleNode(config, trustRoot = trustRoot).apply { start() }
|
return SimpleNode(config, trustRoot = trustRoot).apply { start() }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun SimpleNode.registerWithNetworkMap(registrationName: X500Name): CordaFuture<NetworkMapService.RegistrationResponse> {
|
private fun SimpleNode.registerWithNetworkMap(registrationName: CordaX500Name): CordaFuture<NetworkMapService.RegistrationResponse> {
|
||||||
val legalIdentity = getTestPartyAndCertificate(registrationName, identity.public)
|
val legalIdentity = getTestPartyAndCertificate(registrationName, identity.public)
|
||||||
val nodeInfo = NodeInfo(listOf(MOCK_HOST_AND_PORT), legalIdentity, NonEmptySet.of(legalIdentity), 1, serial = 1)
|
val nodeInfo = NodeInfo(listOf(MOCK_HOST_AND_PORT), legalIdentity, NonEmptySet.of(legalIdentity), 1, serial = 1)
|
||||||
val registration = NodeRegistration(nodeInfo, System.currentTimeMillis(), AddOrRemove.ADD, Instant.MAX)
|
val registration = NodeRegistration(nodeInfo, System.currentTimeMillis(), AddOrRemove.ADD, Instant.MAX)
|
||||||
|
@ -10,6 +10,7 @@ import net.corda.core.concurrent.CordaFuture
|
|||||||
import net.corda.core.crypto.*
|
import net.corda.core.crypto.*
|
||||||
import net.corda.core.flows.*
|
import net.corda.core.flows.*
|
||||||
import net.corda.core.flows.ContractUpgradeFlow.Acceptor
|
import net.corda.core.flows.ContractUpgradeFlow.Acceptor
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.identity.PartyAndCertificate
|
import net.corda.core.identity.PartyAndCertificate
|
||||||
import net.corda.core.internal.*
|
import net.corda.core.internal.*
|
||||||
@ -28,7 +29,9 @@ import net.corda.core.node.services.NetworkMapCache.MapChange
|
|||||||
import net.corda.core.serialization.SerializeAsToken
|
import net.corda.core.serialization.SerializeAsToken
|
||||||
import net.corda.core.serialization.SingletonSerializeAsToken
|
import net.corda.core.serialization.SingletonSerializeAsToken
|
||||||
import net.corda.core.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
import net.corda.core.utilities.*
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
|
import net.corda.core.utilities.cert
|
||||||
|
import net.corda.core.utilities.debug
|
||||||
import net.corda.node.services.NotaryChangeHandler
|
import net.corda.node.services.NotaryChangeHandler
|
||||||
import net.corda.node.services.NotifyTransactionHandler
|
import net.corda.node.services.NotifyTransactionHandler
|
||||||
import net.corda.node.services.TransactionKeyHandler
|
import net.corda.node.services.TransactionKeyHandler
|
||||||
@ -65,7 +68,6 @@ import net.corda.node.services.vault.VaultSoftLockManager
|
|||||||
import net.corda.node.utilities.*
|
import net.corda.node.utilities.*
|
||||||
import net.corda.node.utilities.AddOrRemove.ADD
|
import net.corda.node.utilities.AddOrRemove.ADD
|
||||||
import org.apache.activemq.artemis.utils.ReusableLatch
|
import org.apache.activemq.artemis.utils.ReusableLatch
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import org.slf4j.Logger
|
import org.slf4j.Logger
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
@ -148,8 +150,9 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
|
|||||||
val nodeReadyFuture: CordaFuture<Unit>
|
val nodeReadyFuture: CordaFuture<Unit>
|
||||||
get() = _nodeReadyFuture
|
get() = _nodeReadyFuture
|
||||||
|
|
||||||
protected val myLegalName: X500Name by lazy {
|
protected val myLegalName: CordaX500Name by lazy {
|
||||||
loadKeyStore(configuration.nodeKeystore, configuration.keyStorePassword).getX509Certificate(X509Utilities.CORDA_CLIENT_CA).subject.withCommonName(null)
|
val cert = loadKeyStore(configuration.nodeKeystore, configuration.keyStorePassword).getX509Certificate(X509Utilities.CORDA_CLIENT_CA)
|
||||||
|
CordaX500Name.build(cert.subject).copy(commonName = null)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Fetch CordaPluginRegistry classes registered in META-INF/services/net.corda.core.node.CordaPluginRegistry files that exist in the classpath */
|
/** Fetch CordaPluginRegistry classes registered in META-INF/services/net.corda.core.node.CordaPluginRegistry files that exist in the classpath */
|
||||||
@ -693,9 +696,9 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
|
|||||||
|
|
||||||
val (id, name) = if (serviceInfo == null) {
|
val (id, name) = if (serviceInfo == null) {
|
||||||
// Create node identity if service info = null
|
// Create node identity if service info = null
|
||||||
Pair("identity", myLegalName.withCommonName(null))
|
Pair("identity", myLegalName.copy(commonName = null))
|
||||||
} else {
|
} else {
|
||||||
val name = serviceInfo.name ?: myLegalName.withCommonName(serviceInfo.type.id)
|
val name = serviceInfo.name ?: myLegalName.copy(commonName = serviceInfo.type.id)
|
||||||
Pair(serviceInfo.type.id, name)
|
Pair(serviceInfo.type.id, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -735,14 +738,14 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
|
|||||||
}
|
}
|
||||||
|
|
||||||
val subject = certificates[0].toX509CertHolder().subject
|
val subject = certificates[0].toX509CertHolder().subject
|
||||||
if (subject != name)
|
if (subject != name.x500Name)
|
||||||
throw ConfigurationException("The name for $id doesn't match what's in the key store: $name vs $subject")
|
throw ConfigurationException("The name for $id doesn't match what's in the key store: $name vs $subject")
|
||||||
|
|
||||||
partyKeys += keys
|
partyKeys += keys
|
||||||
return PartyAndCertificate(CertificateFactory.getInstance("X509").generateCertPath(certificates))
|
return PartyAndCertificate(CertificateFactory.getInstance("X509").generateCertPath(certificates))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun migrateKeysFromFile(keyStore: KeyStoreWrapper, serviceName: X500Name,
|
private fun migrateKeysFromFile(keyStore: KeyStoreWrapper, serviceName: CordaX500Name,
|
||||||
pubKeyFile: Path, privKeyFile: Path, compositeKeyFile:Path,
|
pubKeyFile: Path, privKeyFile: Path, compositeKeyFile:Path,
|
||||||
privateKeyAlias: String, compositeKeyAlias: String) {
|
privateKeyAlias: String, compositeKeyAlias: String) {
|
||||||
log.info("Migrating $privateKeyAlias from file to key store...")
|
log.info("Migrating $privateKeyAlias from file to key store...")
|
||||||
|
@ -3,13 +3,12 @@ package net.corda.node.internal
|
|||||||
import net.corda.client.rpc.notUsed
|
import net.corda.client.rpc.notUsed
|
||||||
import net.corda.core.concurrent.CordaFuture
|
import net.corda.core.concurrent.CordaFuture
|
||||||
import net.corda.core.contracts.ContractState
|
import net.corda.core.contracts.ContractState
|
||||||
import net.corda.core.contracts.StateAndRef
|
|
||||||
import net.corda.core.contracts.UpgradedContract
|
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
import net.corda.core.flows.FlowInitiator
|
import net.corda.core.flows.FlowInitiator
|
||||||
import net.corda.core.flows.FlowLogic
|
import net.corda.core.flows.FlowLogic
|
||||||
import net.corda.core.flows.StartableByRPC
|
import net.corda.core.flows.StartableByRPC
|
||||||
import net.corda.core.identity.AbstractParty
|
import net.corda.core.identity.AbstractParty
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.messaging.*
|
import net.corda.core.messaging.*
|
||||||
import net.corda.core.node.NodeInfo
|
import net.corda.core.node.NodeInfo
|
||||||
@ -26,7 +25,6 @@ import net.corda.node.services.messaging.requirePermission
|
|||||||
import net.corda.node.services.statemachine.FlowStateMachineImpl
|
import net.corda.node.services.statemachine.FlowStateMachineImpl
|
||||||
import net.corda.node.services.statemachine.StateMachineManager
|
import net.corda.node.services.statemachine.StateMachineManager
|
||||||
import net.corda.node.utilities.CordaPersistence
|
import net.corda.node.utilities.CordaPersistence
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
@ -191,7 +189,7 @@ class CordaRPCOpsImpl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun partyFromX500Name(x500Name: X500Name): Party? {
|
override fun partyFromX500Name(x500Name: CordaX500Name): Party? {
|
||||||
return database.transaction {
|
return database.transaction {
|
||||||
services.identityService.partyFromX500Name(x500Name)
|
services.identityService.partyFromX500Name(x500Name)
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package net.corda.node.internal
|
|||||||
|
|
||||||
import com.codahale.metrics.JmxReporter
|
import com.codahale.metrics.JmxReporter
|
||||||
import net.corda.core.concurrent.CordaFuture
|
import net.corda.core.concurrent.CordaFuture
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.PartyAndCertificate
|
import net.corda.core.identity.PartyAndCertificate
|
||||||
import net.corda.core.internal.concurrent.doneFuture
|
import net.corda.core.internal.concurrent.doneFuture
|
||||||
import net.corda.core.internal.concurrent.flatMap
|
import net.corda.core.internal.concurrent.flatMap
|
||||||
@ -39,7 +40,6 @@ import org.apache.activemq.artemis.api.core.ActiveMQNotConnectedException
|
|||||||
import org.apache.activemq.artemis.api.core.RoutingType
|
import org.apache.activemq.artemis.api.core.RoutingType
|
||||||
import org.apache.activemq.artemis.api.core.client.ActiveMQClient
|
import org.apache.activemq.artemis.api.core.client.ActiveMQClient
|
||||||
import org.apache.activemq.artemis.api.core.client.ClientMessage
|
import org.apache.activemq.artemis.api.core.client.ClientMessage
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import org.slf4j.Logger
|
import org.slf4j.Logger
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
@ -378,4 +378,4 @@ open class Node(override val configuration: FullNodeConfiguration,
|
|||||||
|
|
||||||
class ConfigurationException(message: String) : Exception(message)
|
class ConfigurationException(message: String) : Exception(message)
|
||||||
|
|
||||||
data class NetworkMapInfo(val address: NetworkHostAndPort, val legalName: X500Name)
|
data class NetworkMapInfo(val address: NetworkHostAndPort, val legalName: CordaX500Name)
|
||||||
|
@ -6,16 +6,14 @@ import com.typesafe.config.ConfigParseOptions
|
|||||||
import com.typesafe.config.ConfigRenderOptions
|
import com.typesafe.config.ConfigRenderOptions
|
||||||
import net.corda.core.crypto.Crypto
|
import net.corda.core.crypto.Crypto
|
||||||
import net.corda.core.crypto.SignatureScheme
|
import net.corda.core.crypto.SignatureScheme
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.internal.copyTo
|
import net.corda.core.internal.copyTo
|
||||||
import net.corda.core.internal.createDirectories
|
import net.corda.core.internal.createDirectories
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
import net.corda.core.internal.exists
|
import net.corda.core.internal.exists
|
||||||
import net.corda.core.utilities.loggerFor
|
import net.corda.core.utilities.loggerFor
|
||||||
import net.corda.core.utilities.toWellFormattedName
|
|
||||||
import net.corda.core.utilities.withCommonName
|
|
||||||
import net.corda.node.utilities.*
|
import net.corda.node.utilities.*
|
||||||
import net.corda.nodeapi.config.SSLConfiguration
|
import net.corda.nodeapi.config.SSLConfiguration
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import org.bouncycastle.asn1.x509.GeneralName
|
import org.bouncycastle.asn1.x509.GeneralName
|
||||||
import org.bouncycastle.asn1.x509.GeneralSubtree
|
import org.bouncycastle.asn1.x509.GeneralSubtree
|
||||||
import org.bouncycastle.asn1.x509.NameConstraints
|
import org.bouncycastle.asn1.x509.NameConstraints
|
||||||
@ -53,7 +51,7 @@ object ConfigHelper {
|
|||||||
*/
|
*/
|
||||||
fun NodeConfiguration.configureWithDevSSLCertificate() = configureDevKeyAndTrustStores(myLegalName)
|
fun NodeConfiguration.configureWithDevSSLCertificate() = configureDevKeyAndTrustStores(myLegalName)
|
||||||
|
|
||||||
fun SSLConfiguration.configureDevKeyAndTrustStores(myLegalName: X500Name) {
|
fun SSLConfiguration.configureDevKeyAndTrustStores(myLegalName: CordaX500Name) {
|
||||||
certificatesDirectory.createDirectories()
|
certificatesDirectory.createDirectories()
|
||||||
if (!trustStoreFile.exists()) {
|
if (!trustStoreFile.exists()) {
|
||||||
javaClass.classLoader.getResourceAsStream("net/corda/node/internal/certificates/cordatruststore.jks").copyTo(trustStoreFile)
|
javaClass.classLoader.getResourceAsStream("net/corda/node/internal/certificates/cordatruststore.jks").copyTo(trustStoreFile)
|
||||||
@ -81,25 +79,25 @@ fun createKeystoreForCordaNode(sslKeyStorePath: Path,
|
|||||||
keyPassword: String,
|
keyPassword: String,
|
||||||
caKeyStore: KeyStore,
|
caKeyStore: KeyStore,
|
||||||
caKeyPassword: String,
|
caKeyPassword: String,
|
||||||
legalName: X500Name,
|
legalName: CordaX500Name,
|
||||||
signatureScheme: SignatureScheme = X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME) {
|
signatureScheme: SignatureScheme = X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME) {
|
||||||
|
|
||||||
val rootCACert = caKeyStore.getX509Certificate(X509Utilities.CORDA_ROOT_CA)
|
val rootCACert = caKeyStore.getX509Certificate(X509Utilities.CORDA_ROOT_CA)
|
||||||
val (intermediateCACert, intermediateCAKeyPair) = caKeyStore.getCertificateAndKeyPair(X509Utilities.CORDA_INTERMEDIATE_CA, caKeyPassword)
|
val (intermediateCACert, intermediateCAKeyPair) = caKeyStore.getCertificateAndKeyPair(X509Utilities.CORDA_INTERMEDIATE_CA, caKeyPassword)
|
||||||
|
|
||||||
val clientKey = Crypto.generateKeyPair(signatureScheme)
|
val clientKey = Crypto.generateKeyPair(signatureScheme)
|
||||||
val clientName = legalName.toWellFormattedName().withCommonName(null)
|
val clientName = legalName.copy(commonName = null)
|
||||||
|
|
||||||
val nameConstraints = NameConstraints(arrayOf(GeneralSubtree(GeneralName(GeneralName.directoryName, clientName))), arrayOf())
|
val nameConstraints = NameConstraints(arrayOf(GeneralSubtree(GeneralName(GeneralName.directoryName, clientName.x500Name))), arrayOf())
|
||||||
val clientCACert = X509Utilities.createCertificate(CertificateType.INTERMEDIATE_CA,
|
val clientCACert = X509Utilities.createCertificate(CertificateType.INTERMEDIATE_CA,
|
||||||
intermediateCACert,
|
intermediateCACert,
|
||||||
intermediateCAKeyPair,
|
intermediateCAKeyPair,
|
||||||
clientName.withCommonName(X509Utilities.CORDA_CLIENT_CA_CN),
|
clientName.copy(commonName = X509Utilities.CORDA_CLIENT_CA_CN).x500Name,
|
||||||
clientKey.public,
|
clientKey.public,
|
||||||
nameConstraints = nameConstraints)
|
nameConstraints = nameConstraints)
|
||||||
|
|
||||||
val tlsKey = Crypto.generateKeyPair(signatureScheme)
|
val tlsKey = Crypto.generateKeyPair(signatureScheme)
|
||||||
val clientTLSCert = X509Utilities.createCertificate(CertificateType.TLS, clientCACert, clientKey, clientName, tlsKey.public)
|
val clientTLSCert = X509Utilities.createCertificate(CertificateType.TLS, clientCACert, clientKey, clientName.x500Name, tlsKey.public)
|
||||||
|
|
||||||
val keyPass = keyPassword.toCharArray()
|
val keyPass = keyPassword.toCharArray()
|
||||||
|
|
||||||
@ -118,4 +116,4 @@ fun createKeystoreForCordaNode(sslKeyStorePath: Path,
|
|||||||
keyPass,
|
keyPass,
|
||||||
arrayOf(clientTLSCert, clientCACert, intermediateCACert, rootCACert))
|
arrayOf(clientTLSCert, clientCACert, intermediateCACert, rootCACert))
|
||||||
tlsKeystore.save(sslKeyStorePath, storePassword)
|
tlsKeystore.save(sslKeyStorePath, storePassword)
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package net.corda.node.services.config
|
package net.corda.node.services.config
|
||||||
|
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.node.services.ServiceInfo
|
import net.corda.core.node.services.ServiceInfo
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
import net.corda.node.internal.NetworkMapInfo
|
import net.corda.node.internal.NetworkMapInfo
|
||||||
@ -8,7 +9,6 @@ import net.corda.node.services.network.NetworkMapService
|
|||||||
import net.corda.nodeapi.User
|
import net.corda.nodeapi.User
|
||||||
import net.corda.nodeapi.config.NodeSSLConfiguration
|
import net.corda.nodeapi.config.NodeSSLConfiguration
|
||||||
import net.corda.nodeapi.config.OldConfig
|
import net.corda.nodeapi.config.OldConfig
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@ -21,7 +21,7 @@ data class BFTSMaRtConfiguration(val replicaId: Int, val debug: Boolean, val exp
|
|||||||
interface NodeConfiguration : NodeSSLConfiguration {
|
interface NodeConfiguration : NodeSSLConfiguration {
|
||||||
// myLegalName should be only used in the initial network registration, we should use the name from the certificate instead of this.
|
// myLegalName should be only used in the initial network registration, we should use the name from the certificate instead of this.
|
||||||
// TODO: Remove this so we don't accidentally use this identity in the code?
|
// TODO: Remove this so we don't accidentally use this identity in the code?
|
||||||
val myLegalName: X500Name
|
val myLegalName: CordaX500Name
|
||||||
val networkMapService: NetworkMapInfo?
|
val networkMapService: NetworkMapInfo?
|
||||||
val minimumPlatformVersion: Int
|
val minimumPlatformVersion: Int
|
||||||
val emailAddress: String
|
val emailAddress: String
|
||||||
@ -42,10 +42,10 @@ interface NodeConfiguration : NodeSSLConfiguration {
|
|||||||
data class FullNodeConfiguration(
|
data class FullNodeConfiguration(
|
||||||
// TODO Remove this subsitution value and use baseDirectory as the subsitution instead
|
// TODO Remove this subsitution value and use baseDirectory as the subsitution instead
|
||||||
@Deprecated(
|
@Deprecated(
|
||||||
"This is a subsitution value which points to the baseDirectory and is manually added into the config before parsing",
|
"This is a substitution value which points to the baseDirectory and is manually added into the config before parsing",
|
||||||
ReplaceWith("baseDirectory"))
|
ReplaceWith("baseDirectory"))
|
||||||
val basedir: Path,
|
val basedir: Path,
|
||||||
override val myLegalName: X500Name,
|
override val myLegalName: CordaX500Name,
|
||||||
override val emailAddress: String,
|
override val emailAddress: String,
|
||||||
override val keyStorePassword: String,
|
override val keyStorePassword: String,
|
||||||
override val trustStorePassword: String,
|
override val trustStorePassword: String,
|
||||||
|
@ -2,10 +2,7 @@ package net.corda.node.services.identity
|
|||||||
|
|
||||||
import net.corda.core.contracts.PartyAndReference
|
import net.corda.core.contracts.PartyAndReference
|
||||||
import net.corda.core.crypto.toStringShort
|
import net.corda.core.crypto.toStringShort
|
||||||
import net.corda.core.identity.AbstractParty
|
import net.corda.core.identity.*
|
||||||
import net.corda.core.identity.AnonymousParty
|
|
||||||
import net.corda.core.identity.Party
|
|
||||||
import net.corda.core.identity.PartyAndCertificate
|
|
||||||
import net.corda.core.internal.toX509CertHolder
|
import net.corda.core.internal.toX509CertHolder
|
||||||
import net.corda.core.node.services.IdentityService
|
import net.corda.core.node.services.IdentityService
|
||||||
import net.corda.core.node.services.UnknownAnonymousPartyException
|
import net.corda.core.node.services.UnknownAnonymousPartyException
|
||||||
@ -14,7 +11,6 @@ import net.corda.core.utilities.cert
|
|||||||
import net.corda.core.utilities.loggerFor
|
import net.corda.core.utilities.loggerFor
|
||||||
import net.corda.core.utilities.subject
|
import net.corda.core.utilities.subject
|
||||||
import net.corda.core.utilities.trace
|
import net.corda.core.utilities.trace
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import org.bouncycastle.cert.X509CertificateHolder
|
import org.bouncycastle.cert.X509CertificateHolder
|
||||||
import java.security.InvalidAlgorithmParameterException
|
import java.security.InvalidAlgorithmParameterException
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
@ -46,7 +42,7 @@ class InMemoryIdentityService(identities: Iterable<PartyAndCertificate> = emptyS
|
|||||||
override val trustRootHolder = trustRoot.toX509CertHolder()
|
override val trustRootHolder = trustRoot.toX509CertHolder()
|
||||||
override val trustAnchor: TrustAnchor = TrustAnchor(trustRoot, null)
|
override val trustAnchor: TrustAnchor = TrustAnchor(trustRoot, null)
|
||||||
private val keyToParties = ConcurrentHashMap<PublicKey, PartyAndCertificate>()
|
private val keyToParties = ConcurrentHashMap<PublicKey, PartyAndCertificate>()
|
||||||
private val principalToParties = ConcurrentHashMap<X500Name, PartyAndCertificate>()
|
private val principalToParties = ConcurrentHashMap<CordaX500Name, PartyAndCertificate>()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
val caCertificatesWithRoot: Set<X509Certificate> = caCertificates.toSet() + trustRoot
|
val caCertificatesWithRoot: Set<X509Certificate> = caCertificates.toSet() + trustRoot
|
||||||
@ -91,7 +87,7 @@ class InMemoryIdentityService(identities: Iterable<PartyAndCertificate> = emptyS
|
|||||||
override fun getAllIdentities(): Iterable<PartyAndCertificate> = ArrayList(keyToParties.values)
|
override fun getAllIdentities(): Iterable<PartyAndCertificate> = ArrayList(keyToParties.values)
|
||||||
|
|
||||||
override fun partyFromKey(key: PublicKey): Party? = keyToParties[key]?.party
|
override fun partyFromKey(key: PublicKey): Party? = keyToParties[key]?.party
|
||||||
override fun partyFromX500Name(principal: X500Name): Party? = principalToParties[principal]?.party
|
override fun partyFromX500Name(name: CordaX500Name): Party? = principalToParties[name]?.party
|
||||||
override fun partyFromAnonymous(party: AbstractParty): Party? {
|
override fun partyFromAnonymous(party: AbstractParty): Party? {
|
||||||
// Expand the anonymous party to a full party (i.e. has a name) if possible
|
// Expand the anonymous party to a full party (i.e. has a name) if possible
|
||||||
val candidate = party as? Party ?: keyToParties[party.owningKey]?.party
|
val candidate = party as? Party ?: keyToParties[party.owningKey]?.party
|
||||||
@ -114,7 +110,7 @@ class InMemoryIdentityService(identities: Iterable<PartyAndCertificate> = emptyS
|
|||||||
val results = LinkedHashSet<Party>()
|
val results = LinkedHashSet<Party>()
|
||||||
for ((x500name, partyAndCertificate) in principalToParties) {
|
for ((x500name, partyAndCertificate) in principalToParties) {
|
||||||
val party = partyAndCertificate.party
|
val party = partyAndCertificate.party
|
||||||
for (rdn in x500name.rdNs) {
|
for (rdn in x500name.x500Name.rdNs) {
|
||||||
val component = rdn.first.value.toString()
|
val component = rdn.first.value.toString()
|
||||||
if (exactMatch && component == query) {
|
if (exactMatch && component == query) {
|
||||||
results += party
|
results += party
|
||||||
|
@ -3,10 +3,7 @@ package net.corda.node.services.identity
|
|||||||
import net.corda.core.contracts.PartyAndReference
|
import net.corda.core.contracts.PartyAndReference
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
import net.corda.core.crypto.toStringShort
|
import net.corda.core.crypto.toStringShort
|
||||||
import net.corda.core.identity.AbstractParty
|
import net.corda.core.identity.*
|
||||||
import net.corda.core.identity.AnonymousParty
|
|
||||||
import net.corda.core.identity.Party
|
|
||||||
import net.corda.core.identity.PartyAndCertificate
|
|
||||||
import net.corda.core.internal.toX509CertHolder
|
import net.corda.core.internal.toX509CertHolder
|
||||||
import net.corda.core.node.services.IdentityService
|
import net.corda.core.node.services.IdentityService
|
||||||
import net.corda.core.node.services.UnknownAnonymousPartyException
|
import net.corda.core.node.services.UnknownAnonymousPartyException
|
||||||
@ -15,7 +12,6 @@ import net.corda.core.utilities.cert
|
|||||||
import net.corda.core.utilities.loggerFor
|
import net.corda.core.utilities.loggerFor
|
||||||
import net.corda.node.utilities.AppendOnlyPersistentMap
|
import net.corda.node.utilities.AppendOnlyPersistentMap
|
||||||
import net.corda.node.utilities.NODE_DATABASE_PREFIX
|
import net.corda.node.utilities.NODE_DATABASE_PREFIX
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import org.bouncycastle.cert.X509CertificateHolder
|
import org.bouncycastle.cert.X509CertificateHolder
|
||||||
import java.io.ByteArrayInputStream
|
import java.io.ByteArrayInputStream
|
||||||
import java.security.InvalidAlgorithmParameterException
|
import java.security.InvalidAlgorithmParameterException
|
||||||
@ -56,11 +52,11 @@ class PersistentIdentityService(identities: Iterable<PartyAndCertificate> = empt
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createX500Map(): AppendOnlyPersistentMap<X500Name, SecureHash, PersistentIdentityNames, String> {
|
fun createX500Map(): AppendOnlyPersistentMap<CordaX500Name, SecureHash, PersistentIdentityNames, String> {
|
||||||
return AppendOnlyPersistentMap(
|
return AppendOnlyPersistentMap(
|
||||||
toPersistentEntityKey = { it.toString() },
|
toPersistentEntityKey = { it.toString() },
|
||||||
fromPersistentEntity = { Pair(X500Name(it.name), SecureHash.parse(it.publicKeyHash)) },
|
fromPersistentEntity = { Pair(CordaX500Name.parse(it.name), SecureHash.parse(it.publicKeyHash)) },
|
||||||
toPersistentEntity = { key: X500Name, value: SecureHash ->
|
toPersistentEntity = { key: CordaX500Name, value: SecureHash ->
|
||||||
PersistentIdentityNames(key.toString(), value.toString())
|
PersistentIdentityNames(key.toString(), value.toString())
|
||||||
},
|
},
|
||||||
persistentEntityClass = PersistentIdentityNames::class.java
|
persistentEntityClass = PersistentIdentityNames::class.java
|
||||||
@ -134,20 +130,20 @@ class PersistentIdentityService(identities: Iterable<PartyAndCertificate> = empt
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun certificateFromKey(owningKey: PublicKey): PartyAndCertificate? = keyToParties[mapToKey(owningKey)]
|
override fun certificateFromKey(owningKey: PublicKey): PartyAndCertificate? = keyToParties[mapToKey(owningKey)]
|
||||||
private fun certificateFromX500Name(name: X500Name): PartyAndCertificate? {
|
private fun certificateFromCordaX500Name(name: CordaX500Name): PartyAndCertificate? {
|
||||||
val partyId = principalToParties[name]
|
val partyId = principalToParties[name]
|
||||||
return if (partyId != null) {
|
return if (partyId != null) {
|
||||||
keyToParties[partyId]
|
keyToParties[partyId]
|
||||||
} else null
|
} else null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun certificateFromParty(party: Party): PartyAndCertificate = certificateFromX500Name(party.name) ?: throw IllegalArgumentException("Unknown identity ${party.name}")
|
override fun certificateFromParty(party: Party): PartyAndCertificate = certificateFromCordaX500Name(party.name) ?: throw IllegalArgumentException("Unknown identity ${party.name}")
|
||||||
|
|
||||||
// We give the caller a copy of the data set to avoid any locking problems
|
// We give the caller a copy of the data set to avoid any locking problems
|
||||||
override fun getAllIdentities(): Iterable<PartyAndCertificate> = keyToParties.allPersisted().map { it.second }.asIterable()
|
override fun getAllIdentities(): Iterable<PartyAndCertificate> = keyToParties.allPersisted().map { it.second }.asIterable()
|
||||||
|
|
||||||
override fun partyFromKey(key: PublicKey): Party? = certificateFromKey(key)?.party
|
override fun partyFromKey(key: PublicKey): Party? = certificateFromKey(key)?.party
|
||||||
override fun partyFromX500Name(principal: X500Name): Party? = certificateFromX500Name(principal)?.party
|
override fun partyFromX500Name(name: CordaX500Name): Party? = certificateFromCordaX500Name(name)?.party
|
||||||
override fun partyFromAnonymous(party: AbstractParty): Party? {
|
override fun partyFromAnonymous(party: AbstractParty): Party? {
|
||||||
// Expand the anonymous party to a full party (i.e. has a name) if possible
|
// Expand the anonymous party to a full party (i.e. has a name) if possible
|
||||||
val candidate = party as? Party ?: partyFromKey(party.owningKey)
|
val candidate = party as? Party ?: partyFromKey(party.owningKey)
|
||||||
@ -172,7 +168,7 @@ class PersistentIdentityService(identities: Iterable<PartyAndCertificate> = empt
|
|||||||
val results = LinkedHashSet<Party>()
|
val results = LinkedHashSet<Party>()
|
||||||
for ((x500name, partyId) in principalToParties.allPersisted()) {
|
for ((x500name, partyId) in principalToParties.allPersisted()) {
|
||||||
val party = keyToParties[partyId]!!.party
|
val party = keyToParties[partyId]!!.party
|
||||||
for (rdn in x500name.rdNs) {
|
for (rdn in x500name.x500Name.rdNs) {
|
||||||
val component = rdn.first.value.toString()
|
val component = rdn.first.value.toString()
|
||||||
if (exactMatch && component == query) {
|
if (exactMatch && component == query) {
|
||||||
results += party
|
results += party
|
||||||
@ -200,4 +196,4 @@ class PersistentIdentityService(identities: Iterable<PartyAndCertificate> = empt
|
|||||||
"Issuing certificate's public key must match the party key ${party.owningKey.toStringShort()}."
|
"Issuing certificate's public key must match the party key ${party.owningKey.toStringShort()}."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ fun freshCertificate(identityService: IdentityService,
|
|||||||
val issuerCertificate = issuer.certificate
|
val issuerCertificate = issuer.certificate
|
||||||
val window = X509Utilities.getCertificateValidityWindow(Duration.ZERO, 3650.days, issuerCertificate)
|
val window = X509Utilities.getCertificateValidityWindow(Duration.ZERO, 3650.days, issuerCertificate)
|
||||||
val ourCertificate = X509Utilities.createCertificate(CertificateType.IDENTITY, issuerCertificate.subject,
|
val ourCertificate = X509Utilities.createCertificate(CertificateType.IDENTITY, issuerCertificate.subject,
|
||||||
issuerSigner, issuer.name, subjectPublicKey, window)
|
issuerSigner, issuer.name.x500Name, subjectPublicKey, window)
|
||||||
val certFactory = CertificateFactory.getInstance("X509")
|
val certFactory = CertificateFactory.getInstance("X509")
|
||||||
val ourCertPath = certFactory.generateCertPath(listOf(ourCertificate.cert) + issuer.certPath.certificates)
|
val ourCertPath = certFactory.generateCertPath(listOf(ourCertificate.cert) + issuer.certPath.certificates)
|
||||||
val anonymisedIdentity = PartyAndCertificate(ourCertPath)
|
val anonymisedIdentity = PartyAndCertificate(ourCertPath)
|
||||||
|
@ -5,8 +5,8 @@ import io.netty.handler.ssl.SslHandler
|
|||||||
import net.corda.core.concurrent.CordaFuture
|
import net.corda.core.concurrent.CordaFuture
|
||||||
import net.corda.core.crypto.AddressFormatException
|
import net.corda.core.crypto.AddressFormatException
|
||||||
import net.corda.core.crypto.newSecureRandom
|
import net.corda.core.crypto.newSecureRandom
|
||||||
import net.corda.core.utilities.parsePublicKeyBase58
|
|
||||||
import net.corda.core.crypto.random63BitValue
|
import net.corda.core.crypto.random63BitValue
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.internal.ThreadBox
|
import net.corda.core.internal.ThreadBox
|
||||||
import net.corda.core.internal.concurrent.openFuture
|
import net.corda.core.internal.concurrent.openFuture
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
@ -51,7 +51,6 @@ import org.apache.activemq.artemis.spi.core.security.jaas.CertificateCallback
|
|||||||
import org.apache.activemq.artemis.spi.core.security.jaas.RolePrincipal
|
import org.apache.activemq.artemis.spi.core.security.jaas.RolePrincipal
|
||||||
import org.apache.activemq.artemis.spi.core.security.jaas.UserPrincipal
|
import org.apache.activemq.artemis.spi.core.security.jaas.UserPrincipal
|
||||||
import org.apache.activemq.artemis.utils.ConfigurationHelper
|
import org.apache.activemq.artemis.utils.ConfigurationHelper
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import rx.Subscription
|
import rx.Subscription
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.math.BigInteger
|
import java.math.BigInteger
|
||||||
@ -373,7 +372,7 @@ class ArtemisMessagingServer(override val config: NodeConfiguration,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun deployBridge(address: ArtemisPeerAddress, legalName: X500Name) {
|
private fun deployBridge(address: ArtemisPeerAddress, legalName: CordaX500Name) {
|
||||||
deployBridge(address.queueName, address.hostAndPort, legalName)
|
deployBridge(address.queueName, address.hostAndPort, legalName)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -386,7 +385,7 @@ class ArtemisMessagingServer(override val config: NodeConfiguration,
|
|||||||
* as defined by ArtemisAddress.queueName. A bridge is then created to forward messages from this queue to the node's
|
* as defined by ArtemisAddress.queueName. A bridge is then created to forward messages from this queue to the node's
|
||||||
* P2P address.
|
* P2P address.
|
||||||
*/
|
*/
|
||||||
private fun deployBridge(queueName: String, target: NetworkHostAndPort, legalName: X500Name) {
|
private fun deployBridge(queueName: String, target: NetworkHostAndPort, legalName: CordaX500Name) {
|
||||||
val connectionDirection = ConnectionDirection.Outbound(
|
val connectionDirection = ConnectionDirection.Outbound(
|
||||||
connectorFactoryClassName = VerifyingNettyConnectorFactory::class.java.name,
|
connectorFactoryClassName = VerifyingNettyConnectorFactory::class.java.name,
|
||||||
expectedCommonName = legalName
|
expectedCommonName = legalName
|
||||||
@ -425,7 +424,7 @@ class ArtemisMessagingServer(override val config: NodeConfiguration,
|
|||||||
private fun getBridgeName(queueName: String, hostAndPort: NetworkHostAndPort): String = "$queueName -> $hostAndPort"
|
private fun getBridgeName(queueName: String, hostAndPort: NetworkHostAndPort): String = "$queueName -> $hostAndPort"
|
||||||
|
|
||||||
// This is called on one of Artemis' background threads
|
// This is called on one of Artemis' background threads
|
||||||
internal fun hostVerificationFail(expectedLegalName: X500Name, errorMsg: String?) {
|
internal fun hostVerificationFail(expectedLegalName: CordaX500Name, errorMsg: String?) {
|
||||||
log.error(errorMsg)
|
log.error(errorMsg)
|
||||||
if (expectedLegalName == config.networkMapService?.legalName) {
|
if (expectedLegalName == config.networkMapService?.legalName) {
|
||||||
// If the peer that failed host verification was the network map node then we're in big trouble and need to bail!
|
// If the peer that failed host verification was the network map node then we're in big trouble and need to bail!
|
||||||
@ -434,7 +433,7 @@ class ArtemisMessagingServer(override val config: NodeConfiguration,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This is called on one of Artemis' background threads
|
// This is called on one of Artemis' background threads
|
||||||
internal fun onTcpConnection(peerLegalName: X500Name) {
|
internal fun onTcpConnection(peerLegalName: CordaX500Name) {
|
||||||
if (peerLegalName == config.networkMapService?.legalName) {
|
if (peerLegalName == config.networkMapService?.legalName) {
|
||||||
_networkMapConnectionFuture!!.set(Unit)
|
_networkMapConnectionFuture!!.set(Unit)
|
||||||
}
|
}
|
||||||
@ -493,7 +492,7 @@ private class VerifyingNettyConnector(configuration: MutableMap<String, Any>,
|
|||||||
override fun createConnection(): Connection? {
|
override fun createConnection(): Connection? {
|
||||||
val connection = super.createConnection() as? NettyConnection
|
val connection = super.createConnection() as? NettyConnection
|
||||||
if (sslEnabled && connection != null) {
|
if (sslEnabled && connection != null) {
|
||||||
val expectedLegalName = configuration[ArtemisTcpTransport.VERIFY_PEER_LEGAL_NAME] as X500Name
|
val expectedLegalName = configuration[ArtemisTcpTransport.VERIFY_PEER_LEGAL_NAME] as CordaX500Name
|
||||||
try {
|
try {
|
||||||
val session = connection.channel
|
val session = connection.channel
|
||||||
.pipeline()
|
.pipeline()
|
||||||
@ -501,14 +500,14 @@ private class VerifyingNettyConnector(configuration: MutableMap<String, Any>,
|
|||||||
.engine()
|
.engine()
|
||||||
.session
|
.session
|
||||||
// Checks the peer name is the one we are expecting.
|
// Checks the peer name is the one we are expecting.
|
||||||
val peerLegalName = session.peerPrincipal.name.let(::X500Name)
|
val peerLegalName = CordaX500Name.parse(session.peerPrincipal.name)
|
||||||
require(peerLegalName == expectedLegalName) {
|
require(peerLegalName == expectedLegalName) {
|
||||||
"Peer has wrong CN - expected $expectedLegalName but got $peerLegalName. This is either a fatal " +
|
"Peer has wrong CN - expected $expectedLegalName but got $peerLegalName. This is either a fatal " +
|
||||||
"misconfiguration by the remote peer or an SSL man-in-the-middle attack!"
|
"misconfiguration by the remote peer or an SSL man-in-the-middle attack!"
|
||||||
}
|
}
|
||||||
// Make sure certificate has the same name.
|
// Make sure certificate has the same name.
|
||||||
val peerCertificate = session.peerCertificateChain[0].toX509CertHolder()
|
val peerCertificate = session.peerCertificateChain[0].toX509CertHolder()
|
||||||
require(peerCertificate.subject == expectedLegalName) {
|
require(peerCertificate.subject == expectedLegalName.x500Name) {
|
||||||
"Peer has wrong subject name in the certificate - expected $expectedLegalName but got ${peerCertificate.subject}. This is either a fatal " +
|
"Peer has wrong subject name in the certificate - expected $expectedLegalName but got ${peerCertificate.subject}. This is either a fatal " +
|
||||||
"misconfiguration by the remote peer or an SSL man-in-the-middle attack!"
|
"misconfiguration by the remote peer or an SSL man-in-the-middle attack!"
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package net.corda.node.services.messaging
|
|||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture
|
import com.google.common.util.concurrent.ListenableFuture
|
||||||
import net.corda.core.concurrent.CordaFuture
|
import net.corda.core.concurrent.CordaFuture
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.internal.concurrent.openFuture
|
import net.corda.core.internal.concurrent.openFuture
|
||||||
import net.corda.core.messaging.MessageRecipients
|
import net.corda.core.messaging.MessageRecipients
|
||||||
import net.corda.core.messaging.SingleMessageRecipient
|
import net.corda.core.messaging.SingleMessageRecipient
|
||||||
@ -9,7 +10,6 @@ import net.corda.core.node.services.PartyInfo
|
|||||||
import net.corda.core.serialization.CordaSerializable
|
import net.corda.core.serialization.CordaSerializable
|
||||||
import net.corda.core.serialization.deserialize
|
import net.corda.core.serialization.deserialize
|
||||||
import net.corda.core.serialization.serialize
|
import net.corda.core.serialization.serialize
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.atomic.AtomicBoolean
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
@ -225,7 +225,7 @@ interface Message {
|
|||||||
// or something like that.
|
// or something like that.
|
||||||
interface ReceivedMessage : Message {
|
interface ReceivedMessage : Message {
|
||||||
/** The authenticated sender. */
|
/** The authenticated sender. */
|
||||||
val peer: X500Name
|
val peer: CordaX500Name
|
||||||
/** Platform version of the sender's node. */
|
/** Platform version of the sender's node. */
|
||||||
val platformVersion: Int
|
val platformVersion: Int
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,10 @@ package net.corda.node.services.messaging
|
|||||||
|
|
||||||
import net.corda.core.concurrent.CordaFuture
|
import net.corda.core.concurrent.CordaFuture
|
||||||
import net.corda.core.crypto.random63BitValue
|
import net.corda.core.crypto.random63BitValue
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
|
import net.corda.core.internal.ThreadBox
|
||||||
import net.corda.core.internal.concurrent.andForget
|
import net.corda.core.internal.concurrent.andForget
|
||||||
import net.corda.core.internal.concurrent.thenMatch
|
import net.corda.core.internal.concurrent.thenMatch
|
||||||
import net.corda.core.internal.ThreadBox
|
|
||||||
import net.corda.core.messaging.CordaRPCOps
|
import net.corda.core.messaging.CordaRPCOps
|
||||||
import net.corda.core.messaging.MessageRecipients
|
import net.corda.core.messaging.MessageRecipients
|
||||||
import net.corda.core.messaging.RPCOps
|
import net.corda.core.messaging.RPCOps
|
||||||
@ -38,13 +39,15 @@ import org.apache.activemq.artemis.api.core.SimpleString
|
|||||||
import org.apache.activemq.artemis.api.core.client.*
|
import org.apache.activemq.artemis.api.core.client.*
|
||||||
import org.apache.activemq.artemis.api.core.client.ActiveMQClient.DEFAULT_ACK_BATCH_SIZE
|
import org.apache.activemq.artemis.api.core.client.ActiveMQClient.DEFAULT_ACK_BATCH_SIZE
|
||||||
import org.apache.activemq.artemis.api.core.management.ActiveMQServerControl
|
import org.apache.activemq.artemis.api.core.management.ActiveMQServerControl
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.*
|
import java.util.concurrent.*
|
||||||
import javax.annotation.concurrent.ThreadSafe
|
import javax.annotation.concurrent.ThreadSafe
|
||||||
import javax.persistence.*
|
import javax.persistence.Column
|
||||||
|
import javax.persistence.Entity
|
||||||
|
import javax.persistence.Id
|
||||||
|
import javax.persistence.Lob
|
||||||
|
|
||||||
// TODO: Stop the wallet explorer and other clients from using this class and get rid of persistentInbox
|
// TODO: Stop the wallet explorer and other clients from using this class and get rid of persistentInbox
|
||||||
|
|
||||||
@ -245,7 +248,7 @@ class NodeMessagingClient(override val config: NodeConfiguration,
|
|||||||
}, {})
|
}, {})
|
||||||
|
|
||||||
val myLegalName = loadKeyStore(config.sslKeystore, config.keyStorePassword).getX509Certificate(X509Utilities.CORDA_CLIENT_TLS).subject
|
val myLegalName = loadKeyStore(config.sslKeystore, config.keyStorePassword).getX509Certificate(X509Utilities.CORDA_CLIENT_TLS).subject
|
||||||
rpcServer = RPCServer(rpcOps, NODE_USER, NODE_USER, locator, userService, myLegalName)
|
rpcServer = RPCServer(rpcOps, NODE_USER, NODE_USER, locator, userService, CordaX500Name.build(myLegalName))
|
||||||
|
|
||||||
fun checkVerifierCount() {
|
fun checkVerifierCount() {
|
||||||
if (session.queueQuery(SimpleString(VERIFICATION_REQUESTS_QUEUE_NAME)).consumerCount == 0) {
|
if (session.queueQuery(SimpleString(VERIFICATION_REQUESTS_QUEUE_NAME)).consumerCount == 0) {
|
||||||
@ -377,7 +380,7 @@ class NodeMessagingClient(override val config: NodeConfiguration,
|
|||||||
val uuid = message.required(HDR_DUPLICATE_DETECTION_ID) { UUID.fromString(message.getStringProperty(it)) }
|
val uuid = message.required(HDR_DUPLICATE_DETECTION_ID) { UUID.fromString(message.getStringProperty(it)) }
|
||||||
log.trace { "Received message from: ${message.address} user: $user topic: $topic sessionID: $sessionID uuid: $uuid" }
|
log.trace { "Received message from: ${message.address} user: $user topic: $topic sessionID: $sessionID uuid: $uuid" }
|
||||||
|
|
||||||
return ArtemisReceivedMessage(TopicSession(topic, sessionID), X500Name(user), platformVersion, uuid, message)
|
return ArtemisReceivedMessage(TopicSession(topic, sessionID), CordaX500Name.parse(user), platformVersion, uuid, message)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
log.error("Unable to process message, ignoring it: $message", e)
|
log.error("Unable to process message, ignoring it: $message", e)
|
||||||
return null
|
return null
|
||||||
@ -390,7 +393,7 @@ class NodeMessagingClient(override val config: NodeConfiguration,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class ArtemisReceivedMessage(override val topicSession: TopicSession,
|
private class ArtemisReceivedMessage(override val topicSession: TopicSession,
|
||||||
override val peer: X500Name,
|
override val peer: CordaX500Name,
|
||||||
override val platformVersion: Int,
|
override val platformVersion: Int,
|
||||||
override val uniqueMessageId: UUID,
|
override val uniqueMessageId: UUID,
|
||||||
private val message: ClientMessage) : ReceivedMessage {
|
private val message: ClientMessage) : ReceivedMessage {
|
||||||
|
@ -12,13 +12,16 @@ import com.google.common.collect.Multimaps
|
|||||||
import com.google.common.collect.SetMultimap
|
import com.google.common.collect.SetMultimap
|
||||||
import com.google.common.util.concurrent.ThreadFactoryBuilder
|
import com.google.common.util.concurrent.ThreadFactoryBuilder
|
||||||
import net.corda.core.crypto.random63BitValue
|
import net.corda.core.crypto.random63BitValue
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.internal.LazyStickyPool
|
import net.corda.core.internal.LazyStickyPool
|
||||||
import net.corda.core.internal.LifeCycle
|
import net.corda.core.internal.LifeCycle
|
||||||
import net.corda.core.messaging.RPCOps
|
import net.corda.core.messaging.RPCOps
|
||||||
import net.corda.core.utilities.seconds
|
|
||||||
import net.corda.core.serialization.SerializationContext
|
import net.corda.core.serialization.SerializationContext
|
||||||
import net.corda.core.serialization.SerializationDefaults.RPC_SERVER_CONTEXT
|
import net.corda.core.serialization.SerializationDefaults.RPC_SERVER_CONTEXT
|
||||||
import net.corda.core.utilities.*
|
import net.corda.core.utilities.Try
|
||||||
|
import net.corda.core.utilities.debug
|
||||||
|
import net.corda.core.utilities.loggerFor
|
||||||
|
import net.corda.core.utilities.seconds
|
||||||
import net.corda.node.services.RPCUserService
|
import net.corda.node.services.RPCUserService
|
||||||
import net.corda.nodeapi.*
|
import net.corda.nodeapi.*
|
||||||
import net.corda.nodeapi.ArtemisMessagingComponent.Companion.NODE_USER
|
import net.corda.nodeapi.ArtemisMessagingComponent.Companion.NODE_USER
|
||||||
@ -32,7 +35,6 @@ import org.apache.activemq.artemis.api.core.client.ServerLocator
|
|||||||
import org.apache.activemq.artemis.api.core.management.ActiveMQServerControl
|
import org.apache.activemq.artemis.api.core.management.ActiveMQServerControl
|
||||||
import org.apache.activemq.artemis.api.core.management.CoreNotificationType
|
import org.apache.activemq.artemis.api.core.management.CoreNotificationType
|
||||||
import org.apache.activemq.artemis.api.core.management.ManagementHelper
|
import org.apache.activemq.artemis.api.core.management.ManagementHelper
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import rx.Notification
|
import rx.Notification
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import rx.Subscriber
|
import rx.Subscriber
|
||||||
@ -76,7 +78,7 @@ class RPCServer(
|
|||||||
private val rpcServerPassword: String,
|
private val rpcServerPassword: String,
|
||||||
private val serverLocator: ServerLocator,
|
private val serverLocator: ServerLocator,
|
||||||
private val userService: RPCUserService,
|
private val userService: RPCUserService,
|
||||||
private val nodeLegalName: X500Name,
|
private val nodeLegalName: CordaX500Name,
|
||||||
private val rpcConfiguration: RPCServerConfiguration = RPCServerConfiguration.default
|
private val rpcConfiguration: RPCServerConfiguration = RPCServerConfiguration.default
|
||||||
) {
|
) {
|
||||||
private companion object {
|
private companion object {
|
||||||
@ -341,7 +343,7 @@ class RPCServer(
|
|||||||
val rpcUser = userService.getUser(validatedUser)
|
val rpcUser = userService.getUser(validatedUser)
|
||||||
if (rpcUser != null) {
|
if (rpcUser != null) {
|
||||||
return rpcUser
|
return rpcUser
|
||||||
} else if (X500Name(validatedUser) == nodeLegalName) {
|
} else if (CordaX500Name.parse(validatedUser) == nodeLegalName) {
|
||||||
return nodeUser
|
return nodeUser
|
||||||
} else {
|
} else {
|
||||||
throw IllegalArgumentException("Validated user '$validatedUser' is not an RPC user nor the NODE user")
|
throw IllegalArgumentException("Validated user '$validatedUser' is not an RPC user nor the NODE user")
|
||||||
|
@ -2,6 +2,7 @@ package net.corda.node.services.network
|
|||||||
|
|
||||||
import net.corda.core.concurrent.CordaFuture
|
import net.corda.core.concurrent.CordaFuture
|
||||||
import net.corda.core.identity.AbstractParty
|
import net.corda.core.identity.AbstractParty
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.internal.VisibleForTesting
|
import net.corda.core.internal.VisibleForTesting
|
||||||
import net.corda.core.internal.bufferUntilSubscribed
|
import net.corda.core.internal.bufferUntilSubscribed
|
||||||
@ -32,7 +33,6 @@ import net.corda.node.utilities.AddOrRemove
|
|||||||
import net.corda.node.utilities.DatabaseTransactionManager
|
import net.corda.node.utilities.DatabaseTransactionManager
|
||||||
import net.corda.node.utilities.bufferUntilDatabaseCommit
|
import net.corda.node.utilities.bufferUntilDatabaseCommit
|
||||||
import net.corda.node.utilities.wrapWithDatabaseTransaction
|
import net.corda.node.utilities.wrapWithDatabaseTransaction
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import org.hibernate.Session
|
import org.hibernate.Session
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import rx.subjects.PublishSubject
|
import rx.subjects.PublishSubject
|
||||||
@ -90,7 +90,7 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO See comment to queryByLegalName why it's left like that.
|
// TODO See comment to queryByLegalName why it's left like that.
|
||||||
override fun getNodeByLegalName(principal: X500Name): NodeInfo? = partyNodes.singleOrNull { it.legalIdentity.name == principal }
|
override fun getNodeByLegalName(principal: CordaX500Name): NodeInfo? = partyNodes.singleOrNull { it.legalIdentity.name == principal }
|
||||||
//serviceHub!!.database.transaction { queryByLegalName(principal).firstOrNull() }
|
//serviceHub!!.database.transaction { queryByLegalName(principal).firstOrNull() }
|
||||||
override fun getNodeByLegalIdentityKey(identityKey: PublicKey): NodeInfo? =
|
override fun getNodeByLegalIdentityKey(identityKey: PublicKey): NodeInfo? =
|
||||||
serviceHub.database.transaction { queryByIdentityKey(identityKey).firstOrNull() }
|
serviceHub.database.transaction { queryByIdentityKey(identityKey).firstOrNull() }
|
||||||
@ -288,10 +288,7 @@ open class PersistentNetworkMapCache(private val serviceHub: ServiceHubInternal)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO It's useless for now, because toString on X500 names is inconsistent and we have:
|
private fun queryByLegalName(name: CordaX500Name): List<NodeInfo> {
|
||||||
// C=ES,L=Madrid,O=Alice Corp,CN=Alice Corp
|
|
||||||
// CN=Alice Corp,O=Alice Corp,L=Madrid,C=ES
|
|
||||||
private fun queryByLegalName(name: X500Name): List<NodeInfo> {
|
|
||||||
createSession {
|
createSession {
|
||||||
val query = it.createQuery(
|
val query = it.createQuery(
|
||||||
"SELECT n FROM ${NodeInfoSchemaV1.PersistentNodeInfo::class.java.name} n JOIN n.legalIdentitiesAndCerts l WHERE l.name = :name",
|
"SELECT n FROM ${NodeInfoSchemaV1.PersistentNodeInfo::class.java.name} n JOIN n.legalIdentitiesAndCerts l WHERE l.name = :name",
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
package net.corda.node.services.persistence
|
package net.corda.node.services.persistence
|
||||||
|
|
||||||
import net.corda.core.identity.AbstractParty
|
import net.corda.core.identity.AbstractParty
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.node.services.IdentityService
|
import net.corda.core.node.services.IdentityService
|
||||||
import net.corda.core.utilities.loggerFor
|
import net.corda.core.utilities.loggerFor
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import javax.persistence.AttributeConverter
|
import javax.persistence.AttributeConverter
|
||||||
import javax.persistence.Converter
|
import javax.persistence.Converter
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converter to persist a party as its's well known identity (where resolvable)
|
* Converter to persist a party as its' well known identity (where resolvable).
|
||||||
* Completely anonymous parties are stored as null (to preserve privacy)
|
* Completely anonymous parties are stored as null (to preserve privacy).
|
||||||
*/
|
*/
|
||||||
@Converter(autoApply = true)
|
@Converter(autoApply = true)
|
||||||
class AbstractPartyToX500NameAsStringConverter(identitySvc: () -> IdentityService) : AttributeConverter<AbstractParty, String> {
|
class AbstractPartyToX500NameAsStringConverter(identitySvc: () -> IdentityService) : AttributeConverter<AbstractParty, String> {
|
||||||
@ -30,7 +30,7 @@ class AbstractPartyToX500NameAsStringConverter(identitySvc: () -> IdentityServic
|
|||||||
|
|
||||||
override fun convertToEntityAttribute(dbData: String?): AbstractParty? {
|
override fun convertToEntityAttribute(dbData: String?): AbstractParty? {
|
||||||
if (dbData != null) {
|
if (dbData != null) {
|
||||||
val party = identityService.partyFromX500Name(X500Name(dbData))
|
val party = identityService.partyFromX500Name(CordaX500Name.parse(dbData))
|
||||||
if (party != null) return party
|
if (party != null) return party
|
||||||
log.warn ("Identity service unable to resolve X500name: $dbData")
|
log.warn ("Identity service unable to resolve X500name: $dbData")
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,11 @@ package net.corda.node.services.transactions
|
|||||||
import co.paralleluniverse.fibers.Suspendable
|
import co.paralleluniverse.fibers.Suspendable
|
||||||
import com.google.common.util.concurrent.SettableFuture
|
import com.google.common.util.concurrent.SettableFuture
|
||||||
import net.corda.core.contracts.StateRef
|
import net.corda.core.contracts.StateRef
|
||||||
import net.corda.core.crypto.*
|
import net.corda.core.crypto.DigitalSignature
|
||||||
|
import net.corda.core.crypto.SecureHash
|
||||||
import net.corda.core.flows.FlowLogic
|
import net.corda.core.flows.FlowLogic
|
||||||
import net.corda.core.flows.NotaryException
|
import net.corda.core.flows.NotaryException
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.node.services.NotaryService
|
import net.corda.core.node.services.NotaryService
|
||||||
import net.corda.core.node.services.TimeWindowChecker
|
import net.corda.core.node.services.TimeWindowChecker
|
||||||
@ -18,7 +20,6 @@ import net.corda.core.utilities.*
|
|||||||
import net.corda.node.services.api.ServiceHubInternal
|
import net.corda.node.services.api.ServiceHubInternal
|
||||||
import net.corda.node.utilities.AppendOnlyPersistentMap
|
import net.corda.node.utilities.AppendOnlyPersistentMap
|
||||||
import net.corda.node.utilities.NODE_DATABASE_PREFIX
|
import net.corda.node.utilities.NODE_DATABASE_PREFIX
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import javax.persistence.Entity
|
import javax.persistence.Entity
|
||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
|
|
||||||
@ -106,7 +107,7 @@ class BFTNonValidatingNotaryService(override val services: ServiceHubInternal, c
|
|||||||
id = SecureHash.parse(it.consumingTxHash),
|
id = SecureHash.parse(it.consumingTxHash),
|
||||||
inputIndex = it.consumingIndex,
|
inputIndex = it.consumingIndex,
|
||||||
requestingParty = Party(
|
requestingParty = Party(
|
||||||
name = X500Name(it.party.name),
|
name = CordaX500Name.parse(it.party.name),
|
||||||
owningKey = parsePublicKeyBase58(it.party.owningKey))))
|
owningKey = parsePublicKeyBase58(it.party.owningKey))))
|
||||||
},
|
},
|
||||||
toPersistentEntity = { (txHash, index) : StateRef, (id, inputIndex, requestingParty): UniquenessProvider.ConsumingTx ->
|
toPersistentEntity = { (txHash, index) : StateRef, (id, inputIndex, requestingParty): UniquenessProvider.ConsumingTx ->
|
||||||
|
@ -2,8 +2,7 @@ package net.corda.node.services.transactions
|
|||||||
|
|
||||||
import net.corda.core.contracts.StateRef
|
import net.corda.core.contracts.StateRef
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
import net.corda.core.utilities.parsePublicKeyBase58
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.utilities.toBase58String
|
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.internal.ThreadBox
|
import net.corda.core.internal.ThreadBox
|
||||||
import net.corda.core.node.services.UniquenessException
|
import net.corda.core.node.services.UniquenessException
|
||||||
@ -11,8 +10,10 @@ import net.corda.core.node.services.UniquenessProvider
|
|||||||
import net.corda.core.schemas.PersistentStateRef
|
import net.corda.core.schemas.PersistentStateRef
|
||||||
import net.corda.core.serialization.SingletonSerializeAsToken
|
import net.corda.core.serialization.SingletonSerializeAsToken
|
||||||
import net.corda.core.utilities.loggerFor
|
import net.corda.core.utilities.loggerFor
|
||||||
import net.corda.node.utilities.*
|
import net.corda.core.utilities.parsePublicKeyBase58
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
import net.corda.core.utilities.toBase58String
|
||||||
|
import net.corda.node.utilities.AppendOnlyPersistentMap
|
||||||
|
import net.corda.node.utilities.NODE_DATABASE_PREFIX
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.annotation.concurrent.ThreadSafe
|
import javax.annotation.concurrent.ThreadSafe
|
||||||
@ -73,7 +74,7 @@ class PersistentUniquenessProvider : UniquenessProvider, SingletonSerializeAsTok
|
|||||||
id = SecureHash.parse(it.consumingTxHash),
|
id = SecureHash.parse(it.consumingTxHash),
|
||||||
inputIndex = it.consumingIndex,
|
inputIndex = it.consumingIndex,
|
||||||
requestingParty = Party(
|
requestingParty = Party(
|
||||||
name = X500Name(it.party.name),
|
name = CordaX500Name.parse(it.party.name),
|
||||||
owningKey = parsePublicKeyBase58(it.party.owningKey))))
|
owningKey = parsePublicKeyBase58(it.party.owningKey))))
|
||||||
},
|
},
|
||||||
toPersistentEntity = { (txHash, index) : StateRef, (id, inputIndex, requestingParty) : UniquenessProvider.ConsumingTx ->
|
toPersistentEntity = { (txHash, index) : StateRef, (id, inputIndex, requestingParty) : UniquenessProvider.ConsumingTx ->
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
package net.corda.node.utilities
|
package net.corda.node.utilities
|
||||||
|
|
||||||
import net.corda.core.crypto.Crypto
|
import net.corda.core.crypto.Crypto
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.internal.exists
|
import net.corda.core.internal.exists
|
||||||
import net.corda.core.internal.read
|
import net.corda.core.internal.read
|
||||||
import net.corda.core.internal.toX509CertHolder
|
import net.corda.core.internal.toX509CertHolder
|
||||||
import net.corda.core.internal.write
|
import net.corda.core.internal.write
|
||||||
import net.corda.core.utilities.cert
|
import net.corda.core.utilities.cert
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import org.bouncycastle.cert.X509CertificateHolder
|
import org.bouncycastle.cert.X509CertificateHolder
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
@ -174,26 +174,26 @@ fun KeyStore.getSupportedKey(alias: String, keyPassword: String): PrivateKey {
|
|||||||
class KeyStoreWrapper(private val storePath: Path, private val storePassword: String) {
|
class KeyStoreWrapper(private val storePath: Path, private val storePassword: String) {
|
||||||
private val keyStore = storePath.read { loadKeyStore(it, storePassword) }
|
private val keyStore = storePath.read { loadKeyStore(it, storePassword) }
|
||||||
|
|
||||||
private fun createCertificate(serviceName: X500Name, pubKey: PublicKey): CertPath {
|
private fun createCertificate(serviceName: CordaX500Name, pubKey: PublicKey): CertPath {
|
||||||
val clientCertPath = keyStore.getCertificateChain(X509Utilities.CORDA_CLIENT_CA)
|
val clientCertPath = keyStore.getCertificateChain(X509Utilities.CORDA_CLIENT_CA)
|
||||||
// Assume key password = store password.
|
// Assume key password = store password.
|
||||||
val clientCA = certificateAndKeyPair(X509Utilities.CORDA_CLIENT_CA)
|
val clientCA = certificateAndKeyPair(X509Utilities.CORDA_CLIENT_CA)
|
||||||
// Create new keys and store in keystore.
|
// Create new keys and store in keystore.
|
||||||
val cert = X509Utilities.createCertificate(CertificateType.IDENTITY, clientCA.certificate, clientCA.keyPair, serviceName, pubKey)
|
val cert = X509Utilities.createCertificate(CertificateType.IDENTITY, clientCA.certificate, clientCA.keyPair, serviceName.x500Name, pubKey)
|
||||||
val certPath = CertificateFactory.getInstance("X509").generateCertPath(listOf(cert.cert) + clientCertPath)
|
val certPath = CertificateFactory.getInstance("X509").generateCertPath(listOf(cert.cert) + clientCertPath)
|
||||||
require(certPath.certificates.isNotEmpty()) { "Certificate path cannot be empty" }
|
require(certPath.certificates.isNotEmpty()) { "Certificate path cannot be empty" }
|
||||||
// TODO: X509Utilities.validateCertificateChain()
|
// TODO: X509Utilities.validateCertificateChain()
|
||||||
return certPath
|
return certPath
|
||||||
}
|
}
|
||||||
|
|
||||||
fun signAndSaveNewKeyPair(serviceName: X500Name, privateKeyAlias: String, keyPair: KeyPair) {
|
fun signAndSaveNewKeyPair(serviceName: CordaX500Name, privateKeyAlias: String, keyPair: KeyPair) {
|
||||||
val certPath = createCertificate(serviceName, keyPair.public)
|
val certPath = createCertificate(serviceName, keyPair.public)
|
||||||
// Assume key password = store password.
|
// Assume key password = store password.
|
||||||
keyStore.addOrReplaceKey(privateKeyAlias, keyPair.private, storePassword.toCharArray(), certPath.certificates.toTypedArray())
|
keyStore.addOrReplaceKey(privateKeyAlias, keyPair.private, storePassword.toCharArray(), certPath.certificates.toTypedArray())
|
||||||
keyStore.save(storePath, storePassword)
|
keyStore.save(storePath, storePassword)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun savePublicKey(serviceName: X500Name, pubKeyAlias: String, pubKey: PublicKey) {
|
fun savePublicKey(serviceName: CordaX500Name, pubKeyAlias: String, pubKey: PublicKey) {
|
||||||
val certPath = createCertificate(serviceName, pubKey)
|
val certPath = createCertificate(serviceName, pubKey)
|
||||||
// Assume key password = store password.
|
// Assume key password = store password.
|
||||||
keyStore.addOrReplaceCertificate(pubKeyAlias, certPath.certificates.first())
|
keyStore.addOrReplaceCertificate(pubKeyAlias, certPath.certificates.first())
|
||||||
|
@ -2,10 +2,10 @@ package net.corda.node.utilities
|
|||||||
|
|
||||||
import net.corda.core.crypto.CompositeKey
|
import net.corda.core.crypto.CompositeKey
|
||||||
import net.corda.core.crypto.generateKeyPair
|
import net.corda.core.crypto.generateKeyPair
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.utilities.loggerFor
|
import net.corda.core.utilities.loggerFor
|
||||||
import net.corda.core.utilities.trace
|
import net.corda.core.utilities.trace
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ object ServiceIdentityGenerator {
|
|||||||
// TODO: This needs to write out to the key store, not just files on disk
|
// TODO: This needs to write out to the key store, not just files on disk
|
||||||
fun generateToDisk(dirs: List<Path>,
|
fun generateToDisk(dirs: List<Path>,
|
||||||
serviceId: String,
|
serviceId: String,
|
||||||
serviceName: X500Name,
|
serviceName: CordaX500Name,
|
||||||
threshold: Int = 1): Party {
|
threshold: Int = 1): Party {
|
||||||
log.trace { "Generating a group identity \"serviceName\" for nodes: ${dirs.joinToString()}" }
|
log.trace { "Generating a group identity \"serviceName\" for nodes: ${dirs.joinToString()}" }
|
||||||
val keyPairs = (1..dirs.size).map { generateKeyPair() }
|
val keyPairs = (1..dirs.size).map { generateKeyPair() }
|
||||||
|
@ -3,6 +3,7 @@ package net.corda.node.utilities
|
|||||||
import net.corda.core.crypto.Crypto
|
import net.corda.core.crypto.Crypto
|
||||||
import net.corda.core.crypto.SignatureScheme
|
import net.corda.core.crypto.SignatureScheme
|
||||||
import net.corda.core.crypto.random63BitValue
|
import net.corda.core.crypto.random63BitValue
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.utilities.cert
|
import net.corda.core.utilities.cert
|
||||||
import net.corda.core.utilities.days
|
import net.corda.core.utilities.days
|
||||||
import net.corda.core.utilities.millis
|
import net.corda.core.utilities.millis
|
||||||
@ -106,7 +107,29 @@ object X509Utilities {
|
|||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun createCertificate(certificateType: CertificateType,
|
fun createCertificate(certificateType: CertificateType,
|
||||||
issuerCertificate: X509CertificateHolder, issuerKeyPair: KeyPair,
|
issuerCertificate: X509CertificateHolder, issuerKeyPair: KeyPair,
|
||||||
subject: X500Name, subjectPublicKey: PublicKey,
|
subject: CordaX500Name, subjectPublicKey: PublicKey,
|
||||||
|
validityWindow: Pair<Duration, Duration> = DEFAULT_VALIDITY_WINDOW,
|
||||||
|
nameConstraints: NameConstraints? = null): X509CertificateHolder {
|
||||||
|
val window = getCertificateValidityWindow(validityWindow.first, validityWindow.second, issuerCertificate)
|
||||||
|
return createCertificate(certificateType, issuerCertificate.subject, issuerKeyPair, subject.x500Name, subjectPublicKey, window, nameConstraints)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a X509 v3 cert.
|
||||||
|
* @param issuerCertificate The Public certificate of the root CA above this used to sign it.
|
||||||
|
* @param issuerKeyPair The KeyPair of the root CA above this used to sign it.
|
||||||
|
* @param subject subject of the generated certificate.
|
||||||
|
* @param subjectPublicKey subject 's public key.
|
||||||
|
* @param validityWindow The certificate's validity window. Default to [DEFAULT_VALIDITY_WINDOW] if not provided.
|
||||||
|
* @return A data class is returned containing the new intermediate CA Cert and its KeyPair for signing downstream certificates.
|
||||||
|
* Note the generated certificate tree is capped at max depth of 1 below this to be in line with commercially available certificates.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun createCertificate(certificateType: CertificateType,
|
||||||
|
issuerCertificate: X509CertificateHolder,
|
||||||
|
issuerKeyPair: KeyPair,
|
||||||
|
subject: X500Name,
|
||||||
|
subjectPublicKey: PublicKey,
|
||||||
validityWindow: Pair<Duration, Duration> = DEFAULT_VALIDITY_WINDOW,
|
validityWindow: Pair<Duration, Duration> = DEFAULT_VALIDITY_WINDOW,
|
||||||
nameConstraints: NameConstraints? = null): X509CertificateHolder {
|
nameConstraints: NameConstraints? = null): X509CertificateHolder {
|
||||||
val window = getCertificateValidityWindow(validityWindow.first, validityWindow.second, issuerCertificate)
|
val window = getCertificateValidityWindow(validityWindow.first, validityWindow.second, issuerCertificate)
|
||||||
|
@ -4,7 +4,6 @@ import net.corda.core.crypto.Crypto
|
|||||||
import net.corda.core.utilities.cert
|
import net.corda.core.utilities.cert
|
||||||
import net.corda.core.internal.*
|
import net.corda.core.internal.*
|
||||||
import net.corda.core.utilities.seconds
|
import net.corda.core.utilities.seconds
|
||||||
import net.corda.core.utilities.validateX500Name
|
|
||||||
import net.corda.node.services.config.NodeConfiguration
|
import net.corda.node.services.config.NodeConfiguration
|
||||||
import net.corda.node.utilities.*
|
import net.corda.node.utilities.*
|
||||||
import net.corda.node.utilities.X509Utilities.CORDA_CLIENT_CA
|
import net.corda.node.utilities.X509Utilities.CORDA_CLIENT_CA
|
||||||
@ -45,7 +44,6 @@ class NetworkRegistrationHelper(private val config: NodeConfiguration, private v
|
|||||||
*/
|
*/
|
||||||
// TODO: Stop killing the calling process from within a called function.
|
// TODO: Stop killing the calling process from within a called function.
|
||||||
fun buildKeystore() {
|
fun buildKeystore() {
|
||||||
validateX500Name(config.myLegalName)
|
|
||||||
config.certificatesDirectory.createDirectories()
|
config.certificatesDirectory.createDirectories()
|
||||||
val caKeyStore = loadOrCreateKeyStore(config.nodeKeystore, keystorePassword)
|
val caKeyStore = loadOrCreateKeyStore(config.nodeKeystore, keystorePassword)
|
||||||
if (!caKeyStore.containsAlias(CORDA_CLIENT_CA)) {
|
if (!caKeyStore.containsAlias(CORDA_CLIENT_CA)) {
|
||||||
@ -53,7 +51,7 @@ class NetworkRegistrationHelper(private val config: NodeConfiguration, private v
|
|||||||
// We use the self sign certificate to store the key temporarily in the keystore while waiting for the request approval.
|
// We use the self sign certificate to store the key temporarily in the keystore while waiting for the request approval.
|
||||||
if (!caKeyStore.containsAlias(SELF_SIGNED_PRIVATE_KEY)) {
|
if (!caKeyStore.containsAlias(SELF_SIGNED_PRIVATE_KEY)) {
|
||||||
val keyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
val keyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||||
val selfSignCert = X509Utilities.createSelfSignedCACertificate(config.myLegalName, keyPair)
|
val selfSignCert = X509Utilities.createSelfSignedCACertificate(config.myLegalName.x500Name, keyPair)
|
||||||
// Save to the key store.
|
// Save to the key store.
|
||||||
caKeyStore.addOrReplaceKey(SELF_SIGNED_PRIVATE_KEY, keyPair.private, privateKeyPassword.toCharArray(),
|
caKeyStore.addOrReplaceKey(SELF_SIGNED_PRIVATE_KEY, keyPair.private, privateKeyPassword.toCharArray(),
|
||||||
arrayOf(selfSignCert))
|
arrayOf(selfSignCert))
|
||||||
@ -126,7 +124,7 @@ class NetworkRegistrationHelper(private val config: NodeConfiguration, private v
|
|||||||
private fun submitOrResumeCertificateSigningRequest(keyPair: KeyPair): String {
|
private fun submitOrResumeCertificateSigningRequest(keyPair: KeyPair): String {
|
||||||
// Retrieve request id from file if exists, else post a request to server.
|
// Retrieve request id from file if exists, else post a request to server.
|
||||||
return if (!requestIdStore.exists()) {
|
return if (!requestIdStore.exists()) {
|
||||||
val request = X509Utilities.createCertificateSigningRequest(config.myLegalName, config.emailAddress, keyPair)
|
val request = X509Utilities.createCertificateSigningRequest(config.myLegalName.x500Name, config.emailAddress, keyPair)
|
||||||
val writer = StringWriter()
|
val writer = StringWriter()
|
||||||
JcaPEMWriter(writer).use {
|
JcaPEMWriter(writer).use {
|
||||||
it.writeObject(PemObject("CERTIFICATE REQUEST", request.encoded))
|
it.writeObject(PemObject("CERTIFICATE REQUEST", request.encoded))
|
||||||
|
@ -2,6 +2,7 @@ package net.corda.node
|
|||||||
|
|
||||||
import co.paralleluniverse.fibers.Suspendable
|
import co.paralleluniverse.fibers.Suspendable
|
||||||
import net.corda.core.flows.*
|
import net.corda.core.flows.*
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.internal.copyToDirectory
|
import net.corda.core.internal.copyToDirectory
|
||||||
import net.corda.core.internal.createDirectories
|
import net.corda.core.internal.createDirectories
|
||||||
@ -9,7 +10,6 @@ import net.corda.core.internal.div
|
|||||||
import net.corda.core.internal.list
|
import net.corda.core.internal.list
|
||||||
import net.corda.core.messaging.startFlow
|
import net.corda.core.messaging.startFlow
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.core.utilities.getX500Name
|
|
||||||
import net.corda.core.utilities.unwrap
|
import net.corda.core.utilities.unwrap
|
||||||
import net.corda.nodeapi.User
|
import net.corda.nodeapi.User
|
||||||
import net.corda.smoketesting.NodeConfig
|
import net.corda.smoketesting.NodeConfig
|
||||||
@ -29,7 +29,7 @@ class CordappSmokeTest {
|
|||||||
private val factory = NodeProcess.Factory()
|
private val factory = NodeProcess.Factory()
|
||||||
|
|
||||||
private val aliceConfig = NodeConfig(
|
private val aliceConfig = NodeConfig(
|
||||||
legalName = getX500Name(O = "Alice Corp", L = "Madrid", C = "ES"),
|
legalName = CordaX500Name(organisation = "Alice Corp", locality = "Madrid", country = "ES"),
|
||||||
p2pPort = port.andIncrement,
|
p2pPort = port.andIncrement,
|
||||||
rpcPort = port.andIncrement,
|
rpcPort = port.andIncrement,
|
||||||
webPort = port.andIncrement,
|
webPort = port.andIncrement,
|
||||||
|
@ -10,6 +10,7 @@ import net.corda.core.flows.InitiatingFlow
|
|||||||
import net.corda.core.flows.StateMachineRunId
|
import net.corda.core.flows.StateMachineRunId
|
||||||
import net.corda.core.identity.AbstractParty
|
import net.corda.core.identity.AbstractParty
|
||||||
import net.corda.core.identity.AnonymousParty
|
import net.corda.core.identity.AnonymousParty
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.internal.FlowStateMachine
|
import net.corda.core.internal.FlowStateMachine
|
||||||
import net.corda.core.internal.concurrent.map
|
import net.corda.core.internal.concurrent.map
|
||||||
@ -46,7 +47,6 @@ import net.corda.testing.contracts.fillWithSomeTestCash
|
|||||||
import net.corda.testing.node.InMemoryMessagingNetwork
|
import net.corda.testing.node.InMemoryMessagingNetwork
|
||||||
import net.corda.testing.node.MockNetwork
|
import net.corda.testing.node.MockNetwork
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
@ -307,7 +307,7 @@ class TwoPartyTradeFlowTests {
|
|||||||
// of gets and puts.
|
// of gets and puts.
|
||||||
private fun makeNodeWithTracking(
|
private fun makeNodeWithTracking(
|
||||||
networkMapAddress: SingleMessageRecipient?,
|
networkMapAddress: SingleMessageRecipient?,
|
||||||
name: X500Name): MockNetwork.MockNode {
|
name: CordaX500Name): MockNetwork.MockNode {
|
||||||
// Create a node in the mock network ...
|
// Create a node in the mock network ...
|
||||||
return mockNet.createNode(networkMapAddress, nodeFactory = object : MockNetwork.Factory<MockNetwork.MockNode> {
|
return mockNet.createNode(networkMapAddress, nodeFactory = object : MockNetwork.Factory<MockNetwork.MockNode> {
|
||||||
override fun create(config: NodeConfiguration,
|
override fun create(config: NodeConfiguration,
|
||||||
|
@ -4,12 +4,12 @@ import net.corda.core.contracts.*
|
|||||||
import net.corda.core.crypto.generateKeyPair
|
import net.corda.core.crypto.generateKeyPair
|
||||||
import net.corda.core.flows.NotaryChangeFlow
|
import net.corda.core.flows.NotaryChangeFlow
|
||||||
import net.corda.core.flows.StateReplacementException
|
import net.corda.core.flows.StateReplacementException
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.node.services.ServiceInfo
|
import net.corda.core.node.services.ServiceInfo
|
||||||
import net.corda.core.transactions.TransactionBuilder
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
import net.corda.core.transactions.WireTransaction
|
import net.corda.core.transactions.WireTransaction
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.core.utilities.getX500Name
|
|
||||||
import net.corda.core.utilities.seconds
|
import net.corda.core.utilities.seconds
|
||||||
import net.corda.node.internal.AbstractNode
|
import net.corda.node.internal.AbstractNode
|
||||||
import net.corda.node.services.network.NetworkMapService
|
import net.corda.node.services.network.NetworkMapService
|
||||||
@ -21,7 +21,6 @@ import net.corda.testing.dummyCommand
|
|||||||
import net.corda.testing.getTestPartyAndCertificate
|
import net.corda.testing.getTestPartyAndCertificate
|
||||||
import net.corda.testing.node.MockNetwork
|
import net.corda.testing.node.MockNetwork
|
||||||
import org.assertj.core.api.Assertions.assertThatExceptionOfType
|
import org.assertj.core.api.Assertions.assertThatExceptionOfType
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
@ -88,7 +87,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, oldNotaryNode)
|
val state = issueMultiPartyState(clientNodeA, clientNodeB, oldNotaryNode)
|
||||||
val newEvilNotary = getTestPartyAndCertificate(getX500Name(OU="Evil Notary",O="Evil R3",L="London",C="GB"), generateKeyPair().public)
|
val newEvilNotary = getTestPartyAndCertificate(CordaX500Name(organisation = "Evil R3", locality = "London", country = "GB"), generateKeyPair().public)
|
||||||
val flow = NotaryChangeFlow(state, newEvilNotary.party)
|
val flow = NotaryChangeFlow(state, newEvilNotary.party)
|
||||||
val future = clientNodeA.services.startFlow(flow)
|
val future = clientNodeA.services.startFlow(flow)
|
||||||
|
|
||||||
|
@ -6,13 +6,13 @@ import net.corda.core.flows.FlowLogic
|
|||||||
import net.corda.core.flows.FlowLogicRef
|
import net.corda.core.flows.FlowLogicRef
|
||||||
import net.corda.core.flows.FlowLogicRefFactory
|
import net.corda.core.flows.FlowLogicRefFactory
|
||||||
import net.corda.core.identity.AbstractParty
|
import net.corda.core.identity.AbstractParty
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.node.ServiceHub
|
import net.corda.core.node.ServiceHub
|
||||||
import net.corda.core.node.services.VaultService
|
import net.corda.core.node.services.VaultService
|
||||||
import net.corda.core.serialization.SingletonSerializeAsToken
|
import net.corda.core.serialization.SingletonSerializeAsToken
|
||||||
import net.corda.core.transactions.TransactionBuilder
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
import net.corda.core.utilities.days
|
import net.corda.core.utilities.days
|
||||||
import net.corda.core.utilities.getX500Name
|
|
||||||
import net.corda.node.services.identity.InMemoryIdentityService
|
import net.corda.node.services.identity.InMemoryIdentityService
|
||||||
import net.corda.node.services.persistence.DBCheckpointStorage
|
import net.corda.node.services.persistence.DBCheckpointStorage
|
||||||
import net.corda.node.services.statemachine.FlowLogicRefFactoryImpl
|
import net.corda.node.services.statemachine.FlowLogicRefFactoryImpl
|
||||||
@ -31,7 +31,6 @@ import net.corda.testing.node.MockServices.Companion.makeTestDatabaseProperties
|
|||||||
import net.corda.testing.node.MockServices.Companion.makeTestIdentityService
|
import net.corda.testing.node.MockServices.Companion.makeTestIdentityService
|
||||||
import net.corda.testing.node.TestClock
|
import net.corda.testing.node.TestClock
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
@ -82,7 +81,7 @@ class NodeSchedulerServiceTest : SingletonSerializeAsToken() {
|
|||||||
val kms = MockKeyManagementService(identityService, ALICE_KEY)
|
val kms = MockKeyManagementService(identityService, ALICE_KEY)
|
||||||
|
|
||||||
database.transaction {
|
database.transaction {
|
||||||
val nullIdentity = X500Name("cn=None")
|
val nullIdentity = CordaX500Name(organisation = "None", locality = "None", country = "GB")
|
||||||
val mockMessagingService = InMemoryMessagingNetwork(false).InMemoryMessaging(
|
val mockMessagingService = InMemoryMessagingNetwork(false).InMemoryMessaging(
|
||||||
false,
|
false,
|
||||||
InMemoryMessagingNetwork.PeerHandle(0, nullIdentity),
|
InMemoryMessagingNetwork.PeerHandle(0, nullIdentity),
|
||||||
@ -90,7 +89,7 @@ class NodeSchedulerServiceTest : SingletonSerializeAsToken() {
|
|||||||
database)
|
database)
|
||||||
services = object : MockServiceHubInternal(
|
services = object : MockServiceHubInternal(
|
||||||
database,
|
database,
|
||||||
testNodeConfiguration(Paths.get("."), getX500Name(O = "Alice", L = "London", C = "GB")),
|
testNodeConfiguration(Paths.get("."), CordaX500Name(organisation = "Alice", locality = "London", country = "GB")),
|
||||||
overrideClock = testClock,
|
overrideClock = testClock,
|
||||||
keyManagement = kms,
|
keyManagement = kms,
|
||||||
network = mockMessagingService), TestReference {
|
network = mockMessagingService), TestReference {
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
package net.corda.node.services.network
|
package net.corda.node.services.network
|
||||||
|
|
||||||
import net.corda.core.concurrent.CordaFuture
|
import net.corda.core.concurrent.CordaFuture
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.messaging.SingleMessageRecipient
|
import net.corda.core.messaging.SingleMessageRecipient
|
||||||
import net.corda.core.node.NodeInfo
|
import net.corda.core.node.NodeInfo
|
||||||
import net.corda.core.node.services.ServiceInfo
|
import net.corda.core.node.services.ServiceInfo
|
||||||
import net.corda.core.serialization.deserialize
|
import net.corda.core.serialization.deserialize
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.core.utilities.getX500Name
|
|
||||||
import net.corda.node.services.config.NodeConfiguration
|
import net.corda.node.services.config.NodeConfiguration
|
||||||
import net.corda.node.services.messaging.MessagingService
|
import net.corda.node.services.messaging.MessagingService
|
||||||
import net.corda.node.services.messaging.send
|
import net.corda.node.services.messaging.send
|
||||||
@ -31,7 +31,6 @@ import net.corda.testing.DUMMY_MAP
|
|||||||
import net.corda.testing.node.MockNetwork
|
import net.corda.testing.node.MockNetwork
|
||||||
import net.corda.testing.node.MockNetwork.MockNode
|
import net.corda.testing.node.MockNetwork.MockNode
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
@ -47,7 +46,7 @@ abstract class AbstractNetworkMapServiceTest<out S : AbstractNetworkMapService>
|
|||||||
lateinit var alice: MockNode
|
lateinit var alice: MockNode
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val subscriberLegalName = getX500Name(O="Subscriber",L="New York",C="US")
|
val subscriberLegalName = CordaX500Name(organisation ="Subscriber", locality ="New York", country ="US")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
@ -251,14 +250,14 @@ abstract class AbstractNetworkMapServiceTest<out S : AbstractNetworkMapService>
|
|||||||
mockNet.runNetwork()
|
mockNet.runNetwork()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addNewNodeToNetworkMap(legalName: X500Name): MockNode {
|
private fun addNewNodeToNetworkMap(legalName: CordaX500Name): MockNode {
|
||||||
val node = mockNet.createNode(mapServiceNode.network.myAddress, legalName = legalName)
|
val node = mockNet.createNode(mapServiceNode.network.myAddress, legalName = legalName)
|
||||||
mockNet.runNetwork()
|
mockNet.runNetwork()
|
||||||
lastSerial = System.currentTimeMillis()
|
lastSerial = System.currentTimeMillis()
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun newNodeSeparateFromNetworkMap(legalName: X500Name): MockNode {
|
private fun newNodeSeparateFromNetworkMap(legalName: CordaX500Name): MockNode {
|
||||||
return mockNet.createNode(legalName = legalName, nodeFactory = NoNMSNodeFactory)
|
return mockNet.createNode(legalName = legalName, nodeFactory = NoNMSNodeFactory)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,17 +3,16 @@ package net.corda.node.services.network
|
|||||||
import net.corda.core.crypto.Crypto
|
import net.corda.core.crypto.Crypto
|
||||||
import net.corda.core.crypto.generateKeyPair
|
import net.corda.core.crypto.generateKeyPair
|
||||||
import net.corda.core.identity.AnonymousParty
|
import net.corda.core.identity.AnonymousParty
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.identity.PartyAndCertificate
|
import net.corda.core.identity.PartyAndCertificate
|
||||||
import net.corda.core.node.services.UnknownAnonymousPartyException
|
import net.corda.core.node.services.UnknownAnonymousPartyException
|
||||||
import net.corda.node.utilities.CertificateAndKeyPair
|
import net.corda.node.utilities.CertificateAndKeyPair
|
||||||
import net.corda.core.utilities.cert
|
import net.corda.core.utilities.cert
|
||||||
import net.corda.core.utilities.getX500Name
|
|
||||||
import net.corda.node.services.identity.InMemoryIdentityService
|
import net.corda.node.services.identity.InMemoryIdentityService
|
||||||
import net.corda.node.utilities.CertificateType
|
import net.corda.node.utilities.CertificateType
|
||||||
import net.corda.node.utilities.X509Utilities
|
import net.corda.node.utilities.X509Utilities
|
||||||
import net.corda.testing.*
|
import net.corda.testing.*
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.security.cert.CertificateFactory
|
import java.security.cert.CertificateFactory
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
@ -63,7 +62,7 @@ class InMemoryIdentityServiceTests {
|
|||||||
val service = InMemoryIdentityService(trustRoot = trustRoot.certificate)
|
val service = InMemoryIdentityService(trustRoot = trustRoot.certificate)
|
||||||
service.verifyAndRegisterIdentity(ALICE_IDENTITY)
|
service.verifyAndRegisterIdentity(ALICE_IDENTITY)
|
||||||
service.verifyAndRegisterIdentity(BOB_IDENTITY)
|
service.verifyAndRegisterIdentity(BOB_IDENTITY)
|
||||||
val alicente = getTestPartyAndCertificate(getX500Name(O = "Alicente Worldwide", L = "London", C = "GB"), generateKeyPair().public)
|
val alicente = getTestPartyAndCertificate(CordaX500Name(organisation = "Alicente Worldwide", locality = "London", country = "GB"), generateKeyPair().public)
|
||||||
service.verifyAndRegisterIdentity(alicente)
|
service.verifyAndRegisterIdentity(alicente)
|
||||||
assertEquals(setOf(ALICE, alicente.party), service.partiesFromName("Alice", false))
|
assertEquals(setOf(ALICE, alicente.party), service.partiesFromName("Alice", false))
|
||||||
assertEquals(setOf(ALICE), service.partiesFromName("Alice Corp", true))
|
assertEquals(setOf(ALICE), service.partiesFromName("Alice Corp", true))
|
||||||
@ -73,8 +72,8 @@ class InMemoryIdentityServiceTests {
|
|||||||
@Test
|
@Test
|
||||||
fun `get identity by name`() {
|
fun `get identity by name`() {
|
||||||
val service = InMemoryIdentityService(trustRoot = DUMMY_CA.certificate)
|
val service = InMemoryIdentityService(trustRoot = DUMMY_CA.certificate)
|
||||||
val identities = listOf("Node A", "Node B", "Node C")
|
val identities = listOf("Org A", "Org B", "Org C")
|
||||||
.map { getTestPartyAndCertificate(getX500Name(O = it, OU = "corda", L = "London", C = "GB"), generateKeyPair().public) }
|
.map { getTestPartyAndCertificate(CordaX500Name(organisation = it, locality = "London", country = "GB"), generateKeyPair().public) }
|
||||||
assertNull(service.partyFromX500Name(identities.first().name))
|
assertNull(service.partyFromX500Name(identities.first().name))
|
||||||
identities.forEach { service.verifyAndRegisterIdentity(it) }
|
identities.forEach { service.verifyAndRegisterIdentity(it) }
|
||||||
identities.forEach { assertEquals(it.party, service.partyFromX500Name(it.name)) }
|
identities.forEach { assertEquals(it.party, service.partyFromX500Name(it.name)) }
|
||||||
@ -87,7 +86,7 @@ class InMemoryIdentityServiceTests {
|
|||||||
fun `assert unknown anonymous key is unrecognised`() {
|
fun `assert unknown anonymous key is unrecognised`() {
|
||||||
withTestSerialization {
|
withTestSerialization {
|
||||||
val rootKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
val rootKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||||
val rootCert = X509Utilities.createSelfSignedCACertificate(ALICE.name, rootKey)
|
val rootCert = X509Utilities.createSelfSignedCACertificate(ALICE.name.x500Name, rootKey)
|
||||||
val txKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
val txKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||||
val service = InMemoryIdentityService(trustRoot = DUMMY_CA.certificate)
|
val service = InMemoryIdentityService(trustRoot = DUMMY_CA.certificate)
|
||||||
// TODO: Generate certificate with an EdDSA key rather than ECDSA
|
// TODO: Generate certificate with an EdDSA key rather than ECDSA
|
||||||
@ -152,17 +151,18 @@ class InMemoryIdentityServiceTests {
|
|||||||
|
|
||||||
assertFailsWith<IllegalArgumentException> {
|
assertFailsWith<IllegalArgumentException> {
|
||||||
val owningKey = Crypto.decodePublicKey(trustRoot.certificate.subjectPublicKeyInfo.encoded)
|
val owningKey = Crypto.decodePublicKey(trustRoot.certificate.subjectPublicKeyInfo.encoded)
|
||||||
service.assertOwnership(Party(trustRoot.certificate.subject, owningKey), anonymousAlice.party.anonymise())
|
val subject = CordaX500Name.build(trustRoot.certificate.subject)
|
||||||
|
service.assertOwnership(Party(subject, owningKey), anonymousAlice.party.anonymise())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createParty(x500Name: X500Name, ca: CertificateAndKeyPair): Pair<PartyAndCertificate, PartyAndCertificate> {
|
private fun createParty(x500Name: CordaX500Name, ca: CertificateAndKeyPair): Pair<PartyAndCertificate, PartyAndCertificate> {
|
||||||
val certFactory = CertificateFactory.getInstance("X509")
|
val certFactory = CertificateFactory.getInstance("X509")
|
||||||
val issuerKeyPair = generateKeyPair()
|
val issuerKeyPair = generateKeyPair()
|
||||||
val issuer = getTestPartyAndCertificate(x500Name, issuerKeyPair.public, ca)
|
val issuer = getTestPartyAndCertificate(x500Name, issuerKeyPair.public, ca)
|
||||||
val txKey = Crypto.generateKeyPair()
|
val txKey = Crypto.generateKeyPair()
|
||||||
val txCert = X509Utilities.createCertificate(CertificateType.IDENTITY, issuer.certificate, issuerKeyPair, x500Name, txKey.public)
|
val txCert = X509Utilities.createCertificate(CertificateType.IDENTITY, issuer.certificate, issuerKeyPair, x500Name.x500Name, txKey.public)
|
||||||
val txCertPath = certFactory.generateCertPath(listOf(txCert.cert) + issuer.certPath.certificates)
|
val txCertPath = certFactory.generateCertPath(listOf(txCert.cert) + issuer.certPath.certificates)
|
||||||
return Pair(issuer, PartyAndCertificate(txCertPath))
|
return Pair(issuer, PartyAndCertificate(txCertPath))
|
||||||
}
|
}
|
||||||
|
@ -3,20 +3,19 @@ package net.corda.node.services.network
|
|||||||
import net.corda.core.crypto.Crypto
|
import net.corda.core.crypto.Crypto
|
||||||
import net.corda.core.crypto.generateKeyPair
|
import net.corda.core.crypto.generateKeyPair
|
||||||
import net.corda.core.identity.AnonymousParty
|
import net.corda.core.identity.AnonymousParty
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.identity.PartyAndCertificate
|
import net.corda.core.identity.PartyAndCertificate
|
||||||
import net.corda.core.node.services.IdentityService
|
import net.corda.core.node.services.IdentityService
|
||||||
import net.corda.core.node.services.UnknownAnonymousPartyException
|
import net.corda.core.node.services.UnknownAnonymousPartyException
|
||||||
import net.corda.node.utilities.CertificateAndKeyPair
|
import net.corda.node.utilities.CertificateAndKeyPair
|
||||||
import net.corda.core.utilities.cert
|
import net.corda.core.utilities.cert
|
||||||
import net.corda.core.utilities.getX500Name
|
|
||||||
import net.corda.node.services.identity.PersistentIdentityService
|
import net.corda.node.services.identity.PersistentIdentityService
|
||||||
import net.corda.node.utilities.CertificateType
|
import net.corda.node.utilities.CertificateType
|
||||||
import net.corda.node.utilities.CordaPersistence
|
import net.corda.node.utilities.CordaPersistence
|
||||||
import net.corda.node.utilities.X509Utilities
|
import net.corda.node.utilities.X509Utilities
|
||||||
import net.corda.testing.*
|
import net.corda.testing.*
|
||||||
import net.corda.testing.node.MockServices
|
import net.corda.testing.node.MockServices
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
@ -97,7 +96,7 @@ class PersistentIdentityServiceTests {
|
|||||||
identityService.verifyAndRegisterIdentity(ALICE_IDENTITY)
|
identityService.verifyAndRegisterIdentity(ALICE_IDENTITY)
|
||||||
identityService.verifyAndRegisterIdentity(BOB_IDENTITY)
|
identityService.verifyAndRegisterIdentity(BOB_IDENTITY)
|
||||||
}
|
}
|
||||||
val alicente = getTestPartyAndCertificate(getX500Name(O = "Alicente Worldwide", L = "London", C = "GB"), generateKeyPair().public)
|
val alicente = getTestPartyAndCertificate(CordaX500Name(organisation = "Alicente Worldwide", locality = "London", country = "GB"), generateKeyPair().public)
|
||||||
database.transaction {
|
database.transaction {
|
||||||
identityService.verifyAndRegisterIdentity(alicente)
|
identityService.verifyAndRegisterIdentity(alicente)
|
||||||
assertEquals(setOf(ALICE, alicente.party), identityService.partiesFromName("Alice", false))
|
assertEquals(setOf(ALICE, alicente.party), identityService.partiesFromName("Alice", false))
|
||||||
@ -108,8 +107,8 @@ class PersistentIdentityServiceTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `get identity by name`() {
|
fun `get identity by name`() {
|
||||||
val identities = listOf("Node A", "Node B", "Node C")
|
val identities = listOf("Organisation A", "Organisation B", "Organisation C")
|
||||||
.map { getTestPartyAndCertificate(getX500Name(O = it, OU = "corda", L = "London", C = "GB"), generateKeyPair().public) }
|
.map { getTestPartyAndCertificate(CordaX500Name(organisation = it, locality = "London", country = "GB"), generateKeyPair().public) }
|
||||||
database.transaction {
|
database.transaction {
|
||||||
assertNull(identityService.partyFromX500Name(identities.first().name))
|
assertNull(identityService.partyFromX500Name(identities.first().name))
|
||||||
}
|
}
|
||||||
@ -132,7 +131,7 @@ class PersistentIdentityServiceTests {
|
|||||||
fun `assert unknown anonymous key is unrecognised`() {
|
fun `assert unknown anonymous key is unrecognised`() {
|
||||||
withTestSerialization {
|
withTestSerialization {
|
||||||
val rootKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
val rootKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||||
val rootCert = X509Utilities.createSelfSignedCACertificate(ALICE.name, rootKey)
|
val rootCert = X509Utilities.createSelfSignedCACertificate(ALICE.name.x500Name, rootKey)
|
||||||
val txKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_IDENTITY_SIGNATURE_SCHEME)
|
val txKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_IDENTITY_SIGNATURE_SCHEME)
|
||||||
val identity = Party(rootCert)
|
val identity = Party(rootCert)
|
||||||
val txIdentity = AnonymousParty(txKey.public)
|
val txIdentity = AnonymousParty(txKey.public)
|
||||||
@ -214,7 +213,8 @@ class PersistentIdentityServiceTests {
|
|||||||
assertFailsWith<IllegalArgumentException> {
|
assertFailsWith<IllegalArgumentException> {
|
||||||
val owningKey = Crypto.decodePublicKey(trustRoot.certificate.subjectPublicKeyInfo.encoded)
|
val owningKey = Crypto.decodePublicKey(trustRoot.certificate.subjectPublicKeyInfo.encoded)
|
||||||
database.transaction {
|
database.transaction {
|
||||||
identityService.assertOwnership(Party(trustRoot.certificate.subject, owningKey), anonymousAlice.party.anonymise())
|
val subject = CordaX500Name.build(trustRoot.certificate.subject)
|
||||||
|
identityService.assertOwnership(Party(subject, owningKey), anonymousAlice.party.anonymise())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -256,12 +256,12 @@ class PersistentIdentityServiceTests {
|
|||||||
assertEquals(anonymousBob, bobReload!!)
|
assertEquals(anonymousBob, bobReload!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createParty(x500Name: X500Name, ca: CertificateAndKeyPair): Pair<PartyAndCertificate, PartyAndCertificate> {
|
private fun createParty(x500Name: CordaX500Name, ca: CertificateAndKeyPair): Pair<PartyAndCertificate, PartyAndCertificate> {
|
||||||
val certFactory = CertificateFactory.getInstance("X509")
|
val certFactory = CertificateFactory.getInstance("X509")
|
||||||
val issuerKeyPair = generateKeyPair()
|
val issuerKeyPair = generateKeyPair()
|
||||||
val issuer = getTestPartyAndCertificate(x500Name, issuerKeyPair.public, ca)
|
val issuer = getTestPartyAndCertificate(x500Name, issuerKeyPair.public, ca)
|
||||||
val txKey = Crypto.generateKeyPair()
|
val txKey = Crypto.generateKeyPair()
|
||||||
val txCert = X509Utilities.createCertificate(CertificateType.IDENTITY, issuer.certificate, issuerKeyPair, x500Name, txKey.public)
|
val txCert = X509Utilities.createCertificate(CertificateType.IDENTITY, issuer.certificate, issuerKeyPair, x500Name.x500Name, txKey.public)
|
||||||
val txCertPath = certFactory.generateCertPath(listOf(txCert.cert) + issuer.certPath.certificates)
|
val txCertPath = certFactory.generateCertPath(listOf(txCert.cert) + issuer.certPath.certificates)
|
||||||
return Pair(issuer, PartyAndCertificate(txCertPath))
|
return Pair(issuer, PartyAndCertificate(txCertPath))
|
||||||
}
|
}
|
||||||
|
@ -4,13 +4,10 @@ import co.paralleluniverse.fibers.Suspendable
|
|||||||
import net.corda.core.flows.FlowLogic
|
import net.corda.core.flows.FlowLogic
|
||||||
import net.corda.core.flows.InitiatedBy
|
import net.corda.core.flows.InitiatedBy
|
||||||
import net.corda.core.flows.InitiatingFlow
|
import net.corda.core.flows.InitiatingFlow
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.node.NodeInfo
|
import net.corda.core.node.NodeInfo
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.*
|
||||||
import net.corda.core.utilities.getOrThrow
|
|
||||||
import net.corda.core.utilities.seconds
|
|
||||||
import net.corda.core.utilities.toBase58String
|
|
||||||
import net.corda.core.utilities.unwrap
|
|
||||||
import net.corda.node.internal.Node
|
import net.corda.node.internal.Node
|
||||||
import net.corda.testing.ALICE
|
import net.corda.testing.ALICE
|
||||||
import net.corda.testing.BOB
|
import net.corda.testing.BOB
|
||||||
@ -18,7 +15,6 @@ import net.corda.testing.CHARLIE
|
|||||||
import net.corda.testing.DUMMY_NOTARY
|
import net.corda.testing.DUMMY_NOTARY
|
||||||
import net.corda.testing.node.NodeBasedTest
|
import net.corda.testing.node.NodeBasedTest
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
@ -26,7 +22,7 @@ import kotlin.test.assertFails
|
|||||||
|
|
||||||
class PersistentNetworkMapCacheTest : NodeBasedTest() {
|
class PersistentNetworkMapCacheTest : NodeBasedTest() {
|
||||||
val partiesList = listOf(DUMMY_NOTARY, ALICE, BOB)
|
val partiesList = listOf(DUMMY_NOTARY, ALICE, BOB)
|
||||||
val addressesMap: HashMap<X500Name, NetworkHostAndPort> = HashMap()
|
val addressesMap: HashMap<CordaX500Name, NetworkHostAndPort> = HashMap()
|
||||||
val infos: MutableSet<NodeInfo> = HashSet()
|
val infos: MutableSet<NodeInfo> = HashSet()
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
|
@ -9,6 +9,7 @@ import net.corda.core.contracts.StateAndRef
|
|||||||
import net.corda.core.crypto.generateKeyPair
|
import net.corda.core.crypto.generateKeyPair
|
||||||
import net.corda.core.crypto.random63BitValue
|
import net.corda.core.crypto.random63BitValue
|
||||||
import net.corda.core.flows.*
|
import net.corda.core.flows.*
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.internal.concurrent.flatMap
|
import net.corda.core.internal.concurrent.flatMap
|
||||||
import net.corda.core.internal.concurrent.map
|
import net.corda.core.internal.concurrent.map
|
||||||
@ -21,8 +22,11 @@ import net.corda.core.serialization.serialize
|
|||||||
import net.corda.core.toFuture
|
import net.corda.core.toFuture
|
||||||
import net.corda.core.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
import net.corda.core.transactions.TransactionBuilder
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
import net.corda.core.utilities.*
|
import net.corda.core.utilities.OpaqueBytes
|
||||||
|
import net.corda.core.utilities.ProgressTracker
|
||||||
import net.corda.core.utilities.ProgressTracker.Change
|
import net.corda.core.utilities.ProgressTracker.Change
|
||||||
|
import net.corda.core.utilities.getOrThrow
|
||||||
|
import net.corda.core.utilities.unwrap
|
||||||
import net.corda.finance.DOLLARS
|
import net.corda.finance.DOLLARS
|
||||||
import net.corda.finance.flows.CashIssueFlow
|
import net.corda.finance.flows.CashIssueFlow
|
||||||
import net.corda.finance.flows.CashPaymentFlow
|
import net.corda.finance.flows.CashPaymentFlow
|
||||||
@ -77,7 +81,7 @@ class FlowFrameworkTests {
|
|||||||
|
|
||||||
// We intentionally create our own notary and ignore the one provided by the network
|
// We intentionally create our own notary and ignore the one provided by the network
|
||||||
val notaryKeyPair = generateKeyPair()
|
val notaryKeyPair = generateKeyPair()
|
||||||
val notaryService = ServiceInfo(ValidatingNotaryService.type, getX500Name(O = "notary-service-2000", L = "London", C = "GB"))
|
val notaryService = ServiceInfo(ValidatingNotaryService.type, CordaX500Name(organisation = "Notary service 2000", locality = "London", country = "GB"))
|
||||||
val overrideServices = mapOf(Pair(notaryService, notaryKeyPair))
|
val overrideServices = mapOf(Pair(notaryService, notaryKeyPair))
|
||||||
// Note that these notaries don't operate correctly as they don't share their state. They are only used for testing
|
// Note that these notaries don't operate correctly as they don't share their state. They are only used for testing
|
||||||
// service addressing.
|
// service addressing.
|
||||||
|
@ -3,6 +3,7 @@ package net.corda.node.services.vault
|
|||||||
import net.corda.core.contracts.*
|
import net.corda.core.contracts.*
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
import net.corda.core.crypto.entropyToKeyPair
|
import net.corda.core.crypto.entropyToKeyPair
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.identity.PartyAndCertificate
|
import net.corda.core.identity.PartyAndCertificate
|
||||||
import net.corda.core.node.services.*
|
import net.corda.core.node.services.*
|
||||||
@ -54,7 +55,7 @@ class VaultQueryTests : TestDependencyInjectionBase() {
|
|||||||
|
|
||||||
// test cash notary
|
// test cash notary
|
||||||
val CASH_NOTARY_KEY: KeyPair by lazy { entropyToKeyPair(BigInteger.valueOf(21)) }
|
val CASH_NOTARY_KEY: KeyPair by lazy { entropyToKeyPair(BigInteger.valueOf(21)) }
|
||||||
val CASH_NOTARY: Party get() = Party(getX500Name(O = "Cash Notary Service", OU = "corda", L = "Zurich", C = "CH"), CASH_NOTARY_KEY.public)
|
val CASH_NOTARY: Party get() = Party(CordaX500Name(organisation = "Cash Notary Service", locality = "Zurich", country = "CH"), CASH_NOTARY_KEY.public)
|
||||||
val CASH_NOTARY_IDENTITY: PartyAndCertificate get() = getTestPartyAndCertificate(CASH_NOTARY.nameOrNull(), CASH_NOTARY_KEY.public)
|
val CASH_NOTARY_IDENTITY: PartyAndCertificate get() = getTestPartyAndCertificate(CASH_NOTARY.nameOrNull(), CASH_NOTARY_KEY.public)
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
@ -1484,15 +1485,15 @@ class VaultQueryTests : TestDependencyInjectionBase() {
|
|||||||
fun `unconsumed fungible assets for selected issuer parties`() {
|
fun `unconsumed fungible assets for selected issuer parties`() {
|
||||||
// GBP issuer
|
// GBP issuer
|
||||||
val gbpCashIssuerKey = entropyToKeyPair(BigInteger.valueOf(1001))
|
val gbpCashIssuerKey = entropyToKeyPair(BigInteger.valueOf(1001))
|
||||||
val gbpCashIssuer = Party(getX500Name(O = "British Pounds Cash Issuer", OU = "corda", L = "London", C = "GB"), gbpCashIssuerKey.public).ref(1)
|
val gbpCashIssuer = Party(CordaX500Name(organisation = "British Pounds Cash Issuer", locality = "London", country = "GB"), gbpCashIssuerKey.public).ref(1)
|
||||||
val gbpCashIssuerServices = MockServices(gbpCashIssuerKey)
|
val gbpCashIssuerServices = MockServices(gbpCashIssuerKey)
|
||||||
// USD issuer
|
// USD issuer
|
||||||
val usdCashIssuerKey = entropyToKeyPair(BigInteger.valueOf(1002))
|
val usdCashIssuerKey = entropyToKeyPair(BigInteger.valueOf(1002))
|
||||||
val usdCashIssuer = Party(getX500Name(O = "US Dollars Cash Issuer", OU = "corda", L = "New York", C = "US"), usdCashIssuerKey.public).ref(1)
|
val usdCashIssuer = Party(CordaX500Name(organisation = "US Dollars Cash Issuer", locality = "New York", country = "US"), usdCashIssuerKey.public).ref(1)
|
||||||
val usdCashIssuerServices = MockServices(usdCashIssuerKey)
|
val usdCashIssuerServices = MockServices(usdCashIssuerKey)
|
||||||
// CHF issuer
|
// CHF issuer
|
||||||
val chfCashIssuerKey = entropyToKeyPair(BigInteger.valueOf(1003))
|
val chfCashIssuerKey = entropyToKeyPair(BigInteger.valueOf(1003))
|
||||||
val chfCashIssuer = Party(getX500Name(O = "Swiss Francs Cash Issuer", OU = "corda", L = "Zurich", C = "CH"), chfCashIssuerKey.public).ref(1)
|
val chfCashIssuer = Party(CordaX500Name(organisation = "Swiss Francs Cash Issuer", locality = "Zurich", country = "CH"), chfCashIssuerKey.public).ref(1)
|
||||||
val chfCashIssuerServices = MockServices(chfCashIssuerKey)
|
val chfCashIssuerServices = MockServices(chfCashIssuerKey)
|
||||||
|
|
||||||
database.transaction {
|
database.transaction {
|
||||||
|
@ -11,7 +11,6 @@ import net.corda.core.serialization.serialize
|
|||||||
import net.corda.core.utilities.cert
|
import net.corda.core.utilities.cert
|
||||||
import net.corda.core.utilities.commonName
|
import net.corda.core.utilities.commonName
|
||||||
import net.corda.core.utilities.getX500Name
|
import net.corda.core.utilities.getX500Name
|
||||||
import net.corda.core.utilities.organisation
|
|
||||||
import net.corda.node.serialization.KryoServerSerializationScheme
|
import net.corda.node.serialization.KryoServerSerializationScheme
|
||||||
import net.corda.node.services.config.createKeystoreForCordaNode
|
import net.corda.node.services.config.createKeystoreForCordaNode
|
||||||
import net.corda.nodeapi.internal.serialization.AllWhitelist
|
import net.corda.nodeapi.internal.serialization.AllWhitelist
|
||||||
@ -318,7 +317,7 @@ class X509UtilitiesTest {
|
|||||||
val peerChain = clientSocket.session.peerCertificates
|
val peerChain = clientSocket.session.peerCertificates
|
||||||
val peerX500Principal = (peerChain[0] as X509Certificate).subjectX500Principal
|
val peerX500Principal = (peerChain[0] as X509Certificate).subjectX500Principal
|
||||||
val x500name = X500Name(peerX500Principal.name)
|
val x500name = X500Name(peerX500Principal.name)
|
||||||
assertEquals(MEGA_CORP.name, x500name)
|
assertEquals(MEGA_CORP.name.x500Name, x500name)
|
||||||
X509Utilities.validateCertificateChain(trustStore.getX509Certificate(X509Utilities.CORDA_ROOT_CA), *peerChain)
|
X509Utilities.validateCertificateChain(trustStore.getX509Certificate(X509Utilities.CORDA_ROOT_CA), *peerChain)
|
||||||
val output = DataOutputStream(clientSocket.outputStream)
|
val output = DataOutputStream(clientSocket.outputStream)
|
||||||
output.writeUTF("Hello World")
|
output.writeUTF("Hello World")
|
||||||
@ -409,7 +408,7 @@ class X509UtilitiesTest {
|
|||||||
emptyMap(),
|
emptyMap(),
|
||||||
true,
|
true,
|
||||||
SerializationContext.UseCase.P2P)
|
SerializationContext.UseCase.P2P)
|
||||||
val expected: X509CertificateHolder = X509Utilities.createSelfSignedCACertificate(ALICE.name, Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME))
|
val expected: X509CertificateHolder = X509Utilities.createSelfSignedCACertificate(ALICE.name.x500Name, Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME))
|
||||||
val serialized = expected.serialize(factory, context).bytes
|
val serialized = expected.serialize(factory, context).bytes
|
||||||
val actual: X509CertificateHolder = serialized.deserialize(factory, context)
|
val actual: X509CertificateHolder = serialized.deserialize(factory, context)
|
||||||
assertEquals(expected, actual)
|
assertEquals(expected, actual)
|
||||||
@ -426,8 +425,8 @@ class X509UtilitiesTest {
|
|||||||
SerializationContext.UseCase.P2P)
|
SerializationContext.UseCase.P2P)
|
||||||
val certFactory = CertificateFactory.getInstance("X509")
|
val certFactory = CertificateFactory.getInstance("X509")
|
||||||
val rootCAKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
val rootCAKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||||
val rootCACert = X509Utilities.createSelfSignedCACertificate(ALICE.name, rootCAKey)
|
val rootCACert = X509Utilities.createSelfSignedCACertificate(ALICE.name.x500Name, rootCAKey)
|
||||||
val certificate = X509Utilities.createCertificate(CertificateType.TLS, rootCACert, rootCAKey, BOB.name, BOB_PUBKEY)
|
val certificate = X509Utilities.createCertificate(CertificateType.TLS, rootCACert, rootCAKey, BOB.name.x500Name, BOB_PUBKEY)
|
||||||
val expected = certFactory.generateCertPath(listOf(certificate.cert, rootCACert.cert))
|
val expected = certFactory.generateCertPath(listOf(certificate.cert, rootCACert.cert))
|
||||||
val serialized = expected.serialize(factory, context).bytes
|
val serialized = expected.serialize(factory, context).bytes
|
||||||
val actual: CertPath = serialized.deserialize(factory, context)
|
val actual: CertPath = serialized.deserialize(factory, context)
|
||||||
|
@ -5,6 +5,7 @@ import com.nhaarman.mockito_kotlin.eq
|
|||||||
import com.nhaarman.mockito_kotlin.mock
|
import com.nhaarman.mockito_kotlin.mock
|
||||||
import net.corda.core.crypto.Crypto
|
import net.corda.core.crypto.Crypto
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.internal.exists
|
import net.corda.core.internal.exists
|
||||||
import net.corda.core.internal.toTypedArray
|
import net.corda.core.internal.toTypedArray
|
||||||
import net.corda.core.internal.toX509CertHolder
|
import net.corda.core.internal.toX509CertHolder
|
||||||
@ -15,6 +16,7 @@ import net.corda.node.utilities.X509Utilities
|
|||||||
import net.corda.node.utilities.loadKeyStore
|
import net.corda.node.utilities.loadKeyStore
|
||||||
import net.corda.testing.ALICE
|
import net.corda.testing.ALICE
|
||||||
import net.corda.testing.testNodeConfiguration
|
import net.corda.testing.testNodeConfiguration
|
||||||
|
import org.bouncycastle.asn1.x500.X500Name
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.rules.TemporaryFolder
|
import org.junit.rules.TemporaryFolder
|
||||||
|
@ -37,9 +37,9 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
|
|||||||
ext.rpcUsers = [['username': "demo", 'password': "demo", 'permissions': ["StartFlow.net.corda.attachmentdemo.AttachmentDemoFlow"]]]
|
ext.rpcUsers = [['username': "demo", 'password': "demo", 'permissions': ["StartFlow.net.corda.attachmentdemo.AttachmentDemoFlow"]]]
|
||||||
|
|
||||||
directory "./build/nodes"
|
directory "./build/nodes"
|
||||||
networkMap "O=Notary Service,OU=corda,L=Zurich,C=CH"
|
networkMap "O=Notary Service,L=Zurich,C=CH"
|
||||||
node {
|
node {
|
||||||
name "O=Notary Service,OU=corda,L=Zurich,C=CH"
|
name "O=Notary Service,L=Zurich,C=CH"
|
||||||
advertisedServices["corda.notary.validating"]
|
advertisedServices["corda.notary.validating"]
|
||||||
p2pPort 10002
|
p2pPort 10002
|
||||||
rpcPort 10003
|
rpcPort 10003
|
||||||
|
@ -50,9 +50,9 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
|
|||||||
directory "./build/nodes"
|
directory "./build/nodes"
|
||||||
// This name "Notary" is hard-coded into BankOfCordaClientApi so if you change it here, change it there too.
|
// This name "Notary" is hard-coded into BankOfCordaClientApi so if you change it here, change it there too.
|
||||||
// In this demo the node that runs a standalone notary also acts as the network map server.
|
// In this demo the node that runs a standalone notary also acts as the network map server.
|
||||||
networkMap "O=Notary Service,OU=corda,L=Zurich,C=CH"
|
networkMap "O=Notary Service,L=Zurich,C=CH"
|
||||||
node {
|
node {
|
||||||
name "O=Notary Service,OU=corda,L=Zurich,C=CH"
|
name "O=Notary Service,L=Zurich,C=CH"
|
||||||
advertisedServices = ["corda.notary.validating"]
|
advertisedServices = ["corda.notary.validating"]
|
||||||
p2pPort 10002
|
p2pPort 10002
|
||||||
rpcPort 10003
|
rpcPort 10003
|
||||||
|
@ -3,10 +3,10 @@ package net.corda.bank
|
|||||||
import joptsimple.OptionParser
|
import joptsimple.OptionParser
|
||||||
import net.corda.bank.api.BankOfCordaClientApi
|
import net.corda.bank.api.BankOfCordaClientApi
|
||||||
import net.corda.bank.api.BankOfCordaWebApi.IssueRequestParams
|
import net.corda.bank.api.BankOfCordaWebApi.IssueRequestParams
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.node.services.ServiceInfo
|
import net.corda.core.node.services.ServiceInfo
|
||||||
import net.corda.core.node.services.ServiceType
|
import net.corda.core.node.services.ServiceType
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
import net.corda.core.utilities.getX500Name
|
|
||||||
import net.corda.finance.flows.CashExitFlow
|
import net.corda.finance.flows.CashExitFlow
|
||||||
import net.corda.finance.flows.CashIssueAndPaymentFlow
|
import net.corda.finance.flows.CashIssueAndPaymentFlow
|
||||||
import net.corda.finance.flows.CashPaymentFlow
|
import net.corda.finance.flows.CashPaymentFlow
|
||||||
@ -28,7 +28,7 @@ fun main(args: Array<String>) {
|
|||||||
val BANK_USERNAME = "bankUser"
|
val BANK_USERNAME = "bankUser"
|
||||||
val BIGCORP_USERNAME = "bigCorpUser"
|
val BIGCORP_USERNAME = "bigCorpUser"
|
||||||
|
|
||||||
val BIGCORP_LEGAL_NAME = getX500Name(O = "BigCorporation", OU = "corda", L = "London", C = "GB")
|
val BIGCORP_LEGAL_NAME = CordaX500Name(organisation = "BigCorporation", locality = "London", country = "GB")
|
||||||
|
|
||||||
private class BankOfCordaDriver {
|
private class BankOfCordaDriver {
|
||||||
enum class Role {
|
enum class Role {
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
package net.corda.bank.api
|
package net.corda.bank.api
|
||||||
|
|
||||||
import net.corda.core.contracts.Amount
|
import net.corda.core.contracts.Amount
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.messaging.CordaRPCOps
|
import net.corda.core.messaging.CordaRPCOps
|
||||||
import net.corda.core.messaging.startFlow
|
import net.corda.core.messaging.startFlow
|
||||||
import net.corda.core.utilities.OpaqueBytes
|
import net.corda.core.utilities.OpaqueBytes
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.core.utilities.loggerFor
|
import net.corda.core.utilities.loggerFor
|
||||||
import net.corda.finance.flows.CashIssueAndPaymentFlow
|
import net.corda.finance.flows.CashIssueAndPaymentFlow
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.ws.rs.*
|
import javax.ws.rs.*
|
||||||
@ -18,9 +18,9 @@ import javax.ws.rs.core.Response
|
|||||||
@Path("bank")
|
@Path("bank")
|
||||||
class BankOfCordaWebApi(val rpc: CordaRPCOps) {
|
class BankOfCordaWebApi(val rpc: CordaRPCOps) {
|
||||||
data class IssueRequestParams(val amount: Long, val currency: String,
|
data class IssueRequestParams(val amount: Long, val currency: String,
|
||||||
val issueToPartyName: X500Name, val issuerBankPartyRef: String,
|
val issueToPartyName: CordaX500Name, val issuerBankPartyRef: String,
|
||||||
val issuerBankName: X500Name,
|
val issuerBankName: CordaX500Name,
|
||||||
val notaryName: X500Name)
|
val notaryName: CordaX500Name)
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
val logger = loggerFor<BankOfCordaWebApi>()
|
val logger = loggerFor<BankOfCordaWebApi>()
|
||||||
|
@ -50,9 +50,9 @@ dependencies {
|
|||||||
|
|
||||||
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
|
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
|
||||||
directory "./build/nodes"
|
directory "./build/nodes"
|
||||||
networkMap "O=Notary Service,OU=corda,L=Zurich,C=CH"
|
networkMap "O=Notary Service,L=Zurich,C=CH"
|
||||||
node {
|
node {
|
||||||
name "O=Notary Service,OU=corda,L=Zurich,C=CH"
|
name "O=Notary Service,L=Zurich,C=CH"
|
||||||
advertisedServices = ["corda.notary.validating", "corda.interest_rates"]
|
advertisedServices = ["corda.notary.validating", "corda.interest_rates"]
|
||||||
p2pPort 10002
|
p2pPort 10002
|
||||||
rpcPort 10003
|
rpcPort 10003
|
||||||
|
@ -5,6 +5,7 @@ import net.corda.core.contracts.ContractState
|
|||||||
import net.corda.core.contracts.TransactionState
|
import net.corda.core.contracts.TransactionState
|
||||||
import net.corda.core.crypto.MerkleTreeException
|
import net.corda.core.crypto.MerkleTreeException
|
||||||
import net.corda.core.crypto.generateKeyPair
|
import net.corda.core.crypto.generateKeyPair
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.node.services.ServiceInfo
|
import net.corda.core.node.services.ServiceInfo
|
||||||
import net.corda.core.transactions.TransactionBuilder
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
@ -20,7 +21,6 @@ import net.corda.node.utilities.CordaPersistence
|
|||||||
import net.corda.node.utilities.configureDatabase
|
import net.corda.node.utilities.configureDatabase
|
||||||
import net.corda.testing.*
|
import net.corda.testing.*
|
||||||
import net.corda.testing.node.*
|
import net.corda.testing.node.*
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
@ -45,7 +45,7 @@ class NodeInterestRatesTest : TestDependencyInjectionBase() {
|
|||||||
""".trimIndent())
|
""".trimIndent())
|
||||||
|
|
||||||
val DUMMY_CASH_ISSUER_KEY = generateKeyPair()
|
val DUMMY_CASH_ISSUER_KEY = generateKeyPair()
|
||||||
val DUMMY_CASH_ISSUER = Party(getX500Name(O="Cash issuer",OU="corda",L="London",C="GB"), DUMMY_CASH_ISSUER_KEY.public)
|
val DUMMY_CASH_ISSUER = Party(CordaX500Name(organisation = "Cash issuer", locality = "London", country = "GB"), DUMMY_CASH_ISSUER_KEY.public)
|
||||||
|
|
||||||
lateinit var oracle: NodeInterestRates.Oracle
|
lateinit var oracle: NodeInterestRates.Oracle
|
||||||
lateinit var database: CordaPersistence
|
lateinit var database: CordaPersistence
|
||||||
|
@ -7,13 +7,11 @@ import javafx.scene.layout.StackPane
|
|||||||
import javafx.scene.shape.Circle
|
import javafx.scene.shape.Circle
|
||||||
import javafx.scene.shape.Line
|
import javafx.scene.shape.Line
|
||||||
import javafx.util.Duration
|
import javafx.util.Duration
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.node.ScreenCoordinate
|
import net.corda.core.node.ScreenCoordinate
|
||||||
import net.corda.core.utilities.ProgressTracker
|
import net.corda.core.utilities.ProgressTracker
|
||||||
import net.corda.core.utilities.getX500Name
|
|
||||||
import net.corda.core.utilities.organisation
|
|
||||||
import net.corda.netmap.simulation.IRSSimulation
|
import net.corda.netmap.simulation.IRSSimulation
|
||||||
import net.corda.testing.node.MockNetwork
|
import net.corda.testing.node.MockNetwork
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class VisualiserViewModel {
|
class VisualiserViewModel {
|
||||||
@ -128,7 +126,7 @@ class VisualiserViewModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun makeNodeWidget(forNode: MockNetwork.MockNode, type: String, label: X500Name = getX500Name(O = "Bank of Bologna", OU = "Corda QA Department", L = "Bologna", C = "IT"),
|
fun makeNodeWidget(forNode: MockNetwork.MockNode, type: String, label: CordaX500Name = CordaX500Name(organisation = "Bank of Bologna", locality = "Bologna", country = "IT"),
|
||||||
nodeType: NetworkMapVisualiser.NodeType, index: Int): NodeWidget {
|
nodeType: NetworkMapVisualiser.NodeType, index: Int): NodeWidget {
|
||||||
fun emitRadarPulse(initialRadius: Double, targetRadius: Double, duration: Double): Pair<Circle, Animation> {
|
fun emitRadarPulse(initialRadius: Double, targetRadius: Double, duration: Double): Pair<Circle, Animation> {
|
||||||
val pulse = Circle(initialRadius).apply {
|
val pulse = Circle(initialRadius).apply {
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
package net.corda.netmap.simulation
|
package net.corda.netmap.simulation
|
||||||
|
|
||||||
import net.corda.core.flows.FlowLogic
|
import net.corda.core.flows.FlowLogic
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.messaging.SingleMessageRecipient
|
import net.corda.core.messaging.SingleMessageRecipient
|
||||||
import net.corda.core.node.CityDatabase
|
import net.corda.core.node.CityDatabase
|
||||||
import net.corda.core.node.WorldMapLocation
|
import net.corda.core.node.WorldMapLocation
|
||||||
import net.corda.core.node.services.ServiceInfo
|
import net.corda.core.node.services.ServiceInfo
|
||||||
import net.corda.core.node.services.ServiceType
|
import net.corda.core.node.services.ServiceType
|
||||||
import net.corda.core.utilities.ProgressTracker
|
import net.corda.core.utilities.ProgressTracker
|
||||||
import net.corda.core.utilities.getX500Name
|
|
||||||
import net.corda.core.utilities.locality
|
|
||||||
import net.corda.irs.api.NodeInterestRates
|
import net.corda.irs.api.NodeInterestRates
|
||||||
import net.corda.node.services.config.NodeConfiguration
|
import net.corda.node.services.config.NodeConfiguration
|
||||||
import net.corda.node.services.network.NetworkMapService
|
import net.corda.node.services.network.NetworkMapService
|
||||||
@ -72,7 +71,7 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
|
|||||||
|
|
||||||
val cfg = testNodeConfiguration(
|
val cfg = testNodeConfiguration(
|
||||||
baseDirectory = config.baseDirectory,
|
baseDirectory = config.baseDirectory,
|
||||||
myLegalName = getX500Name(O = "Bank $letter", L = city, C = country))
|
myLegalName = CordaX500Name(organisation = "Bank $letter", locality = city, country = country))
|
||||||
return SimulatedNode(cfg, network, networkMapAddr, advertisedServices, id, overrideServices, entropyRoot)
|
return SimulatedNode(cfg, network, networkMapAddr, advertisedServices, id, overrideServices, entropyRoot)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +111,7 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
|
|||||||
|
|
||||||
object RatesOracleFactory : MockNetwork.Factory<SimulatedNode> {
|
object RatesOracleFactory : MockNetwork.Factory<SimulatedNode> {
|
||||||
// TODO: Make a more realistic legal name
|
// TODO: Make a more realistic legal name
|
||||||
val RATES_SERVICE_NAME = getX500Name(O = "Rates Service Provider", OU = "corda", L = "Madrid", C = "ES")
|
val RATES_SERVICE_NAME = CordaX500Name(organisation = "Rates Service Provider", locality = "Madrid", country = "ES")
|
||||||
|
|
||||||
override fun create(config: NodeConfiguration, network: MockNetwork, networkMapAddr: SingleMessageRecipient?,
|
override fun create(config: NodeConfiguration, network: MockNetwork, networkMapAddr: SingleMessageRecipient?,
|
||||||
advertisedServices: Set<ServiceInfo>, id: Int, overrideServices: Map<ServiceInfo, KeyPair>?,
|
advertisedServices: Set<ServiceInfo>, id: Int, overrideServices: Map<ServiceInfo, KeyPair>?,
|
||||||
|
@ -3,12 +3,12 @@ package net.corda.notarydemo
|
|||||||
import net.corda.cordform.CordformContext
|
import net.corda.cordform.CordformContext
|
||||||
import net.corda.cordform.CordformDefinition
|
import net.corda.cordform.CordformDefinition
|
||||||
import net.corda.cordform.CordformNode
|
import net.corda.cordform.CordformNode
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
import net.corda.core.internal.stream
|
import net.corda.core.internal.stream
|
||||||
import net.corda.core.internal.toTypedArray
|
import net.corda.core.internal.toTypedArray
|
||||||
import net.corda.core.node.services.ServiceInfo
|
import net.corda.core.node.services.ServiceInfo
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
import net.corda.core.utilities.getX500Name
|
|
||||||
import net.corda.demorun.runNodes
|
import net.corda.demorun.runNodes
|
||||||
import net.corda.demorun.util.*
|
import net.corda.demorun.util.*
|
||||||
import net.corda.node.services.transactions.BFTNonValidatingNotaryService
|
import net.corda.node.services.transactions.BFTNonValidatingNotaryService
|
||||||
@ -22,8 +22,8 @@ fun main(args: Array<String>) = BFTNotaryCordform.runNodes()
|
|||||||
private val clusterSize = 4 // Minimum size that tolerates a faulty replica.
|
private val clusterSize = 4 // Minimum size that tolerates a faulty replica.
|
||||||
private val notaryNames = createNotaryNames(clusterSize)
|
private val notaryNames = createNotaryNames(clusterSize)
|
||||||
|
|
||||||
object BFTNotaryCordform : CordformDefinition("build" / "notary-demo-nodes", notaryNames[0]) {
|
object BFTNotaryCordform : CordformDefinition("build" / "notary-demo-nodes", notaryNames[0].x500Name) {
|
||||||
private val clusterName = getX500Name(O = "BFT", OU = "corda", L = "Zurich", C = "CH")
|
private val clusterName = CordaX500Name(organisation = "BFT", locality = "Zurich", country = "CH")
|
||||||
private val advertisedService = ServiceInfo(BFTNonValidatingNotaryService.type, clusterName)
|
private val advertisedService = ServiceInfo(BFTNonValidatingNotaryService.type, clusterName)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@ -65,6 +65,6 @@ object BFTNotaryCordform : CordformDefinition("build" / "notary-demo-nodes", not
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun setup(context: CordformContext) {
|
override fun setup(context: CordformContext) {
|
||||||
ServiceIdentityGenerator.generateToDisk(notaryNames.map { context.baseDirectory(it) }, advertisedService.type.id, clusterName, minCorrectReplicas(clusterSize))
|
ServiceIdentityGenerator.generateToDisk(notaryNames.map { context.baseDirectory(it.x500Name) }, advertisedService.type.id, clusterName, minCorrectReplicas(clusterSize))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,10 @@ package net.corda.notarydemo
|
|||||||
import net.corda.cordform.CordformContext
|
import net.corda.cordform.CordformContext
|
||||||
import net.corda.cordform.CordformDefinition
|
import net.corda.cordform.CordformDefinition
|
||||||
import net.corda.cordform.CordformNode
|
import net.corda.cordform.CordformNode
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
import net.corda.core.node.services.ServiceInfo
|
import net.corda.core.node.services.ServiceInfo
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
import net.corda.core.utilities.getX500Name
|
|
||||||
import net.corda.demorun.runNodes
|
import net.corda.demorun.runNodes
|
||||||
import net.corda.demorun.util.*
|
import net.corda.demorun.util.*
|
||||||
import net.corda.node.services.transactions.RaftValidatingNotaryService
|
import net.corda.node.services.transactions.RaftValidatingNotaryService
|
||||||
@ -16,12 +16,12 @@ import net.corda.testing.BOB
|
|||||||
|
|
||||||
fun main(args: Array<String>) = RaftNotaryCordform.runNodes()
|
fun main(args: Array<String>) = RaftNotaryCordform.runNodes()
|
||||||
|
|
||||||
internal fun createNotaryNames(clusterSize: Int) = (0 until clusterSize).map { getX500Name(O = "Notary Service $it", OU = "corda", L = "Zurich", C = "CH") }
|
internal fun createNotaryNames(clusterSize: Int) = (0 until clusterSize).map { CordaX500Name(commonName ="Notary Service $it", organisationUnit = "corda", organisation = "R3 Ltd", locality = "Zurich", state = null, country = "CH") }
|
||||||
|
|
||||||
private val notaryNames = createNotaryNames(3)
|
private val notaryNames = createNotaryNames(3)
|
||||||
|
|
||||||
object RaftNotaryCordform : CordformDefinition("build" / "notary-demo-nodes", notaryNames[0]) {
|
object RaftNotaryCordform : CordformDefinition("build" / "notary-demo-nodes", notaryNames[0].x500Name) {
|
||||||
private val clusterName = getX500Name(O = "Raft", OU = "corda", L = "Zurich", C = "CH")
|
private val clusterName = CordaX500Name(organisation = "Raft", locality = "Zurich", country = "CH")
|
||||||
private val advertisedService = ServiceInfo(RaftValidatingNotaryService.type, clusterName)
|
private val advertisedService = ServiceInfo(RaftValidatingNotaryService.type, clusterName)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@ -62,6 +62,6 @@ object RaftNotaryCordform : CordformDefinition("build" / "notary-demo-nodes", no
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun setup(context: CordformContext) {
|
override fun setup(context: CordformContext) {
|
||||||
ServiceIdentityGenerator.generateToDisk(notaryNames.map { context.baseDirectory(it) }, advertisedService.type.id, clusterName)
|
ServiceIdentityGenerator.generateToDisk(notaryNames.map { context.baseDirectory(it.x500Name) }, advertisedService.type.id, clusterName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ fun main(args: Array<String>) = SingleNotaryCordform.runNodes()
|
|||||||
|
|
||||||
val notaryDemoUser = User("demou", "demop", setOf(startFlowPermission<DummyIssueAndMove>(), startFlowPermission<RPCStartableNotaryFlowClient>()))
|
val notaryDemoUser = User("demou", "demop", setOf(startFlowPermission<DummyIssueAndMove>(), startFlowPermission<RPCStartableNotaryFlowClient>()))
|
||||||
|
|
||||||
object SingleNotaryCordform : CordformDefinition("build" / "notary-demo-nodes", DUMMY_NOTARY.name) {
|
object SingleNotaryCordform : CordformDefinition("build" / "notary-demo-nodes", DUMMY_NOTARY.name.x500Name) {
|
||||||
init {
|
init {
|
||||||
node {
|
node {
|
||||||
name(ALICE.name)
|
name(ALICE.name)
|
||||||
|
@ -63,9 +63,9 @@ dependencies {
|
|||||||
|
|
||||||
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
|
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
|
||||||
directory "./build/nodes"
|
directory "./build/nodes"
|
||||||
networkMap "O=Notary Service,OU=corda,L=Zurich,C=CH"
|
networkMap "O=Notary Service,L=Zurich,C=CH"
|
||||||
node {
|
node {
|
||||||
name "O=Notary Service,OU=corda,L=Zurich,C=CH"
|
name "O=Notary Service,L=Zurich,C=CH"
|
||||||
advertisedServices = ["corda.notary.validating"]
|
advertisedServices = ["corda.notary.validating"]
|
||||||
p2pPort 10002
|
p2pPort 10002
|
||||||
cordapps = ["net.corda:finance:$corda_release_version"]
|
cordapps = ["net.corda:finance:$corda_release_version"]
|
||||||
|
@ -1,21 +1,21 @@
|
|||||||
package net.corda.vega
|
package net.corda.vega
|
||||||
|
|
||||||
import com.opengamma.strata.product.common.BuySell
|
import com.opengamma.strata.product.common.BuySell
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.node.services.ServiceInfo
|
import net.corda.core.node.services.ServiceInfo
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
|
import net.corda.node.services.transactions.SimpleNotaryService
|
||||||
import net.corda.testing.DUMMY_BANK_A
|
import net.corda.testing.DUMMY_BANK_A
|
||||||
import net.corda.testing.DUMMY_BANK_B
|
import net.corda.testing.DUMMY_BANK_B
|
||||||
import net.corda.testing.DUMMY_NOTARY
|
import net.corda.testing.DUMMY_NOTARY
|
||||||
import net.corda.testing.driver.driver
|
|
||||||
import net.corda.node.services.transactions.SimpleNotaryService
|
|
||||||
import net.corda.testing.IntegrationTestCategory
|
import net.corda.testing.IntegrationTestCategory
|
||||||
|
import net.corda.testing.driver.driver
|
||||||
import net.corda.testing.http.HttpApi
|
import net.corda.testing.http.HttpApi
|
||||||
import net.corda.vega.api.PortfolioApi
|
import net.corda.vega.api.PortfolioApi
|
||||||
import net.corda.vega.api.PortfolioApiUtils
|
import net.corda.vega.api.PortfolioApiUtils
|
||||||
import net.corda.vega.api.SwapDataModel
|
import net.corda.vega.api.SwapDataModel
|
||||||
import net.corda.vega.api.SwapDataView
|
import net.corda.vega.api.SwapDataView
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
@ -52,7 +52,7 @@ class SimmValuationTest : IntegrationTestCategory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getPartyWithName(partyApi: HttpApi, counterparty: X500Name): PortfolioApi.ApiParty {
|
private fun getPartyWithName(partyApi: HttpApi, counterparty: CordaX500Name): PortfolioApi.ApiParty {
|
||||||
return getAvailablePartiesFor(partyApi).counterparties.single { it.text == counterparty }
|
return getAvailablePartiesFor(partyApi).counterparties.single { it.text == counterparty }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import net.corda.core.contracts.StateAndRef
|
|||||||
import net.corda.core.utilities.parsePublicKeyBase58
|
import net.corda.core.utilities.parsePublicKeyBase58
|
||||||
import net.corda.core.utilities.toBase58String
|
import net.corda.core.utilities.toBase58String
|
||||||
import net.corda.core.identity.AbstractParty
|
import net.corda.core.identity.AbstractParty
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.messaging.CordaRPCOps
|
import net.corda.core.messaging.CordaRPCOps
|
||||||
import net.corda.core.messaging.startFlow
|
import net.corda.core.messaging.startFlow
|
||||||
@ -242,7 +243,7 @@ class PortfolioApi(val rpc: CordaRPCOps) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class ApiParty(val id: String, val text: X500Name)
|
data class ApiParty(val id: String, val text: CordaX500Name)
|
||||||
data class AvailableParties(val self: ApiParty, val counterparties: List<ApiParty>)
|
data class AvailableParties(val self: ApiParty, val counterparties: List<ApiParty>)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -51,9 +51,9 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
|
|||||||
directory "./build/nodes"
|
directory "./build/nodes"
|
||||||
// This name "Notary" is hard-coded into TraderDemoClientApi so if you change it here, change it there too.
|
// This name "Notary" is hard-coded into TraderDemoClientApi so if you change it here, change it there too.
|
||||||
// In this demo the node that runs a standalone notary also acts as the network map server.
|
// In this demo the node that runs a standalone notary also acts as the network map server.
|
||||||
networkMap "O=Notary Service,OU=corda,L=Zurich,C=CH"
|
networkMap "O=Notary Service,L=Zurich,C=CH"
|
||||||
node {
|
node {
|
||||||
name "O=Notary Service,OU=corda,L=Zurich,C=CH"
|
name "O=Notary Service,L=Zurich,C=CH"
|
||||||
advertisedServices = ["corda.notary.validating"]
|
advertisedServices = ["corda.notary.validating"]
|
||||||
p2pPort 10002
|
p2pPort 10002
|
||||||
cordapps = ["net.corda:finance:$corda_release_version"]
|
cordapps = ["net.corda:finance:$corda_release_version"]
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package net.corda.traderdemo
|
package net.corda.traderdemo
|
||||||
|
|
||||||
import net.corda.core.contracts.Amount
|
import net.corda.core.contracts.Amount
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.internal.Emoji
|
import net.corda.core.internal.Emoji
|
||||||
import net.corda.core.messaging.CordaRPCOps
|
import net.corda.core.messaging.CordaRPCOps
|
||||||
import net.corda.core.messaging.startFlow
|
import net.corda.core.messaging.startFlow
|
||||||
@ -21,7 +22,6 @@ import net.corda.testing.DUMMY_NOTARY
|
|||||||
import net.corda.testing.contracts.calculateRandomlySizedAmounts
|
import net.corda.testing.contracts.calculateRandomlySizedAmounts
|
||||||
import net.corda.traderdemo.flow.CommercialPaperIssueFlow
|
import net.corda.traderdemo.flow.CommercialPaperIssueFlow
|
||||||
import net.corda.traderdemo.flow.SellerFlow
|
import net.corda.traderdemo.flow.SellerFlow
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -42,7 +42,7 @@ class TraderDemoClientApi(val rpc: CordaRPCOps) {
|
|||||||
return rpc.vaultQueryBy<CommercialPaper.State>(countCriteria).otherResults.single() as Long
|
return rpc.vaultQueryBy<CommercialPaper.State>(countCriteria).otherResults.single() as Long
|
||||||
}
|
}
|
||||||
|
|
||||||
fun runIssuer(amount: Amount<Currency>, buyerName: X500Name, sellerName: X500Name) {
|
fun runIssuer(amount: Amount<Currency>, buyerName: CordaX500Name, sellerName: CordaX500Name) {
|
||||||
val ref = OpaqueBytes.of(1)
|
val ref = OpaqueBytes.of(1)
|
||||||
val buyer = rpc.partyFromX500Name(buyerName) ?: throw IllegalStateException("Don't know $buyerName")
|
val buyer = rpc.partyFromX500Name(buyerName) ?: throw IllegalStateException("Don't know $buyerName")
|
||||||
val seller = rpc.partyFromX500Name(sellerName) ?: throw IllegalStateException("Don't know $sellerName")
|
val seller = rpc.partyFromX500Name(sellerName) ?: throw IllegalStateException("Don't know $sellerName")
|
||||||
@ -75,7 +75,7 @@ class TraderDemoClientApi(val rpc: CordaRPCOps) {
|
|||||||
println("Commercial paper issued to seller")
|
println("Commercial paper issued to seller")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun runSeller(amount: Amount<Currency> = 1000.0.DOLLARS, buyerName: X500Name) {
|
fun runSeller(amount: Amount<Currency> = 1000.0.DOLLARS, buyerName: CordaX500Name) {
|
||||||
val otherParty = rpc.partyFromX500Name(buyerName) ?: throw IllegalStateException("Don't know $buyerName")
|
val otherParty = rpc.partyFromX500Name(buyerName) ?: throw IllegalStateException("Don't know $buyerName")
|
||||||
// The seller will sell some commercial paper to the buyer, who will pay with (self issued) cash.
|
// The seller will sell some commercial paper to the buyer, who will pay with (self issued) cash.
|
||||||
//
|
//
|
||||||
|
@ -2,6 +2,7 @@ package net.corda.demorun
|
|||||||
|
|
||||||
import net.corda.cordform.CordformDefinition
|
import net.corda.cordform.CordformDefinition
|
||||||
import net.corda.cordform.CordformNode
|
import net.corda.cordform.CordformNode
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.testing.driver.NetworkMapStartStrategy
|
import net.corda.testing.driver.NetworkMapStartStrategy
|
||||||
import net.corda.testing.driver.PortAllocation
|
import net.corda.testing.driver.PortAllocation
|
||||||
import net.corda.testing.driver.driver
|
import net.corda.testing.driver.driver
|
||||||
@ -17,7 +18,7 @@ fun CordformDefinition.clean() {
|
|||||||
fun CordformDefinition.runNodes() = driver(
|
fun CordformDefinition.runNodes() = driver(
|
||||||
isDebug = true,
|
isDebug = true,
|
||||||
driverDirectory = driverDirectory,
|
driverDirectory = driverDirectory,
|
||||||
networkMapStartStrategy = NetworkMapStartStrategy.Nominated(networkMapNodeName),
|
networkMapStartStrategy = NetworkMapStartStrategy.Nominated(CordaX500Name.build(networkMapNodeName)),
|
||||||
portAllocation = PortAllocation.Incremental(10001)
|
portAllocation = PortAllocation.Incremental(10001)
|
||||||
) {
|
) {
|
||||||
setup(this)
|
setup(this)
|
||||||
|
@ -2,6 +2,7 @@ package net.corda.demorun.util
|
|||||||
|
|
||||||
import net.corda.cordform.CordformDefinition
|
import net.corda.cordform.CordformDefinition
|
||||||
import net.corda.cordform.CordformNode
|
import net.corda.cordform.CordformNode
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.node.services.ServiceInfo
|
import net.corda.core.node.services.ServiceInfo
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
import net.corda.nodeapi.User
|
import net.corda.nodeapi.User
|
||||||
@ -11,7 +12,7 @@ fun CordformDefinition.node(configure: CordformNode.() -> Unit) {
|
|||||||
addNode { cordformNode -> cordformNode.configure() }
|
addNode { cordformNode -> cordformNode.configure() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun CordformNode.name(name: X500Name) = name(name.toString())
|
fun CordformNode.name(name: CordaX500Name) = name(name.toString())
|
||||||
|
|
||||||
fun CordformNode.rpcUsers(vararg users: User) {
|
fun CordformNode.rpcUsers(vararg users: User) {
|
||||||
rpcUsers = users.map { it.toMap() }
|
rpcUsers = users.map { it.toMap() }
|
||||||
|
@ -4,16 +4,14 @@ package net.corda.testing
|
|||||||
|
|
||||||
import com.nhaarman.mockito_kotlin.spy
|
import com.nhaarman.mockito_kotlin.spy
|
||||||
import com.nhaarman.mockito_kotlin.whenever
|
import com.nhaarman.mockito_kotlin.whenever
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.node.ServiceHub
|
import net.corda.core.node.ServiceHub
|
||||||
import net.corda.core.transactions.TransactionBuilder
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
import net.corda.core.utilities.commonName
|
|
||||||
import net.corda.core.utilities.organisation
|
|
||||||
import net.corda.node.services.config.NodeConfiguration
|
import net.corda.node.services.config.NodeConfiguration
|
||||||
import net.corda.node.services.config.VerifierType
|
import net.corda.node.services.config.VerifierType
|
||||||
import net.corda.testing.node.MockServices
|
import net.corda.testing.node.MockServices
|
||||||
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
|
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
|
||||||
import net.corda.testing.node.MockServices.Companion.makeTestDatabaseProperties
|
import net.corda.testing.node.MockServices.Companion.makeTestDatabaseProperties
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
|
|
||||||
@ -52,7 +50,7 @@ import java.nio.file.Path
|
|||||||
|
|
||||||
fun testNodeConfiguration(
|
fun testNodeConfiguration(
|
||||||
baseDirectory: Path,
|
baseDirectory: Path,
|
||||||
myLegalName: X500Name): NodeConfiguration {
|
myLegalName: CordaX500Name): NodeConfiguration {
|
||||||
abstract class MockableNodeConfiguration : NodeConfiguration // Otherwise Mockito is defeated by val getters.
|
abstract class MockableNodeConfiguration : NodeConfiguration // Otherwise Mockito is defeated by val getters.
|
||||||
val nc = spy<MockableNodeConfiguration>()
|
val nc = spy<MockableNodeConfiguration>()
|
||||||
whenever(nc.baseDirectory).thenReturn(baseDirectory)
|
whenever(nc.baseDirectory).thenReturn(baseDirectory)
|
||||||
|
@ -6,6 +6,7 @@ import net.corda.client.rpc.internal.RPCClient
|
|||||||
import net.corda.client.rpc.internal.RPCClientConfiguration
|
import net.corda.client.rpc.internal.RPCClientConfiguration
|
||||||
import net.corda.core.concurrent.CordaFuture
|
import net.corda.core.concurrent.CordaFuture
|
||||||
import net.corda.core.crypto.random63BitValue
|
import net.corda.core.crypto.random63BitValue
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.internal.concurrent.fork
|
import net.corda.core.internal.concurrent.fork
|
||||||
import net.corda.core.internal.concurrent.map
|
import net.corda.core.internal.concurrent.map
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
@ -42,7 +43,6 @@ import org.apache.activemq.artemis.core.settings.impl.AddressFullMessagePolicy
|
|||||||
import org.apache.activemq.artemis.core.settings.impl.AddressSettings
|
import org.apache.activemq.artemis.core.settings.impl.AddressSettings
|
||||||
import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection
|
import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection
|
||||||
import org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager3
|
import org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager3
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import java.lang.reflect.Method
|
import java.lang.reflect.Method
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
@ -60,7 +60,7 @@ interface RPCDriverExposedDSLInterface : DriverDSLExposedInterface {
|
|||||||
*/
|
*/
|
||||||
fun <I : RPCOps> startInVmRpcServer(
|
fun <I : RPCOps> startInVmRpcServer(
|
||||||
rpcUser: User = rpcTestUser,
|
rpcUser: User = rpcTestUser,
|
||||||
nodeLegalName: X500Name = fakeNodeLegalName,
|
nodeLegalName: CordaX500Name = fakeNodeLegalName,
|
||||||
maxFileSize: Int = ArtemisMessagingServer.MAX_FILE_SIZE,
|
maxFileSize: Int = ArtemisMessagingServer.MAX_FILE_SIZE,
|
||||||
maxBufferedBytesPerClient: Long = 10L * ArtemisMessagingServer.MAX_FILE_SIZE,
|
maxBufferedBytesPerClient: Long = 10L * ArtemisMessagingServer.MAX_FILE_SIZE,
|
||||||
configuration: RPCServerConfiguration = RPCServerConfiguration.default,
|
configuration: RPCServerConfiguration = RPCServerConfiguration.default,
|
||||||
@ -105,7 +105,7 @@ interface RPCDriverExposedDSLInterface : DriverDSLExposedInterface {
|
|||||||
fun <I : RPCOps> startRpcServer(
|
fun <I : RPCOps> startRpcServer(
|
||||||
serverName: String = "driver-rpc-server-${random63BitValue()}",
|
serverName: String = "driver-rpc-server-${random63BitValue()}",
|
||||||
rpcUser: User = rpcTestUser,
|
rpcUser: User = rpcTestUser,
|
||||||
nodeLegalName: X500Name = fakeNodeLegalName,
|
nodeLegalName: CordaX500Name = fakeNodeLegalName,
|
||||||
maxFileSize: Int = ArtemisMessagingServer.MAX_FILE_SIZE,
|
maxFileSize: Int = ArtemisMessagingServer.MAX_FILE_SIZE,
|
||||||
maxBufferedBytesPerClient: Long = 10L * ArtemisMessagingServer.MAX_FILE_SIZE,
|
maxBufferedBytesPerClient: Long = 10L * ArtemisMessagingServer.MAX_FILE_SIZE,
|
||||||
configuration: RPCServerConfiguration = RPCServerConfiguration.default,
|
configuration: RPCServerConfiguration = RPCServerConfiguration.default,
|
||||||
@ -174,7 +174,7 @@ interface RPCDriverExposedDSLInterface : DriverDSLExposedInterface {
|
|||||||
|
|
||||||
fun <I : RPCOps> startRpcServerWithBrokerRunning(
|
fun <I : RPCOps> startRpcServerWithBrokerRunning(
|
||||||
rpcUser: User = rpcTestUser,
|
rpcUser: User = rpcTestUser,
|
||||||
nodeLegalName: X500Name = fakeNodeLegalName,
|
nodeLegalName: CordaX500Name = fakeNodeLegalName,
|
||||||
configuration: RPCServerConfiguration = RPCServerConfiguration.default,
|
configuration: RPCServerConfiguration = RPCServerConfiguration.default,
|
||||||
ops: I,
|
ops: I,
|
||||||
brokerHandle: RpcBrokerHandle
|
brokerHandle: RpcBrokerHandle
|
||||||
@ -211,7 +211,7 @@ data class RpcServerHandle(
|
|||||||
)
|
)
|
||||||
|
|
||||||
val rpcTestUser = User("user1", "test", permissions = emptySet())
|
val rpcTestUser = User("user1", "test", permissions = emptySet())
|
||||||
val fakeNodeLegalName = X500Name("CN=not:a:valid:name")
|
val fakeNodeLegalName = CordaX500Name(organisation = "Not:a:real:name", locality = "Nowhere", country = "GB")
|
||||||
|
|
||||||
// Use a global pool so that we can run RPC tests in parallel
|
// Use a global pool so that we can run RPC tests in parallel
|
||||||
private val globalPortAllocation = PortAllocation.Incremental(10000)
|
private val globalPortAllocation = PortAllocation.Incremental(10000)
|
||||||
@ -327,7 +327,7 @@ data class RPCDriverDSL(
|
|||||||
|
|
||||||
override fun <I : RPCOps> startInVmRpcServer(
|
override fun <I : RPCOps> startInVmRpcServer(
|
||||||
rpcUser: User,
|
rpcUser: User,
|
||||||
nodeLegalName: X500Name,
|
nodeLegalName: CordaX500Name,
|
||||||
maxFileSize: Int,
|
maxFileSize: Int,
|
||||||
maxBufferedBytesPerClient: Long,
|
maxBufferedBytesPerClient: Long,
|
||||||
configuration: RPCServerConfiguration,
|
configuration: RPCServerConfiguration,
|
||||||
@ -364,7 +364,7 @@ data class RPCDriverDSL(
|
|||||||
override fun <I : RPCOps> startRpcServer(
|
override fun <I : RPCOps> startRpcServer(
|
||||||
serverName: String,
|
serverName: String,
|
||||||
rpcUser: User,
|
rpcUser: User,
|
||||||
nodeLegalName: X500Name,
|
nodeLegalName: CordaX500Name,
|
||||||
maxFileSize: Int,
|
maxFileSize: Int,
|
||||||
maxBufferedBytesPerClient: Long,
|
maxBufferedBytesPerClient: Long,
|
||||||
configuration: RPCServerConfiguration,
|
configuration: RPCServerConfiguration,
|
||||||
@ -460,7 +460,7 @@ data class RPCDriverDSL(
|
|||||||
|
|
||||||
override fun <I : RPCOps> startRpcServerWithBrokerRunning(
|
override fun <I : RPCOps> startRpcServerWithBrokerRunning(
|
||||||
rpcUser: User,
|
rpcUser: User,
|
||||||
nodeLegalName: X500Name,
|
nodeLegalName: CordaX500Name,
|
||||||
configuration: RPCServerConfiguration,
|
configuration: RPCServerConfiguration,
|
||||||
ops: I,
|
ops: I,
|
||||||
brokerHandle: RpcBrokerHandle
|
brokerHandle: RpcBrokerHandle
|
||||||
|
@ -11,6 +11,7 @@ import net.corda.cordform.CordformNode
|
|||||||
import net.corda.cordform.NodeDefinition
|
import net.corda.cordform.NodeDefinition
|
||||||
import net.corda.core.concurrent.CordaFuture
|
import net.corda.core.concurrent.CordaFuture
|
||||||
import net.corda.core.concurrent.firstOf
|
import net.corda.core.concurrent.firstOf
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.internal.ThreadBox
|
import net.corda.core.internal.ThreadBox
|
||||||
import net.corda.core.internal.concurrent.*
|
import net.corda.core.internal.concurrent.*
|
||||||
@ -88,7 +89,7 @@ interface DriverDSLExposedInterface : CordformContext {
|
|||||||
*/
|
*/
|
||||||
fun startNode(
|
fun startNode(
|
||||||
defaultParameters: NodeParameters = NodeParameters(),
|
defaultParameters: NodeParameters = NodeParameters(),
|
||||||
providedName: X500Name? = defaultParameters.providedName,
|
providedName: CordaX500Name? = defaultParameters.providedName,
|
||||||
advertisedServices: Set<ServiceInfo> = defaultParameters.advertisedServices,
|
advertisedServices: Set<ServiceInfo> = defaultParameters.advertisedServices,
|
||||||
rpcUsers: List<User> = defaultParameters.rpcUsers,
|
rpcUsers: List<User> = defaultParameters.rpcUsers,
|
||||||
verifierType: VerifierType = defaultParameters.verifierType,
|
verifierType: VerifierType = defaultParameters.verifierType,
|
||||||
@ -124,7 +125,7 @@ interface DriverDSLExposedInterface : CordformContext {
|
|||||||
* @return The [Party] identity of the distributed notary service, and the [NodeInfo]s of the notaries in the cluster.
|
* @return The [Party] identity of the distributed notary service, and the [NodeInfo]s of the notaries in the cluster.
|
||||||
*/
|
*/
|
||||||
fun startNotaryCluster(
|
fun startNotaryCluster(
|
||||||
notaryName: X500Name,
|
notaryName: CordaX500Name,
|
||||||
clusterSize: Int = 3,
|
clusterSize: Int = 3,
|
||||||
type: ServiceType = RaftValidatingNotaryService.type,
|
type: ServiceType = RaftValidatingNotaryService.type,
|
||||||
verifierType: VerifierType = VerifierType.InMemory,
|
verifierType: VerifierType = VerifierType.InMemory,
|
||||||
@ -252,14 +253,14 @@ sealed class PortAllocation {
|
|||||||
* Helper builder for configuring a [node] from Java.
|
* Helper builder for configuring a [node] from Java.
|
||||||
*/
|
*/
|
||||||
data class NodeParameters(
|
data class NodeParameters(
|
||||||
val providedName: X500Name? = null,
|
val providedName: CordaX500Name? = null,
|
||||||
val advertisedServices: Set<ServiceInfo> = emptySet(),
|
val advertisedServices: Set<ServiceInfo> = emptySet(),
|
||||||
val rpcUsers: List<User> = emptyList(),
|
val rpcUsers: List<User> = emptyList(),
|
||||||
val verifierType: VerifierType = VerifierType.InMemory,
|
val verifierType: VerifierType = VerifierType.InMemory,
|
||||||
val customOverrides: Map<String, Any?> = emptyMap(),
|
val customOverrides: Map<String, Any?> = emptyMap(),
|
||||||
val startInSameProcess: Boolean? = null
|
val startInSameProcess: Boolean? = null
|
||||||
) {
|
) {
|
||||||
fun setProvidedName(providedName: X500Name?) = copy(providedName = providedName)
|
fun setProvidedName(providedName: CordaX500Name?) = copy(providedName = providedName)
|
||||||
fun setAdvertisedServices(advertisedServices: Set<ServiceInfo>) = copy(advertisedServices = advertisedServices)
|
fun setAdvertisedServices(advertisedServices: Set<ServiceInfo>) = copy(advertisedServices = advertisedServices)
|
||||||
fun setRpcUsers(rpcUsers: List<User>) = copy(rpcUsers = rpcUsers)
|
fun setRpcUsers(rpcUsers: List<User>) = copy(rpcUsers = rpcUsers)
|
||||||
fun setVerifierType(verifierType: VerifierType) = copy(verifierType = verifierType)
|
fun setVerifierType(verifierType: VerifierType) = copy(verifierType = verifierType)
|
||||||
@ -641,19 +642,19 @@ class DriverDSL(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun networkMapServiceConfigLookup(networkMapCandidates: List<NodeDefinition>): (X500Name) -> Map<String, String>? {
|
private fun networkMapServiceConfigLookup(networkMapCandidates: List<NodeDefinition>): (CordaX500Name) -> Map<String, String>? {
|
||||||
return networkMapStartStrategy.run {
|
return networkMapStartStrategy.run {
|
||||||
when (this) {
|
when (this) {
|
||||||
is NetworkMapStartStrategy.Dedicated -> {
|
is NetworkMapStartStrategy.Dedicated -> {
|
||||||
serviceConfig(dedicatedNetworkMapAddress).let {
|
serviceConfig(dedicatedNetworkMapAddress).let {
|
||||||
{ _: X500Name -> it }
|
{ _: CordaX500Name -> it }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is NetworkMapStartStrategy.Nominated -> {
|
is NetworkMapStartStrategy.Nominated -> {
|
||||||
serviceConfig(networkMapCandidates.filter {
|
serviceConfig(networkMapCandidates.filter {
|
||||||
it.name == legalName.toString()
|
it.name == legalName.toString()
|
||||||
}.single().config.getString("p2pAddress").parseNetworkHostAndPort()).let {
|
}.single().config.getString("p2pAddress").parseNetworkHostAndPort()).let {
|
||||||
{ nodeName: X500Name -> if (nodeName == legalName) null else it }
|
{ nodeName: CordaX500Name -> if (nodeName == legalName) null else it }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -662,7 +663,7 @@ class DriverDSL(
|
|||||||
|
|
||||||
override fun startNode(
|
override fun startNode(
|
||||||
defaultParameters: NodeParameters,
|
defaultParameters: NodeParameters,
|
||||||
providedName: X500Name?,
|
providedName: CordaX500Name?,
|
||||||
advertisedServices: Set<ServiceInfo>,
|
advertisedServices: Set<ServiceInfo>,
|
||||||
rpcUsers: List<User>,
|
rpcUsers: List<User>,
|
||||||
verifierType: VerifierType,
|
verifierType: VerifierType,
|
||||||
@ -673,13 +674,13 @@ class DriverDSL(
|
|||||||
val rpcAddress = portAllocation.nextHostAndPort()
|
val rpcAddress = portAllocation.nextHostAndPort()
|
||||||
val webAddress = portAllocation.nextHostAndPort()
|
val webAddress = portAllocation.nextHostAndPort()
|
||||||
// TODO: Derive name from the full picked name, don't just wrap the common name
|
// TODO: Derive name from the full picked name, don't just wrap the common name
|
||||||
val name = providedName ?: getX500Name(O = "${oneOf(names).organisation}-${p2pAddress.port}", L = "London", C = "GB")
|
val name = providedName ?: CordaX500Name(organisation = "${oneOf(names).organisation}-${p2pAddress.port}", locality = "London", country = "GB")
|
||||||
val networkMapServiceConfigLookup = networkMapServiceConfigLookup(listOf(object : NodeDefinition {
|
val networkMapServiceConfigLookup = networkMapServiceConfigLookup(listOf(object : NodeDefinition {
|
||||||
override fun getName() = name.toString()
|
override fun getName() = name.toString()
|
||||||
override fun getConfig() = configOf("p2pAddress" to p2pAddress.toString())
|
override fun getConfig() = configOf("p2pAddress" to p2pAddress.toString())
|
||||||
}))
|
}))
|
||||||
val config = ConfigHelper.loadConfig(
|
val config = ConfigHelper.loadConfig(
|
||||||
baseDirectory = baseDirectory(name),
|
baseDirectory = baseDirectory(name.x500Name),
|
||||||
allowMissingConfig = true,
|
allowMissingConfig = true,
|
||||||
configOverrides = configOf(
|
configOverrides = configOf(
|
||||||
"myLegalName" to name.toString(),
|
"myLegalName" to name.toString(),
|
||||||
@ -701,10 +702,10 @@ class DriverDSL(
|
|||||||
return nodes.map { node ->
|
return nodes.map { node ->
|
||||||
portAllocation.nextHostAndPort() // rpcAddress
|
portAllocation.nextHostAndPort() // rpcAddress
|
||||||
val webAddress = portAllocation.nextHostAndPort()
|
val webAddress = portAllocation.nextHostAndPort()
|
||||||
val name = X500Name(node.name)
|
val name = CordaX500Name.parse(node.name)
|
||||||
|
|
||||||
val config = ConfigHelper.loadConfig(
|
val config = ConfigHelper.loadConfig(
|
||||||
baseDirectory = baseDirectory(name),
|
baseDirectory = baseDirectory(name.x500Name),
|
||||||
allowMissingConfig = true,
|
allowMissingConfig = true,
|
||||||
configOverrides = node.config + mapOf(
|
configOverrides = node.config + mapOf(
|
||||||
"extraAdvertisedServiceIds" to node.advertisedServices,
|
"extraAdvertisedServiceIds" to node.advertisedServices,
|
||||||
@ -718,15 +719,15 @@ class DriverDSL(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun startNotaryCluster(
|
override fun startNotaryCluster(
|
||||||
notaryName: X500Name,
|
notaryName: CordaX500Name,
|
||||||
clusterSize: Int,
|
clusterSize: Int,
|
||||||
type: ServiceType,
|
type: ServiceType,
|
||||||
verifierType: VerifierType,
|
verifierType: VerifierType,
|
||||||
rpcUsers: List<User>,
|
rpcUsers: List<User>,
|
||||||
startInSameProcess: Boolean?
|
startInSameProcess: Boolean?
|
||||||
): CordaFuture<Pair<Party, List<NodeHandle>>> {
|
): CordaFuture<Pair<Party, List<NodeHandle>>> {
|
||||||
val nodeNames = (0 until clusterSize).map { getX500Name(O = "Notary Service $it", OU = "corda", L = "Zurich", C = "CH") }
|
val nodeNames = (0 until clusterSize).map { CordaX500Name(organisation = "Notary Service $it", locality = "Zurich", country = "CH") }
|
||||||
val paths = nodeNames.map { baseDirectory(it) }
|
val paths = nodeNames.map { baseDirectory(it.x500Name) }
|
||||||
ServiceIdentityGenerator.generateToDisk(paths, type.id, notaryName)
|
ServiceIdentityGenerator.generateToDisk(paths, type.id, notaryName)
|
||||||
val advertisedServices = setOf(ServiceInfo(type, notaryName))
|
val advertisedServices = setOf(ServiceInfo(type, notaryName))
|
||||||
val notaryClusterAddress = portAllocation.nextHostAndPort()
|
val notaryClusterAddress = portAllocation.nextHostAndPort()
|
||||||
@ -791,13 +792,16 @@ class DriverDSL(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun baseDirectory(nodeName: X500Name): Path = driverDirectory / nodeName.organisation.replace(WHITESPACE, "")
|
override fun baseDirectory(nodeName: X500Name): Path {
|
||||||
|
val nodeDirectoryName = String(nodeName.organisation.filter { !it.isWhitespace() }.toCharArray())
|
||||||
|
return driverDirectory / nodeDirectoryName
|
||||||
|
}
|
||||||
|
|
||||||
override fun startDedicatedNetworkMapService(startInProcess: Boolean?): CordaFuture<NodeHandle> {
|
override fun startDedicatedNetworkMapService(startInProcess: Boolean?): CordaFuture<NodeHandle> {
|
||||||
val webAddress = portAllocation.nextHostAndPort()
|
val webAddress = portAllocation.nextHostAndPort()
|
||||||
val networkMapLegalName = networkMapStartStrategy.legalName
|
val networkMapLegalName = networkMapStartStrategy.legalName
|
||||||
val config = ConfigHelper.loadConfig(
|
val config = ConfigHelper.loadConfig(
|
||||||
baseDirectory = baseDirectory(networkMapLegalName),
|
baseDirectory = baseDirectory(networkMapLegalName.x500Name),
|
||||||
allowMissingConfig = true,
|
allowMissingConfig = true,
|
||||||
configOverrides = configOf(
|
configOverrides = configOf(
|
||||||
"myLegalName" to networkMapLegalName.toString(),
|
"myLegalName" to networkMapLegalName.toString(),
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
package net.corda.testing.driver
|
package net.corda.testing.driver
|
||||||
|
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
import net.corda.testing.DUMMY_MAP
|
import net.corda.testing.DUMMY_MAP
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
|
|
||||||
sealed class NetworkMapStartStrategy {
|
sealed class NetworkMapStartStrategy {
|
||||||
internal abstract val startDedicated: Boolean
|
internal abstract val startDedicated: Boolean
|
||||||
internal abstract val legalName: X500Name
|
internal abstract val legalName: CordaX500Name
|
||||||
internal fun serviceConfig(address: NetworkHostAndPort) = mapOf(
|
internal fun serviceConfig(address: NetworkHostAndPort) = mapOf(
|
||||||
"address" to address.toString(),
|
"address" to address.toString(),
|
||||||
"legalName" to legalName.toString()
|
"legalName" to legalName.toString()
|
||||||
@ -17,7 +17,7 @@ sealed class NetworkMapStartStrategy {
|
|||||||
override val legalName = DUMMY_MAP.name
|
override val legalName = DUMMY_MAP.name
|
||||||
}
|
}
|
||||||
|
|
||||||
class Nominated(override val legalName: X500Name) : NetworkMapStartStrategy() {
|
class Nominated(override val legalName: CordaX500Name) : NetworkMapStartStrategy() {
|
||||||
override val startDedicated = false
|
override val startDedicated = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ package net.corda.testing.node
|
|||||||
import com.google.common.util.concurrent.Futures
|
import com.google.common.util.concurrent.Futures
|
||||||
import com.google.common.util.concurrent.ListenableFuture
|
import com.google.common.util.concurrent.ListenableFuture
|
||||||
import com.google.common.util.concurrent.SettableFuture
|
import com.google.common.util.concurrent.SettableFuture
|
||||||
import net.corda.core.utilities.getX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.internal.ThreadBox
|
import net.corda.core.internal.ThreadBox
|
||||||
import net.corda.core.messaging.AllPossibleRecipients
|
import net.corda.core.messaging.AllPossibleRecipients
|
||||||
import net.corda.core.messaging.MessageRecipientGroup
|
import net.corda.core.messaging.MessageRecipientGroup
|
||||||
@ -20,7 +20,6 @@ import net.corda.node.utilities.AffinityExecutor
|
|||||||
import net.corda.node.utilities.CordaPersistence
|
import net.corda.node.utilities.CordaPersistence
|
||||||
import net.corda.testing.node.InMemoryMessagingNetwork.InMemoryMessaging
|
import net.corda.testing.node.InMemoryMessagingNetwork.InMemoryMessaging
|
||||||
import org.apache.activemq.artemis.utils.ReusableLatch
|
import org.apache.activemq.artemis.utils.ReusableLatch
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import rx.subjects.PublishSubject
|
import rx.subjects.PublishSubject
|
||||||
@ -80,8 +79,8 @@ class InMemoryMessagingNetwork(
|
|||||||
|
|
||||||
// Holds the mapping from services to peers advertising the service.
|
// Holds the mapping from services to peers advertising the service.
|
||||||
private val serviceToPeersMapping = HashMap<ServiceHandle, LinkedHashSet<PeerHandle>>()
|
private val serviceToPeersMapping = HashMap<ServiceHandle, LinkedHashSet<PeerHandle>>()
|
||||||
// Holds the mapping from node's X500Name to PeerHandle.
|
// Holds the mapping from node's X.500 name to PeerHandle.
|
||||||
private val peersMapping = HashMap<X500Name, PeerHandle>()
|
private val peersMapping = HashMap<CordaX500Name, PeerHandle>()
|
||||||
|
|
||||||
@Suppress("unused") // Used by the visualiser tool.
|
@Suppress("unused") // Used by the visualiser tool.
|
||||||
/** A stream of (sender, message, recipients) triples */
|
/** A stream of (sender, message, recipients) triples */
|
||||||
@ -127,7 +126,7 @@ class InMemoryMessagingNetwork(
|
|||||||
id: Int,
|
id: Int,
|
||||||
executor: AffinityExecutor,
|
executor: AffinityExecutor,
|
||||||
advertisedServices: List<ServiceEntry>,
|
advertisedServices: List<ServiceEntry>,
|
||||||
description: X500Name = getX500Name(O = "In memory node $id", L = "London", C = "UK"),
|
description: CordaX500Name = CordaX500Name(organisation = "In memory node $id", locality = "London", country = "UK"),
|
||||||
database: CordaPersistence)
|
database: CordaPersistence)
|
||||||
: MessagingServiceBuilder<InMemoryMessaging> {
|
: MessagingServiceBuilder<InMemoryMessaging> {
|
||||||
val peerHandle = PeerHandle(id, description)
|
val peerHandle = PeerHandle(id, description)
|
||||||
@ -200,7 +199,7 @@ class InMemoryMessagingNetwork(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
data class PeerHandle(val id: Int, val description: X500Name) : SingleMessageRecipient {
|
data class PeerHandle(val id: Int, val description: CordaX500Name) : SingleMessageRecipient {
|
||||||
override fun toString() = description.toString()
|
override fun toString() = description.toString()
|
||||||
override fun equals(other: Any?) = other is PeerHandle && other.id == id
|
override fun equals(other: Any?) = other is PeerHandle && other.id == id
|
||||||
override fun hashCode() = id.hashCode()
|
override fun hashCode() = id.hashCode()
|
||||||
@ -289,7 +288,7 @@ class InMemoryMessagingNetwork(
|
|||||||
override val platformVersion: Int,
|
override val platformVersion: Int,
|
||||||
override val uniqueMessageId: UUID,
|
override val uniqueMessageId: UUID,
|
||||||
override val debugTimestamp: Instant,
|
override val debugTimestamp: Instant,
|
||||||
override val peer: X500Name) : ReceivedMessage
|
override val peer: CordaX500Name) : ReceivedMessage
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An [InMemoryMessaging] provides a [MessagingService] that isn't backed by any kind of network or disk storage
|
* An [InMemoryMessaging] provides a [MessagingService] that isn't backed by any kind of network or disk storage
|
||||||
|
@ -2,12 +2,12 @@ package net.corda.testing.node
|
|||||||
|
|
||||||
import co.paralleluniverse.common.util.VisibleForTesting
|
import co.paralleluniverse.common.util.VisibleForTesting
|
||||||
import net.corda.core.crypto.entropyToKeyPair
|
import net.corda.core.crypto.entropyToKeyPair
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.node.NodeInfo
|
import net.corda.core.node.NodeInfo
|
||||||
import net.corda.core.node.services.NetworkMapCache
|
import net.corda.core.node.services.NetworkMapCache
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
import net.corda.core.utilities.NonEmptySet
|
import net.corda.core.utilities.NonEmptySet
|
||||||
import net.corda.core.utilities.getX500Name
|
|
||||||
import net.corda.node.services.api.ServiceHubInternal
|
import net.corda.node.services.api.ServiceHubInternal
|
||||||
import net.corda.node.services.network.PersistentNetworkMapCache
|
import net.corda.node.services.network.PersistentNetworkMapCache
|
||||||
import net.corda.testing.getTestPartyAndCertificate
|
import net.corda.testing.getTestPartyAndCertificate
|
||||||
@ -20,8 +20,8 @@ import java.math.BigInteger
|
|||||||
*/
|
*/
|
||||||
class MockNetworkMapCache(serviceHub: ServiceHubInternal) : PersistentNetworkMapCache(serviceHub) {
|
class MockNetworkMapCache(serviceHub: ServiceHubInternal) : PersistentNetworkMapCache(serviceHub) {
|
||||||
private companion object {
|
private companion object {
|
||||||
val BANK_C = getTestPartyAndCertificate(getX500Name(O = "Bank C", L = "London", C = "GB"), entropyToKeyPair(BigInteger.valueOf(1000)).public)
|
val BANK_C = getTestPartyAndCertificate(CordaX500Name(organisation = "Bank C", locality = "London", country = "GB"), entropyToKeyPair(BigInteger.valueOf(1000)).public)
|
||||||
val BANK_D = getTestPartyAndCertificate(getX500Name(O = "Bank D", L = "London", C = "GB"), entropyToKeyPair(BigInteger.valueOf(2000)).public)
|
val BANK_D = getTestPartyAndCertificate(CordaX500Name(organisation = "Bank D", locality = "London", country = "GB"), entropyToKeyPair(BigInteger.valueOf(2000)).public)
|
||||||
val BANK_C_ADDR = NetworkHostAndPort("bankC", 8080)
|
val BANK_C_ADDR = NetworkHostAndPort("bankC", 8080)
|
||||||
val BANK_D_ADDR = NetworkHostAndPort("bankD", 8080)
|
val BANK_D_ADDR = NetworkHostAndPort("bankD", 8080)
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import com.google.common.jimfs.Jimfs
|
|||||||
import com.nhaarman.mockito_kotlin.whenever
|
import com.nhaarman.mockito_kotlin.whenever
|
||||||
import net.corda.core.crypto.entropyToKeyPair
|
import net.corda.core.crypto.entropyToKeyPair
|
||||||
import net.corda.core.crypto.random63BitValue
|
import net.corda.core.crypto.random63BitValue
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.PartyAndCertificate
|
import net.corda.core.identity.PartyAndCertificate
|
||||||
import net.corda.core.internal.concurrent.doneFuture
|
import net.corda.core.internal.concurrent.doneFuture
|
||||||
import net.corda.core.internal.createDirectories
|
import net.corda.core.internal.createDirectories
|
||||||
@ -31,7 +32,6 @@ import net.corda.node.utilities.CertificateAndKeyPair
|
|||||||
import net.corda.testing.*
|
import net.corda.testing.*
|
||||||
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
|
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
|
||||||
import org.apache.activemq.artemis.utils.ReusableLatch
|
import org.apache.activemq.artemis.utils.ReusableLatch
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import org.slf4j.Logger
|
import org.slf4j.Logger
|
||||||
import java.math.BigInteger
|
import java.math.BigInteger
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
@ -288,7 +288,7 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false,
|
|||||||
* @param configOverrides add/override behaviour of the [NodeConfiguration] mock object.
|
* @param configOverrides add/override behaviour of the [NodeConfiguration] mock object.
|
||||||
*/
|
*/
|
||||||
fun createNode(networkMapAddress: SingleMessageRecipient? = null, forcedID: Int? = null,
|
fun createNode(networkMapAddress: SingleMessageRecipient? = null, forcedID: Int? = null,
|
||||||
start: Boolean = true, legalName: X500Name? = null, overrideServices: Map<ServiceInfo, KeyPair>? = null,
|
start: Boolean = true, legalName: CordaX500Name? = null, overrideServices: Map<ServiceInfo, KeyPair>? = null,
|
||||||
entropyRoot: BigInteger = BigInteger.valueOf(random63BitValue()),
|
entropyRoot: BigInteger = BigInteger.valueOf(random63BitValue()),
|
||||||
vararg advertisedServices: ServiceInfo,
|
vararg advertisedServices: ServiceInfo,
|
||||||
configOverrides: (NodeConfiguration) -> Any? = {}): MockNode {
|
configOverrides: (NodeConfiguration) -> Any? = {}): MockNode {
|
||||||
@ -297,14 +297,14 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false,
|
|||||||
|
|
||||||
/** Like the other [createNode] but takes a [Factory] and propagates its [MockNode] subtype. */
|
/** Like the other [createNode] but takes a [Factory] and propagates its [MockNode] subtype. */
|
||||||
fun <N : MockNode> createNode(networkMapAddress: SingleMessageRecipient? = null, forcedID: Int? = null, nodeFactory: Factory<N>,
|
fun <N : MockNode> createNode(networkMapAddress: SingleMessageRecipient? = null, forcedID: Int? = null, nodeFactory: Factory<N>,
|
||||||
start: Boolean = true, legalName: X500Name? = null, overrideServices: Map<ServiceInfo, KeyPair>? = null,
|
start: Boolean = true, legalName: CordaX500Name? = null, overrideServices: Map<ServiceInfo, KeyPair>? = null,
|
||||||
entropyRoot: BigInteger = BigInteger.valueOf(random63BitValue()),
|
entropyRoot: BigInteger = BigInteger.valueOf(random63BitValue()),
|
||||||
vararg advertisedServices: ServiceInfo,
|
vararg advertisedServices: ServiceInfo,
|
||||||
configOverrides: (NodeConfiguration) -> Any? = {}): N {
|
configOverrides: (NodeConfiguration) -> Any? = {}): N {
|
||||||
val id = forcedID ?: nextNodeId++
|
val id = forcedID ?: nextNodeId++
|
||||||
val config = testNodeConfiguration(
|
val config = testNodeConfiguration(
|
||||||
baseDirectory = baseDirectory(id).createDirectories(),
|
baseDirectory = baseDirectory(id).createDirectories(),
|
||||||
myLegalName = legalName ?: getX500Name(O = "Mock Company $id", L = "London", C = "GB")).also {
|
myLegalName = legalName ?: CordaX500Name(organisation = "Mock Company $id", locality = "London", country = "GB")).also {
|
||||||
whenever(it.dataSourceProperties).thenReturn(makeTestDataSourceProperties("node_${id}_net_$networkId"))
|
whenever(it.dataSourceProperties).thenReturn(makeTestDataSourceProperties("node_${id}_net_$networkId"))
|
||||||
configOverrides(it)
|
configOverrides(it)
|
||||||
}
|
}
|
||||||
@ -369,15 +369,15 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false,
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun createNotaryNode(networkMapAddress: SingleMessageRecipient? = null,
|
fun createNotaryNode(networkMapAddress: SingleMessageRecipient? = null,
|
||||||
legalName: X500Name? = null,
|
legalName: CordaX500Name? = null,
|
||||||
overrideServices: Map<ServiceInfo, KeyPair>? = null,
|
overrideServices: Map<ServiceInfo, KeyPair>? = null,
|
||||||
serviceName: X500Name? = null): MockNode {
|
serviceName: CordaX500Name? = null): MockNode {
|
||||||
return createNode(networkMapAddress, legalName = legalName, overrideServices = overrideServices,
|
return createNode(networkMapAddress, legalName = legalName, overrideServices = overrideServices,
|
||||||
advertisedServices = *arrayOf(ServiceInfo(NetworkMapService.type), ServiceInfo(ValidatingNotaryService.type, serviceName)))
|
advertisedServices = *arrayOf(ServiceInfo(NetworkMapService.type), ServiceInfo(ValidatingNotaryService.type, serviceName)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createPartyNode(networkMapAddress: SingleMessageRecipient,
|
fun createPartyNode(networkMapAddress: SingleMessageRecipient,
|
||||||
legalName: X500Name? = null,
|
legalName: CordaX500Name? = null,
|
||||||
overrideServices: Map<ServiceInfo, KeyPair>? = null): MockNode {
|
overrideServices: Map<ServiceInfo, KeyPair>? = null): MockNode {
|
||||||
return createNode(networkMapAddress, legalName = legalName, overrideServices = overrideServices)
|
return createNode(networkMapAddress, legalName = legalName, overrideServices = overrideServices)
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
package net.corda.testing.node
|
package net.corda.testing.node
|
||||||
|
|
||||||
import net.corda.core.concurrent.CordaFuture
|
import net.corda.core.concurrent.CordaFuture
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.internal.concurrent.*
|
import net.corda.core.internal.concurrent.*
|
||||||
import net.corda.core.internal.createDirectories
|
import net.corda.core.internal.createDirectories
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
import net.corda.core.node.services.ServiceInfo
|
import net.corda.core.node.services.ServiceInfo
|
||||||
import net.corda.core.node.services.ServiceType
|
import net.corda.core.node.services.ServiceType
|
||||||
import net.corda.core.utilities.*
|
import net.corda.core.utilities.getOrThrow
|
||||||
|
import net.corda.core.utilities.getX500Name
|
||||||
|
import net.corda.core.utilities.organisation
|
||||||
import net.corda.node.internal.Node
|
import net.corda.node.internal.Node
|
||||||
import net.corda.node.services.config.ConfigHelper
|
import net.corda.node.services.config.ConfigHelper
|
||||||
import net.corda.node.services.config.FullNodeConfiguration
|
import net.corda.node.services.config.FullNodeConfiguration
|
||||||
@ -37,6 +40,8 @@ import kotlin.concurrent.thread
|
|||||||
*/
|
*/
|
||||||
// TODO Some of the logic here duplicates what's in the driver
|
// TODO Some of the logic here duplicates what's in the driver
|
||||||
abstract class NodeBasedTest : TestDependencyInjectionBase() {
|
abstract class NodeBasedTest : TestDependencyInjectionBase() {
|
||||||
|
val WHITESPACE = "\\s++".toRegex()
|
||||||
|
|
||||||
@Rule
|
@Rule
|
||||||
@JvmField
|
@JvmField
|
||||||
val tempFolder = TemporaryFolder()
|
val tempFolder = TemporaryFolder()
|
||||||
@ -81,7 +86,7 @@ abstract class NodeBasedTest : TestDependencyInjectionBase() {
|
|||||||
* You can use this method to start the network map node in a more customised manner. Otherwise it
|
* You can use this method to start the network map node in a more customised manner. Otherwise it
|
||||||
* will automatically be started with the default parameters.
|
* will automatically be started with the default parameters.
|
||||||
*/
|
*/
|
||||||
fun startNetworkMapNode(legalName: X500Name = DUMMY_MAP.name,
|
fun startNetworkMapNode(legalName: CordaX500Name = DUMMY_MAP.name,
|
||||||
platformVersion: Int = 1,
|
platformVersion: Int = 1,
|
||||||
advertisedServices: Set<ServiceInfo> = emptySet(),
|
advertisedServices: Set<ServiceInfo> = emptySet(),
|
||||||
rpcUsers: List<User> = emptyList(),
|
rpcUsers: List<User> = emptyList(),
|
||||||
@ -93,7 +98,7 @@ abstract class NodeBasedTest : TestDependencyInjectionBase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
fun startNode(legalName: X500Name,
|
fun startNode(legalName: CordaX500Name,
|
||||||
platformVersion: Int = 1,
|
platformVersion: Int = 1,
|
||||||
advertisedServices: Set<ServiceInfo> = emptySet(),
|
advertisedServices: Set<ServiceInfo> = emptySet(),
|
||||||
rpcUsers: List<User> = emptyList(),
|
rpcUsers: List<User> = emptyList(),
|
||||||
@ -126,7 +131,7 @@ abstract class NodeBasedTest : TestDependencyInjectionBase() {
|
|||||||
return if (waitForConnection) node.nodeReadyFuture.map { node } else doneFuture(node)
|
return if (waitForConnection) node.nodeReadyFuture.map { node } else doneFuture(node)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun startNotaryCluster(notaryName: X500Name,
|
fun startNotaryCluster(notaryName: CordaX500Name,
|
||||||
clusterSize: Int,
|
clusterSize: Int,
|
||||||
serviceType: ServiceType = RaftValidatingNotaryService.type): CordaFuture<List<Node>> {
|
serviceType: ServiceType = RaftValidatingNotaryService.type): CordaFuture<List<Node>> {
|
||||||
ServiceIdentityGenerator.generateToDisk(
|
ServiceIdentityGenerator.generateToDisk(
|
||||||
@ -138,14 +143,14 @@ abstract class NodeBasedTest : TestDependencyInjectionBase() {
|
|||||||
val nodeAddresses = getFreeLocalPorts("localhost", clusterSize).map { it.toString() }
|
val nodeAddresses = getFreeLocalPorts("localhost", clusterSize).map { it.toString() }
|
||||||
|
|
||||||
val masterNodeFuture = startNode(
|
val masterNodeFuture = startNode(
|
||||||
getX500Name(O = "${notaryName.organisation}-0", L = notaryName.locality, C = notaryName.country),
|
CordaX500Name(organisation = "${notaryName.organisation}-0", locality = notaryName.locality, country = notaryName.country),
|
||||||
advertisedServices = setOf(serviceInfo),
|
advertisedServices = setOf(serviceInfo),
|
||||||
configOverrides = mapOf("notaryNodeAddress" to nodeAddresses[0],
|
configOverrides = mapOf("notaryNodeAddress" to nodeAddresses[0],
|
||||||
"database" to mapOf("serverNameTablePrefix" to if (clusterSize > 1) "${notaryName.organisation}0".replace(Regex("[^0-9A-Za-z]+"), "") else "")))
|
"database" to mapOf("serverNameTablePrefix" to if (clusterSize > 1) "${notaryName.organisation}0".replace(Regex("[^0-9A-Za-z]+"), "") else "")))
|
||||||
|
|
||||||
val remainingNodesFutures = (1 until clusterSize).map {
|
val remainingNodesFutures = (1 until clusterSize).map {
|
||||||
startNode(
|
startNode(
|
||||||
getX500Name(O = "${notaryName.organisation}-$it", L = notaryName.locality, C = notaryName.country),
|
CordaX500Name(organisation = "${notaryName.organisation}-$it", locality = notaryName.locality, country = notaryName.country),
|
||||||
advertisedServices = setOf(serviceInfo),
|
advertisedServices = setOf(serviceInfo),
|
||||||
configOverrides = mapOf(
|
configOverrides = mapOf(
|
||||||
"notaryNodeAddress" to nodeAddresses[it],
|
"notaryNodeAddress" to nodeAddresses[it],
|
||||||
@ -160,13 +165,13 @@ abstract class NodeBasedTest : TestDependencyInjectionBase() {
|
|||||||
|
|
||||||
protected fun baseDirectory(legalName: X500Name) = tempFolder.root.toPath() / legalName.organisation.replace(WHITESPACE, "")
|
protected fun baseDirectory(legalName: X500Name) = tempFolder.root.toPath() / legalName.organisation.replace(WHITESPACE, "")
|
||||||
|
|
||||||
private fun startNodeInternal(legalName: X500Name,
|
private fun startNodeInternal(legalName: CordaX500Name,
|
||||||
platformVersion: Int,
|
platformVersion: Int,
|
||||||
advertisedServices: Set<ServiceInfo>,
|
advertisedServices: Set<ServiceInfo>,
|
||||||
rpcUsers: List<User>,
|
rpcUsers: List<User>,
|
||||||
configOverrides: Map<String, Any>,
|
configOverrides: Map<String, Any>,
|
||||||
noNetworkMap: Boolean = false): Node {
|
noNetworkMap: Boolean = false): Node {
|
||||||
val baseDirectory = baseDirectory(legalName).createDirectories()
|
val baseDirectory = baseDirectory(legalName.x500Name).createDirectories()
|
||||||
val localPort = getFreeLocalPorts("localhost", 2)
|
val localPort = getFreeLocalPorts("localhost", 2)
|
||||||
val p2pAddress = configOverrides["p2pAddress"] ?: localPort[0].toString()
|
val p2pAddress = configOverrides["p2pAddress"] ?: localPort[0].toString()
|
||||||
val config = ConfigHelper.loadConfig(
|
val config = ConfigHelper.loadConfig(
|
||||||
|
@ -5,12 +5,11 @@ import com.typesafe.config.ConfigFactory.empty
|
|||||||
import com.typesafe.config.ConfigRenderOptions
|
import com.typesafe.config.ConfigRenderOptions
|
||||||
import com.typesafe.config.ConfigValue
|
import com.typesafe.config.ConfigValue
|
||||||
import com.typesafe.config.ConfigValueFactory
|
import com.typesafe.config.ConfigValueFactory
|
||||||
import net.corda.core.utilities.organisation
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.nodeapi.User
|
import net.corda.nodeapi.User
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
|
|
||||||
class NodeConfig(
|
class NodeConfig(
|
||||||
val legalName: X500Name,
|
val legalName: CordaX500Name,
|
||||||
val p2pPort: Int,
|
val p2pPort: Int,
|
||||||
val rpcPort: Int,
|
val rpcPort: Int,
|
||||||
val webPort: Int,
|
val webPort: Int,
|
||||||
|
@ -6,6 +6,7 @@ package net.corda.testing
|
|||||||
import net.corda.core.contracts.StateRef
|
import net.corda.core.contracts.StateRef
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
import net.corda.core.crypto.generateKeyPair
|
import net.corda.core.crypto.generateKeyPair
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.identity.PartyAndCertificate
|
import net.corda.core.identity.PartyAndCertificate
|
||||||
import net.corda.core.node.services.IdentityService
|
import net.corda.core.node.services.IdentityService
|
||||||
@ -18,7 +19,6 @@ import net.corda.node.utilities.CertificateType
|
|||||||
import net.corda.node.utilities.X509Utilities
|
import net.corda.node.utilities.X509Utilities
|
||||||
import net.corda.nodeapi.config.SSLConfiguration
|
import net.corda.nodeapi.config.SSLConfiguration
|
||||||
import net.corda.nodeapi.internal.serialization.AMQP_ENABLED
|
import net.corda.nodeapi.internal.serialization.AMQP_ENABLED
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
import java.security.KeyPair
|
import java.security.KeyPair
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
@ -59,20 +59,20 @@ val ALICE_PUBKEY: PublicKey get() = ALICE_KEY.public
|
|||||||
val BOB_PUBKEY: PublicKey get() = BOB_KEY.public
|
val BOB_PUBKEY: PublicKey get() = BOB_KEY.public
|
||||||
val CHARLIE_PUBKEY: PublicKey get() = CHARLIE_KEY.public
|
val CHARLIE_PUBKEY: PublicKey get() = CHARLIE_KEY.public
|
||||||
|
|
||||||
val MEGA_CORP_IDENTITY: PartyAndCertificate get() = getTestPartyAndCertificate(getX500Name(O = "MegaCorp", L = "London", C = "GB"), MEGA_CORP_PUBKEY)
|
val MEGA_CORP_IDENTITY: PartyAndCertificate get() = getTestPartyAndCertificate(CordaX500Name(organisation = "MegaCorp", locality = "London", country = "GB"), MEGA_CORP_PUBKEY)
|
||||||
val MEGA_CORP: Party get() = MEGA_CORP_IDENTITY.party
|
val MEGA_CORP: Party get() = MEGA_CORP_IDENTITY.party
|
||||||
val MINI_CORP_IDENTITY: PartyAndCertificate get() = getTestPartyAndCertificate(getX500Name(O = "MiniCorp", L = "London", C = "GB"), MINI_CORP_PUBKEY)
|
val MINI_CORP_IDENTITY: PartyAndCertificate get() = getTestPartyAndCertificate(CordaX500Name(organisation = "MiniCorp", locality = "London", country = "GB"), MINI_CORP_PUBKEY)
|
||||||
val MINI_CORP: Party get() = MINI_CORP_IDENTITY.party
|
val MINI_CORP: Party get() = MINI_CORP_IDENTITY.party
|
||||||
|
|
||||||
val BOC_KEY: KeyPair by lazy { generateKeyPair() }
|
val BOC_KEY: KeyPair by lazy { generateKeyPair() }
|
||||||
val BOC_PUBKEY: PublicKey get() = BOC_KEY.public
|
val BOC_PUBKEY: PublicKey get() = BOC_KEY.public
|
||||||
val BOC_IDENTITY: PartyAndCertificate get() = getTestPartyAndCertificate(getX500Name(O = "BankOfCorda", L = "London", C = "GB"), BOC_PUBKEY)
|
val BOC_IDENTITY: PartyAndCertificate get() = getTestPartyAndCertificate(CordaX500Name(organisation = "BankOfCorda", locality = "London", country = "GB"), BOC_PUBKEY)
|
||||||
val BOC: Party get() = BOC_IDENTITY.party
|
val BOC: Party get() = BOC_IDENTITY.party
|
||||||
val BOC_PARTY_REF = BOC.ref(OpaqueBytes.of(1)).reference
|
val BOC_PARTY_REF = BOC.ref(OpaqueBytes.of(1)).reference
|
||||||
|
|
||||||
val BIG_CORP_KEY: KeyPair by lazy { generateKeyPair() }
|
val BIG_CORP_KEY: KeyPair by lazy { generateKeyPair() }
|
||||||
val BIG_CORP_PUBKEY: PublicKey get() = BIG_CORP_KEY.public
|
val BIG_CORP_PUBKEY: PublicKey get() = BIG_CORP_KEY.public
|
||||||
val BIG_CORP_IDENTITY: PartyAndCertificate get() = getTestPartyAndCertificate(getX500Name(O = "BigCorporation", L = "London", C = "GB"), BIG_CORP_PUBKEY)
|
val BIG_CORP_IDENTITY: PartyAndCertificate get() = getTestPartyAndCertificate(CordaX500Name(organisation = "BigCorporation", locality = "London", country = "GB"), BIG_CORP_PUBKEY)
|
||||||
val BIG_CORP: Party get() = BIG_CORP_IDENTITY.party
|
val BIG_CORP: Party get() = BIG_CORP_IDENTITY.party
|
||||||
val BIG_CORP_PARTY_REF = BIG_CORP.ref(OpaqueBytes.of(1)).reference
|
val BIG_CORP_PARTY_REF = BIG_CORP.ref(OpaqueBytes.of(1)).reference
|
||||||
|
|
||||||
@ -116,7 +116,7 @@ fun getFreeLocalPorts(hostName: String, numberToAlloc: Int): List<NetworkHostAnd
|
|||||||
}
|
}
|
||||||
|
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
fun configureTestSSL(legalName: X500Name = MEGA_CORP.name): SSLConfiguration = object : SSLConfiguration {
|
fun configureTestSSL(legalName: CordaX500Name = MEGA_CORP.name): SSLConfiguration = object : SSLConfiguration {
|
||||||
override val certificatesDirectory = Files.createTempDirectory("certs")
|
override val certificatesDirectory = Files.createTempDirectory("certs")
|
||||||
override val keyStorePassword: String get() = "cordacadevpass"
|
override val keyStorePassword: String get() = "cordacadevpass"
|
||||||
override val trustStorePassword: String get() = "trustpass"
|
override val trustStorePassword: String get() = "trustpass"
|
||||||
@ -128,7 +128,7 @@ fun configureTestSSL(legalName: X500Name = MEGA_CORP.name): SSLConfiguration = o
|
|||||||
|
|
||||||
fun getTestPartyAndCertificate(party: Party, trustRoot: CertificateAndKeyPair = DUMMY_CA): PartyAndCertificate {
|
fun getTestPartyAndCertificate(party: Party, trustRoot: CertificateAndKeyPair = DUMMY_CA): PartyAndCertificate {
|
||||||
val certFactory = CertificateFactory.getInstance("X509")
|
val certFactory = CertificateFactory.getInstance("X509")
|
||||||
val certHolder = X509Utilities.createCertificate(CertificateType.IDENTITY, trustRoot.certificate, trustRoot.keyPair, party.name, party.owningKey)
|
val certHolder = X509Utilities.createCertificate(CertificateType.IDENTITY, trustRoot.certificate, trustRoot.keyPair, party.name.x500Name, party.owningKey)
|
||||||
val certPath = certFactory.generateCertPath(listOf(certHolder.cert, trustRoot.certificate.cert))
|
val certPath = certFactory.generateCertPath(listOf(certHolder.cert, trustRoot.certificate.cert))
|
||||||
return PartyAndCertificate(certPath)
|
return PartyAndCertificate(certPath)
|
||||||
}
|
}
|
||||||
@ -136,7 +136,7 @@ fun getTestPartyAndCertificate(party: Party, trustRoot: CertificateAndKeyPair =
|
|||||||
/**
|
/**
|
||||||
* Build a test party with a nonsense certificate authority for testing purposes.
|
* Build a test party with a nonsense certificate authority for testing purposes.
|
||||||
*/
|
*/
|
||||||
fun getTestPartyAndCertificate(name: X500Name, publicKey: PublicKey, trustRoot: CertificateAndKeyPair = DUMMY_CA): PartyAndCertificate {
|
fun getTestPartyAndCertificate(name: CordaX500Name, publicKey: PublicKey, trustRoot: CertificateAndKeyPair = DUMMY_CA): PartyAndCertificate {
|
||||||
return getTestPartyAndCertificate(Party(name, publicKey), trustRoot)
|
return getTestPartyAndCertificate(Party(name, publicKey), trustRoot)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,4 +150,4 @@ inline fun <reified T : Any> amqpSpecific(reason: String, function: () -> Unit)
|
|||||||
function()
|
function()
|
||||||
} else {
|
} else {
|
||||||
loggerFor<T>().info("Ignoring AMQP specific test, reason: $reason" )
|
loggerFor<T>().info("Ignoring AMQP specific test, reason: $reason" )
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import net.corda.core.contracts.Command
|
|||||||
import net.corda.core.contracts.TypeOnlyCommandData
|
import net.corda.core.contracts.TypeOnlyCommandData
|
||||||
import net.corda.core.crypto.entropyToKeyPair
|
import net.corda.core.crypto.entropyToKeyPair
|
||||||
import net.corda.core.crypto.generateKeyPair
|
import net.corda.core.crypto.generateKeyPair
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.identity.PartyAndCertificate
|
import net.corda.core.identity.PartyAndCertificate
|
||||||
import net.corda.node.utilities.CertificateAndKeyPair
|
import net.corda.node.utilities.CertificateAndKeyPair
|
||||||
@ -25,42 +26,42 @@ val DUMMY_KEY_2: KeyPair by lazy { generateKeyPair() }
|
|||||||
val DUMMY_NOTARY_KEY: KeyPair by lazy { entropyToKeyPair(BigInteger.valueOf(20)) }
|
val DUMMY_NOTARY_KEY: KeyPair by lazy { entropyToKeyPair(BigInteger.valueOf(20)) }
|
||||||
/** Dummy notary identity for tests and simulations */
|
/** Dummy notary identity for tests and simulations */
|
||||||
val DUMMY_NOTARY_IDENTITY: PartyAndCertificate get() = getTestPartyAndCertificate(DUMMY_NOTARY)
|
val DUMMY_NOTARY_IDENTITY: PartyAndCertificate get() = getTestPartyAndCertificate(DUMMY_NOTARY)
|
||||||
val DUMMY_NOTARY: Party get() = Party(getX500Name(O = "Notary Service", OU = "corda", L = "Zurich", C = "CH"), DUMMY_NOTARY_KEY.public)
|
val DUMMY_NOTARY: Party get() = Party(CordaX500Name(organisation = "Notary Service", locality = "Zurich", country = "CH"), DUMMY_NOTARY_KEY.public)
|
||||||
|
|
||||||
val DUMMY_MAP_KEY: KeyPair by lazy { entropyToKeyPair(BigInteger.valueOf(30)) }
|
val DUMMY_MAP_KEY: KeyPair by lazy { entropyToKeyPair(BigInteger.valueOf(30)) }
|
||||||
/** Dummy network map service identity for tests and simulations */
|
/** Dummy network map service identity for tests and simulations */
|
||||||
val DUMMY_MAP: Party get() = Party(getX500Name(O = "Network Map Service", OU = "corda", L = "Amsterdam", C = "NL"), DUMMY_MAP_KEY.public)
|
val DUMMY_MAP: Party get() = Party(CordaX500Name(organisation = "Network Map Service", locality = "Amsterdam", country = "NL"), DUMMY_MAP_KEY.public)
|
||||||
|
|
||||||
val DUMMY_BANK_A_KEY: KeyPair by lazy { entropyToKeyPair(BigInteger.valueOf(40)) }
|
val DUMMY_BANK_A_KEY: KeyPair by lazy { entropyToKeyPair(BigInteger.valueOf(40)) }
|
||||||
/** Dummy bank identity for tests and simulations */
|
/** Dummy bank identity for tests and simulations */
|
||||||
val DUMMY_BANK_A: Party get() = Party(getX500Name(O = "Bank A", L = "London", C = "GB"), DUMMY_BANK_A_KEY.public)
|
val DUMMY_BANK_A: Party get() = Party(CordaX500Name(organisation = "Bank A", locality = "London", country = "GB"), DUMMY_BANK_A_KEY.public)
|
||||||
|
|
||||||
val DUMMY_BANK_B_KEY: KeyPair by lazy { entropyToKeyPair(BigInteger.valueOf(50)) }
|
val DUMMY_BANK_B_KEY: KeyPair by lazy { entropyToKeyPair(BigInteger.valueOf(50)) }
|
||||||
/** Dummy bank identity for tests and simulations */
|
/** Dummy bank identity for tests and simulations */
|
||||||
val DUMMY_BANK_B: Party get() = Party(getX500Name(O = "Bank B", L = "New York", C = "US"), DUMMY_BANK_B_KEY.public)
|
val DUMMY_BANK_B: Party get() = Party(CordaX500Name(organisation = "Bank B", locality = "New York", country = "US"), DUMMY_BANK_B_KEY.public)
|
||||||
|
|
||||||
val DUMMY_BANK_C_KEY: KeyPair by lazy { entropyToKeyPair(BigInteger.valueOf(60)) }
|
val DUMMY_BANK_C_KEY: KeyPair by lazy { entropyToKeyPair(BigInteger.valueOf(60)) }
|
||||||
/** Dummy bank identity for tests and simulations */
|
/** Dummy bank identity for tests and simulations */
|
||||||
val DUMMY_BANK_C: Party get() = Party(getX500Name(O = "Bank C", L = "Tokyo", C = "JP"), DUMMY_BANK_C_KEY.public)
|
val DUMMY_BANK_C: Party get() = Party(CordaX500Name(organisation = "Bank C", locality = "Tokyo", country = "JP"), DUMMY_BANK_C_KEY.public)
|
||||||
|
|
||||||
val ALICE_KEY: KeyPair by lazy { entropyToKeyPair(BigInteger.valueOf(70)) }
|
val ALICE_KEY: KeyPair by lazy { entropyToKeyPair(BigInteger.valueOf(70)) }
|
||||||
/** Dummy individual identity for tests and simulations */
|
/** Dummy individual identity for tests and simulations */
|
||||||
val ALICE_IDENTITY: PartyAndCertificate get() = getTestPartyAndCertificate(ALICE)
|
val ALICE_IDENTITY: PartyAndCertificate get() = getTestPartyAndCertificate(ALICE)
|
||||||
val ALICE: Party get() = Party(getX500Name(O = "Alice Corp", L = "Madrid", C = "ES"), ALICE_KEY.public)
|
val ALICE: Party get() = Party(CordaX500Name(organisation = "Alice Corp", locality = "Madrid", country = "ES"), ALICE_KEY.public)
|
||||||
|
|
||||||
val BOB_KEY: KeyPair by lazy { entropyToKeyPair(BigInteger.valueOf(80)) }
|
val BOB_KEY: KeyPair by lazy { entropyToKeyPair(BigInteger.valueOf(80)) }
|
||||||
/** Dummy individual identity for tests and simulations */
|
/** Dummy individual identity for tests and simulations */
|
||||||
val BOB_IDENTITY: PartyAndCertificate get() = getTestPartyAndCertificate(BOB)
|
val BOB_IDENTITY: PartyAndCertificate get() = getTestPartyAndCertificate(BOB)
|
||||||
val BOB: Party get() = Party(getX500Name(O = "Bob Plc", L = "Rome", C = "IT"), BOB_KEY.public)
|
val BOB: Party get() = Party(CordaX500Name(organisation = "Bob Plc", locality = "Rome", country = "IT"), BOB_KEY.public)
|
||||||
|
|
||||||
val CHARLIE_KEY: KeyPair by lazy { entropyToKeyPair(BigInteger.valueOf(90)) }
|
val CHARLIE_KEY: KeyPair by lazy { entropyToKeyPair(BigInteger.valueOf(90)) }
|
||||||
/** Dummy individual identity for tests and simulations */
|
/** Dummy individual identity for tests and simulations */
|
||||||
val CHARLIE_IDENTITY: PartyAndCertificate get() = getTestPartyAndCertificate(CHARLIE)
|
val CHARLIE_IDENTITY: PartyAndCertificate get() = getTestPartyAndCertificate(CHARLIE)
|
||||||
val CHARLIE: Party get() = Party(getX500Name(O = "Charlie Ltd", L = "Athens", C = "GR"), CHARLIE_KEY.public)
|
val CHARLIE: Party get() = Party(CordaX500Name(organisation = "Charlie Ltd", locality = "Athens", country = "GR"), CHARLIE_KEY.public)
|
||||||
|
|
||||||
val DUMMY_REGULATOR_KEY: KeyPair by lazy { entropyToKeyPair(BigInteger.valueOf(100)) }
|
val DUMMY_REGULATOR_KEY: KeyPair by lazy { entropyToKeyPair(BigInteger.valueOf(100)) }
|
||||||
/** Dummy regulator for tests and simulations */
|
/** Dummy regulator for tests and simulations */
|
||||||
val DUMMY_REGULATOR: Party get() = Party(getX500Name(O = "Regulator A", OU = "Corda", L = "Paris", C = "FR"), DUMMY_REGULATOR_KEY.public)
|
val DUMMY_REGULATOR: Party get() = Party(CordaX500Name(organisation = "Regulator A", locality = "Paris", country = "FR"), DUMMY_REGULATOR_KEY.public)
|
||||||
|
|
||||||
val DUMMY_CA_KEY: KeyPair by lazy { entropyToKeyPair(BigInteger.valueOf(110)) }
|
val DUMMY_CA_KEY: KeyPair by lazy { entropyToKeyPair(BigInteger.valueOf(110)) }
|
||||||
val DUMMY_CA: CertificateAndKeyPair by lazy {
|
val DUMMY_CA: CertificateAndKeyPair by lazy {
|
||||||
@ -74,4 +75,4 @@ fun dummyCommand(vararg signers: PublicKey = arrayOf(generateKeyPair().public) )
|
|||||||
object DummyCommandData : TypeOnlyCommandData()
|
object DummyCommandData : TypeOnlyCommandData()
|
||||||
|
|
||||||
val DUMMY_IDENTITY_1: PartyAndCertificate get() = getTestPartyAndCertificate(DUMMY_PARTY)
|
val DUMMY_IDENTITY_1: PartyAndCertificate get() = getTestPartyAndCertificate(DUMMY_PARTY)
|
||||||
val DUMMY_PARTY: Party get() = Party(getX500Name(O = "Dummy", L = "Madrid", C = "ES"), DUMMY_KEY_1.public)
|
val DUMMY_PARTY: Party get() = Party(CordaX500Name(organisation = "Dummy", locality = "Madrid", country = "ES"), DUMMY_KEY_1.public)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package net.corda.testing.messaging
|
package net.corda.testing.messaging
|
||||||
|
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
import net.corda.core.utilities.getX500Name
|
|
||||||
import net.corda.nodeapi.ArtemisMessagingComponent
|
import net.corda.nodeapi.ArtemisMessagingComponent
|
||||||
import net.corda.nodeapi.ArtemisTcpTransport
|
import net.corda.nodeapi.ArtemisTcpTransport
|
||||||
import net.corda.nodeapi.ConnectionDirection
|
import net.corda.nodeapi.ConnectionDirection
|
||||||
@ -15,8 +15,9 @@ import org.apache.activemq.artemis.api.core.client.*
|
|||||||
class SimpleMQClient(val target: NetworkHostAndPort,
|
class SimpleMQClient(val target: NetworkHostAndPort,
|
||||||
override val config: SSLConfiguration? = configureTestSSL(DEFAULT_MQ_LEGAL_NAME)) : ArtemisMessagingComponent() {
|
override val config: SSLConfiguration? = configureTestSSL(DEFAULT_MQ_LEGAL_NAME)) : ArtemisMessagingComponent() {
|
||||||
companion object {
|
companion object {
|
||||||
val DEFAULT_MQ_LEGAL_NAME = getX500Name(O = "SimpleMQClient", OU = "corda", L = "London", C = "GB")
|
val DEFAULT_MQ_LEGAL_NAME = CordaX500Name(organisation = "SimpleMQClient", locality = "London", country = "GB")
|
||||||
}
|
}
|
||||||
|
|
||||||
lateinit var sessionFactory: ClientSessionFactory
|
lateinit var sessionFactory: ClientSessionFactory
|
||||||
lateinit var session: ClientSession
|
lateinit var session: ClientSession
|
||||||
lateinit var producer: ClientProducer
|
lateinit var producer: ClientProducer
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
package net.corda.demobench.model
|
package net.corda.demobench.model
|
||||||
|
|
||||||
import com.typesafe.config.Config
|
import com.typesafe.config.Config
|
||||||
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.node.services.ServiceInfo
|
import net.corda.core.node.services.ServiceInfo
|
||||||
import net.corda.core.node.services.ServiceType
|
import net.corda.core.node.services.ServiceType
|
||||||
import net.corda.core.utilities.parseNetworkHostAndPort
|
import net.corda.core.utilities.parseNetworkHostAndPort
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
@ -21,7 +21,7 @@ class InstallFactory : Controller() {
|
|||||||
val rpcPort = config.parsePort("rpcAddress")
|
val rpcPort = config.parsePort("rpcAddress")
|
||||||
val webPort = config.parsePort("webAddress")
|
val webPort = config.parsePort("webAddress")
|
||||||
val h2Port = config.getInt("h2port")
|
val h2Port = config.getInt("h2port")
|
||||||
val x500name = X500Name(config.getString("myLegalName"))
|
val x500name = CordaX500Name.parse(config.getString("myLegalName"))
|
||||||
val extraServices = config.parseExtraServices("extraAdvertisedServiceIds")
|
val extraServices = config.parseExtraServices("extraAdvertisedServiceIds")
|
||||||
val tempDir = Files.createTempDirectory(baseDir, ".node")
|
val tempDir = Files.createTempDirectory(baseDir, ".node")
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ class InstallFactory : Controller() {
|
|||||||
|
|
||||||
if (config.hasPath("networkMapService")) {
|
if (config.hasPath("networkMapService")) {
|
||||||
val nmap = config.getConfig("networkMapService")
|
val nmap = config.getConfig("networkMapService")
|
||||||
nodeConfig.networkMap = NetworkMapConfig(X500Name(nmap.getString("legalName")), nmap.parsePort("address"))
|
nodeConfig.networkMap = NetworkMapConfig(CordaX500Name.parse(nmap.getString("legalName")), nmap.parsePort("address"))
|
||||||
} else {
|
} else {
|
||||||
log.info("Node '${nodeConfig.legalName}' is the network map")
|
log.info("Node '${nodeConfig.legalName}' is the network map")
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user