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:
Ross Nicoll
2017-09-12 01:03:10 +01:00
committed by GitHub
parent 9d76c66e5e
commit de3468f8a7
114 changed files with 867 additions and 769 deletions

View File

@ -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)
} }
} }
} }

View File

@ -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(

View File

@ -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(),

View File

@ -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,

View File

@ -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

View File

@ -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()})"
} }

View 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!!
}
}

View File

@ -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()

View File

@ -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

View File

@ -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" }
}
}
}
}

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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()

View File

@ -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)
} }
} }

View File

@ -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" }
}
}
}

View File

@ -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)
}

View File

@ -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"

View File

@ -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")
}
}
}

View File

@ -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)

View File

@ -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")
}
}
}

View File

@ -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`() {

View File

@ -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"))
}
}
}

View File

@ -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

View File

@ -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

View File

@ -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] */

View File

@ -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) }

View File

@ -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()
} }

View File

@ -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) }

View File

@ -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>)

View File

@ -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"

View File

@ -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
} }

View File

@ -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`() {

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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...")

View File

@ -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)
} }

View File

@ -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)

View File

@ -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)
} }

View File

@ -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,

View File

@ -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

View File

@ -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()}."
} }
} }
} }

View File

@ -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)

View File

@ -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!"
} }

View File

@ -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
} }

View File

@ -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 {

View File

@ -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")

View File

@ -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",

View File

@ -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")
} }

View File

@ -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 ->

View File

@ -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 ->

View File

@ -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())

View File

@ -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() }

View File

@ -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)

View File

@ -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))

View File

@ -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,

View File

@ -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,

View File

@ -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)

View File

@ -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 {

View File

@ -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)
} }

View File

@ -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))
} }

View File

@ -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))
} }

View File

@ -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

View File

@ -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.

View File

@ -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 {

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 {

View File

@ -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>()

View File

@ -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

View File

@ -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

View File

@ -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 {

View File

@ -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>?,

View File

@ -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))
} }
} }

View File

@ -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)
} }
} }

View File

@ -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)

View File

@ -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"]

View File

@ -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 }
} }

View File

@ -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>)
/** /**

View File

@ -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"]

View File

@ -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.
// //

View File

@ -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)

View File

@ -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() }

View File

@ -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)

View File

@ -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

View File

@ -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(),

View File

@ -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
} }
} }

View File

@ -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

View File

@ -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)
} }

View File

@ -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)
} }

View File

@ -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(

View File

@ -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,

View File

@ -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" )
} }

View File

@ -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)

View File

@ -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

View File

@ -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