mirror of
https://github.com/corda/corda.git
synced 2024-12-20 05:28:21 +00:00
Enforce X500Name format defined in design doc (#1427)
* Standardise X500Name format - WIP * address PR issues * failing test fix and replace X500Name with getX500Name * gradle plugin fix * Added country code validation
This commit is contained in:
parent
d9d17be284
commit
57412d4498
@ -216,15 +216,15 @@ tasks.withType(Test) {
|
|||||||
|
|
||||||
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 "CN=Controller,O=R3,OU=corda,L=London,C=GB"
|
networkMap "O=Controller,OU=corda,L=London,C=GB"
|
||||||
node {
|
node {
|
||||||
name "CN=Controller,O=R3,OU=corda,L=London,C=GB"
|
name "O=Controller,OU=corda,L=London,C=GB"
|
||||||
advertisedServices = ["corda.notary.validating"]
|
advertisedServices = ["corda.notary.validating"]
|
||||||
p2pPort 10002
|
p2pPort 10002
|
||||||
cordapps = []
|
cordapps = []
|
||||||
}
|
}
|
||||||
node {
|
node {
|
||||||
name "CN=Bank A,O=R3,OU=corda,L=London,C=GB"
|
name "O=Bank A,OU=corda,L=London,C=GB"
|
||||||
advertisedServices = []
|
advertisedServices = []
|
||||||
p2pPort 10012
|
p2pPort 10012
|
||||||
rpcPort 10013
|
rpcPort 10013
|
||||||
@ -232,7 +232,7 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
|
|||||||
cordapps = []
|
cordapps = []
|
||||||
}
|
}
|
||||||
node {
|
node {
|
||||||
name "CN=Bank B,O=R3,OU=corda,L=London,C=GB"
|
name "O=Bank B,OU=corda,L=London,C=GB"
|
||||||
advertisedServices = []
|
advertisedServices = []
|
||||||
p2pPort 10007
|
p2pPort 10007
|
||||||
rpcPort 10008
|
rpcPort 10008
|
||||||
|
@ -6,12 +6,12 @@ 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;
|
||||||
import net.corda.core.utilities.OpaqueBytes;
|
import net.corda.core.utilities.OpaqueBytes;
|
||||||
|
import net.corda.core.utilities.X500NameUtils;
|
||||||
import net.corda.finance.flows.AbstractCashFlow;
|
import net.corda.finance.flows.AbstractCashFlow;
|
||||||
import net.corda.finance.flows.CashIssueFlow;
|
import net.corda.finance.flows.CashIssueFlow;
|
||||||
import net.corda.nodeapi.User;
|
import net.corda.nodeapi.User;
|
||||||
import net.corda.smoketesting.NodeConfig;
|
import net.corda.smoketesting.NodeConfig;
|
||||||
import net.corda.smoketesting.NodeProcess;
|
import net.corda.smoketesting.NodeProcess;
|
||||||
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;
|
||||||
@ -43,7 +43,7 @@ public class StandaloneCordaRPCJavaClientTest {
|
|||||||
private NodeInfo notaryNode;
|
private NodeInfo notaryNode;
|
||||||
|
|
||||||
private NodeConfig notaryConfig = new NodeConfig(
|
private NodeConfig notaryConfig = new NodeConfig(
|
||||||
new X500Name("CN=Notary Service,O=R3,OU=corda,L=Zurich,C=CH"),
|
X500NameUtils.getX500Name("Notary Service", "Zurich", "CH"),
|
||||||
port.getAndIncrement(),
|
port.getAndIncrement(),
|
||||||
port.getAndIncrement(),
|
port.getAndIncrement(),
|
||||||
port.getAndIncrement(),
|
port.getAndIncrement(),
|
||||||
|
@ -9,10 +9,7 @@ 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.OpaqueBytes
|
import net.corda.core.utilities.*
|
||||||
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
|
||||||
@ -26,7 +23,6 @@ import net.corda.nodeapi.User
|
|||||||
import net.corda.smoketesting.NodeConfig
|
import net.corda.smoketesting.NodeConfig
|
||||||
import net.corda.smoketesting.NodeProcess
|
import net.corda.smoketesting.NodeProcess
|
||||||
import org.apache.commons.io.output.NullOutputStream
|
import org.apache.commons.io.output.NullOutputStream
|
||||||
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
|
||||||
@ -58,12 +54,12 @@ class StandaloneCordaRPClientTest {
|
|||||||
private lateinit var notaryNode: NodeInfo
|
private lateinit var notaryNode: NodeInfo
|
||||||
|
|
||||||
private val notaryConfig = NodeConfig(
|
private val notaryConfig = NodeConfig(
|
||||||
legalName = X500Name("CN=Notary Service,O=R3,OU=corda,L=Zurich,C=CH"),
|
legalName = getX500Name(O = "Notary Service", OU = "corda", L = "Zurich", C = "CH"),
|
||||||
p2pPort = port.andIncrement,
|
p2pPort = port.andIncrement,
|
||||||
rpcPort = port.andIncrement,
|
rpcPort = port.andIncrement,
|
||||||
webPort = port.andIncrement,
|
webPort = port.andIncrement,
|
||||||
extraServices = listOf("corda.notary.validating"),
|
extraServices = listOf("corda.notary.validating"),
|
||||||
users = listOf(user)
|
users = listOf(user)
|
||||||
)
|
)
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
myLegalName : "CN=Bank A,O=Bank A,L=London,C=GB"
|
myLegalName : "O=Bank A,L=London,C=GB"
|
||||||
keyStorePassword : "cordacadevpass"
|
keyStorePassword : "cordacadevpass"
|
||||||
trustStorePassword : "trustpass"
|
trustStorePassword : "trustpass"
|
||||||
p2pAddress : "localhost:10002"
|
p2pAddress : "localhost:10002"
|
||||||
@ -7,6 +7,6 @@ webAddress : "localhost:10004"
|
|||||||
extraAdvertisedServiceIds : [ "corda.interest_rates" ]
|
extraAdvertisedServiceIds : [ "corda.interest_rates" ]
|
||||||
networkMapService : {
|
networkMapService : {
|
||||||
address : "localhost:10000"
|
address : "localhost:10000"
|
||||||
legalName : "CN=Network Map Service,O=R3,OU=corda,L=London,C=GB"
|
legalName : "O=Network Map Service,OU=corda,L=London,C=GB"
|
||||||
}
|
}
|
||||||
useHTTPS : false
|
useHTTPS : false
|
||||||
|
@ -7,6 +7,6 @@ webAddress : "localhost:10007"
|
|||||||
extraAdvertisedServiceIds : [ "corda.interest_rates" ]
|
extraAdvertisedServiceIds : [ "corda.interest_rates" ]
|
||||||
networkMapService : {
|
networkMapService : {
|
||||||
address : "localhost:10000"
|
address : "localhost:10000"
|
||||||
legalName : "CN=Network Map Service,O=R3,OU=corda,L=London,C=GB"
|
legalName : "O=Network Map Service,OU=corda,L=London,C=GB"
|
||||||
}
|
}
|
||||||
useHTTPS : false
|
useHTTPS : false
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
myLegalName : "CN=Notary Service,O=R3,OU=corda,L=London,C=GB"
|
myLegalName : "O=Notary Service,OU=corda,L=London,C=GB"
|
||||||
keyStorePassword : "cordacadevpass"
|
keyStorePassword : "cordacadevpass"
|
||||||
trustStorePassword : "trustpass"
|
trustStorePassword : "trustpass"
|
||||||
p2pAddress : "localhost:10000"
|
p2pAddress : "localhost:10000"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
gradlePluginsVersion=0.16.0
|
gradlePluginsVersion=0.16.1
|
||||||
kotlinVersion=1.1.4
|
kotlinVersion=1.1.4
|
||||||
guavaVersion=21.0
|
guavaVersion=21.0
|
||||||
bouncycastleVersion=1.57
|
bouncycastleVersion=1.57
|
||||||
|
@ -6,7 +6,7 @@ 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.locationOrNull
|
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.
|
||||||
@ -44,7 +44,7 @@ data class NodeInfo(val addresses: List<NetworkHostAndPort>,
|
|||||||
* Uses node's owner X500 name to infer the node's location. Used in Explorer in map view.
|
* Uses node's owner X500 name to infer the node's location. Used in Explorer in map view.
|
||||||
*/
|
*/
|
||||||
fun getWorldMapLocation(): WorldMapLocation? {
|
fun getWorldMapLocation(): WorldMapLocation? {
|
||||||
val nodeOwnerLocation = legalIdentity.name.locationOrNull
|
val nodeOwnerLocation = legalIdentity.name.locality
|
||||||
return nodeOwnerLocation?.let { CityDatabase[it] }
|
return nodeOwnerLocation.let { CityDatabase[it] }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
253
core/src/main/kotlin/net/corda/core/utilities/CountryCode.kt
Normal file
253
core/src/main/kotlin/net/corda/core/utilities/CountryCode.kt
Normal file
@ -0,0 +1,253 @@
|
|||||||
|
package net.corda.core.utilities
|
||||||
|
|
||||||
|
val countryCodes = hashSetOf(
|
||||||
|
"AF",
|
||||||
|
"AX",
|
||||||
|
"AL",
|
||||||
|
"DZ",
|
||||||
|
"AS",
|
||||||
|
"AD",
|
||||||
|
"AO",
|
||||||
|
"AI",
|
||||||
|
"AQ",
|
||||||
|
"AG",
|
||||||
|
"AR",
|
||||||
|
"AM",
|
||||||
|
"AW",
|
||||||
|
"AU",
|
||||||
|
"AT",
|
||||||
|
"AZ",
|
||||||
|
"BS",
|
||||||
|
"BH",
|
||||||
|
"BD",
|
||||||
|
"BB",
|
||||||
|
"BY",
|
||||||
|
"BE",
|
||||||
|
"BZ",
|
||||||
|
"BJ",
|
||||||
|
"BM",
|
||||||
|
"BT",
|
||||||
|
"BO",
|
||||||
|
"BQ",
|
||||||
|
"BA",
|
||||||
|
"BW",
|
||||||
|
"BV",
|
||||||
|
"BR",
|
||||||
|
"IO",
|
||||||
|
"BN",
|
||||||
|
"BG",
|
||||||
|
"BF",
|
||||||
|
"BI",
|
||||||
|
"KH",
|
||||||
|
"CM",
|
||||||
|
"CA",
|
||||||
|
"CV",
|
||||||
|
"KY",
|
||||||
|
"CF",
|
||||||
|
"TD",
|
||||||
|
"CL",
|
||||||
|
"CN",
|
||||||
|
"CX",
|
||||||
|
"CC",
|
||||||
|
"CO",
|
||||||
|
"KM",
|
||||||
|
"CG",
|
||||||
|
"CD",
|
||||||
|
"CK",
|
||||||
|
"CR",
|
||||||
|
"CI",
|
||||||
|
"HR",
|
||||||
|
"CU",
|
||||||
|
"CW",
|
||||||
|
"CY",
|
||||||
|
"CZ",
|
||||||
|
"DK",
|
||||||
|
"DJ",
|
||||||
|
"DM",
|
||||||
|
"DO",
|
||||||
|
"EC",
|
||||||
|
"EG",
|
||||||
|
"SV",
|
||||||
|
"GQ",
|
||||||
|
"ER",
|
||||||
|
"EE",
|
||||||
|
"ET",
|
||||||
|
"FK",
|
||||||
|
"FO",
|
||||||
|
"FJ",
|
||||||
|
"FI",
|
||||||
|
"FR",
|
||||||
|
"GF",
|
||||||
|
"PF",
|
||||||
|
"TF",
|
||||||
|
"GA",
|
||||||
|
"GM",
|
||||||
|
"GE",
|
||||||
|
"DE",
|
||||||
|
"GH",
|
||||||
|
"GI",
|
||||||
|
"GR",
|
||||||
|
"GL",
|
||||||
|
"GD",
|
||||||
|
"GP",
|
||||||
|
"GU",
|
||||||
|
"GT",
|
||||||
|
"GG",
|
||||||
|
"GN",
|
||||||
|
"GW",
|
||||||
|
"GY",
|
||||||
|
"HT",
|
||||||
|
"HM",
|
||||||
|
"VA",
|
||||||
|
"HN",
|
||||||
|
"HK",
|
||||||
|
"HU",
|
||||||
|
"IS",
|
||||||
|
"IN",
|
||||||
|
"ID",
|
||||||
|
"IR",
|
||||||
|
"IQ",
|
||||||
|
"IE",
|
||||||
|
"IM",
|
||||||
|
"IL",
|
||||||
|
"IT",
|
||||||
|
"JM",
|
||||||
|
"JP",
|
||||||
|
"JE",
|
||||||
|
"JO",
|
||||||
|
"KZ",
|
||||||
|
"KE",
|
||||||
|
"KI",
|
||||||
|
"KP",
|
||||||
|
"KR",
|
||||||
|
"KW",
|
||||||
|
"KG",
|
||||||
|
"LA",
|
||||||
|
"LV",
|
||||||
|
"LB",
|
||||||
|
"LS",
|
||||||
|
"LR",
|
||||||
|
"LY",
|
||||||
|
"LI",
|
||||||
|
"LT",
|
||||||
|
"LU",
|
||||||
|
"MO",
|
||||||
|
"MK",
|
||||||
|
"MG",
|
||||||
|
"MW",
|
||||||
|
"MY",
|
||||||
|
"MV",
|
||||||
|
"ML",
|
||||||
|
"MT",
|
||||||
|
"MH",
|
||||||
|
"MQ",
|
||||||
|
"MR",
|
||||||
|
"MU",
|
||||||
|
"YT",
|
||||||
|
"MX",
|
||||||
|
"FM",
|
||||||
|
"MD",
|
||||||
|
"MC",
|
||||||
|
"MN",
|
||||||
|
"ME",
|
||||||
|
"MS",
|
||||||
|
"MA",
|
||||||
|
"MZ",
|
||||||
|
"MM",
|
||||||
|
"NA",
|
||||||
|
"NR",
|
||||||
|
"NP",
|
||||||
|
"NL",
|
||||||
|
"NC",
|
||||||
|
"NZ",
|
||||||
|
"NI",
|
||||||
|
"NE",
|
||||||
|
"NG",
|
||||||
|
"NU",
|
||||||
|
"NF",
|
||||||
|
"MP",
|
||||||
|
"NO",
|
||||||
|
"OM",
|
||||||
|
"PK",
|
||||||
|
"PW",
|
||||||
|
"PS",
|
||||||
|
"PA",
|
||||||
|
"PG",
|
||||||
|
"PY",
|
||||||
|
"PE",
|
||||||
|
"PH",
|
||||||
|
"PN",
|
||||||
|
"PL",
|
||||||
|
"PT",
|
||||||
|
"PR",
|
||||||
|
"QA",
|
||||||
|
"RE",
|
||||||
|
"RO",
|
||||||
|
"RU",
|
||||||
|
"RW",
|
||||||
|
"BL",
|
||||||
|
"SH",
|
||||||
|
"KN",
|
||||||
|
"LC",
|
||||||
|
"MF",
|
||||||
|
"PM",
|
||||||
|
"VC",
|
||||||
|
"WS",
|
||||||
|
"SM",
|
||||||
|
"ST",
|
||||||
|
"SA",
|
||||||
|
"SN",
|
||||||
|
"RS",
|
||||||
|
"SC",
|
||||||
|
"SL",
|
||||||
|
"SG",
|
||||||
|
"SX",
|
||||||
|
"SK",
|
||||||
|
"SI",
|
||||||
|
"SB",
|
||||||
|
"SO",
|
||||||
|
"ZA",
|
||||||
|
"GS",
|
||||||
|
"SS",
|
||||||
|
"ES",
|
||||||
|
"LK",
|
||||||
|
"SD",
|
||||||
|
"SR",
|
||||||
|
"SJ",
|
||||||
|
"SZ",
|
||||||
|
"SE",
|
||||||
|
"CH",
|
||||||
|
"SY",
|
||||||
|
"TW",
|
||||||
|
"TJ",
|
||||||
|
"TZ",
|
||||||
|
"TH",
|
||||||
|
"TL",
|
||||||
|
"TG",
|
||||||
|
"TK",
|
||||||
|
"TO",
|
||||||
|
"TT",
|
||||||
|
"TN",
|
||||||
|
"TR",
|
||||||
|
"TM",
|
||||||
|
"TC",
|
||||||
|
"TV",
|
||||||
|
"UG",
|
||||||
|
"UA",
|
||||||
|
"AE",
|
||||||
|
"GB",
|
||||||
|
"US",
|
||||||
|
"UM",
|
||||||
|
"UY",
|
||||||
|
"UZ",
|
||||||
|
"VU",
|
||||||
|
"VE",
|
||||||
|
"VN",
|
||||||
|
"VG",
|
||||||
|
"VI",
|
||||||
|
"WF",
|
||||||
|
"EH",
|
||||||
|
"YE",
|
||||||
|
"ZM",
|
||||||
|
"ZW"
|
||||||
|
)
|
@ -3,6 +3,7 @@
|
|||||||
package net.corda.core.utilities
|
package net.corda.core.utilities
|
||||||
|
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
import org.bouncycastle.asn1.x500.X500Name
|
||||||
|
import org.bouncycastle.asn1.x500.style.BCStyle
|
||||||
import java.lang.Character.UnicodeScript.*
|
import java.lang.Character.UnicodeScript.*
|
||||||
import java.text.Normalizer
|
import java.text.Normalizer
|
||||||
import java.util.regex.Pattern
|
import java.util.regex.Pattern
|
||||||
@ -21,16 +22,9 @@ import javax.security.auth.x500.X500Principal
|
|||||||
* @throws IllegalArgumentException if the name does not meet the required rules. The message indicates why not.
|
* @throws IllegalArgumentException if the name does not meet the required rules. The message indicates why not.
|
||||||
*/
|
*/
|
||||||
fun validateLegalName(normalizedLegalName: String) {
|
fun validateLegalName(normalizedLegalName: String) {
|
||||||
legalNameRules.forEach { it.validate(normalizedLegalName) }
|
Rule.legalNameRules.forEach { it.validate(normalizedLegalName) }
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Implement X500 attribute validation once the specification has been finalised.
|
|
||||||
fun validateX500Name(x500Name: X500Name) {
|
|
||||||
validateLegalName(x500Name.commonName)
|
|
||||||
}
|
|
||||||
|
|
||||||
val WHITESPACE = "\\s++".toRegex()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The normalize function will trim the input string, replace any multiple spaces with a single space,
|
* 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.
|
* and normalize the string according to NFKC normalization form.
|
||||||
@ -40,82 +34,137 @@ fun normaliseLegalName(legalName: String): String {
|
|||||||
return Normalizer.normalize(trimmedLegalName, Normalizer.Form.NFKC)
|
return Normalizer.normalize(trimmedLegalName, Normalizer.Form.NFKC)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val legalNameRules: List<Rule<String>> = listOf(
|
val WHITESPACE = "\\s++".toRegex()
|
||||||
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()
|
|
||||||
)
|
|
||||||
|
|
||||||
private class UnicodeNormalizationRule : Rule<String> {
|
private val mandatoryAttributes = setOf(BCStyle.O, BCStyle.C, BCStyle.L)
|
||||||
override fun validate(legalName: String) {
|
private val supportedAttributes = mandatoryAttributes + setOf(BCStyle.CN, BCStyle.ST, BCStyle.OU)
|
||||||
require(legalName == normaliseLegalName(legalName)) { "Legal name must be normalized. Please use 'normaliseLegalName' to normalize the legal name before validation." }
|
|
||||||
|
/**
|
||||||
|
* 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.toList() }
|
||||||
|
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 < 127) { "Organisation attribute (O) must contain less then 127 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(x500Name.organisationUnit!!.length < 64) { "Organisation Unit attribute (OU) must contain less then 64 characters." } }
|
||||||
|
x500Name.commonName?.let { require(x500Name.commonName!!.length < 64) { "Common Name attribute (CN) must contain less then 64 characters." } }
|
||||||
}
|
}
|
||||||
|
|
||||||
private class UnicodeRangeRule(vararg supportScripts: Character.UnicodeScript) : Rule<String> {
|
private sealed class Rule<in T> {
|
||||||
private val pattern = supportScripts.map { "\\p{Is$it}" }.joinToString(separator = "", prefix = "[", postfix = "]*").let { Pattern.compile(it) }
|
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()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override fun validate(legalName: String) {
|
abstract fun validate(legalName: T)
|
||||||
require(pattern.matcher(legalName).matches()) {
|
|
||||||
val illegalChars = legalName.replace(pattern.toRegex(), "").toSet()
|
private class UnicodeNormalizationRule : Rule<String>() {
|
||||||
if (illegalChars.size > 1) {
|
override fun validate(legalName: String) {
|
||||||
"Forbidden characters $illegalChars in \"$legalName\"."
|
require(legalName == normaliseLegalName(legalName)) { "Legal name must be normalized. Please use 'normaliseLegalName' to normalize the legal name before validation." }
|
||||||
} else {
|
}
|
||||||
"Forbidden character $illegalChars in \"$legalName\"."
|
}
|
||||||
|
|
||||||
|
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> {
|
private class CharacterRule(vararg val bannedChars: Char) : Rule<String>() {
|
||||||
override fun validate(legalName: String) {
|
override fun validate(legalName: String) {
|
||||||
bannedChars.forEach {
|
bannedChars.forEach {
|
||||||
require(!legalName.contains(it, true)) { "Character not allowed in legal names: $it" }
|
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" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private interface Rule<in T> {
|
|
||||||
fun validate(legalName: T)
|
|
||||||
}
|
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
@file:JvmName("X500NameUtils")
|
@file:JvmName("X500NameUtils")
|
||||||
|
|
||||||
package net.corda.core.utilities
|
package net.corda.core.utilities
|
||||||
|
|
||||||
import net.corda.core.internal.toX509CertHolder
|
import net.corda.core.internal.toX509CertHolder
|
||||||
import org.bouncycastle.asn1.ASN1Encodable
|
import org.bouncycastle.asn1.ASN1ObjectIdentifier
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
import org.bouncycastle.asn1.x500.X500Name
|
||||||
import org.bouncycastle.asn1.x500.X500NameBuilder
|
import org.bouncycastle.asn1.x500.X500NameBuilder
|
||||||
import org.bouncycastle.asn1.x500.style.BCStyle
|
import org.bouncycastle.asn1.x500.style.BCStyle
|
||||||
@ -11,68 +12,47 @@ import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter
|
|||||||
import java.security.KeyPair
|
import java.security.KeyPair
|
||||||
import java.security.cert.X509Certificate
|
import java.security.cert.X509Certificate
|
||||||
|
|
||||||
/**
|
val X500Name.commonName: String? get() = getRDNValueString(BCStyle.CN)
|
||||||
* Rebuild the distinguished name, adding a postfix to the common name. If no common name is present.
|
val X500Name.organisationUnit: String? get() = getRDNValueString(BCStyle.OU)
|
||||||
* @throws IllegalArgumentException if the distinguished name does not contain a common name element.
|
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.")
|
||||||
fun X500Name.appendToCommonName(commonName: String): X500Name = mutateCommonName { attr -> attr.toString() + commonName }
|
val X500Name.locality: String get() = getRDNValueString(BCStyle.L) ?: throw IllegalArgumentException("Malformed X500 name, locality attribute (L) cannot be empty.")
|
||||||
|
val X500Name.country: String get() = getRDNValueString(BCStyle.C) ?: throw IllegalArgumentException("Malformed X500 name, country attribute (C) cannot be empty.")
|
||||||
|
|
||||||
/**
|
private fun X500Name.getRDNValueString(identifier: ASN1ObjectIdentifier): String? = getRDNs(identifier).firstOrNull()?.first?.value?.toString()
|
||||||
* Rebuild the distinguished name, replacing the common name with the given value. If no common name is present, this
|
|
||||||
* adds one.
|
|
||||||
* @throws IllegalArgumentException if the distinguished name does not contain a common name element.
|
|
||||||
*/
|
|
||||||
fun X500Name.replaceCommonName(commonName: String): X500Name = mutateCommonName { _ -> commonName }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Rebuild the distinguished name, replacing the common name with a value generated from the provided function.
|
|
||||||
*
|
|
||||||
* @param mutator a function to generate the new value from the previous one.
|
|
||||||
* @throws IllegalArgumentException if the distinguished name does not contain a common name element.
|
|
||||||
*/
|
|
||||||
private fun X500Name.mutateCommonName(mutator: (ASN1Encodable) -> String): X500Name {
|
|
||||||
val builder = X500NameBuilder(BCStyle.INSTANCE)
|
|
||||||
var matched = false
|
|
||||||
this.rdNs.forEach { rdn ->
|
|
||||||
rdn.typesAndValues.forEach { typeAndValue ->
|
|
||||||
when (typeAndValue.type) {
|
|
||||||
BCStyle.CN -> {
|
|
||||||
matched = true
|
|
||||||
builder.addRDN(typeAndValue.type, mutator(typeAndValue.value))
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
builder.addRDN(typeAndValue)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
require(matched) { "Input X.500 name must include a common name (CN) attribute: ${this}" }
|
|
||||||
return builder.build()
|
|
||||||
}
|
|
||||||
|
|
||||||
val X500Name.commonName: String get() = getRDNs(BCStyle.CN).first().first.value.toString()
|
|
||||||
val X500Name.orgName: String? get() = getRDNs(BCStyle.O).firstOrNull()?.first?.value?.toString()
|
|
||||||
val X500Name.location: String get() = getRDNs(BCStyle.L).first().first.value.toString()
|
|
||||||
val X500Name.locationOrNull: String? get() = try {
|
|
||||||
location
|
|
||||||
} catch (e: Exception) {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
val X509Certificate.subject: X500Name get() = toX509CertHolder().subject
|
val X509Certificate.subject: X500Name get() = toX509CertHolder().subject
|
||||||
val X509CertificateHolder.cert: X509Certificate get() = JcaX509CertificateConverter().getCertificate(this)
|
val X509CertificateHolder.cert: X509Certificate get() = JcaX509CertificateConverter().getCertificate(this)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a distinguished name from the provided values.
|
* Generate a distinguished name from the provided X500 .
|
||||||
|
*
|
||||||
|
* @param O organisation name.
|
||||||
|
* @param L locality.
|
||||||
|
* @param C county.
|
||||||
|
* @param CN common name.
|
||||||
|
* @param OU organisation unit.
|
||||||
|
* @param ST state.
|
||||||
*/
|
*/
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
fun getX509Name(myLegalName: String, nearestCity: String, email: String, country: String? = null): X500Name {
|
fun getX500Name(O: String, L: String, C: String, CN: String? = null, OU: String? = null, ST: String? = null): X500Name {
|
||||||
return X500NameBuilder(BCStyle.INSTANCE).let { builder ->
|
return X500NameBuilder(BCStyle.INSTANCE).apply {
|
||||||
builder.addRDN(BCStyle.CN, myLegalName)
|
addRDN(BCStyle.C, C)
|
||||||
builder.addRDN(BCStyle.L, nearestCity)
|
ST?.let { addRDN(BCStyle.ST, it) }
|
||||||
country?.let { builder.addRDN(BCStyle.C, it) }
|
addRDN(BCStyle.L, L)
|
||||||
builder.addRDN(BCStyle.E, email)
|
addRDN(BCStyle.O, O)
|
||||||
builder.build()
|
OU?.let { addRDN(BCStyle.OU, it) }
|
||||||
}
|
CN?.let { addRDN(BCStyle.CN, it) }
|
||||||
|
}.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)
|
||||||
}
|
}
|
||||||
|
|
||||||
data class CertificateAndKeyPair(val certificate: X509CertificateHolder, val keyPair: KeyPair)
|
data class CertificateAndKeyPair(val certificate: X509CertificateHolder, val keyPair: KeyPair)
|
||||||
|
@ -7,11 +7,11 @@ import net.corda.core.internal.div
|
|||||||
import net.corda.core.serialization.serialize
|
import net.corda.core.serialization.serialize
|
||||||
import net.corda.core.utilities.OpaqueBytes
|
import net.corda.core.utilities.OpaqueBytes
|
||||||
import net.corda.core.utilities.cert
|
import net.corda.core.utilities.cert
|
||||||
|
import net.corda.core.utilities.getX500Name
|
||||||
import net.corda.core.utilities.toBase58String
|
import net.corda.core.utilities.toBase58String
|
||||||
import net.corda.node.utilities.*
|
import net.corda.node.utilities.*
|
||||||
import net.corda.testing.TestDependencyInjectionBase
|
import net.corda.testing.TestDependencyInjectionBase
|
||||||
import net.corda.testing.kryoSpecific
|
import net.corda.testing.kryoSpecific
|
||||||
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
|
||||||
@ -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(X500Name("CN=Test CA"), caKeyPair)
|
val ca = X509Utilities.createSelfSignedCACertificate(getX500Name(CN = "Test CA", O = "R3", 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, X500Name("CN=CompositeKey"), compositeKey)
|
val compositeKeyCert = X509Utilities.createCertificate(CertificateType.IDENTITY, ca, caKeyPair, getX500Name(CN = "CompositeKey", O = "R3", 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"
|
||||||
|
@ -2,6 +2,7 @@ package net.corda.core.crypto
|
|||||||
|
|
||||||
import net.corda.core.internal.toTypedArray
|
import net.corda.core.internal.toTypedArray
|
||||||
import net.corda.core.utilities.cert
|
import net.corda.core.utilities.cert
|
||||||
|
import net.corda.core.utilities.getX500Name
|
||||||
import net.corda.node.utilities.*
|
import net.corda.node.utilities.*
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
import org.bouncycastle.asn1.x500.X500Name
|
||||||
import org.bouncycastle.asn1.x509.GeneralName
|
import org.bouncycastle.asn1.x509.GeneralName
|
||||||
@ -19,13 +20,13 @@ class X509NameConstraintsTest {
|
|||||||
|
|
||||||
private fun makeKeyStores(subjectName: X500Name, nameConstraints: NameConstraints): Pair<KeyStore, KeyStore> {
|
private fun makeKeyStores(subjectName: X500Name, nameConstraints: NameConstraints): Pair<KeyStore, KeyStore> {
|
||||||
val rootKeys = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
val rootKeys = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||||
val rootCACert = X509Utilities.createSelfSignedCACertificate(net.corda.core.utilities.getX509Name("Corda Root CA", "London", "demo@r3.com", null), rootKeys)
|
val rootCACert = X509Utilities.createSelfSignedCACertificate(getX500Name(CN = "Corda Root CA", O = "R3CEV", L = "London", C = "GB"), rootKeys)
|
||||||
|
|
||||||
val intermediateCAKeyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
val intermediateCAKeyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||||
val intermediateCACert = X509Utilities.createCertificate(CertificateType.INTERMEDIATE_CA, rootCACert, rootKeys, net.corda.core.utilities.getX509Name("Corda Intermediate CA", "London", "demo@r3.com", null), intermediateCAKeyPair.public)
|
val intermediateCACert = X509Utilities.createCertificate(CertificateType.INTERMEDIATE_CA, rootCACert, rootKeys, getX500Name(CN = "Corda Intermediate CA", O = "R3CEV", L = "London", C = "GB"), intermediateCAKeyPair.public)
|
||||||
|
|
||||||
val clientCAKeyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
val clientCAKeyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||||
val clientCACert = X509Utilities.createCertificate(CertificateType.INTERMEDIATE_CA, intermediateCACert, intermediateCAKeyPair, net.corda.core.utilities.getX509Name("Corda Client CA", "London", "demo@r3.com", null), clientCAKeyPair.public, nameConstraints = nameConstraints)
|
val clientCACert = X509Utilities.createCertificate(CertificateType.INTERMEDIATE_CA, intermediateCACert, intermediateCAKeyPair, getX500Name(CN = "Corda Client CA", O = "R3CEV", L = "London", C = "GB"), clientCAKeyPair.public, nameConstraints = nameConstraints)
|
||||||
|
|
||||||
val keyPass = "password"
|
val keyPass = "password"
|
||||||
val trustStore = KeyStore.getInstance(KEYSTORE_TYPE)
|
val trustStore = KeyStore.getInstance(KEYSTORE_TYPE)
|
||||||
|
@ -3,10 +3,10 @@ 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
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.math.BigInteger
|
import java.math.BigInteger
|
||||||
|
|
||||||
@ -15,7 +15,7 @@ class PartyAndCertificateTest {
|
|||||||
fun `kryo serialisation`() {
|
fun `kryo serialisation`() {
|
||||||
withTestSerialization {
|
withTestSerialization {
|
||||||
val original = getTestPartyAndCertificate(Party(
|
val original = getTestPartyAndCertificate(Party(
|
||||||
X500Name("CN=Test Corp,O=Test Corp,L=Madrid,C=ES"),
|
getX500Name(O = "Test Corp", L = "Madrid", C = "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)
|
||||||
|
@ -2,14 +2,14 @@ package net.corda.core.node
|
|||||||
|
|
||||||
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.testing.getTestX509Name
|
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 = getTestX509Name("service.name")
|
val name = getX500Name(O = "service.name", L = "London", C = "GB")
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `type and name encodes correctly`() {
|
fun `type and name encodes correctly`() {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package net.corda.core.utilities
|
package net.corda.core.utilities
|
||||||
|
|
||||||
|
import org.bouncycastle.asn1.x500.X500Name
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertFailsWith
|
import kotlin.test.assertFailsWith
|
||||||
@ -99,4 +100,33 @@ class LegalNameValidatorTest {
|
|||||||
validateLegalName("Legal Name With\n\rLine\nBreaks")
|
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"))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -34,7 +34,7 @@ NetworkMapService plus Simple Notary configuration file.
|
|||||||
|
|
||||||
.. parsed-literal::
|
.. parsed-literal::
|
||||||
|
|
||||||
myLegalName : "CN=Notary Service,O=R3,OU=corda,L=London,C=GB"
|
myLegalName : "O=Notary Service,OU=corda,L=London,C=GB"
|
||||||
keyStorePassword : "cordacadevpass"
|
keyStorePassword : "cordacadevpass"
|
||||||
trustStorePassword : "trustpass"
|
trustStorePassword : "trustpass"
|
||||||
p2pAddress : "localhost:12345"
|
p2pAddress : "localhost:12345"
|
||||||
|
@ -17,9 +17,9 @@ notary/network map node:
|
|||||||
|
|
||||||
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 "CN=Controller,O=R3,OU=corda,L=London,C=UK"
|
networkMap "O=Controller,OU=corda,L=London,C=UK"
|
||||||
node {
|
node {
|
||||||
name "CN=Controller,O=R3,OU=corda,L=London,C=UK"
|
name "O=Controller,OU=corda,L=London,C=UK"
|
||||||
advertisedServices = ["corda.notary.validating"]
|
advertisedServices = ["corda.notary.validating"]
|
||||||
p2pPort 10002
|
p2pPort 10002
|
||||||
rpcPort 10003
|
rpcPort 10003
|
||||||
|
@ -70,9 +70,9 @@ task integrationTest(type: Test) {
|
|||||||
|
|
||||||
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 "CN=Notary Service,O=R3,OU=corda,L=London,C=GB"
|
networkMap "O=Notary Service,OU=corda,L=London,C=GB"
|
||||||
node {
|
node {
|
||||||
name "CN=Notary Service,O=R3,OU=corda,L=London,C=GB"
|
name "O=Notary Service,OU=corda,L=London,C=GB"
|
||||||
advertisedServices = ["corda.notary.validating"]
|
advertisedServices = ["corda.notary.validating"]
|
||||||
p2pPort 10002
|
p2pPort 10002
|
||||||
rpcPort 10003
|
rpcPort 10003
|
||||||
@ -80,7 +80,7 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
|
|||||||
cordapps = []
|
cordapps = []
|
||||||
}
|
}
|
||||||
node {
|
node {
|
||||||
name "CN=Alice Corp,O=Alice Corp,L=London,C=GB"
|
name "O=Alice Corp,L=London,C=GB"
|
||||||
advertisedServices = []
|
advertisedServices = []
|
||||||
p2pPort 10005
|
p2pPort 10005
|
||||||
rpcPort 10006
|
rpcPort 10006
|
||||||
|
@ -16,19 +16,17 @@ import net.corda.core.node.services.vault.QueryCriteria.VaultQueryCriteria;
|
|||||||
import net.corda.core.transactions.LedgerTransaction;
|
import net.corda.core.transactions.LedgerTransaction;
|
||||||
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.transactions.WireTransaction;
|
|
||||||
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.DummyState;
|
import net.corda.testing.contracts.DummyState;
|
||||||
import org.bouncycastle.asn1.x500.X500Name;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
import java.security.SignatureException;
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -124,7 +122,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(new X500Name("CN=Notary Service,O=R3,OU=corda,L=London,C=UK"));
|
Party specificNotary = getServiceHub().getNetworkMapCache().getNotary(X500NameUtils.getX500Name("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
|
||||||
@ -135,7 +133,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(new X500Name("CN=NodeA,O=NodeA,L=London,C=UK")).getLegalIdentity();
|
Party namedCounterparty = getServiceHub().getNetworkMapCache().getNodeByLegalName(X500NameUtils.getX500Name("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
|
||||||
|
@ -16,16 +16,12 @@ import net.corda.core.node.services.vault.QueryCriteria.VaultQueryCriteria
|
|||||||
import net.corda.core.transactions.LedgerTransaction
|
import net.corda.core.transactions.LedgerTransaction
|
||||||
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.ProgressTracker
|
import net.corda.core.utilities.*
|
||||||
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.seconds
|
|
||||||
import net.corda.core.utilities.unwrap
|
|
||||||
import net.corda.finance.contracts.asset.Cash
|
import net.corda.finance.contracts.asset.Cash
|
||||||
import net.corda.testing.ALICE_PUBKEY
|
import net.corda.testing.ALICE_PUBKEY
|
||||||
import net.corda.testing.contracts.DummyContract
|
import net.corda.testing.contracts.DummyContract
|
||||||
import net.corda.testing.contracts.DummyState
|
import net.corda.testing.contracts.DummyState
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
|
||||||
@ -63,6 +59,7 @@ object FlowCookbook {
|
|||||||
// subflow's progress steps in our flow's progress tracker.
|
// subflow's progress steps in our flow's progress tracker.
|
||||||
override fun childProgressTracker() = CollectSignaturesFlow.tracker()
|
override fun childProgressTracker() = CollectSignaturesFlow.tracker()
|
||||||
}
|
}
|
||||||
|
|
||||||
object VERIFYING_SIGS : Step("Verifying a transaction's signatures.")
|
object VERIFYING_SIGS : Step("Verifying a transaction's signatures.")
|
||||||
object FINALISATION : Step("Finalising a transaction.") {
|
object FINALISATION : Step("Finalising a transaction.") {
|
||||||
override fun childProgressTracker() = FinalityFlow.tracker()
|
override fun childProgressTracker() = FinalityFlow.tracker()
|
||||||
@ -105,7 +102,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(X500Name("CN=Notary Service,O=R3,OU=corda,L=London,C=UK"))
|
val specificNotary: Party? = serviceHub.networkMapCache.getNotary(getX500Name(O = "Notary Service", OU = "corda", L = "London", C = "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
|
||||||
@ -116,7 +113,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(X500Name("CN=NodeA,O=NodeA,L=London,C=UK"))?.legalIdentity
|
val namedCounterparty: Party? = serviceHub.networkMapCache.getNodeByLegalName(getX500Name(O = "NodeA", L = "London", C = "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
|
||||||
@ -389,7 +386,7 @@ object FlowCookbook {
|
|||||||
subFlow(SendTransactionFlow(counterparty, twiceSignedTx))
|
subFlow(SendTransactionFlow(counterparty, twiceSignedTx))
|
||||||
|
|
||||||
// Optional request verification to further restrict data access.
|
// Optional request verification to further restrict data access.
|
||||||
subFlow(object :SendTransactionFlow(counterparty, twiceSignedTx){
|
subFlow(object : SendTransactionFlow(counterparty, twiceSignedTx) {
|
||||||
override fun verifyDataRequest(dataRequest: FetchDataFlow.Request.Data) {
|
override fun verifyDataRequest(dataRequest: FetchDataFlow.Request.Data) {
|
||||||
// Extra request verification.
|
// Extra request verification.
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
myLegalName : "CN=Notary Service,O=R3,OU=corda,L=London,C=GB"
|
myLegalName : "O=Notary Service,OU=corda,L=London,C=GB"
|
||||||
keyStorePassword : "cordacadevpass"
|
keyStorePassword : "cordacadevpass"
|
||||||
trustStorePassword : "trustpass"
|
trustStorePassword : "trustpass"
|
||||||
p2pAddress : "my-network-map:10000"
|
p2pAddress : "my-network-map:10000"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
myLegalName : "CN=Bank A,O=Bank A,L=London,C=GB"
|
myLegalName : "O=Bank A,L=London,C=GB"
|
||||||
keyStorePassword : "cordacadevpass"
|
keyStorePassword : "cordacadevpass"
|
||||||
trustStorePassword : "trustpass"
|
trustStorePassword : "trustpass"
|
||||||
dataSourceProperties : {
|
dataSourceProperties : {
|
||||||
@ -13,7 +13,7 @@ webAddress : "localhost:10004"
|
|||||||
extraAdvertisedServiceIds : [ "corda.interest_rates" ]
|
extraAdvertisedServiceIds : [ "corda.interest_rates" ]
|
||||||
networkMapService : {
|
networkMapService : {
|
||||||
address : "my-network-map:10000"
|
address : "my-network-map:10000"
|
||||||
legalName : "CN=Network Map Service,O=R3,OU=corda,L=London,C=GB"
|
legalName : "O=Network Map Service,OU=corda,L=London,C=GB"
|
||||||
}
|
}
|
||||||
useHTTPS : false
|
useHTTPS : false
|
||||||
rpcUsers : [
|
rpcUsers : [
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
myLegalName : "CN=Bank A,O=Bank A,L=London,C=GB"
|
myLegalName : "O=Bank A,L=London,C=GB"
|
||||||
p2pAddress : "my-corda-node:10002"
|
p2pAddress : "my-corda-node:10002"
|
||||||
webAddress : "localhost:10003"
|
webAddress : "localhost:10003"
|
||||||
networkMapService : {
|
networkMapService : {
|
||||||
address : "my-network-map:10000"
|
address : "my-network-map:10000"
|
||||||
legalName : "CN=Network Map Service,O=R3,OU=corda,L=London,C=GB"
|
legalName : "O=Network Map Service,OU=corda,L=London,C=GB"
|
||||||
}
|
}
|
||||||
verifierType: "OutOfProcess"
|
verifierType: "OutOfProcess"
|
||||||
|
@ -25,9 +25,9 @@ Let's take a look at the nodes we're going to deploy. Open the project's ``build
|
|||||||
|
|
||||||
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 "CN=Controller,O=R3,OU=corda,L=London,C=UK"
|
networkMap "O=Controller,OU=corda,L=London,C=UK"
|
||||||
node {
|
node {
|
||||||
name "CN=Controller,O=R3,OU=corda,L=London,C=UK"
|
name "O=Controller,OU=corda,L=London,C=UK"
|
||||||
advertisedServices = ["corda.notary.validating"]
|
advertisedServices = ["corda.notary.validating"]
|
||||||
p2pPort 10002
|
p2pPort 10002
|
||||||
rpcPort 10003
|
rpcPort 10003
|
||||||
@ -156,7 +156,7 @@ The vaults of Node A and Node B should both display the following output:
|
|||||||
participants:
|
participants:
|
||||||
- "CN=NodeA,O=NodeA,L=London,C=GB"
|
- "CN=NodeA,O=NodeA,L=London,C=GB"
|
||||||
- "CN=NodeB,O=NodeB,L=New York,C=US"
|
- "CN=NodeB,O=NodeB,L=New York,C=US"
|
||||||
notary: "CN=Controller,O=R3,OU=corda,L=London,C=GB,OU=corda.notary.validating"
|
notary: "O=Controller,OU=corda,L=London,C=GB,OU=corda.notary.validating"
|
||||||
encumbrance: null
|
encumbrance: null
|
||||||
ref:
|
ref:
|
||||||
txhash: "656A1BF64D5AEEC6F6C944E287F34EF133336F5FC2C5BFB9A0BFAE25E826125F"
|
txhash: "656A1BF64D5AEEC6F6C944E287F34EF133336F5FC2C5BFB9A0BFAE25E826125F"
|
||||||
|
@ -68,7 +68,7 @@ Yaml (yet another markup language) is a simple JSON-like way to describe object
|
|||||||
that make it helpful for our use case, like a lightweight syntax and support for "bare words" which mean you can
|
that make it helpful for our use case, like a lightweight syntax and support for "bare words" which mean you can
|
||||||
often skip the quotes around strings. Here is an example of how this syntax is used:
|
often skip the quotes around strings. Here is an example of how this syntax is used:
|
||||||
|
|
||||||
``flow start CashIssue amount: $1000, issueRef: 1234, recipient: "CN=Bank A,O=Bank A,L=London,C=GB", notary: "CN=Notary Service,O=R3,OU=corda,L=London,C=GB"``
|
``flow start CashIssue amount: $1000, issueRef: 1234, recipient: "O=Bank A,L=London,C=GB", notary: "O=Notary Service,OU=corda,L=London,C=GB"``
|
||||||
|
|
||||||
This invokes a constructor of a flow with the following prototype in the code:
|
This invokes a constructor of a flow with the following prototype in the code:
|
||||||
|
|
||||||
|
@ -279,11 +279,11 @@ and adds an RPC user for all but the "Controller" node (which serves as the nota
|
|||||||
// No permissions required as we are not invoking flows.
|
// No permissions required as we are not invoking flows.
|
||||||
val user = User("user1", "test", permissions = setOf())
|
val user = User("user1", "test", permissions = setOf())
|
||||||
driver(isDebug = true) {
|
driver(isDebug = true) {
|
||||||
startNode(X500Name("CN=Controller,O=R3,OU=corda,L=London,C=UK"), setOf(ServiceInfo(ValidatingNotaryService.type)))
|
startNode(getX500Name(O="Controller",OU="corda",L="London",C='UK"), setOf(ServiceInfo(ValidatingNotaryService.type)))
|
||||||
val (nodeA, nodeB, nodeC) = Futures.allAsList(
|
val (nodeA, nodeB, nodeC) = Futures.allAsList(
|
||||||
startNode(X500Name("CN=NodeA,O=NodeA,L=London,C=UK"), rpcUsers = listOf(user)),
|
startNode(getX500Name(O="NodeA",L="London",C="UK"), rpcUsers = listOf(user)),
|
||||||
startNode(X500Name("CN=NodeB,O=NodeB,L=New York,C=US"), rpcUsers = listOf(user)),
|
startNode(getX500Name(O="NodeB",L="New York",C="US"), rpcUsers = listOf(user)),
|
||||||
startNode(X500Name("CN=NodeC,O=NodeC,L=Paris,C=FR"), rpcUsers = listOf(user))).getOrThrow()
|
startNode(getX500Name(O="NodeC",L="Paris",C="FR"), rpcUsers = listOf(user))).getOrThrow()
|
||||||
|
|
||||||
startWebserver(nodeA)
|
startWebserver(nodeA)
|
||||||
startWebserver(nodeB)
|
startWebserver(nodeB)
|
||||||
@ -454,7 +454,7 @@ We can see a list of the states in our node's vault using ``run vaultAndUpdates`
|
|||||||
participants:
|
participants:
|
||||||
- "CN=NodeB,O=NodeB,L=New York,C=US"
|
- "CN=NodeB,O=NodeB,L=New York,C=US"
|
||||||
- "CN=NodeA,O=NodeA,L=London,C=UK"
|
- "CN=NodeA,O=NodeA,L=London,C=UK"
|
||||||
notary: "CN=Controller,O=R3,OU=corda,L=London,C=UK,OU=corda.notary.validating"
|
notary: "O=Controller,OU=corda,L=London,C=UK,OU=corda.notary.validating"
|
||||||
encumbrance: null
|
encumbrance: null
|
||||||
ref:
|
ref:
|
||||||
txhash: "52A1B18E6ABD535EF36B2075469B01D2EF888034F721C4BECD26F40355C8C9DC"
|
txhash: "52A1B18E6ABD535EF36B2075469B01D2EF888034F721C4BECD26F40355C8C9DC"
|
||||||
@ -488,14 +488,14 @@ abbreviated the output below):
|
|||||||
participants:
|
participants:
|
||||||
- "CN=NodeB,O=NodeB,L=New York,C=US"
|
- "CN=NodeB,O=NodeB,L=New York,C=US"
|
||||||
- "CN=NodeA,O=NodeA,L=London,C=UK"
|
- "CN=NodeA,O=NodeA,L=London,C=UK"
|
||||||
notary: "CN=Controller,O=R3,OU=corda,L=London,C=UK,OU=corda.notary.validating"
|
notary: "O=Controller,OU=corda,L=London,C=UK,OU=corda.notary.validating"
|
||||||
encumbrance: null
|
encumbrance: null
|
||||||
commands:
|
commands:
|
||||||
- value: {}
|
- value: {}
|
||||||
signers:
|
signers:
|
||||||
- "8Kqd4oWdx4KQAVc3u5qvHZTGJxMtrShFudAzLUTdZUzbF9aPQcCZD5KXViC"
|
- "8Kqd4oWdx4KQAVc3u5qvHZTGJxMtrShFudAzLUTdZUzbF9aPQcCZD5KXViC"
|
||||||
- "8Kqd4oWdx4KQAVcBx98LBHwXwC3a7hNptQomrg9mq2ScY7t1Qqsyk5dCNAr"
|
- "8Kqd4oWdx4KQAVcBx98LBHwXwC3a7hNptQomrg9mq2ScY7t1Qqsyk5dCNAr"
|
||||||
notary: "CN=Controller,O=R3,OU=corda,L=London,C=UK,OU=corda.notary.validating"
|
notary: "O=Controller,OU=corda,L=London,C=UK,OU=corda.notary.validating"
|
||||||
type: {}
|
type: {}
|
||||||
timeWindow: null
|
timeWindow: null
|
||||||
mustSign:
|
mustSign:
|
||||||
@ -578,11 +578,11 @@ Debugging is done via IntelliJ as follows:
|
|||||||
// No permissions required as we are not invoking flows.
|
// No permissions required as we are not invoking flows.
|
||||||
val user = User("user1", "test", permissions = setOf())
|
val user = User("user1", "test", permissions = setOf())
|
||||||
driver(isDebug = true) {
|
driver(isDebug = true) {
|
||||||
startNode(X500Name("CN=Controller,O=R3,OU=corda,L=London,C=UK"), setOf(ServiceInfo(ValidatingNotaryService.type)))
|
startNode(getX500Name(O="Controller",OU="corda",L="London",C="UK"), setOf(ServiceInfo(ValidatingNotaryService.type)))
|
||||||
val (nodeA, nodeB, nodeC) = Futures.allAsList(
|
val (nodeA, nodeB, nodeC) = Futures.allAsList(
|
||||||
startNode(X500Name("CN=NodeA,O=NodeA,L=London,C=UK"), rpcUsers = listOf(user)),
|
startNode(getX500Name(O="NodeA",L=London,C=UK"), rpcUsers = listOf(user)),
|
||||||
startNode(X500Name("CN=NodeB,O=NodeB,L=New York,C=US"), rpcUsers = listOf(user)),
|
startNode(getX500Name(O="NodeB",L=New York,C=US"), rpcUsers = listOf(user)),
|
||||||
startNode(X500Name("CN=NodeC,O=NodeC,L=Paris,C=FR"), rpcUsers = listOf(user))).getOrThrow()
|
startNode(getX500Name(O="NodeC",L=Paris,C=FR"), rpcUsers = listOf(user))).getOrThrow()
|
||||||
|
|
||||||
startWebserver(nodeA)
|
startWebserver(nodeA)
|
||||||
startWebserver(nodeB)
|
startWebserver(nodeB)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package net.corda.finance.contracts.universal
|
package net.corda.finance.contracts.universal
|
||||||
|
|
||||||
import net.corda.core.utilities.commonName
|
import net.corda.core.utilities.organisation
|
||||||
import net.corda.core.crypto.toStringShort
|
import net.corda.core.crypto.toStringShort
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
@ -48,7 +48,7 @@ private class PrettyPrint(arr : Arrangement) {
|
|||||||
|
|
||||||
fun createPartyName(party : Party) : String
|
fun createPartyName(party : Party) : String
|
||||||
{
|
{
|
||||||
val parts = party.name.commonName.toLowerCase().split(' ')
|
val parts = party.name.organisation.toLowerCase().split(' ')
|
||||||
|
|
||||||
var camelName = parts.drop(1).fold(parts.first()) {
|
var camelName = parts.drop(1).fold(parts.first()) {
|
||||||
s, i -> s + i.first().toUpperCase() + i.drop(1)
|
s, i -> s + i.first().toUpperCase() + i.drop(1)
|
||||||
@ -66,7 +66,7 @@ private class PrettyPrint(arr : Arrangement) {
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
parties.forEach {
|
parties.forEach {
|
||||||
println( "val ${createPartyName(it)} = Party(\"${it.name.commonName}\", \"${it.owningKey.toStringShort()}\")" )
|
println("val ${createPartyName(it)} = Party(\"${it.name.organisation}\", \"${it.owningKey.toStringShort()}\")")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
@file:JvmName("CashUtilities") // So the static extension functions get put into a class with a better name than CashKt
|
@file:JvmName("CashUtilities")
|
||||||
|
|
||||||
|
// So the static extension functions get put into a class with a better name than CashKt
|
||||||
package net.corda.finance.contracts.asset
|
package net.corda.finance.contracts.asset
|
||||||
|
|
||||||
import co.paralleluniverse.fibers.Suspendable
|
import co.paralleluniverse.fibers.Suspendable
|
||||||
import net.corda.finance.contracts.asset.cash.selection.CashSelectionH2Impl
|
|
||||||
import net.corda.core.contracts.*
|
import net.corda.core.contracts.*
|
||||||
import net.corda.core.contracts.Amount.Companion.sumOrThrow
|
import net.corda.core.contracts.Amount.Companion.sumOrThrow
|
||||||
import net.corda.core.crypto.entropyToKeyPair
|
|
||||||
import net.corda.core.crypto.NullKeys.NULL_PARTY
|
import net.corda.core.crypto.NullKeys.NULL_PARTY
|
||||||
import net.corda.core.utilities.toBase58String
|
import net.corda.core.crypto.entropyToKeyPair
|
||||||
import net.corda.core.identity.AbstractParty
|
import net.corda.core.identity.AbstractParty
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.internal.Emoji
|
import net.corda.core.internal.Emoji
|
||||||
@ -18,11 +18,13 @@ 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.finance.contracts.asset.cash.selection.CashSelectionH2Impl
|
||||||
import net.corda.finance.schemas.CashSchemaV1
|
import net.corda.finance.schemas.CashSchemaV1
|
||||||
import net.corda.finance.utils.sumCash
|
import net.corda.finance.utils.sumCash
|
||||||
import net.corda.finance.utils.sumCashOrNull
|
import net.corda.finance.utils.sumCashOrNull
|
||||||
import net.corda.finance.utils.sumCashOrZero
|
import net.corda.finance.utils.sumCashOrZero
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import java.math.BigInteger
|
import java.math.BigInteger
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
import java.sql.DatabaseMetaData
|
import java.sql.DatabaseMetaData
|
||||||
@ -56,7 +58,7 @@ interface CashSelection {
|
|||||||
instance.set(cashSelectionAlgo)
|
instance.set(cashSelectionAlgo)
|
||||||
cashSelectionAlgo
|
cashSelectionAlgo
|
||||||
} ?: throw ClassNotFoundException("\nUnable to load compatible cash selection algorithm implementation for JDBC driver ($_metadata)." +
|
} ?: throw ClassNotFoundException("\nUnable to load compatible cash selection algorithm implementation for JDBC driver ($_metadata)." +
|
||||||
"\nPlease specify an implementation in META-INF/services/net.corda.finance.contracts.asset.CashSelection")
|
"\nPlease specify an implementation in META-INF/services/net.corda.finance.contracts.asset.CashSelection")
|
||||||
}.invoke()
|
}.invoke()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -345,7 +347,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(X500Name("CN=Snake Oil Issuer,O=R3,OU=corda,L=London,C=GB"), DUMMY_CASH_ISSUER_KEY.public).ref(1) }
|
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) }
|
||||||
/** 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] */
|
||||||
|
@ -1,9 +1,5 @@
|
|||||||
package net.corda.finance.contracts.asset
|
package net.corda.finance.contracts.asset
|
||||||
|
|
||||||
import net.corda.finance.contracts.NetCommand
|
|
||||||
import net.corda.finance.contracts.NetType
|
|
||||||
import net.corda.finance.contracts.NettableState
|
|
||||||
import net.corda.finance.contracts.asset.Obligation.Lifecycle.NORMAL
|
|
||||||
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
|
||||||
@ -16,7 +12,12 @@ 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.contracts.NetCommand
|
||||||
|
import net.corda.finance.contracts.NetType
|
||||||
|
import net.corda.finance.contracts.NettableState
|
||||||
|
import net.corda.finance.contracts.asset.Obligation.Lifecycle.NORMAL
|
||||||
import net.corda.finance.utils.sumFungibleOrNull
|
import net.corda.finance.utils.sumFungibleOrNull
|
||||||
import net.corda.finance.utils.sumObligations
|
import net.corda.finance.utils.sumObligations
|
||||||
import net.corda.finance.utils.sumObligationsOrNull
|
import net.corda.finance.utils.sumObligationsOrNull
|
||||||
@ -793,4 +794,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(X500Name("CN=Snake Oil Issuer,O=R3,OU=corda,L=London,C=GB"), DUMMY_OBLIGATION_ISSUER_KEY.public) }
|
val DUMMY_OBLIGATION_ISSUER by lazy { Party(getX500Name(O = "Snake Oil Issuer", OU = "corda", L = "London", C = "GB"), DUMMY_OBLIGATION_ISSUER_KEY.public) }
|
||||||
|
@ -90,7 +90,7 @@ class Node extends CordformNode {
|
|||||||
def dirName
|
def dirName
|
||||||
try {
|
try {
|
||||||
X500Name x500Name = new X500Name(name)
|
X500Name x500Name = new X500Name(name)
|
||||||
dirName = x500Name.getRDNs(BCStyle.CN).getAt(0).getFirst().getValue().toString()
|
dirName = x500Name.getRDNs(BCStyle.O).getAt(0).getFirst().getValue().toString()
|
||||||
} catch(IllegalArgumentException ignore) {
|
} catch(IllegalArgumentException ignore) {
|
||||||
// Can't parse as an X500 name, use the full string
|
// Can't parse as an X500 name, use the full string
|
||||||
dirName = name
|
dirName = name
|
||||||
|
@ -3,7 +3,6 @@ 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.internal.noneOrSingle
|
import net.corda.core.internal.noneOrSingle
|
||||||
import net.corda.core.utilities.validateX500Name
|
|
||||||
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.bouncycastle.asn1.x500.X500Name
|
||||||
|
@ -6,7 +6,7 @@ import com.typesafe.config.ConfigRenderOptions.defaults
|
|||||||
import com.typesafe.config.ConfigValueFactory
|
import com.typesafe.config.ConfigValueFactory
|
||||||
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.testing.getTestX509Name
|
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.bouncycastle.asn1.x500.X500Name
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
@ -112,7 +112,7 @@ class ConfigParsingTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun x500Name() {
|
fun x500Name() {
|
||||||
testPropertyType<X500NameData, X500NameListData, X500Name>(getTestX509Name("Mock Party"), getTestX509Name("Mock Party 2"), valuesToString = true)
|
testPropertyType<X500NameData, X500NameListData, X500Name>(getX500Name(O = "Mock Party", L = "London", C = "GB"), getX500Name(O = "Mock Party 2", L = "London", C = "GB"), valuesToString = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -6,15 +6,15 @@ import net.corda.core.flows.StartableByRPC
|
|||||||
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
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
class AdvertisedServiceTests {
|
class AdvertisedServiceTests {
|
||||||
private val serviceName = X500Name("CN=Custom Service,O=R3,OU=corda,L=London,C=GB")
|
private val serviceName = getX500Name(O = "Custom Service", OU = "corda", L = "London", C = "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"
|
||||||
|
@ -15,6 +15,7 @@ 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
|
||||||
@ -25,7 +26,6 @@ import net.corda.node.utilities.ServiceIdentityGenerator
|
|||||||
import net.corda.testing.contracts.DummyContract
|
import net.corda.testing.contracts.DummyContract
|
||||||
import net.corda.testing.dummyCommand
|
import net.corda.testing.dummyCommand
|
||||||
import net.corda.testing.node.MockNetwork
|
import net.corda.testing.node.MockNetwork
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
@ -34,7 +34,7 @@ import kotlin.test.assertTrue
|
|||||||
|
|
||||||
class BFTNotaryServiceTests {
|
class BFTNotaryServiceTests {
|
||||||
companion object {
|
companion object {
|
||||||
private val clusterName = X500Name("CN=BFT,O=R3,OU=corda,L=Zurich,C=CH")
|
private val clusterName = getX500Name(O = "BFT", OU = "corda", L = "Zurich", C = "CH")
|
||||||
private val serviceType = BFTNonValidatingNotaryService.type
|
private val serviceType = BFTNonValidatingNotaryService.type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,19 +10,19 @@ 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.DummyContract
|
import net.corda.testing.contracts.DummyContract
|
||||||
import net.corda.testing.dummyCommand
|
import net.corda.testing.dummyCommand
|
||||||
import net.corda.testing.node.NodeBasedTest
|
import net.corda.testing.node.NodeBasedTest
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertFailsWith
|
import kotlin.test.assertFailsWith
|
||||||
|
|
||||||
class RaftNotaryServiceTests : NodeBasedTest() {
|
class RaftNotaryServiceTests : NodeBasedTest() {
|
||||||
private val notaryName = X500Name("CN=RAFT Notary Service,O=R3,OU=corda,L=London,C=GB")
|
private val notaryName = getX500Name(O = "RAFT Notary Service", OU = "corda", L = "London", C = "GB")
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `detect double spend`() {
|
fun `detect double spend`() {
|
||||||
|
@ -12,6 +12,7 @@ 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.*
|
||||||
@ -30,8 +31,8 @@ import java.util.concurrent.atomic.AtomicInteger
|
|||||||
|
|
||||||
class P2PMessagingTest : NodeBasedTest() {
|
class P2PMessagingTest : NodeBasedTest() {
|
||||||
private companion object {
|
private companion object {
|
||||||
val DISTRIBUTED_SERVICE_NAME = getTestX509Name("DistributedService")
|
val DISTRIBUTED_SERVICE_NAME = getX500Name(O = "DistributedService", L = "London", C = "GB")
|
||||||
val SERVICE_2_NAME = getTestX509Name("Service 2")
|
val SERVICE_2_NAME = getX500Name(O = "Service 2", L = "London", C = "GB")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -2,12 +2,9 @@ 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.utilities.cert
|
|
||||||
import net.corda.core.crypto.random63BitValue
|
import net.corda.core.crypto.random63BitValue
|
||||||
import net.corda.core.node.NodeInfo
|
import net.corda.core.node.NodeInfo
|
||||||
import net.corda.core.utilities.seconds
|
import net.corda.core.utilities.*
|
||||||
import net.corda.core.utilities.NonEmptySet
|
|
||||||
import net.corda.core.utilities.getOrThrow
|
|
||||||
import net.corda.node.internal.NetworkMapInfo
|
import net.corda.node.internal.NetworkMapInfo
|
||||||
import net.corda.node.services.config.configureWithDevSSLCertificate
|
import net.corda.node.services.config.configureWithDevSSLCertificate
|
||||||
import net.corda.node.services.messaging.sendRequest
|
import net.corda.node.services.messaging.sendRequest
|
||||||
@ -30,7 +27,7 @@ class P2PSecurityTest : NodeBasedTest() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `incorrect legal name for the network map service config`() {
|
fun `incorrect legal name for the network map service config`() {
|
||||||
val incorrectNetworkMapName = getTestX509Name("NetworkMap-${random63BitValue()}")
|
val incorrectNetworkMapName = getX500Name(O = "NetworkMap-${random63BitValue()}", L = "London", C = "GB")
|
||||||
val node = startNode(BOB.name, configOverrides = mapOf(
|
val node = startNode(BOB.name, configOverrides = mapOf(
|
||||||
"networkMapService" to mapOf(
|
"networkMapService" to mapOf(
|
||||||
"address" to networkMapNode.configuration.p2pAddress.toString(),
|
"address" to networkMapNode.configuration.p2pAddress.toString(),
|
||||||
|
@ -147,6 +147,10 @@ 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 {
|
||||||
|
loadKeyStore(configuration.nodeKeystore, configuration.keyStorePassword).getX509Certificate(X509Utilities.CORDA_CLIENT_CA).subject.withCommonName(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 */
|
||||||
open val pluginRegistries: List<CordaPluginRegistry> by lazy {
|
open val pluginRegistries: List<CordaPluginRegistry> by lazy {
|
||||||
ServiceLoader.load(CordaPluginRegistry::class.java).toList()
|
ServiceLoader.load(CordaPluginRegistry::class.java).toList()
|
||||||
@ -414,7 +418,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
|
|||||||
checkpointStorage = DBCheckpointStorage()
|
checkpointStorage = DBCheckpointStorage()
|
||||||
_services = ServiceHubInternalImpl()
|
_services = ServiceHubInternalImpl()
|
||||||
attachments = NodeAttachmentService(services.monitoringService.metrics)
|
attachments = NodeAttachmentService(services.monitoringService.metrics)
|
||||||
val legalIdentity = obtainIdentity("identity", configuration.myLegalName)
|
val legalIdentity = obtainIdentity()
|
||||||
network = makeMessagingService(legalIdentity)
|
network = makeMessagingService(legalIdentity)
|
||||||
info = makeInfo(legalIdentity)
|
info = makeInfo(legalIdentity)
|
||||||
|
|
||||||
@ -497,9 +501,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
|
|||||||
*/
|
*/
|
||||||
protected open fun makeServiceEntries(): List<ServiceEntry> {
|
protected open fun makeServiceEntries(): List<ServiceEntry> {
|
||||||
return advertisedServices.map {
|
return advertisedServices.map {
|
||||||
val serviceId = it.type.id
|
val identity = obtainIdentity(it)
|
||||||
val serviceName = it.name ?: X500Name("${configuration.myLegalName},OU=$serviceId")
|
|
||||||
val identity = obtainIdentity(serviceId, serviceName)
|
|
||||||
ServiceEntry(it, identity)
|
ServiceEntry(it, identity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -525,12 +527,6 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
|
|||||||
"or if you don't have one yet, fill out the config file and run corda.jar --initial-registration. " +
|
"or if you don't have one yet, fill out the config file and run corda.jar --initial-registration. " +
|
||||||
"Read more at: https://docs.corda.net/permissioning.html"
|
"Read more at: https://docs.corda.net/permissioning.html"
|
||||||
}
|
}
|
||||||
val identitiesKeystore = loadKeyStore(configuration.sslKeystore, configuration.keyStorePassword)
|
|
||||||
val tlsIdentity = identitiesKeystore.getX509Certificate(X509Utilities.CORDA_CLIENT_TLS).subject
|
|
||||||
|
|
||||||
require(tlsIdentity == configuration.myLegalName) {
|
|
||||||
"Expected '${configuration.myLegalName}' but got '$tlsIdentity' from the keystore."
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Specific class so that MockNode can catch it.
|
// Specific class so that MockNode can catch it.
|
||||||
@ -692,15 +688,23 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
|
|||||||
|
|
||||||
protected abstract fun startMessagingService(rpcOps: RPCOps)
|
protected abstract fun startMessagingService(rpcOps: RPCOps)
|
||||||
|
|
||||||
private fun obtainIdentity(id: String, name: X500Name): PartyAndCertificate {
|
private fun obtainIdentity(serviceInfo: ServiceInfo? = null): PartyAndCertificate {
|
||||||
// Load the private identity key, creating it if necessary. The identity key is a long term well known key that
|
// Load the private identity key, creating it if necessary. The identity key is a long term well known key that
|
||||||
// is distributed to other peers and we use it (or a key signed by it) when we need to do something
|
// is distributed to other peers and we use it (or a key signed by it) when we need to do something
|
||||||
// "permissioned". The identity file is what gets distributed and contains the node's legal name along with
|
// "permissioned". The identity file is what gets distributed and contains the node's legal name along with
|
||||||
// the public key. Obviously in a real system this would need to be a certificate chain of some kind to ensure
|
// the public key. Obviously in a real system this would need to be a certificate chain of some kind to ensure
|
||||||
// the legal name is actually validated in some way.
|
// the legal name is actually validated in some way.
|
||||||
|
val keyStore = KeyStoreWrapper(configuration.nodeKeystore, configuration.keyStorePassword)
|
||||||
|
|
||||||
|
val (id, name) = if (serviceInfo == null) {
|
||||||
|
// Create node identity if service info = null
|
||||||
|
Pair("identity", myLegalName.withCommonName(null))
|
||||||
|
} else {
|
||||||
|
val name = serviceInfo.name ?: myLegalName.withCommonName(serviceInfo.type.id)
|
||||||
|
Pair(serviceInfo.type.id, name)
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Integrate with Key management service?
|
// TODO: Integrate with Key management service?
|
||||||
val keyStore = KeyStoreWrapper(configuration.nodeKeystore, configuration.keyStorePassword)
|
|
||||||
val privateKeyAlias = "$id-private-key"
|
val privateKeyAlias = "$id-private-key"
|
||||||
val compositeKeyAlias = "$id-composite-key"
|
val compositeKeyAlias = "$id-composite-key"
|
||||||
|
|
||||||
@ -715,7 +719,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
|
|||||||
migrateKeysFromFile(keyStore, name, pubIdentityFile, privKeyFile, compositeKeyFile, privateKeyAlias, compositeKeyAlias)
|
migrateKeysFromFile(keyStore, name, pubIdentityFile, privKeyFile, compositeKeyFile, privateKeyAlias, compositeKeyAlias)
|
||||||
} else {
|
} else {
|
||||||
log.info("$privateKeyAlias not found in key store ${configuration.nodeKeystore}, generating fresh key!")
|
log.info("$privateKeyAlias not found in key store ${configuration.nodeKeystore}, generating fresh key!")
|
||||||
keyStore.saveNewKeyPair(name, privateKeyAlias, generateKeyPair())
|
keyStore.signAndSaveNewKeyPair(name, privateKeyAlias, generateKeyPair())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -751,7 +755,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
|
|||||||
// Load the private key.
|
// Load the private key.
|
||||||
val publicKey = Crypto.decodePublicKey(pubKeyFile.readAll())
|
val publicKey = Crypto.decodePublicKey(pubKeyFile.readAll())
|
||||||
val privateKey = Crypto.decodePrivateKey(privKeyFile.readAll())
|
val privateKey = Crypto.decodePrivateKey(privKeyFile.readAll())
|
||||||
keyStore.saveNewKeyPair(serviceName, privateKeyAlias, KeyPair(publicKey, privateKey))
|
keyStore.signAndSaveNewKeyPair(serviceName, privateKeyAlias, KeyPair(publicKey, privateKey))
|
||||||
// Store composite key separately.
|
// Store composite key separately.
|
||||||
if (compositeKeyFile.exists()) {
|
if (compositeKeyFile.exists()) {
|
||||||
keyStore.savePublicKey(serviceName, compositeKeyAlias, Crypto.decodePublicKey(compositeKeyFile.readAll()))
|
keyStore.savePublicKey(serviceName, compositeKeyAlias, Crypto.decodePublicKey(compositeKeyFile.readAll()))
|
||||||
|
@ -3,14 +3,11 @@ package net.corda.node.internal
|
|||||||
import com.jcabi.manifests.Manifests
|
import com.jcabi.manifests.Manifests
|
||||||
import com.typesafe.config.ConfigException
|
import com.typesafe.config.ConfigException
|
||||||
import joptsimple.OptionException
|
import joptsimple.OptionException
|
||||||
import net.corda.core.utilities.commonName
|
|
||||||
import net.corda.core.utilities.orgName
|
|
||||||
import net.corda.core.internal.concurrent.thenMatch
|
|
||||||
import net.corda.core.internal.createDirectories
|
|
||||||
import net.corda.core.internal.div
|
|
||||||
import net.corda.core.internal.*
|
import net.corda.core.internal.*
|
||||||
|
import net.corda.core.internal.concurrent.thenMatch
|
||||||
import net.corda.core.node.services.ServiceInfo
|
import net.corda.core.node.services.ServiceInfo
|
||||||
import net.corda.core.utilities.loggerFor
|
import net.corda.core.utilities.loggerFor
|
||||||
|
import net.corda.core.utilities.organisation
|
||||||
import net.corda.node.*
|
import net.corda.node.*
|
||||||
import net.corda.node.services.config.FullNodeConfiguration
|
import net.corda.node.services.config.FullNodeConfiguration
|
||||||
import net.corda.node.services.transactions.bftSMaRtSerialFilter
|
import net.corda.node.services.transactions.bftSMaRtSerialFilter
|
||||||
@ -102,8 +99,7 @@ open class NodeStartup(val args: Array<String>) {
|
|||||||
|
|
||||||
node.nodeReadyFuture.thenMatch({
|
node.nodeReadyFuture.thenMatch({
|
||||||
val elapsed = (System.currentTimeMillis() - startTime) / 10 / 100.0
|
val elapsed = (System.currentTimeMillis() - startTime) / 10 / 100.0
|
||||||
// TODO: Replace this with a standard function to get an unambiguous rendering of the X.500 name.
|
val name = node.info.legalIdentity.name.organisation
|
||||||
val name = node.info.legalIdentity.name.orgName ?: node.info.legalIdentity.name.commonName
|
|
||||||
Node.printBasicNodeInfo("Node for \"$name\" started up and registered in $elapsed sec")
|
Node.printBasicNodeInfo("Node for \"$name\" started up and registered in $elapsed sec")
|
||||||
|
|
||||||
// Don't start the shell if there's no console attached.
|
// Don't start the shell if there's no console attached.
|
||||||
|
@ -11,6 +11,8 @@ 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.x500.X500Name
|
||||||
@ -86,11 +88,18 @@ fun createKeystoreForCordaNode(sslKeyStorePath: Path,
|
|||||||
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 nameConstraints = NameConstraints(arrayOf(GeneralSubtree(GeneralName(GeneralName.directoryName, legalName))), arrayOf())
|
val clientName = legalName.toWellFormattedName().withCommonName(null)
|
||||||
val clientCACert = X509Utilities.createCertificate(CertificateType.INTERMEDIATE_CA, intermediateCACert, intermediateCAKeyPair, legalName, clientKey.public, nameConstraints = nameConstraints)
|
|
||||||
|
val nameConstraints = NameConstraints(arrayOf(GeneralSubtree(GeneralName(GeneralName.directoryName, clientName))), arrayOf())
|
||||||
|
val clientCACert = X509Utilities.createCertificate(CertificateType.INTERMEDIATE_CA,
|
||||||
|
intermediateCACert,
|
||||||
|
intermediateCAKeyPair,
|
||||||
|
clientName.withCommonName(X509Utilities.CORDA_CLIENT_CA_CN),
|
||||||
|
clientKey.public,
|
||||||
|
nameConstraints = nameConstraints)
|
||||||
|
|
||||||
val tlsKey = Crypto.generateKeyPair(signatureScheme)
|
val tlsKey = Crypto.generateKeyPair(signatureScheme)
|
||||||
val clientTLSCert = X509Utilities.createCertificate(CertificateType.TLS, clientCACert, clientKey, legalName, tlsKey.public)
|
val clientTLSCert = X509Utilities.createCertificate(CertificateType.TLS, clientCACert, clientKey, clientName, tlsKey.public)
|
||||||
|
|
||||||
val keyPass = keyPassword.toCharArray()
|
val keyPass = keyPassword.toCharArray()
|
||||||
|
|
||||||
|
@ -19,6 +19,8 @@ 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.
|
||||||
|
// TODO: Remove this so we don't accidentally use this identity in the code?
|
||||||
val myLegalName: X500Name
|
val myLegalName: X500Name
|
||||||
val networkMapService: NetworkMapInfo?
|
val networkMapService: NetworkMapInfo?
|
||||||
val minimumPlatformVersion: Int
|
val minimumPlatformVersion: Int
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package net.corda.node.services.identity
|
package net.corda.node.services.identity
|
||||||
|
|
||||||
import net.corda.core.contracts.PartyAndReference
|
import net.corda.core.contracts.PartyAndReference
|
||||||
import net.corda.core.utilities.cert
|
|
||||||
import net.corda.core.crypto.toStringShort
|
import net.corda.core.crypto.toStringShort
|
||||||
import net.corda.core.identity.AbstractParty
|
import net.corda.core.identity.AbstractParty
|
||||||
import net.corda.core.identity.AnonymousParty
|
import net.corda.core.identity.AnonymousParty
|
||||||
@ -11,7 +10,9 @@ 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
|
||||||
import net.corda.core.serialization.SingletonSerializeAsToken
|
import net.corda.core.serialization.SingletonSerializeAsToken
|
||||||
|
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.trace
|
import net.corda.core.utilities.trace
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
import org.bouncycastle.asn1.x500.X500Name
|
||||||
import org.bouncycastle.cert.X509CertificateHolder
|
import org.bouncycastle.cert.X509CertificateHolder
|
||||||
@ -65,8 +66,17 @@ class InMemoryIdentityService(identities: Iterable<PartyAndCertificate> = emptyS
|
|||||||
@Throws(CertificateExpiredException::class, CertificateNotYetValidException::class, InvalidAlgorithmParameterException::class)
|
@Throws(CertificateExpiredException::class, CertificateNotYetValidException::class, InvalidAlgorithmParameterException::class)
|
||||||
override fun verifyAndRegisterIdentity(identity: PartyAndCertificate): PartyAndCertificate? {
|
override fun verifyAndRegisterIdentity(identity: PartyAndCertificate): PartyAndCertificate? {
|
||||||
// Validate the chain first, before we do anything clever with it
|
// Validate the chain first, before we do anything clever with it
|
||||||
identity.verify(trustAnchor)
|
try {
|
||||||
|
identity.verify(trustAnchor)
|
||||||
|
} catch (e: CertPathValidatorException) {
|
||||||
|
log.error("Certificate validation failed for ${identity.name} against trusted root ${trustAnchor.trustedCert.subject}.")
|
||||||
|
log.error("Certificate path :")
|
||||||
|
identity.certPath.certificates.reversed().forEachIndexed { index, certificate ->
|
||||||
|
val space = (0 until index).map { " " }.joinToString("")
|
||||||
|
log.error("$space${certificate.toX509CertHolder().subject}")
|
||||||
|
}
|
||||||
|
throw e
|
||||||
|
}
|
||||||
log.trace { "Registering identity $identity" }
|
log.trace { "Registering identity $identity" }
|
||||||
keyToParties[identity.owningKey] = identity
|
keyToParties[identity.owningKey] = identity
|
||||||
// Always keep the first party we registered, as that's the well known identity
|
// Always keep the first party we registered, as that's the well known identity
|
||||||
|
@ -244,7 +244,8 @@ class NodeMessagingClient(override val config: NodeConfiguration,
|
|||||||
}
|
}
|
||||||
}, {})
|
}, {})
|
||||||
|
|
||||||
rpcServer = RPCServer(rpcOps, NODE_USER, NODE_USER, locator, userService, config.myLegalName)
|
val myLegalName = loadKeyStore(config.sslKeystore, config.keyStorePassword).getX509Certificate(X509Utilities.CORDA_CLIENT_TLS).subject
|
||||||
|
rpcServer = RPCServer(rpcOps, NODE_USER, NODE_USER, locator, userService, 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) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package net.corda.node.shell
|
package net.corda.node.shell
|
||||||
|
|
||||||
import net.corda.core.utilities.commonName
|
import net.corda.core.utilities.organisation
|
||||||
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.internal.concurrent.openFuture
|
import net.corda.core.internal.concurrent.openFuture
|
||||||
@ -110,7 +110,7 @@ class FlowWatchPrintingSubscriber(private val toStream: RenderPrintWriter) : Sub
|
|||||||
return when (flowInitiator) {
|
return when (flowInitiator) {
|
||||||
is FlowInitiator.Scheduled -> flowInitiator.scheduledState.ref.toString()
|
is FlowInitiator.Scheduled -> flowInitiator.scheduledState.ref.toString()
|
||||||
is FlowInitiator.Shell -> "Shell" // TODO Change when we will have more information on shell user.
|
is FlowInitiator.Shell -> "Shell" // TODO Change when we will have more information on shell user.
|
||||||
is FlowInitiator.Peer -> flowInitiator.party.name.commonName
|
is FlowInitiator.Peer -> flowInitiator.party.name.organisation
|
||||||
is FlowInitiator.RPC -> "RPC: " + flowInitiator.username
|
is FlowInitiator.RPC -> "RPC: " + flowInitiator.username
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -183,10 +183,11 @@ class KeyStoreWrapper(private val storePath: Path, private val storePassword: St
|
|||||||
val cert = X509Utilities.createCertificate(CertificateType.IDENTITY, clientCA.certificate, clientCA.keyPair, serviceName, pubKey)
|
val cert = X509Utilities.createCertificate(CertificateType.IDENTITY, clientCA.certificate, clientCA.keyPair, serviceName, 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()
|
||||||
return certPath
|
return certPath
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveNewKeyPair(serviceName: X500Name, privateKeyAlias: String, keyPair: KeyPair) {
|
fun signAndSaveNewKeyPair(serviceName: X500Name, 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())
|
||||||
|
@ -1,13 +1,17 @@
|
|||||||
package net.corda.node.utilities
|
package net.corda.node.utilities
|
||||||
|
|
||||||
import net.corda.core.crypto.*
|
import net.corda.core.crypto.Crypto
|
||||||
|
import net.corda.core.crypto.SignatureScheme
|
||||||
|
import net.corda.core.crypto.random63BitValue
|
||||||
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
|
||||||
import org.bouncycastle.asn1.ASN1EncodableVector
|
import org.bouncycastle.asn1.ASN1EncodableVector
|
||||||
import org.bouncycastle.asn1.ASN1Sequence
|
import org.bouncycastle.asn1.ASN1Sequence
|
||||||
import org.bouncycastle.asn1.DERSequence
|
import org.bouncycastle.asn1.DERSequence
|
||||||
|
import org.bouncycastle.asn1.DERUTF8String
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
import org.bouncycastle.asn1.x500.X500Name
|
||||||
|
import org.bouncycastle.asn1.x500.style.BCStyle
|
||||||
import org.bouncycastle.asn1.x509.*
|
import org.bouncycastle.asn1.x509.*
|
||||||
import org.bouncycastle.asn1.x509.Extension
|
import org.bouncycastle.asn1.x509.Extension
|
||||||
import org.bouncycastle.cert.X509CertificateHolder
|
import org.bouncycastle.cert.X509CertificateHolder
|
||||||
@ -44,6 +48,8 @@ object X509Utilities {
|
|||||||
val CORDA_CLIENT_TLS = "cordaclienttls"
|
val CORDA_CLIENT_TLS = "cordaclienttls"
|
||||||
val CORDA_CLIENT_CA = "cordaclientca"
|
val CORDA_CLIENT_CA = "cordaclientca"
|
||||||
|
|
||||||
|
val CORDA_CLIENT_CA_CN = "Corda Client CA Certificate"
|
||||||
|
|
||||||
private val DEFAULT_VALIDITY_WINDOW = Pair(0.millis, 3650.days)
|
private val DEFAULT_VALIDITY_WINDOW = Pair(0.millis, 3650.days)
|
||||||
/**
|
/**
|
||||||
* Helper function to return the latest out of an instant and an optional date.
|
* Helper function to return the latest out of an instant and an optional date.
|
||||||
@ -107,6 +113,7 @@ object X509Utilities {
|
|||||||
return createCertificate(certificateType, issuerCertificate.subject, issuerKeyPair, subject, subjectPublicKey, window, nameConstraints)
|
return createCertificate(certificateType, issuerCertificate.subject, issuerKeyPair, subject, subjectPublicKey, window, nameConstraints)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Throws(CertPathValidatorException::class)
|
||||||
fun validateCertificateChain(trustedRoot: X509CertificateHolder, vararg certificates: Certificate) {
|
fun validateCertificateChain(trustedRoot: X509CertificateHolder, vararg certificates: Certificate) {
|
||||||
require(certificates.isNotEmpty()) { "Certificate path must contain at least one certificate" }
|
require(certificates.isNotEmpty()) { "Certificate path must contain at least one certificate" }
|
||||||
val certFactory = CertificateFactory.getInstance("X509")
|
val certFactory = CertificateFactory.getInstance("X509")
|
||||||
@ -225,12 +232,12 @@ object X509Utilities {
|
|||||||
/**
|
/**
|
||||||
* Create certificate signing request using provided information.
|
* Create certificate signing request using provided information.
|
||||||
*/
|
*/
|
||||||
fun createCertificateSigningRequest(subject: X500Name, keyPair: KeyPair, signatureScheme: SignatureScheme): PKCS10CertificationRequest {
|
fun createCertificateSigningRequest(subject: X500Name, email: String, keyPair: KeyPair, signatureScheme: SignatureScheme): PKCS10CertificationRequest {
|
||||||
val signer = ContentSignerBuilder.build(signatureScheme, keyPair.private, Crypto.findProvider(signatureScheme.providerName))
|
val signer = ContentSignerBuilder.build(signatureScheme, keyPair.private, Crypto.findProvider(signatureScheme.providerName))
|
||||||
return JcaPKCS10CertificationRequestBuilder(subject, keyPair.public).build(signer)
|
return JcaPKCS10CertificationRequestBuilder(subject, keyPair.public).addAttribute(BCStyle.E, DERUTF8String(email)).build(signer)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createCertificateSigningRequest(subject: X500Name, keyPair: KeyPair) = createCertificateSigningRequest(subject, keyPair, DEFAULT_TLS_SIGNATURE_SCHEME)
|
fun createCertificateSigningRequest(subject: X500Name, email: String, keyPair: KeyPair) = createCertificateSigningRequest(subject, email, keyPair, DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ import kotlin.system.exitProcess
|
|||||||
* Helper for managing the node registration process, which checks for any existing certificates and requests them if
|
* Helper for managing the node registration process, which checks for any existing certificates and requests them if
|
||||||
* needed.
|
* needed.
|
||||||
*/
|
*/
|
||||||
class NetworkRegistrationHelper(val config: NodeConfiguration, val certService: NetworkRegistrationService) {
|
class NetworkRegistrationHelper(private val config: NodeConfiguration, private val certService: NetworkRegistrationService) {
|
||||||
companion object {
|
companion object {
|
||||||
val pollInterval = 10.seconds
|
val pollInterval = 10.seconds
|
||||||
val SELF_SIGNED_PRIVATE_KEY = "Self Signed Private Key"
|
val SELF_SIGNED_PRIVATE_KEY = "Self Signed Private Key"
|
||||||
@ -100,7 +100,6 @@ class NetworkRegistrationHelper(val config: NodeConfiguration, val certService:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Poll Certificate Signing Server for approved certificate,
|
* Poll Certificate Signing Server for approved certificate,
|
||||||
* enter a slow polling loop if server return null.
|
* enter a slow polling loop if server return null.
|
||||||
@ -127,7 +126,7 @@ class NetworkRegistrationHelper(val config: NodeConfiguration, val certService:
|
|||||||
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, keyPair)
|
val request = X509Utilities.createCertificateSigningRequest(config.myLegalName, 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))
|
||||||
|
@ -9,11 +9,11 @@ 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.nodeapi.User
|
import net.corda.nodeapi.User
|
||||||
import net.corda.smoketesting.NodeConfig
|
import net.corda.smoketesting.NodeConfig
|
||||||
import net.corda.smoketesting.NodeProcess
|
import net.corda.smoketesting.NodeProcess
|
||||||
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.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
import java.util.concurrent.atomic.AtomicInteger
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
@ -28,7 +28,7 @@ class CordappSmokeTest {
|
|||||||
private val factory = NodeProcess.Factory()
|
private val factory = NodeProcess.Factory()
|
||||||
|
|
||||||
private val aliceConfig = NodeConfig(
|
private val aliceConfig = NodeConfig(
|
||||||
legalName = X500Name("CN=Alice Corp,O=Alice Corp,L=Madrid,C=ES"),
|
legalName = getX500Name(O = "Alice Corp", L = "Madrid", C = "ES"),
|
||||||
p2pPort = port.andIncrement,
|
p2pPort = port.andIncrement,
|
||||||
rpcPort = port.andIncrement,
|
rpcPort = port.andIncrement,
|
||||||
webPort = port.andIncrement,
|
webPort = port.andIncrement,
|
||||||
|
@ -9,6 +9,7 @@ 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
|
||||||
@ -86,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(X500Name("CN=Evil Notary,O=Evil R3,OU=corda,L=London,C=GB"), generateKeyPair().public)
|
val newEvilNotary = getTestPartyAndCertificate(getX500Name(OU="Evil Notary",O="Evil R3",L="London",C="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)
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package net.corda.node.services.config
|
package net.corda.node.services.config
|
||||||
|
|
||||||
import net.corda.core.utilities.commonName
|
import net.corda.core.utilities.organisation
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
import net.corda.testing.ALICE
|
|
||||||
import net.corda.nodeapi.User
|
import net.corda.nodeapi.User
|
||||||
|
import net.corda.testing.ALICE
|
||||||
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.assertj.core.api.Assertions.assertThatThrownBy
|
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||||
@ -21,7 +21,7 @@ class FullNodeConfigurationTest {
|
|||||||
emailAddress = "",
|
emailAddress = "",
|
||||||
keyStorePassword = "cordacadevpass",
|
keyStorePassword = "cordacadevpass",
|
||||||
trustStorePassword = "trustpass",
|
trustStorePassword = "trustpass",
|
||||||
dataSourceProperties = makeTestDataSourceProperties(ALICE.name.commonName),
|
dataSourceProperties = makeTestDataSourceProperties(ALICE.name.organisation),
|
||||||
database = makeTestDatabaseProperties(),
|
database = makeTestDatabaseProperties(),
|
||||||
certificateSigningService = URL("http://localhost"),
|
certificateSigningService = URL("http://localhost"),
|
||||||
rpcUsers = emptyList(),
|
rpcUsers = emptyList(),
|
||||||
|
@ -12,6 +12,7 @@ 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
|
||||||
@ -24,6 +25,9 @@ import net.corda.node.utilities.configureDatabase
|
|||||||
import net.corda.testing.*
|
import net.corda.testing.*
|
||||||
import net.corda.testing.node.InMemoryMessagingNetwork
|
import net.corda.testing.node.InMemoryMessagingNetwork
|
||||||
import net.corda.testing.node.MockKeyManagementService
|
import net.corda.testing.node.MockKeyManagementService
|
||||||
|
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
|
||||||
|
import net.corda.testing.node.MockServices.Companion.makeTestDatabaseProperties
|
||||||
|
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.bouncycastle.asn1.x500.X500Name
|
||||||
@ -31,16 +35,12 @@ import org.junit.After
|
|||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
import java.security.PublicKey
|
|
||||||
import java.time.Clock
|
import java.time.Clock
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.util.concurrent.CountDownLatch
|
import java.util.concurrent.CountDownLatch
|
||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.Executors
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
import net.corda.testing.node.MockServices.Companion.makeTestDatabaseProperties
|
|
||||||
import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties
|
|
||||||
import net.corda.testing.node.MockServices.Companion.makeTestIdentityService
|
|
||||||
|
|
||||||
class NodeSchedulerServiceTest : SingletonSerializeAsToken() {
|
class NodeSchedulerServiceTest : SingletonSerializeAsToken() {
|
||||||
val realClock: Clock = Clock.systemUTC()
|
val realClock: Clock = Clock.systemUTC()
|
||||||
@ -89,7 +89,7 @@ class NodeSchedulerServiceTest : SingletonSerializeAsToken() {
|
|||||||
database)
|
database)
|
||||||
services = object : MockServiceHubInternal(
|
services = object : MockServiceHubInternal(
|
||||||
database,
|
database,
|
||||||
testNodeConfiguration(Paths.get("."), getTestX509Name("Alice")),
|
testNodeConfiguration(Paths.get("."), getX500Name(O = "Alice", L = "London", C = "GB")),
|
||||||
overrideClock = testClock,
|
overrideClock = testClock,
|
||||||
keyManagement = kms,
|
keyManagement = kms,
|
||||||
network = mockMessagingService), TestReference {
|
network = mockMessagingService), TestReference {
|
||||||
|
@ -6,6 +6,7 @@ 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
|
||||||
@ -46,7 +47,7 @@ abstract class AbstractNetworkMapServiceTest<out S : AbstractNetworkMapService>
|
|||||||
lateinit var alice: MockNode
|
lateinit var alice: MockNode
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val subscriberLegalName = X500Name("CN=Subscriber,OU=Corda QA Department,O=R3 CEV,L=New York,C=US")
|
val subscriberLegalName = getX500Name(O="Subscriber",L="New York",C="US")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
package net.corda.node.services.network
|
package net.corda.node.services.network
|
||||||
|
|
||||||
import net.corda.core.utilities.CertificateAndKeyPair
|
|
||||||
import net.corda.core.crypto.Crypto
|
import net.corda.core.crypto.Crypto
|
||||||
import net.corda.core.utilities.cert
|
|
||||||
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.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.core.utilities.CertificateAndKeyPair
|
||||||
|
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
|
||||||
@ -62,7 +63,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(X500Name("O=Alicente Worldwide,L=London,C=GB"), generateKeyPair().public)
|
val alicente = getTestPartyAndCertificate(getX500Name(O = "Alicente Worldwide", L = "London", C = "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,7 +74,7 @@ class InMemoryIdentityServiceTests {
|
|||||||
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("Node A", "Node B", "Node C")
|
||||||
.map { getTestPartyAndCertificate(X500Name("CN=$it,O=R3,OU=corda,L=London,C=GB"), generateKeyPair().public) }
|
.map { getTestPartyAndCertificate(getX500Name(O = it, OU = "corda", L = "London", C = "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)) }
|
||||||
|
@ -9,6 +9,7 @@ import net.corda.core.node.services.IdentityService
|
|||||||
import net.corda.core.node.services.UnknownAnonymousPartyException
|
import net.corda.core.node.services.UnknownAnonymousPartyException
|
||||||
import net.corda.core.utilities.CertificateAndKeyPair
|
import net.corda.core.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
|
||||||
@ -96,7 +97,7 @@ class PersistentIdentityServiceTests {
|
|||||||
identityService.verifyAndRegisterIdentity(ALICE_IDENTITY)
|
identityService.verifyAndRegisterIdentity(ALICE_IDENTITY)
|
||||||
identityService.verifyAndRegisterIdentity(BOB_IDENTITY)
|
identityService.verifyAndRegisterIdentity(BOB_IDENTITY)
|
||||||
}
|
}
|
||||||
val alicente = getTestPartyAndCertificate(X500Name("O=Alicente Worldwide,L=London,C=GB"), generateKeyPair().public)
|
val alicente = getTestPartyAndCertificate(getX500Name(O = "Alicente Worldwide", L = "London", C = "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,7 +109,7 @@ 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("Node A", "Node B", "Node C")
|
||||||
.map { getTestPartyAndCertificate(X500Name("CN=$it,O=R3,OU=corda,L=London,C=GB"), generateKeyPair().public) }
|
.map { getTestPartyAndCertificate(getX500Name(O = it, OU = "corda", L = "London", C = "GB"), generateKeyPair().public) }
|
||||||
database.transaction {
|
database.transaction {
|
||||||
assertNull(identityService.partyFromX500Name(identities.first().name))
|
assertNull(identityService.partyFromX500Name(identities.first().name))
|
||||||
}
|
}
|
||||||
|
@ -21,11 +21,8 @@ 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.OpaqueBytes
|
import net.corda.core.utilities.*
|
||||||
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
|
||||||
@ -79,7 +76,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, getTestX509Name("notary-service-2000"))
|
val notaryService = ServiceInfo(ValidatingNotaryService.type, getX500Name(O = "notary-service-2000", L = "London", C = "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.
|
||||||
|
@ -32,7 +32,6 @@ import net.corda.testing.schemas.DummyLinearStateSchemaV1
|
|||||||
import org.assertj.core.api.Assertions
|
import org.assertj.core.api.Assertions
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.assertj.core.api.Assertions.assertThatThrownBy
|
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import org.junit.*
|
import org.junit.*
|
||||||
import org.junit.rules.ExpectedException
|
import org.junit.rules.ExpectedException
|
||||||
import java.lang.Thread.sleep
|
import java.lang.Thread.sleep
|
||||||
@ -55,7 +54,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(X500Name("CN=Cash Notary Service,O=R3,OU=corda,L=Zurich,C=CH"), CASH_NOTARY_KEY.public)
|
val CASH_NOTARY: Party get() = Party(getX500Name(O = "Cash Notary Service", OU = "corda", L = "Zurich", C = "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
|
||||||
@ -278,7 +277,7 @@ class VaultQueryTests : TestDependencyInjectionBase() {
|
|||||||
val sortAttributeTxnId = SortAttribute.Standard(Sort.CommonStateAttribute.STATE_REF_TXN_ID)
|
val sortAttributeTxnId = SortAttribute.Standard(Sort.CommonStateAttribute.STATE_REF_TXN_ID)
|
||||||
val sortAttributeIndex = SortAttribute.Standard(Sort.CommonStateAttribute.STATE_REF_INDEX)
|
val sortAttributeIndex = SortAttribute.Standard(Sort.CommonStateAttribute.STATE_REF_INDEX)
|
||||||
val sortBy = Sort(setOf(Sort.SortColumn(sortAttributeTxnId, Sort.Direction.ASC),
|
val sortBy = Sort(setOf(Sort.SortColumn(sortAttributeTxnId, Sort.Direction.ASC),
|
||||||
Sort.SortColumn(sortAttributeIndex, Sort.Direction.ASC)))
|
Sort.SortColumn(sortAttributeIndex, Sort.Direction.ASC)))
|
||||||
val criteria = VaultQueryCriteria()
|
val criteria = VaultQueryCriteria()
|
||||||
val results = vaultQuerySvc.queryBy<Cash.State>(criteria, sortBy)
|
val results = vaultQuerySvc.queryBy<Cash.State>(criteria, sortBy)
|
||||||
|
|
||||||
@ -295,11 +294,11 @@ class VaultQueryTests : TestDependencyInjectionBase() {
|
|||||||
@Test
|
@Test
|
||||||
fun `unconsumed states for state refs`() {
|
fun `unconsumed states for state refs`() {
|
||||||
val stateRefs =
|
val stateRefs =
|
||||||
database.transaction {
|
database.transaction {
|
||||||
services.fillWithSomeTestLinearStates(8)
|
services.fillWithSomeTestLinearStates(8)
|
||||||
val issuedStates = services.fillWithSomeTestLinearStates(2)
|
val issuedStates = services.fillWithSomeTestLinearStates(2)
|
||||||
issuedStates.states.map { it.ref }.toList()
|
issuedStates.states.map { it.ref }.toList()
|
||||||
}
|
}
|
||||||
database.transaction {
|
database.transaction {
|
||||||
// DOCSTART VaultQueryExample2
|
// DOCSTART VaultQueryExample2
|
||||||
val sortAttribute = SortAttribute.Standard(Sort.CommonStateAttribute.STATE_REF_TXN_ID)
|
val sortAttribute = SortAttribute.Standard(Sort.CommonStateAttribute.STATE_REF_TXN_ID)
|
||||||
@ -472,15 +471,15 @@ class VaultQueryTests : TestDependencyInjectionBase() {
|
|||||||
@Test
|
@Test
|
||||||
fun `unconsumed states with soft locking`() {
|
fun `unconsumed states with soft locking`() {
|
||||||
val (lockId1, lockId2) =
|
val (lockId1, lockId2) =
|
||||||
database.transaction {
|
database.transaction {
|
||||||
val issuedStates = services.fillWithSomeTestCash(100.DOLLARS, notaryServices, CASH_NOTARY, 10, 10, Random(0L)).states.toList()
|
val issuedStates = services.fillWithSomeTestCash(100.DOLLARS, notaryServices, CASH_NOTARY, 10, 10, Random(0L)).states.toList()
|
||||||
vaultSvc.softLockReserve(UUID.randomUUID(), NonEmptySet.of(issuedStates[1].ref, issuedStates[2].ref, issuedStates[3].ref))
|
vaultSvc.softLockReserve(UUID.randomUUID(), NonEmptySet.of(issuedStates[1].ref, issuedStates[2].ref, issuedStates[3].ref))
|
||||||
val lockId1 = UUID.randomUUID()
|
val lockId1 = UUID.randomUUID()
|
||||||
vaultSvc.softLockReserve(lockId1, NonEmptySet.of(issuedStates[4].ref, issuedStates[5].ref))
|
vaultSvc.softLockReserve(lockId1, NonEmptySet.of(issuedStates[4].ref, issuedStates[5].ref))
|
||||||
val lockId2 = UUID.randomUUID()
|
val lockId2 = UUID.randomUUID()
|
||||||
vaultSvc.softLockReserve(lockId2, NonEmptySet.of(issuedStates[6].ref))
|
vaultSvc.softLockReserve(lockId2, NonEmptySet.of(issuedStates[6].ref))
|
||||||
Pair(lockId1, lockId2)
|
Pair(lockId1, lockId2)
|
||||||
}
|
}
|
||||||
database.transaction {
|
database.transaction {
|
||||||
// excluding soft locked states
|
// excluding soft locked states
|
||||||
val criteriaExclusive = VaultQueryCriteria(softLockingCondition = SoftLockingCondition(SoftLockingType.UNLOCKED_ONLY))
|
val criteriaExclusive = VaultQueryCriteria(softLockingCondition = SoftLockingCondition(SoftLockingType.UNLOCKED_ONLY))
|
||||||
@ -739,10 +738,10 @@ class VaultQueryTests : TestDependencyInjectionBase() {
|
|||||||
val avgCriteria = VaultCustomQueryCriteria(avg)
|
val avgCriteria = VaultCustomQueryCriteria(avg)
|
||||||
|
|
||||||
val results = vaultQuerySvc.queryBy<FungibleAsset<*>>(sumCriteria
|
val results = vaultQuerySvc.queryBy<FungibleAsset<*>>(sumCriteria
|
||||||
.and(countCriteria)
|
.and(countCriteria)
|
||||||
.and(maxCriteria)
|
.and(maxCriteria)
|
||||||
.and(minCriteria)
|
.and(minCriteria)
|
||||||
.and(avgCriteria))
|
.and(avgCriteria))
|
||||||
// DOCEND VaultQueryExample21
|
// DOCEND VaultQueryExample21
|
||||||
|
|
||||||
assertThat(results.otherResults).hasSize(5)
|
assertThat(results.otherResults).hasSize(5)
|
||||||
@ -778,9 +777,9 @@ class VaultQueryTests : TestDependencyInjectionBase() {
|
|||||||
val avgCriteria = VaultCustomQueryCriteria(avg)
|
val avgCriteria = VaultCustomQueryCriteria(avg)
|
||||||
|
|
||||||
val results = vaultQuerySvc.queryBy<FungibleAsset<*>>(sumCriteria
|
val results = vaultQuerySvc.queryBy<FungibleAsset<*>>(sumCriteria
|
||||||
.and(maxCriteria)
|
.and(maxCriteria)
|
||||||
.and(minCriteria)
|
.and(minCriteria)
|
||||||
.and(avgCriteria))
|
.and(avgCriteria))
|
||||||
// DOCEND VaultQueryExample22
|
// DOCEND VaultQueryExample22
|
||||||
|
|
||||||
assertThat(results.otherResults).hasSize(24)
|
assertThat(results.otherResults).hasSize(24)
|
||||||
@ -826,9 +825,10 @@ class VaultQueryTests : TestDependencyInjectionBase() {
|
|||||||
}
|
}
|
||||||
database.transaction {
|
database.transaction {
|
||||||
// DOCSTART VaultQueryExample23
|
// DOCSTART VaultQueryExample23
|
||||||
val sum = builder { CashSchemaV1.PersistentCashState::pennies.sum(groupByColumns = listOf(CashSchemaV1.PersistentCashState::issuerParty,
|
val sum = builder {
|
||||||
CashSchemaV1.PersistentCashState::currency),
|
CashSchemaV1.PersistentCashState::pennies.sum(groupByColumns = listOf(CashSchemaV1.PersistentCashState::issuerParty,
|
||||||
orderBy = Sort.Direction.DESC)
|
CashSchemaV1.PersistentCashState::currency),
|
||||||
|
orderBy = Sort.Direction.DESC)
|
||||||
}
|
}
|
||||||
|
|
||||||
val results = vaultQuerySvc.queryBy<FungibleAsset<*>>(VaultCustomQueryCriteria(sum))
|
val results = vaultQuerySvc.queryBy<FungibleAsset<*>>(VaultCustomQueryCriteria(sum))
|
||||||
@ -880,16 +880,16 @@ class VaultQueryTests : TestDependencyInjectionBase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `aggregate functions count by contract type and state status`() {
|
fun `aggregate functions count by contract type and state status`() {
|
||||||
val (linearStatesJKL,linearStatesXYZ,dealStates) =
|
val (linearStatesJKL, linearStatesXYZ, dealStates) =
|
||||||
database.transaction {
|
database.transaction {
|
||||||
// create new states
|
// create new states
|
||||||
services.fillWithSomeTestCash(100.DOLLARS, notaryServices, DUMMY_NOTARY, 10, 10, Random(0L))
|
services.fillWithSomeTestCash(100.DOLLARS, notaryServices, DUMMY_NOTARY, 10, 10, Random(0L))
|
||||||
val linearStatesXYZ = services.fillWithSomeTestLinearStates(1, "XYZ")
|
val linearStatesXYZ = services.fillWithSomeTestLinearStates(1, "XYZ")
|
||||||
val linearStatesJKL = services.fillWithSomeTestLinearStates(2, "JKL")
|
val linearStatesJKL = services.fillWithSomeTestLinearStates(2, "JKL")
|
||||||
services.fillWithSomeTestLinearStates(3, "ABC")
|
services.fillWithSomeTestLinearStates(3, "ABC")
|
||||||
val dealStates = services.fillWithSomeTestDeals(listOf("123", "456", "789"))
|
val dealStates = services.fillWithSomeTestDeals(listOf("123", "456", "789"))
|
||||||
Triple(linearStatesJKL,linearStatesXYZ,dealStates)
|
Triple(linearStatesJKL, linearStatesXYZ, dealStates)
|
||||||
}
|
}
|
||||||
val count = builder { VaultSchemaV1.VaultStates::recordedTime.count() }
|
val count = builder { VaultSchemaV1.VaultStates::recordedTime.count() }
|
||||||
database.transaction {
|
database.transaction {
|
||||||
// count fungible assets
|
// count fungible assets
|
||||||
@ -906,15 +906,15 @@ class VaultQueryTests : TestDependencyInjectionBase() {
|
|||||||
assertThat(dealStateCount).isEqualTo(3L)
|
assertThat(dealStateCount).isEqualTo(3L)
|
||||||
}
|
}
|
||||||
val cashUpdates =
|
val cashUpdates =
|
||||||
database.transaction {
|
database.transaction {
|
||||||
// consume some states
|
// consume some states
|
||||||
services.consumeLinearStates(linearStatesXYZ.states.toList(), DUMMY_NOTARY)
|
services.consumeLinearStates(linearStatesXYZ.states.toList(), DUMMY_NOTARY)
|
||||||
services.consumeLinearStates(linearStatesJKL.states.toList(), DUMMY_NOTARY)
|
services.consumeLinearStates(linearStatesJKL.states.toList(), DUMMY_NOTARY)
|
||||||
services.consumeDeals(dealStates.states.filter { it.state.data.linearId.externalId == "456" }, DUMMY_NOTARY)
|
services.consumeDeals(dealStates.states.filter { it.state.data.linearId.externalId == "456" }, DUMMY_NOTARY)
|
||||||
services.consumeCash(50.DOLLARS, notary = DUMMY_NOTARY)
|
services.consumeCash(50.DOLLARS, notary = DUMMY_NOTARY)
|
||||||
|
|
||||||
// UNCONSUMED states (default)
|
// UNCONSUMED states (default)
|
||||||
}
|
}
|
||||||
database.transaction {
|
database.transaction {
|
||||||
// count fungible assets
|
// count fungible assets
|
||||||
val countCriteriaUnconsumed = QueryCriteria.VaultCustomQueryCriteria(count, Vault.StateStatus.UNCONSUMED)
|
val countCriteriaUnconsumed = QueryCriteria.VaultCustomQueryCriteria(count, Vault.StateStatus.UNCONSUMED)
|
||||||
@ -1228,9 +1228,9 @@ class VaultQueryTests : TestDependencyInjectionBase() {
|
|||||||
@Test
|
@Test
|
||||||
fun `unconsumed linear heads for linearId without external Id`() {
|
fun `unconsumed linear heads for linearId without external Id`() {
|
||||||
val issuedStates =
|
val issuedStates =
|
||||||
database.transaction {
|
database.transaction {
|
||||||
services.fillWithSomeTestLinearStates(10)
|
services.fillWithSomeTestLinearStates(10)
|
||||||
}
|
}
|
||||||
database.transaction {
|
database.transaction {
|
||||||
// DOCSTART VaultQueryExample8
|
// DOCSTART VaultQueryExample8
|
||||||
val linearIds = issuedStates.states.map { it.state.data.linearId }.toList()
|
val linearIds = issuedStates.states.map { it.state.data.linearId }.toList()
|
||||||
@ -1244,12 +1244,12 @@ class VaultQueryTests : TestDependencyInjectionBase() {
|
|||||||
@Test
|
@Test
|
||||||
fun `unconsumed linear heads by linearId`() {
|
fun `unconsumed linear heads by linearId`() {
|
||||||
val (linearState1, linearState3) =
|
val (linearState1, linearState3) =
|
||||||
database.transaction {
|
database.transaction {
|
||||||
val linearState1 = services.fillWithSomeTestLinearStates(1, "ID1")
|
val linearState1 = services.fillWithSomeTestLinearStates(1, "ID1")
|
||||||
services.fillWithSomeTestLinearStates(1, "ID2")
|
services.fillWithSomeTestLinearStates(1, "ID2")
|
||||||
val linearState3 = services.fillWithSomeTestLinearStates(1, "ID3")
|
val linearState3 = services.fillWithSomeTestLinearStates(1, "ID3")
|
||||||
Pair(linearState1, linearState3)
|
Pair(linearState1, linearState3)
|
||||||
}
|
}
|
||||||
database.transaction {
|
database.transaction {
|
||||||
val linearIds = listOf(linearState1.states.first().state.data.linearId, linearState3.states.first().state.data.linearId)
|
val linearIds = listOf(linearState1.states.first().state.data.linearId, linearState3.states.first().state.data.linearId)
|
||||||
val criteria = LinearStateQueryCriteria(linearId = linearIds)
|
val criteria = LinearStateQueryCriteria(linearId = linearIds)
|
||||||
@ -1278,14 +1278,14 @@ class VaultQueryTests : TestDependencyInjectionBase() {
|
|||||||
@Test
|
@Test
|
||||||
fun `all linear states for a given linear id`() {
|
fun `all linear states for a given linear id`() {
|
||||||
val linearId =
|
val linearId =
|
||||||
database.transaction {
|
database.transaction {
|
||||||
val txns = services.fillWithSomeTestLinearStates(1, "TEST")
|
val txns = services.fillWithSomeTestLinearStates(1, "TEST")
|
||||||
val linearState = txns.states.first()
|
val linearState = txns.states.first()
|
||||||
services.evolveLinearState(linearState, DUMMY_NOTARY) // consume current and produce new state reference
|
services.evolveLinearState(linearState, DUMMY_NOTARY) // consume current and produce new state reference
|
||||||
services.evolveLinearState(linearState, DUMMY_NOTARY) // consume current and produce new state reference
|
services.evolveLinearState(linearState, DUMMY_NOTARY) // consume current and produce new state reference
|
||||||
services.evolveLinearState(linearState, DUMMY_NOTARY) // consume current and produce new state reference
|
services.evolveLinearState(linearState, DUMMY_NOTARY) // consume current and produce new state reference
|
||||||
linearState.state.data.linearId
|
linearState.state.data.linearId
|
||||||
}
|
}
|
||||||
database.transaction {
|
database.transaction {
|
||||||
// should now have 1 UNCONSUMED & 3 CONSUMED state refs for Linear State with "TEST"
|
// should now have 1 UNCONSUMED & 3 CONSUMED state refs for Linear State with "TEST"
|
||||||
// DOCSTART VaultQueryExample9
|
// DOCSTART VaultQueryExample9
|
||||||
@ -1300,14 +1300,14 @@ class VaultQueryTests : TestDependencyInjectionBase() {
|
|||||||
@Test
|
@Test
|
||||||
fun `all linear states for a given id sorted by uuid`() {
|
fun `all linear states for a given id sorted by uuid`() {
|
||||||
val linearStates =
|
val linearStates =
|
||||||
database.transaction {
|
database.transaction {
|
||||||
val txns = services.fillWithSomeTestLinearStates(2, "TEST")
|
val txns = services.fillWithSomeTestLinearStates(2, "TEST")
|
||||||
val linearStates = txns.states.toList()
|
val linearStates = txns.states.toList()
|
||||||
services.evolveLinearStates(linearStates, DUMMY_NOTARY) // consume current and produce new state reference
|
services.evolveLinearStates(linearStates, DUMMY_NOTARY) // consume current and produce new state reference
|
||||||
services.evolveLinearStates(linearStates, DUMMY_NOTARY) // consume current and produce new state reference
|
services.evolveLinearStates(linearStates, DUMMY_NOTARY) // consume current and produce new state reference
|
||||||
services.evolveLinearStates(linearStates, DUMMY_NOTARY) // consume current and produce new state reference
|
services.evolveLinearStates(linearStates, DUMMY_NOTARY) // consume current and produce new state reference
|
||||||
linearStates
|
linearStates
|
||||||
}
|
}
|
||||||
database.transaction {
|
database.transaction {
|
||||||
// should now have 1 UNCONSUMED & 3 CONSUMED state refs for Linear State with "TEST"
|
// should now have 1 UNCONSUMED & 3 CONSUMED state refs for Linear State with "TEST"
|
||||||
val linearStateCriteria = LinearStateQueryCriteria(uuid = linearStates.map { it.state.data.linearId.id }, status = Vault.StateStatus.ALL)
|
val linearStateCriteria = LinearStateQueryCriteria(uuid = linearStates.map { it.state.data.linearId.id }, status = Vault.StateStatus.ALL)
|
||||||
@ -1340,11 +1340,11 @@ class VaultQueryTests : TestDependencyInjectionBase() {
|
|||||||
@Test
|
@Test
|
||||||
fun `unconsumed deal states sorted`() {
|
fun `unconsumed deal states sorted`() {
|
||||||
val uid =
|
val uid =
|
||||||
database.transaction {
|
database.transaction {
|
||||||
val linearStates = services.fillWithSomeTestLinearStates(10)
|
val linearStates = services.fillWithSomeTestLinearStates(10)
|
||||||
services.fillWithSomeTestDeals(listOf("123", "456", "789"))
|
services.fillWithSomeTestDeals(listOf("123", "456", "789"))
|
||||||
linearStates.states.first().state.data.linearId.id
|
linearStates.states.first().state.data.linearId.id
|
||||||
}
|
}
|
||||||
database.transaction {
|
database.transaction {
|
||||||
val linearStateCriteria = LinearStateQueryCriteria(uuid = listOf(uid))
|
val linearStateCriteria = LinearStateQueryCriteria(uuid = listOf(uid))
|
||||||
val dealStateCriteria = LinearStateQueryCriteria(externalId = listOf("123", "456", "789"))
|
val dealStateCriteria = LinearStateQueryCriteria(externalId = listOf("123", "456", "789"))
|
||||||
@ -1378,14 +1378,14 @@ class VaultQueryTests : TestDependencyInjectionBase() {
|
|||||||
@Test
|
@Test
|
||||||
fun `return consumed linear states for a given linear id`() {
|
fun `return consumed linear states for a given linear id`() {
|
||||||
val txns =
|
val txns =
|
||||||
database.transaction {
|
database.transaction {
|
||||||
val txns = services.fillWithSomeTestLinearStates(1, "TEST")
|
val txns = services.fillWithSomeTestLinearStates(1, "TEST")
|
||||||
val linearState = txns.states.first()
|
val linearState = txns.states.first()
|
||||||
val linearState2 = services.evolveLinearState(linearState, DUMMY_NOTARY) // consume current and produce new state reference
|
val linearState2 = services.evolveLinearState(linearState, DUMMY_NOTARY) // consume current and produce new state reference
|
||||||
val linearState3 = services.evolveLinearState(linearState2, DUMMY_NOTARY) // consume current and produce new state reference
|
val linearState3 = services.evolveLinearState(linearState2, DUMMY_NOTARY) // consume current and produce new state reference
|
||||||
services.evolveLinearState(linearState3, DUMMY_NOTARY) // consume current and produce new state reference
|
services.evolveLinearState(linearState3, DUMMY_NOTARY) // consume current and produce new state reference
|
||||||
txns
|
txns
|
||||||
}
|
}
|
||||||
database.transaction {
|
database.transaction {
|
||||||
// should now have 1 UNCONSUMED & 3 CONSUMED state refs for Linear State with "TEST"
|
// should now have 1 UNCONSUMED & 3 CONSUMED state refs for Linear State with "TEST"
|
||||||
val linearStateCriteria = LinearStateQueryCriteria(linearId = txns.states.map { it.state.data.linearId }, status = Vault.StateStatus.CONSUMED)
|
val linearStateCriteria = LinearStateQueryCriteria(linearId = txns.states.map { it.state.data.linearId }, status = Vault.StateStatus.CONSUMED)
|
||||||
@ -1484,15 +1484,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(X500Name("CN=British Pounds Cash Issuer,O=R3,OU=corda,L=London,C=GB"), gbpCashIssuerKey.public).ref(1)
|
val gbpCashIssuer = Party(getX500Name(O = "British Pounds Cash Issuer", OU = "corda", L = "London", C = "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(X500Name("CN=US Dollars Cash Issuer,O=R3,OU=corda,L=New York,C=US"), usdCashIssuerKey.public).ref(1)
|
val usdCashIssuer = Party(getX500Name(O = "US Dollars Cash Issuer", OU = "corda", L = "New York", C = "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(X500Name("CN=Swiss Francs Cash Issuer,O=R3,OU=corda,L=Zurich,C=CH"), chfCashIssuerKey.public).ref(1)
|
val chfCashIssuer = Party(getX500Name(O = "Swiss Francs Cash Issuer", OU = "corda", L = "Zurich", C = "CH"), chfCashIssuerKey.public).ref(1)
|
||||||
val chfCashIssuerServices = MockServices(chfCashIssuerKey)
|
val chfCashIssuerServices = MockServices(chfCashIssuerKey)
|
||||||
|
|
||||||
database.transaction {
|
database.transaction {
|
||||||
@ -1871,14 +1871,14 @@ class VaultQueryTests : TestDependencyInjectionBase() {
|
|||||||
@Test
|
@Test
|
||||||
fun `unconsumed linear heads for a given external id or uuid`() {
|
fun `unconsumed linear heads for a given external id or uuid`() {
|
||||||
val uuid =
|
val uuid =
|
||||||
database.transaction {
|
database.transaction {
|
||||||
services.fillWithSomeTestLinearStates(1, "TEST1")
|
services.fillWithSomeTestLinearStates(1, "TEST1")
|
||||||
val aState = services.fillWithSomeTestLinearStates(1, "TEST2").states
|
val aState = services.fillWithSomeTestLinearStates(1, "TEST2").states
|
||||||
services.consumeLinearStates(aState.toList(), DUMMY_NOTARY)
|
services.consumeLinearStates(aState.toList(), DUMMY_NOTARY)
|
||||||
services.fillWithSomeTestLinearStates(1, "TEST1").states.first().state.data.linearId.id
|
services.fillWithSomeTestLinearStates(1, "TEST1").states.first().state.data.linearId.id
|
||||||
|
|
||||||
// 2 unconsumed states with same external ID, 1 consumed with different external ID
|
// 2 unconsumed states with same external ID, 1 consumed with different external ID
|
||||||
}
|
}
|
||||||
database.transaction {
|
database.transaction {
|
||||||
val results = builder {
|
val results = builder {
|
||||||
val externalIdCondition = VaultSchemaV1.VaultLinearStates::externalId.equal("TEST1")
|
val externalIdCondition = VaultSchemaV1.VaultLinearStates::externalId.equal("TEST1")
|
||||||
@ -1919,12 +1919,12 @@ class VaultQueryTests : TestDependencyInjectionBase() {
|
|||||||
identitySvc.verifyAndRegisterIdentity(BOB_IDENTITY)
|
identitySvc.verifyAndRegisterIdentity(BOB_IDENTITY)
|
||||||
identitySvc.verifyAndRegisterIdentity(CHARLIE_IDENTITY)
|
identitySvc.verifyAndRegisterIdentity(CHARLIE_IDENTITY)
|
||||||
|
|
||||||
services.fillWithSomeTestLinearStates(1, "TEST1", listOf(ALICE,BOB,CHARLIE))
|
services.fillWithSomeTestLinearStates(1, "TEST1", listOf(ALICE, BOB, CHARLIE))
|
||||||
services.fillWithSomeTestLinearStates(1)
|
services.fillWithSomeTestLinearStates(1)
|
||||||
services.fillWithSomeTestLinearStates(1, "TEST3")
|
services.fillWithSomeTestLinearStates(1, "TEST3")
|
||||||
}
|
}
|
||||||
database.transaction {
|
database.transaction {
|
||||||
val linearStateCriteria = LinearStateQueryCriteria(participants = listOf(ALICE,BOB,CHARLIE))
|
val linearStateCriteria = LinearStateQueryCriteria(participants = listOf(ALICE, BOB, CHARLIE))
|
||||||
val results = vaultQuerySvc.queryBy<LinearState>(linearStateCriteria)
|
val results = vaultQuerySvc.queryBy<LinearState>(linearStateCriteria)
|
||||||
|
|
||||||
assertThat(results.states).hasSize(1)
|
assertThat(results.states).hasSize(1)
|
||||||
@ -1984,12 +1984,12 @@ class VaultQueryTests : TestDependencyInjectionBase() {
|
|||||||
database.transaction {
|
database.transaction {
|
||||||
// Base criteria
|
// Base criteria
|
||||||
val baseCriteria = VaultQueryCriteria(notary = listOf(DUMMY_NOTARY),
|
val baseCriteria = VaultQueryCriteria(notary = listOf(DUMMY_NOTARY),
|
||||||
status = Vault.StateStatus.CONSUMED)
|
status = Vault.StateStatus.CONSUMED)
|
||||||
|
|
||||||
// Enrich and override QueryCriteria with additional default attributes (such as soft locks)
|
// Enrich and override QueryCriteria with additional default attributes (such as soft locks)
|
||||||
val enrichedCriteria = VaultQueryCriteria(contractStateTypes = setOf(DealState::class.java), // enrich
|
val enrichedCriteria = VaultQueryCriteria(contractStateTypes = setOf(DealState::class.java), // enrich
|
||||||
softLockingCondition = QueryCriteria.SoftLockingCondition(QueryCriteria.SoftLockingType.UNLOCKED_AND_SPECIFIED, listOf(UUID.randomUUID())),
|
softLockingCondition = QueryCriteria.SoftLockingCondition(QueryCriteria.SoftLockingType.UNLOCKED_AND_SPECIFIED, listOf(UUID.randomUUID())),
|
||||||
status = Vault.StateStatus.UNCONSUMED) // override
|
status = Vault.StateStatus.UNCONSUMED) // override
|
||||||
// Sorting
|
// Sorting
|
||||||
val sortAttribute = SortAttribute.Standard(Sort.CommonStateAttribute.STATE_REF)
|
val sortAttribute = SortAttribute.Standard(Sort.CommonStateAttribute.STATE_REF)
|
||||||
val sorter = Sort(setOf(Sort.SortColumn(sortAttribute, Sort.Direction.ASC)))
|
val sorter = Sort(setOf(Sort.SortColumn(sortAttribute, Sort.Direction.ASC)))
|
||||||
@ -2007,28 +2007,28 @@ class VaultQueryTests : TestDependencyInjectionBase() {
|
|||||||
@Test
|
@Test
|
||||||
fun trackCashStates_unconsumed() {
|
fun trackCashStates_unconsumed() {
|
||||||
val updates =
|
val updates =
|
||||||
database.transaction {
|
database.transaction {
|
||||||
// DOCSTART VaultQueryExample15
|
// DOCSTART VaultQueryExample15
|
||||||
vaultQuerySvc.trackBy<Cash.State>().updates // UNCONSUMED default
|
vaultQuerySvc.trackBy<Cash.State>().updates // UNCONSUMED default
|
||||||
// DOCEND VaultQueryExample15
|
// DOCEND VaultQueryExample15
|
||||||
}
|
}
|
||||||
val (linearStates,dealStates) =
|
val (linearStates, dealStates) =
|
||||||
database.transaction {
|
database.transaction {
|
||||||
services.fillWithSomeTestCash(100.DOLLARS, notaryServices, DUMMY_NOTARY, 5, 5, Random(0L))
|
services.fillWithSomeTestCash(100.DOLLARS, notaryServices, DUMMY_NOTARY, 5, 5, Random(0L))
|
||||||
val linearStates = services.fillWithSomeTestLinearStates(10).states
|
val linearStates = services.fillWithSomeTestLinearStates(10).states
|
||||||
val dealStates = services.fillWithSomeTestDeals(listOf("123", "456", "789")).states
|
val dealStates = services.fillWithSomeTestDeals(listOf("123", "456", "789")).states
|
||||||
// add more cash
|
// add more cash
|
||||||
services.fillWithSomeTestCash(100.POUNDS, notaryServices, DUMMY_NOTARY, 1, 1, Random(0L))
|
services.fillWithSomeTestCash(100.POUNDS, notaryServices, DUMMY_NOTARY, 1, 1, Random(0L))
|
||||||
// add another deal
|
// add another deal
|
||||||
services.fillWithSomeTestDeals(listOf("SAMPLE DEAL"))
|
services.fillWithSomeTestDeals(listOf("SAMPLE DEAL"))
|
||||||
Pair(linearStates,dealStates)
|
Pair(linearStates, dealStates)
|
||||||
}
|
}
|
||||||
database.transaction {
|
database.transaction {
|
||||||
// consume stuff
|
// consume stuff
|
||||||
services.consumeCash(100.DOLLARS, notary = DUMMY_NOTARY)
|
services.consumeCash(100.DOLLARS, notary = DUMMY_NOTARY)
|
||||||
services.consumeDeals(dealStates.toList(), DUMMY_NOTARY)
|
services.consumeDeals(dealStates.toList(), DUMMY_NOTARY)
|
||||||
services.consumeLinearStates(linearStates.toList(), DUMMY_NOTARY)
|
services.consumeLinearStates(linearStates.toList(), DUMMY_NOTARY)
|
||||||
}
|
}
|
||||||
|
|
||||||
updates.expectEvents {
|
updates.expectEvents {
|
||||||
sequence(
|
sequence(
|
||||||
@ -2049,22 +2049,22 @@ class VaultQueryTests : TestDependencyInjectionBase() {
|
|||||||
@Test
|
@Test
|
||||||
fun trackCashStates_consumed() {
|
fun trackCashStates_consumed() {
|
||||||
val updates =
|
val updates =
|
||||||
database.transaction {
|
database.transaction {
|
||||||
val criteria = VaultQueryCriteria(status = Vault.StateStatus.CONSUMED)
|
val criteria = VaultQueryCriteria(status = Vault.StateStatus.CONSUMED)
|
||||||
vaultQuerySvc.trackBy<Cash.State>(criteria).updates
|
vaultQuerySvc.trackBy<Cash.State>(criteria).updates
|
||||||
}
|
}
|
||||||
val (linearStates,dealStates) =
|
val (linearStates, dealStates) =
|
||||||
database.transaction {
|
database.transaction {
|
||||||
services.fillWithSomeTestCash(100.DOLLARS, notaryServices, DUMMY_NOTARY, 5, 5, Random(0L))
|
services.fillWithSomeTestCash(100.DOLLARS, notaryServices, DUMMY_NOTARY, 5, 5, Random(0L))
|
||||||
val linearStates = services.fillWithSomeTestLinearStates(10).states
|
val linearStates = services.fillWithSomeTestLinearStates(10).states
|
||||||
val dealStates = services.fillWithSomeTestDeals(listOf("123", "456", "789")).states
|
val dealStates = services.fillWithSomeTestDeals(listOf("123", "456", "789")).states
|
||||||
|
|
||||||
// add more cash
|
// add more cash
|
||||||
services.fillWithSomeTestCash(100.POUNDS, notaryServices, DUMMY_NOTARY, 1, 1, Random(0L))
|
services.fillWithSomeTestCash(100.POUNDS, notaryServices, DUMMY_NOTARY, 1, 1, Random(0L))
|
||||||
// add another deal
|
// add another deal
|
||||||
services.fillWithSomeTestDeals(listOf("SAMPLE DEAL"))
|
services.fillWithSomeTestDeals(listOf("SAMPLE DEAL"))
|
||||||
Pair(linearStates,dealStates)
|
Pair(linearStates, dealStates)
|
||||||
}
|
}
|
||||||
database.transaction {
|
database.transaction {
|
||||||
// consume stuff
|
// consume stuff
|
||||||
services.consumeCash(100.POUNDS, notary = DUMMY_NOTARY)
|
services.consumeCash(100.POUNDS, notary = DUMMY_NOTARY)
|
||||||
@ -2095,21 +2095,21 @@ class VaultQueryTests : TestDependencyInjectionBase() {
|
|||||||
@Test
|
@Test
|
||||||
fun trackCashStates_all() {
|
fun trackCashStates_all() {
|
||||||
val updates =
|
val updates =
|
||||||
database.transaction {
|
database.transaction {
|
||||||
val criteria = VaultQueryCriteria(status = Vault.StateStatus.ALL)
|
val criteria = VaultQueryCriteria(status = Vault.StateStatus.ALL)
|
||||||
vaultQuerySvc.trackBy<Cash.State>(criteria).updates
|
vaultQuerySvc.trackBy<Cash.State>(criteria).updates
|
||||||
}
|
}
|
||||||
val (linearStates,dealStates) =
|
val (linearStates, dealStates) =
|
||||||
database.transaction {
|
database.transaction {
|
||||||
services.fillWithSomeTestCash(100.DOLLARS, notaryServices, DUMMY_NOTARY, 5, 5, Random(0L))
|
services.fillWithSomeTestCash(100.DOLLARS, notaryServices, DUMMY_NOTARY, 5, 5, Random(0L))
|
||||||
val linearStates = services.fillWithSomeTestLinearStates(10).states
|
val linearStates = services.fillWithSomeTestLinearStates(10).states
|
||||||
val dealStates = services.fillWithSomeTestDeals(listOf("123", "456", "789")).states
|
val dealStates = services.fillWithSomeTestDeals(listOf("123", "456", "789")).states
|
||||||
// add more cash
|
// add more cash
|
||||||
services.fillWithSomeTestCash(100.POUNDS, notaryServices, DUMMY_NOTARY, 1, 1, Random(0L))
|
services.fillWithSomeTestCash(100.POUNDS, notaryServices, DUMMY_NOTARY, 1, 1, Random(0L))
|
||||||
// add another deal
|
// add another deal
|
||||||
services.fillWithSomeTestDeals(listOf("SAMPLE DEAL"))
|
services.fillWithSomeTestDeals(listOf("SAMPLE DEAL"))
|
||||||
Pair(linearStates,dealStates)
|
Pair(linearStates, dealStates)
|
||||||
}
|
}
|
||||||
database.transaction {
|
database.transaction {
|
||||||
// consume stuff
|
// consume stuff
|
||||||
services.consumeCash(99.POUNDS, notary = DUMMY_NOTARY)
|
services.consumeCash(99.POUNDS, notary = DUMMY_NOTARY)
|
||||||
@ -2150,24 +2150,24 @@ class VaultQueryTests : TestDependencyInjectionBase() {
|
|||||||
@Test
|
@Test
|
||||||
fun trackLinearStates() {
|
fun trackLinearStates() {
|
||||||
val updates =
|
val updates =
|
||||||
database.transaction {
|
database.transaction {
|
||||||
// DOCSTART VaultQueryExample16
|
// DOCSTART VaultQueryExample16
|
||||||
val (snapshot, updates) = vaultQuerySvc.trackBy<LinearState>()
|
val (snapshot, updates) = vaultQuerySvc.trackBy<LinearState>()
|
||||||
// DOCEND VaultQueryExample16
|
// DOCEND VaultQueryExample16
|
||||||
assertThat(snapshot.states).hasSize(0)
|
assertThat(snapshot.states).hasSize(0)
|
||||||
updates
|
updates
|
||||||
}
|
}
|
||||||
val (linearStates,dealStates) =
|
val (linearStates, dealStates) =
|
||||||
database.transaction {
|
database.transaction {
|
||||||
services.fillWithSomeTestCash(100.DOLLARS, notaryServices, DUMMY_NOTARY, 3, 3, Random(0L))
|
services.fillWithSomeTestCash(100.DOLLARS, notaryServices, DUMMY_NOTARY, 3, 3, Random(0L))
|
||||||
val linearStates = services.fillWithSomeTestLinearStates(10).states
|
val linearStates = services.fillWithSomeTestLinearStates(10).states
|
||||||
val dealStates = services.fillWithSomeTestDeals(listOf("123", "456", "789")).states
|
val dealStates = services.fillWithSomeTestDeals(listOf("123", "456", "789")).states
|
||||||
// add more cash
|
// add more cash
|
||||||
services.fillWithSomeTestCash(100.POUNDS, notaryServices, DUMMY_NOTARY, 1, 1, Random(0L))
|
services.fillWithSomeTestCash(100.POUNDS, notaryServices, DUMMY_NOTARY, 1, 1, Random(0L))
|
||||||
// add another deal
|
// add another deal
|
||||||
services.fillWithSomeTestDeals(listOf("SAMPLE DEAL"))
|
services.fillWithSomeTestDeals(listOf("SAMPLE DEAL"))
|
||||||
Pair(linearStates,dealStates)
|
Pair(linearStates, dealStates)
|
||||||
}
|
}
|
||||||
database.transaction {
|
database.transaction {
|
||||||
// consume stuff
|
// consume stuff
|
||||||
services.consumeCash(100.DOLLARS, notary = DUMMY_NOTARY)
|
services.consumeCash(100.DOLLARS, notary = DUMMY_NOTARY)
|
||||||
@ -2199,24 +2199,24 @@ class VaultQueryTests : TestDependencyInjectionBase() {
|
|||||||
@Test
|
@Test
|
||||||
fun trackDealStates() {
|
fun trackDealStates() {
|
||||||
val updates =
|
val updates =
|
||||||
database.transaction {
|
database.transaction {
|
||||||
// DOCSTART VaultQueryExample17
|
// DOCSTART VaultQueryExample17
|
||||||
val (snapshot, updates) = vaultQuerySvc.trackBy<DealState>()
|
val (snapshot, updates) = vaultQuerySvc.trackBy<DealState>()
|
||||||
// DOCEND VaultQueryExample17
|
// DOCEND VaultQueryExample17
|
||||||
assertThat(snapshot.states).hasSize(0)
|
assertThat(snapshot.states).hasSize(0)
|
||||||
updates
|
updates
|
||||||
}
|
}
|
||||||
val (linearStates,dealStates) =
|
val (linearStates, dealStates) =
|
||||||
database.transaction {
|
database.transaction {
|
||||||
services.fillWithSomeTestCash(100.DOLLARS, notaryServices, DUMMY_NOTARY, 3, 3, Random(0L))
|
services.fillWithSomeTestCash(100.DOLLARS, notaryServices, DUMMY_NOTARY, 3, 3, Random(0L))
|
||||||
val linearStates = services.fillWithSomeTestLinearStates(10).states
|
val linearStates = services.fillWithSomeTestLinearStates(10).states
|
||||||
val dealStates = services.fillWithSomeTestDeals(listOf("123", "456", "789")).states
|
val dealStates = services.fillWithSomeTestDeals(listOf("123", "456", "789")).states
|
||||||
// add more cash
|
// add more cash
|
||||||
services.fillWithSomeTestCash(100.POUNDS, notaryServices, DUMMY_NOTARY, 1, 1, Random(0L))
|
services.fillWithSomeTestCash(100.POUNDS, notaryServices, DUMMY_NOTARY, 1, 1, Random(0L))
|
||||||
// add another deal
|
// add another deal
|
||||||
services.fillWithSomeTestDeals(listOf("SAMPLE DEAL"))
|
services.fillWithSomeTestDeals(listOf("SAMPLE DEAL"))
|
||||||
Pair(linearStates,dealStates)
|
Pair(linearStates, dealStates)
|
||||||
}
|
}
|
||||||
database.transaction {
|
database.transaction {
|
||||||
// consume stuff
|
// consume stuff
|
||||||
services.consumeCash(100.DOLLARS, notary = DUMMY_NOTARY)
|
services.consumeCash(100.DOLLARS, notary = DUMMY_NOTARY)
|
||||||
|
@ -3,21 +3,25 @@ package net.corda.node.utilities
|
|||||||
import net.corda.core.crypto.Crypto
|
import net.corda.core.crypto.Crypto
|
||||||
import net.corda.core.crypto.Crypto.EDDSA_ED25519_SHA512
|
import net.corda.core.crypto.Crypto.EDDSA_ED25519_SHA512
|
||||||
import net.corda.core.crypto.Crypto.generateKeyPair
|
import net.corda.core.crypto.Crypto.generateKeyPair
|
||||||
import net.corda.core.utilities.cert
|
|
||||||
import net.corda.core.utilities.commonName
|
|
||||||
import net.corda.core.utilities.getX509Name
|
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
import net.corda.core.internal.toTypedArray
|
import net.corda.core.internal.toTypedArray
|
||||||
import net.corda.core.serialization.SerializationContext
|
import net.corda.core.serialization.SerializationContext
|
||||||
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.cert
|
||||||
|
import net.corda.core.utilities.commonName
|
||||||
|
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
|
||||||
import net.corda.nodeapi.internal.serialization.KryoHeaderV0_1
|
import net.corda.nodeapi.internal.serialization.KryoHeaderV0_1
|
||||||
import net.corda.nodeapi.internal.serialization.SerializationContextImpl
|
import net.corda.nodeapi.internal.serialization.SerializationContextImpl
|
||||||
import net.corda.nodeapi.internal.serialization.SerializationFactoryImpl
|
import net.corda.nodeapi.internal.serialization.SerializationFactoryImpl
|
||||||
import net.corda.testing.*
|
import net.corda.testing.ALICE
|
||||||
|
import net.corda.testing.BOB
|
||||||
|
import net.corda.testing.BOB_PUBKEY
|
||||||
|
import net.corda.testing.MEGA_CORP
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
import org.bouncycastle.asn1.x500.X500Name
|
||||||
import org.bouncycastle.asn1.x509.BasicConstraints
|
import org.bouncycastle.asn1.x509.BasicConstraints
|
||||||
import org.bouncycastle.asn1.x509.Extension
|
import org.bouncycastle.asn1.x509.Extension
|
||||||
@ -54,7 +58,7 @@ class X509UtilitiesTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `create valid self-signed CA certificate`() {
|
fun `create valid self-signed CA certificate`() {
|
||||||
val caKey = generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
val caKey = generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||||
val caCert = X509Utilities.createSelfSignedCACertificate(getTestX509Name("Test Cert"), caKey)
|
val caCert = X509Utilities.createSelfSignedCACertificate(getX500Name(CN = "Test Cert", O = "R3 Ltd", L = "London", C = "GB"), caKey)
|
||||||
assertTrue { caCert.subject.commonName == "Test Cert" } // using our subject common name
|
assertTrue { caCert.subject.commonName == "Test Cert" } // using our subject common name
|
||||||
assertEquals(caCert.issuer, caCert.subject) //self-signed
|
assertEquals(caCert.issuer, caCert.subject) //self-signed
|
||||||
caCert.isValidOn(Date()) // throws on verification problems
|
caCert.isValidOn(Date()) // throws on verification problems
|
||||||
@ -69,7 +73,7 @@ class X509UtilitiesTest {
|
|||||||
fun `load and save a PEM file certificate`() {
|
fun `load and save a PEM file certificate`() {
|
||||||
val tmpCertificateFile = tempFile("cacert.pem")
|
val tmpCertificateFile = tempFile("cacert.pem")
|
||||||
val caKey = generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
val caKey = generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||||
val caCert = X509Utilities.createSelfSignedCACertificate(getTestX509Name("Test Cert"), caKey)
|
val caCert = X509Utilities.createSelfSignedCACertificate(getX500Name(CN = "Test Cert", O = "R3 Ltd", L = "London", C = "GB"), caKey)
|
||||||
X509Utilities.saveCertificateAsPEMFile(caCert, tmpCertificateFile)
|
X509Utilities.saveCertificateAsPEMFile(caCert, tmpCertificateFile)
|
||||||
val readCertificate = X509Utilities.loadCertificateFromPEMFile(tmpCertificateFile)
|
val readCertificate = X509Utilities.loadCertificateFromPEMFile(tmpCertificateFile)
|
||||||
assertEquals(caCert, readCertificate)
|
assertEquals(caCert, readCertificate)
|
||||||
@ -78,8 +82,8 @@ class X509UtilitiesTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `create valid server certificate chain`() {
|
fun `create valid server certificate chain`() {
|
||||||
val caKey = generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
val caKey = generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||||
val caCert = X509Utilities.createSelfSignedCACertificate(getTestX509Name("Test CA Cert"), caKey)
|
val caCert = X509Utilities.createSelfSignedCACertificate(getX500Name(CN = "Test CA Cert", O = "R3 Ltd", L = "London", C = "GB"), caKey)
|
||||||
val subject = getTestX509Name("Server Cert")
|
val subject = getX500Name(CN = "Server Cert", O = "R3 Ltd", L = "London", C = "GB")
|
||||||
val keyPair = generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
val keyPair = generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||||
val serverCert = X509Utilities.createCertificate(CertificateType.TLS, caCert, caKey, subject, keyPair.public)
|
val serverCert = X509Utilities.createCertificate(CertificateType.TLS, caCert, caKey, subject, keyPair.public)
|
||||||
assertTrue { serverCert.subject.toString().contains("CN=Server Cert") } // using our subject common name
|
assertTrue { serverCert.subject.toString().contains("CN=Server Cert") } // using our subject common name
|
||||||
@ -208,7 +212,7 @@ class X509UtilitiesTest {
|
|||||||
serverCertAndKey.certificate.isValidOn(Date())
|
serverCertAndKey.certificate.isValidOn(Date())
|
||||||
serverCertAndKey.certificate.isSignatureValid(JcaContentVerifierProviderBuilder().build(caCertAndKey.certificate.subjectPublicKeyInfo))
|
serverCertAndKey.certificate.isSignatureValid(JcaContentVerifierProviderBuilder().build(caCertAndKey.certificate.subjectPublicKeyInfo))
|
||||||
|
|
||||||
assertTrue { serverCertAndKey.certificate.subject.toString().contains(MEGA_CORP.name.commonName) }
|
assertTrue { serverCertAndKey.certificate.subject.toString().contains(MEGA_CORP.name.organisation) }
|
||||||
|
|
||||||
// Load back server certificate
|
// Load back server certificate
|
||||||
val sslKeyStore = loadKeyStore(tmpSSLKeyStore, "serverstorepass")
|
val sslKeyStore = loadKeyStore(tmpSSLKeyStore, "serverstorepass")
|
||||||
@ -217,7 +221,7 @@ class X509UtilitiesTest {
|
|||||||
sslCertAndKey.certificate.isValidOn(Date())
|
sslCertAndKey.certificate.isValidOn(Date())
|
||||||
sslCertAndKey.certificate.isSignatureValid(JcaContentVerifierProviderBuilder().build(serverCertAndKey.certificate.subjectPublicKeyInfo))
|
sslCertAndKey.certificate.isSignatureValid(JcaContentVerifierProviderBuilder().build(serverCertAndKey.certificate.subjectPublicKeyInfo))
|
||||||
|
|
||||||
assertTrue { sslCertAndKey.certificate.subject.toString().contains(MEGA_CORP.name.commonName) }
|
assertTrue { sslCertAndKey.certificate.subject.toString().contains(MEGA_CORP.name.organisation) }
|
||||||
// Now sign something with private key and verify against certificate public key
|
// Now sign something with private key and verify against certificate public key
|
||||||
val testData = "123456".toByteArray()
|
val testData = "123456".toByteArray()
|
||||||
val signature = Crypto.doSign(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME, serverCertAndKey.keyPair.private, testData)
|
val signature = Crypto.doSign(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME, serverCertAndKey.keyPair.private, testData)
|
||||||
@ -355,10 +359,10 @@ class X509UtilitiesTest {
|
|||||||
trustStorePassword: String
|
trustStorePassword: String
|
||||||
): KeyStore {
|
): KeyStore {
|
||||||
val rootCAKey = generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
val rootCAKey = generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||||
val rootCACert = X509Utilities.createSelfSignedCACertificate(getX509Name("Corda Node Root CA", "London", "demo@r3.com", null), rootCAKey)
|
val rootCACert = X509Utilities.createSelfSignedCACertificate(getX500Name(CN = "Corda Node Root CA", O = "R3CEV", L = "London", C = "GB"), rootCAKey)
|
||||||
|
|
||||||
val intermediateCAKeyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
val intermediateCAKeyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||||
val intermediateCACert = X509Utilities.createCertificate(CertificateType.INTERMEDIATE_CA, rootCACert, rootCAKey, getX509Name("Corda Node Intermediate CA", "London", "demo@r3.com", null), intermediateCAKeyPair.public)
|
val intermediateCACert = X509Utilities.createCertificate(CertificateType.INTERMEDIATE_CA, rootCACert, rootCAKey, getX500Name(CN = "Corda Node Intermediate CA", O = "R3CEV", L = "London", C = "GB"), intermediateCAKeyPair.public)
|
||||||
|
|
||||||
val keyPass = keyPassword.toCharArray()
|
val keyPass = keyPassword.toCharArray()
|
||||||
val keyStore = loadOrCreateKeyStore(keyStoreFilePath, storePassword)
|
val keyStore = loadOrCreateKeyStore(keyStoreFilePath, storePassword)
|
||||||
|
@ -5,15 +5,15 @@ 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.utilities.cert
|
|
||||||
import net.corda.core.utilities.commonName
|
|
||||||
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
|
||||||
|
import net.corda.core.utilities.cert
|
||||||
|
import net.corda.core.utilities.commonName
|
||||||
|
import net.corda.core.utilities.getX500Name
|
||||||
import net.corda.node.utilities.X509Utilities
|
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.getTestX509Name
|
|
||||||
import net.corda.testing.testNodeConfiguration
|
import net.corda.testing.testNodeConfiguration
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
@ -34,7 +34,7 @@ class NetworkRegistrationHelperTest {
|
|||||||
val identities = listOf("CORDA_CLIENT_CA",
|
val identities = listOf("CORDA_CLIENT_CA",
|
||||||
"CORDA_INTERMEDIATE_CA",
|
"CORDA_INTERMEDIATE_CA",
|
||||||
"CORDA_ROOT_CA")
|
"CORDA_ROOT_CA")
|
||||||
.map { getTestX509Name(it) }
|
.map { getX500Name(CN = it, O = "R3 Ltd", L = "London", C = "GB") }
|
||||||
val certs = identities.stream().map { X509Utilities.createSelfSignedCACertificate(it, Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)) }
|
val certs = identities.stream().map { X509Utilities.createSelfSignedCACertificate(it, Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)) }
|
||||||
.map { it.cert }.toTypedArray()
|
.map { it.cert }.toTypedArray()
|
||||||
|
|
||||||
|
@ -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 "CN=Notary Service,O=R3,OU=corda,L=Zurich,C=CH"
|
networkMap "O=Notary Service,OU=corda,L=Zurich,C=CH"
|
||||||
node {
|
node {
|
||||||
name "CN=Notary Service,O=R3,OU=corda,L=Zurich,C=CH"
|
name "O=Notary Service,OU=corda,L=Zurich,C=CH"
|
||||||
advertisedServices["corda.notary.validating"]
|
advertisedServices["corda.notary.validating"]
|
||||||
p2pPort 10002
|
p2pPort 10002
|
||||||
rpcPort 10003
|
rpcPort 10003
|
||||||
@ -47,7 +47,7 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
|
|||||||
rpcUsers = ext.rpcUsers
|
rpcUsers = ext.rpcUsers
|
||||||
}
|
}
|
||||||
node {
|
node {
|
||||||
name "CN=Bank A,O=Bank A,L=London,C=GB"
|
name "O=Bank A,L=London,C=GB"
|
||||||
advertisedServices = []
|
advertisedServices = []
|
||||||
p2pPort 10005
|
p2pPort 10005
|
||||||
rpcPort 10006
|
rpcPort 10006
|
||||||
@ -55,7 +55,7 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
|
|||||||
rpcUsers = ext.rpcUsers
|
rpcUsers = ext.rpcUsers
|
||||||
}
|
}
|
||||||
node {
|
node {
|
||||||
name "CN=Bank B,O=Bank B,L=New York,C=US"
|
name "O=Bank B,L=New York,C=US"
|
||||||
advertisedServices = []
|
advertisedServices = []
|
||||||
p2pPort 10008
|
p2pPort 10008
|
||||||
rpcPort 10009
|
rpcPort 10009
|
||||||
|
@ -50,16 +50,16 @@ 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 "CN=Notary Service,O=R3,OU=corda,L=Zurich,C=CH"
|
networkMap "O=Notary Service,OU=corda,L=Zurich,C=CH"
|
||||||
node {
|
node {
|
||||||
name "CN=Notary Service,O=R3,OU=corda,L=Zurich,C=CH"
|
name "O=Notary Service,OU=corda,L=Zurich,C=CH"
|
||||||
advertisedServices = ["corda.notary.validating"]
|
advertisedServices = ["corda.notary.validating"]
|
||||||
p2pPort 10002
|
p2pPort 10002
|
||||||
rpcPort 10003
|
rpcPort 10003
|
||||||
cordapps = ["net.corda:finance:$corda_release_version"]
|
cordapps = ["net.corda:finance:$corda_release_version"]
|
||||||
}
|
}
|
||||||
node {
|
node {
|
||||||
name "CN=BankOfCorda,O=R3,L=New York,C=US"
|
name "O=BankOfCorda,L=New York,C=US"
|
||||||
advertisedServices = ["corda.issuer.USD"]
|
advertisedServices = ["corda.issuer.USD"]
|
||||||
p2pPort 10005
|
p2pPort 10005
|
||||||
rpcPort 10006
|
rpcPort 10006
|
||||||
@ -74,7 +74,7 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
node {
|
node {
|
||||||
name "CN=BigCorporation,O=R3,OU=corda,L=London,C=GB"
|
name "O=BigCorporation,OU=corda,L=London,C=GB"
|
||||||
advertisedServices = []
|
advertisedServices = []
|
||||||
p2pPort 10008
|
p2pPort 10008
|
||||||
rpcPort 10009
|
rpcPort 10009
|
||||||
|
@ -6,6 +6,7 @@ import net.corda.bank.api.BankOfCordaWebApi.IssueRequestParams
|
|||||||
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
|
||||||
@ -15,7 +16,6 @@ import net.corda.nodeapi.User
|
|||||||
import net.corda.testing.BOC
|
import net.corda.testing.BOC
|
||||||
import net.corda.testing.DUMMY_NOTARY
|
import net.corda.testing.DUMMY_NOTARY
|
||||||
import net.corda.testing.driver.driver
|
import net.corda.testing.driver.driver
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import kotlin.system.exitProcess
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -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 = X500Name("CN=BigCorporation,O=R3,OU=corda,L=London,C=GB")
|
val BIGCORP_LEGAL_NAME = getX500Name(O = "BigCorporation", OU = "corda", L = "London", C = "GB")
|
||||||
|
|
||||||
private class BankOfCordaDriver {
|
private class BankOfCordaDriver {
|
||||||
enum class Role {
|
enum class Role {
|
||||||
|
@ -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 "CN=Notary Service,O=R3,OU=corda,L=Zurich,C=CH"
|
networkMap "O=Notary Service,OU=corda,L=Zurich,C=CH"
|
||||||
node {
|
node {
|
||||||
name "CN=Notary Service,O=R3,OU=corda,L=Zurich,C=CH"
|
name "O=Notary Service,OU=corda,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
|
||||||
@ -61,7 +61,7 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
|
|||||||
useTestClock true
|
useTestClock true
|
||||||
}
|
}
|
||||||
node {
|
node {
|
||||||
name "CN=Bank A,O=Bank A,L=London,C=GB"
|
name "O=Bank A,L=London,C=GB"
|
||||||
advertisedServices = []
|
advertisedServices = []
|
||||||
p2pPort 10005
|
p2pPort 10005
|
||||||
rpcPort 10006
|
rpcPort 10006
|
||||||
@ -70,7 +70,7 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
|
|||||||
useTestClock true
|
useTestClock true
|
||||||
}
|
}
|
||||||
node {
|
node {
|
||||||
name "CN=Bank B,O=Bank B,L=New York,C=US"
|
name "O=Bank B,L=New York,C=US"
|
||||||
advertisedServices = []
|
advertisedServices = []
|
||||||
p2pPort 10008
|
p2pPort 10008
|
||||||
rpcPort 10009
|
rpcPort 10009
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
define(['utils/dayCountBasisLookup'], (dayCountBasisLookup) => {
|
define(['utils/dayCountBasisLookup'], (dayCountBasisLookup) => {
|
||||||
return {
|
return {
|
||||||
fixedRatePayer: "CN=Bank A,O=Bank A,L=London,C=GB",
|
fixedRatePayer: "O=Bank A,L=London,C=GB",
|
||||||
notional: {
|
notional: {
|
||||||
quantity: 2500000000
|
quantity: 2500000000
|
||||||
},
|
},
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
define(['utils/dayCountBasisLookup'], (dayCountBasisLookup) => {
|
define(['utils/dayCountBasisLookup'], (dayCountBasisLookup) => {
|
||||||
return {
|
return {
|
||||||
floatingRatePayer: "CN=Bank B,O=Bank B,L=New York,C=US",
|
floatingRatePayer: "O=Bank B,L=New York,C=US",
|
||||||
notional: {
|
notional: {
|
||||||
quantity: 2500000000
|
quantity: 2500000000
|
||||||
},
|
},
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"fixedLeg": {
|
"fixedLeg": {
|
||||||
"fixedRatePayer": "CN=Bank A,O=Bank A,L=London,C=GB",
|
"fixedRatePayer": "O=Bank A,L=London,C=GB",
|
||||||
"notional": "€25000000",
|
"notional": "€25000000",
|
||||||
"paymentFrequency": "SemiAnnual",
|
"paymentFrequency": "SemiAnnual",
|
||||||
"effectiveDate": "2016-03-11",
|
"effectiveDate": "2016-03-11",
|
||||||
@ -22,7 +22,7 @@
|
|||||||
"interestPeriodAdjustment": "Adjusted"
|
"interestPeriodAdjustment": "Adjusted"
|
||||||
},
|
},
|
||||||
"floatingLeg": {
|
"floatingLeg": {
|
||||||
"floatingRatePayer": "CN=Bank B,O=Bank B,L=New York,C=US",
|
"floatingRatePayer": "O=Bank B,L=New York,C=US",
|
||||||
"notional": "€25000000",
|
"notional": "€25000000",
|
||||||
"paymentFrequency": "Quarterly",
|
"paymentFrequency": "Quarterly",
|
||||||
"effectiveDate": "2016-03-11",
|
"effectiveDate": "2016-03-11",
|
||||||
|
@ -11,6 +11,7 @@ import net.corda.core.node.services.ServiceInfo
|
|||||||
import net.corda.core.transactions.TransactionBuilder
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
import net.corda.core.utilities.ProgressTracker
|
import net.corda.core.utilities.ProgressTracker
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
|
import net.corda.core.utilities.getX500Name
|
||||||
import net.corda.finance.DOLLARS
|
import net.corda.finance.DOLLARS
|
||||||
import net.corda.finance.contracts.Fix
|
import net.corda.finance.contracts.Fix
|
||||||
import net.corda.finance.contracts.FixOf
|
import net.corda.finance.contracts.FixOf
|
||||||
@ -48,7 +49,7 @@ class NodeInterestRatesTest : TestDependencyInjectionBase() {
|
|||||||
""".trimIndent())
|
""".trimIndent())
|
||||||
|
|
||||||
val DUMMY_CASH_ISSUER_KEY = generateKeyPair()
|
val DUMMY_CASH_ISSUER_KEY = generateKeyPair()
|
||||||
val DUMMY_CASH_ISSUER = Party(X500Name("CN=Cash issuer,O=R3,OU=corda,L=London,C=GB"), DUMMY_CASH_ISSUER_KEY.public)
|
val DUMMY_CASH_ISSUER = Party(getX500Name(O="Cash issuer",OU="corda",L="London",C="GB"), DUMMY_CASH_ISSUER_KEY.public)
|
||||||
|
|
||||||
lateinit var oracle: NodeInterestRates.Oracle
|
lateinit var oracle: NodeInterestRates.Oracle
|
||||||
lateinit var database: CordaPersistence
|
lateinit var database: CordaPersistence
|
||||||
|
@ -11,7 +11,7 @@ import javafx.scene.input.KeyCodeCombination
|
|||||||
import javafx.scene.layout.VBox
|
import javafx.scene.layout.VBox
|
||||||
import javafx.stage.Stage
|
import javafx.stage.Stage
|
||||||
import javafx.util.Duration
|
import javafx.util.Duration
|
||||||
import net.corda.core.utilities.commonName
|
import net.corda.core.utilities.organisation
|
||||||
import net.corda.core.serialization.deserialize
|
import net.corda.core.serialization.deserialize
|
||||||
import net.corda.core.utilities.ProgressTracker
|
import net.corda.core.utilities.ProgressTracker
|
||||||
import net.corda.netmap.VisualiserViewModel.Style
|
import net.corda.netmap.VisualiserViewModel.Style
|
||||||
@ -233,7 +233,7 @@ class NetworkMapVisualiser : Application() {
|
|||||||
} else if (!viewModel.trackerBoxes.containsKey(tracker)) {
|
} else if (!viewModel.trackerBoxes.containsKey(tracker)) {
|
||||||
// New flow started up; add.
|
// New flow started up; add.
|
||||||
val extraLabel = viewModel.simulation.extraNodeLabels[node]
|
val extraLabel = viewModel.simulation.extraNodeLabels[node]
|
||||||
val label = if (extraLabel != null) "${node.info.legalIdentity.name.commonName}: $extraLabel" else node.info.legalIdentity.name.commonName
|
val label = if (extraLabel != null) "${node.info.legalIdentity.name.organisation}: $extraLabel" else node.info.legalIdentity.name.organisation
|
||||||
val widget = view.buildProgressTrackerWidget(label, tracker.topLevelTracker)
|
val widget = view.buildProgressTrackerWidget(label, tracker.topLevelTracker)
|
||||||
println("Added: $tracker, $widget")
|
println("Added: $tracker, $widget")
|
||||||
viewModel.trackerBoxes[tracker] = widget
|
viewModel.trackerBoxes[tracker] = widget
|
||||||
|
@ -9,7 +9,8 @@ import javafx.scene.shape.Line
|
|||||||
import javafx.util.Duration
|
import javafx.util.Duration
|
||||||
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.commonName
|
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 org.bouncycastle.asn1.x500.X500Name
|
||||||
@ -127,7 +128,7 @@ class VisualiserViewModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun makeNodeWidget(forNode: MockNetwork.MockNode, type: String, label: X500Name = X500Name("CN=Bank of Bologna,OU=Corda QA Department,O=R3 CEV,L=Bologna,C=IT"),
|
fun makeNodeWidget(forNode: MockNetwork.MockNode, type: String, label: X500Name = getX500Name(O = "Bank of Bologna", OU = "Corda QA Department", L = "Bologna", C = "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 {
|
||||||
@ -157,7 +158,7 @@ class VisualiserViewModel {
|
|||||||
view.root.children += longPulseOuterDot
|
view.root.children += longPulseOuterDot
|
||||||
view.root.children += innerDot
|
view.root.children += innerDot
|
||||||
|
|
||||||
val nameLabel = Label(label.commonName)
|
val nameLabel = Label(label.organisation)
|
||||||
val nameLabelRect = StackPane(nameLabel).apply {
|
val nameLabelRect = StackPane(nameLabel).apply {
|
||||||
styleClass += "node-label"
|
styleClass += "node-label"
|
||||||
alignment = Pos.CENTER_RIGHT
|
alignment = Pos.CENTER_RIGHT
|
||||||
|
@ -1,27 +1,27 @@
|
|||||||
package net.corda.netmap.simulation
|
package net.corda.netmap.simulation
|
||||||
|
|
||||||
import net.corda.core.utilities.locationOrNull
|
|
||||||
import net.corda.core.flows.FlowLogic
|
import net.corda.core.flows.FlowLogic
|
||||||
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.containsType
|
import net.corda.core.node.services.containsType
|
||||||
import net.corda.testing.DUMMY_MAP
|
|
||||||
import net.corda.testing.DUMMY_NOTARY
|
|
||||||
import net.corda.testing.DUMMY_REGULATOR
|
|
||||||
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
|
||||||
import net.corda.node.services.statemachine.StateMachineManager
|
import net.corda.node.services.statemachine.StateMachineManager
|
||||||
import net.corda.node.services.transactions.SimpleNotaryService
|
import net.corda.node.services.transactions.SimpleNotaryService
|
||||||
|
import net.corda.testing.DUMMY_MAP
|
||||||
|
import net.corda.testing.DUMMY_NOTARY
|
||||||
|
import net.corda.testing.DUMMY_REGULATOR
|
||||||
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 net.corda.testing.node.TestClock
|
import net.corda.testing.node.TestClock
|
||||||
import net.corda.testing.node.setTo
|
import net.corda.testing.node.setTo
|
||||||
import net.corda.testing.testNodeConfiguration
|
import net.corda.testing.testNodeConfiguration
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import rx.subjects.PublishSubject
|
import rx.subjects.PublishSubject
|
||||||
import java.math.BigInteger
|
import java.math.BigInteger
|
||||||
@ -57,7 +57,7 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
|
|||||||
entropyRoot: BigInteger)
|
entropyRoot: BigInteger)
|
||||||
: MockNetwork.MockNode(config, mockNet, networkMapAddress, advertisedServices, id, overrideServices, entropyRoot) {
|
: MockNetwork.MockNode(config, mockNet, networkMapAddress, advertisedServices, id, overrideServices, entropyRoot) {
|
||||||
override fun findMyLocation(): WorldMapLocation? {
|
override fun findMyLocation(): WorldMapLocation? {
|
||||||
return configuration.myLegalName.locationOrNull?.let { CityDatabase[it] }
|
return configuration.myLegalName.locality.let { CityDatabase[it] }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean,
|
|||||||
|
|
||||||
val cfg = testNodeConfiguration(
|
val cfg = testNodeConfiguration(
|
||||||
baseDirectory = config.baseDirectory,
|
baseDirectory = config.baseDirectory,
|
||||||
myLegalName = X500Name("CN=Bank $letter,O=Bank $letter,L=$city,C=$country"))
|
myLegalName = getX500Name(O = "Bank $letter", L = city, C = country))
|
||||||
return SimulatedNode(cfg, network, networkMapAddr, advertisedServices, id, overrideServices, entropyRoot)
|
return SimulatedNode(cfg, network, networkMapAddr, advertisedServices, id, overrideServices, entropyRoot)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +112,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 = X500Name("CN=Rates Service Provider,O=R3,OU=corda,L=Madrid,C=ES")
|
val RATES_SERVICE_NAME = getX500Name(O = "Rates Service Provider", OU = "corda", L = "Madrid", C = "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>?,
|
||||||
|
@ -1,21 +1,21 @@
|
|||||||
package net.corda.notarydemo
|
package net.corda.notarydemo
|
||||||
|
|
||||||
import net.corda.core.internal.div
|
|
||||||
import net.corda.core.node.services.ServiceInfo
|
|
||||||
import net.corda.testing.ALICE
|
|
||||||
import net.corda.testing.BOB
|
|
||||||
import net.corda.demorun.util.*
|
|
||||||
import net.corda.demorun.runNodes
|
|
||||||
import net.corda.node.services.transactions.BFTNonValidatingNotaryService
|
|
||||||
import net.corda.node.utilities.ServiceIdentityGenerator
|
|
||||||
import net.corda.cordform.CordformDefinition
|
|
||||||
import net.corda.cordform.CordformContext
|
import net.corda.cordform.CordformContext
|
||||||
|
import net.corda.cordform.CordformDefinition
|
||||||
import net.corda.cordform.CordformNode
|
import net.corda.cordform.CordformNode
|
||||||
|
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.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
|
import net.corda.core.utilities.getX500Name
|
||||||
|
import net.corda.demorun.runNodes
|
||||||
|
import net.corda.demorun.util.*
|
||||||
|
import net.corda.node.services.transactions.BFTNonValidatingNotaryService
|
||||||
import net.corda.node.services.transactions.minCorrectReplicas
|
import net.corda.node.services.transactions.minCorrectReplicas
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
import net.corda.node.utilities.ServiceIdentityGenerator
|
||||||
|
import net.corda.testing.ALICE
|
||||||
|
import net.corda.testing.BOB
|
||||||
|
|
||||||
fun main(args: Array<String>) = BFTNotaryCordform.runNodes()
|
fun main(args: Array<String>) = BFTNotaryCordform.runNodes()
|
||||||
|
|
||||||
@ -23,7 +23,7 @@ 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]) {
|
||||||
private val clusterName = X500Name("CN=BFT,O=R3,OU=corda,L=Zurich,C=CH")
|
private val clusterName = getX500Name(O = "BFT", OU = "corda", L = "Zurich", C = "CH")
|
||||||
private val advertisedService = ServiceInfo(BFTNonValidatingNotaryService.type, clusterName)
|
private val advertisedService = ServiceInfo(BFTNonValidatingNotaryService.type, clusterName)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
@ -1,30 +1,27 @@
|
|||||||
package net.corda.notarydemo
|
package net.corda.notarydemo
|
||||||
|
|
||||||
import net.corda.core.utilities.appendToCommonName
|
import net.corda.cordform.CordformContext
|
||||||
|
import net.corda.cordform.CordformDefinition
|
||||||
|
import net.corda.cordform.CordformNode
|
||||||
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.testing.ALICE
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
import net.corda.testing.BOB
|
import net.corda.core.utilities.getX500Name
|
||||||
import net.corda.testing.DUMMY_NOTARY
|
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
|
||||||
import net.corda.node.utilities.ServiceIdentityGenerator
|
import net.corda.node.utilities.ServiceIdentityGenerator
|
||||||
import net.corda.cordform.CordformDefinition
|
import net.corda.testing.ALICE
|
||||||
import net.corda.cordform.CordformContext
|
import net.corda.testing.BOB
|
||||||
import net.corda.cordform.CordformNode
|
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
|
||||||
import net.corda.demorun.runNodes
|
|
||||||
import net.corda.demorun.util.node
|
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
|
|
||||||
fun main(args: Array<String>) = RaftNotaryCordform.runNodes()
|
fun main(args: Array<String>) = RaftNotaryCordform.runNodes()
|
||||||
|
|
||||||
internal fun createNotaryNames(clusterSize: Int) = (0 until clusterSize).map { DUMMY_NOTARY.name.appendToCommonName(" $it") }
|
internal fun createNotaryNames(clusterSize: Int) = (0 until clusterSize).map { getX500Name(CN = "Notary Service $it", O = "R3 Ltd", OU = "corda", L = "Zurich", C = "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]) {
|
||||||
private val clusterName = X500Name("CN=Raft,O=R3,OU=corda,L=Zurich,C=CH")
|
private val clusterName = getX500Name(O = "Raft", OU = "corda", L = "Zurich", C = "CH")
|
||||||
private val advertisedService = ServiceInfo(RaftValidatingNotaryService.type, clusterName)
|
private val advertisedService = ServiceInfo(RaftValidatingNotaryService.type, clusterName)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
@ -63,29 +63,29 @@ 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 "CN=Notary Service,O=R3,OU=corda,L=Zurich,C=CH"
|
networkMap "O=Notary Service,OU=corda,L=Zurich,C=CH"
|
||||||
node {
|
node {
|
||||||
name "CN=Notary Service,O=R3,OU=corda,L=Zurich,C=CH"
|
name "O=Notary Service,OU=corda,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"]
|
||||||
}
|
}
|
||||||
node {
|
node {
|
||||||
name "CN=Bank A,O=Bank A,L=London,C=GB"
|
name "O=Bank A,L=London,C=GB"
|
||||||
advertisedServices = []
|
advertisedServices = []
|
||||||
p2pPort 10004
|
p2pPort 10004
|
||||||
webPort 10005
|
webPort 10005
|
||||||
cordapps = ["net.corda:finance:$corda_release_version"]
|
cordapps = ["net.corda:finance:$corda_release_version"]
|
||||||
}
|
}
|
||||||
node {
|
node {
|
||||||
name "CN=Bank B,O=Bank B,L=New York,C=US"
|
name "O=Bank B,L=New York,C=US"
|
||||||
advertisedServices = []
|
advertisedServices = []
|
||||||
p2pPort 10006
|
p2pPort 10006
|
||||||
webPort 10007
|
webPort 10007
|
||||||
cordapps = ["net.corda:finance:$corda_release_version"]
|
cordapps = ["net.corda:finance:$corda_release_version"]
|
||||||
}
|
}
|
||||||
node {
|
node {
|
||||||
name "CN=Bank C,O=Bank C,L=Tokyo,C=Japan"
|
name "O=Bank C,L=Tokyo,C=Japan"
|
||||||
advertisedServices = []
|
advertisedServices = []
|
||||||
p2pPort 10008
|
p2pPort 10008
|
||||||
webPort 10009
|
webPort 10009
|
||||||
|
@ -5,11 +5,11 @@ import com.opengamma.strata.product.swap.IborRateCalculation
|
|||||||
import com.opengamma.strata.product.swap.RateCalculationSwapLeg
|
import com.opengamma.strata.product.swap.RateCalculationSwapLeg
|
||||||
import com.opengamma.strata.product.swap.SwapLegType
|
import com.opengamma.strata.product.swap.SwapLegType
|
||||||
import net.corda.core.contracts.hash
|
import net.corda.core.contracts.hash
|
||||||
import net.corda.core.utilities.commonName
|
|
||||||
import net.corda.core.identity.AbstractParty
|
import net.corda.core.identity.AbstractParty
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.utilities.toBase58String
|
|
||||||
import net.corda.core.messaging.CordaRPCOps
|
import net.corda.core.messaging.CordaRPCOps
|
||||||
|
import net.corda.core.utilities.organisation
|
||||||
|
import net.corda.core.utilities.toBase58String
|
||||||
import net.corda.vega.contracts.IRSState
|
import net.corda.vega.contracts.IRSState
|
||||||
import net.corda.vega.contracts.PortfolioState
|
import net.corda.vega.contracts.PortfolioState
|
||||||
import net.corda.vega.portfolio.Portfolio
|
import net.corda.vega.portfolio.Portfolio
|
||||||
@ -136,7 +136,7 @@ class PortfolioApiUtils(private val ownParty: Party) {
|
|||||||
|
|
||||||
return TradeView(
|
return TradeView(
|
||||||
fixedLeg = mapOf(
|
fixedLeg = mapOf(
|
||||||
"fixedRatePayer" to (fixedRatePayer.nameOrNull()?.commonName ?: fixedRatePayer.owningKey.toBase58String()),
|
"fixedRatePayer" to (fixedRatePayer.nameOrNull()?.organisation ?: fixedRatePayer.owningKey.toBase58String()),
|
||||||
"notional" to mapOf(
|
"notional" to mapOf(
|
||||||
"token" to fixedLeg.currency.code,
|
"token" to fixedLeg.currency.code,
|
||||||
"quantity" to fixedLeg.notionalSchedule.amount.initialValue
|
"quantity" to fixedLeg.notionalSchedule.amount.initialValue
|
||||||
@ -152,7 +152,7 @@ class PortfolioApiUtils(private val ownParty: Party) {
|
|||||||
"paymentCalendar" to mapOf<String, Any>() // TODO
|
"paymentCalendar" to mapOf<String, Any>() // TODO
|
||||||
),
|
),
|
||||||
floatingLeg = mapOf(
|
floatingLeg = mapOf(
|
||||||
"floatingRatePayer" to (floatingRatePayer.nameOrNull()?.commonName ?: floatingRatePayer.owningKey.toBase58String()),
|
"floatingRatePayer" to (floatingRatePayer.nameOrNull()?.organisation ?: floatingRatePayer.owningKey.toBase58String()),
|
||||||
"notional" to mapOf(
|
"notional" to mapOf(
|
||||||
"token" to floatingLeg.currency.code,
|
"token" to floatingLeg.currency.code,
|
||||||
"quantity" to floatingLeg.notionalSchedule.amount.initialValue
|
"quantity" to floatingLeg.notionalSchedule.amount.initialValue
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
var FixedLegViewModel = (function () {
|
var FixedLegViewModel = (function () {
|
||||||
function FixedLegViewModel() {
|
function FixedLegViewModel() {
|
||||||
this.fixedRatePayer = "CN=Bank A,O=Bank A,L=London,C=GB";
|
this.fixedRatePayer = "O=Bank A,L=London,C=GB";
|
||||||
this.notional = {
|
this.notional = {
|
||||||
quantity: 2500000000
|
quantity: 2500000000
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
export class FixedLegViewModel {
|
export class FixedLegViewModel {
|
||||||
constructor() { }
|
constructor() { }
|
||||||
|
|
||||||
fixedRatePayer = "CN=Bank A,O=Bank A,L=London,C=GB";
|
fixedRatePayer = "O=Bank A,L=London,C=GB";
|
||||||
notional: Object = {
|
notional: Object = {
|
||||||
quantity: 2500000000
|
quantity: 2500000000
|
||||||
};
|
};
|
||||||
|
@ -51,15 +51,15 @@ 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 "CN=Notary Service,O=R3,OU=corda,L=Zurich,C=CH"
|
networkMap "O=Notary Service,OU=corda,L=Zurich,C=CH"
|
||||||
node {
|
node {
|
||||||
name "CN=Notary Service,O=R3,OU=corda,L=Zurich,C=CH"
|
name "O=Notary Service,OU=corda,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"]
|
||||||
}
|
}
|
||||||
node {
|
node {
|
||||||
name "CN=Bank A,O=Bank A,L=London,C=GB"
|
name "O=Bank A,L=London,C=GB"
|
||||||
advertisedServices = []
|
advertisedServices = []
|
||||||
p2pPort 10005
|
p2pPort 10005
|
||||||
rpcPort 10006
|
rpcPort 10006
|
||||||
@ -67,7 +67,7 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
|
|||||||
rpcUsers = ext.rpcUsers
|
rpcUsers = ext.rpcUsers
|
||||||
}
|
}
|
||||||
node {
|
node {
|
||||||
name "CN=Bank B,O=Bank B,L=New York,C=US"
|
name "O=Bank B,L=New York,C=US"
|
||||||
advertisedServices = []
|
advertisedServices = []
|
||||||
p2pPort 10008
|
p2pPort 10008
|
||||||
rpcPort 10009
|
rpcPort 10009
|
||||||
@ -75,7 +75,7 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
|
|||||||
rpcUsers = ext.rpcUsers
|
rpcUsers = ext.rpcUsers
|
||||||
}
|
}
|
||||||
node {
|
node {
|
||||||
name "CN=BankOfCorda,O=R3,L=New York,C=US"
|
name "O=BankOfCorda,L=New York,C=US"
|
||||||
advertisedServices = []
|
advertisedServices = []
|
||||||
p2pPort 10011
|
p2pPort 10011
|
||||||
rpcPort 10012
|
rpcPort 10012
|
||||||
|
@ -34,7 +34,7 @@ fun convertToStackSnapshotFrames(snapshot: FlowStackSnapshot): List<StackSnapsho
|
|||||||
val dataTypes = it.stackObjects.map {
|
val dataTypes = it.stackObjects.map {
|
||||||
if (it == null) null else it::class.qualifiedName
|
if (it == null) null else it::class.qualifiedName
|
||||||
}
|
}
|
||||||
val stackTraceElement = it.stackTraceElement!!
|
val stackTraceElement = it.stackTraceElement
|
||||||
StackSnapshotFrame(stackTraceElement.methodName, stackTraceElement.className, dataTypes)
|
StackSnapshotFrame(stackTraceElement.methodName, stackTraceElement.className, dataTypes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import com.nhaarman.mockito_kotlin.whenever
|
|||||||
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.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
|
||||||
@ -60,7 +61,7 @@ fun testNodeConfiguration(
|
|||||||
whenever(nc.keyStorePassword).thenReturn("cordacadevpass")
|
whenever(nc.keyStorePassword).thenReturn("cordacadevpass")
|
||||||
whenever(nc.trustStorePassword).thenReturn("trustpass")
|
whenever(nc.trustStorePassword).thenReturn("trustpass")
|
||||||
whenever(nc.rpcUsers).thenReturn(emptyList())
|
whenever(nc.rpcUsers).thenReturn(emptyList())
|
||||||
whenever(nc.dataSourceProperties).thenReturn(makeTestDataSourceProperties(myLegalName.commonName))
|
whenever(nc.dataSourceProperties).thenReturn(makeTestDataSourceProperties(myLegalName.organisation))
|
||||||
whenever(nc.database).thenReturn(makeTestDatabaseProperties())
|
whenever(nc.database).thenReturn(makeTestDatabaseProperties())
|
||||||
whenever(nc.emailAddress).thenReturn("")
|
whenever(nc.emailAddress).thenReturn("")
|
||||||
whenever(nc.exportJMXto).thenReturn("")
|
whenever(nc.exportJMXto).thenReturn("")
|
||||||
|
@ -11,9 +11,6 @@ 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.utilities.appendToCommonName
|
|
||||||
import net.corda.core.utilities.commonName
|
|
||||||
import net.corda.core.utilities.getX509Name
|
|
||||||
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.*
|
||||||
@ -654,7 +651,7 @@ 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 ?: getX509Name("${oneOf(names).commonName}-${p2pAddress.port}", "London", "demo@r3.com", null)
|
val name = providedName ?: getX500Name(O = "${oneOf(names).organisation}-${p2pAddress.port}", L = "London", C = "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())
|
||||||
@ -706,7 +703,7 @@ class DriverDSL(
|
|||||||
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 { DUMMY_NOTARY.name.appendToCommonName(" $it") }
|
val nodeNames = (0 until clusterSize).map { getX500Name(O = "Notary Service $it", OU = "corda", L = "Zurich", C = "CH") }
|
||||||
val paths = nodeNames.map { baseDirectory(it) }
|
val paths = nodeNames.map { baseDirectory(it) }
|
||||||
ServiceIdentityGenerator.generateToDisk(paths, type.id, notaryName)
|
ServiceIdentityGenerator.generateToDisk(paths, type.id, notaryName)
|
||||||
val advertisedServices = setOf(ServiceInfo(type, notaryName))
|
val advertisedServices = setOf(ServiceInfo(type, notaryName))
|
||||||
@ -772,7 +769,7 @@ class DriverDSL(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun baseDirectory(nodeName: X500Name): Path = driverDirectory / nodeName.commonName.replace(WHITESPACE, "")
|
override fun baseDirectory(nodeName: X500Name): Path = driverDirectory / nodeName.organisation.replace(WHITESPACE, "")
|
||||||
|
|
||||||
override fun startDedicatedNetworkMapService(startInProcess: Boolean?): CordaFuture<NodeHandle> {
|
override fun startDedicatedNetworkMapService(startInProcess: Boolean?): CordaFuture<NodeHandle> {
|
||||||
val webAddress = portAllocation.nextHostAndPort()
|
val webAddress = portAllocation.nextHostAndPort()
|
||||||
@ -859,13 +856,13 @@ class DriverDSL(
|
|||||||
config: Config
|
config: Config
|
||||||
): CordaFuture<Pair<Node, Thread>> {
|
): CordaFuture<Pair<Node, Thread>> {
|
||||||
return executorService.fork {
|
return executorService.fork {
|
||||||
log.info("Starting in-process Node ${nodeConf.myLegalName.commonName}")
|
log.info("Starting in-process Node ${nodeConf.myLegalName.organisation}")
|
||||||
// Write node.conf
|
// Write node.conf
|
||||||
writeConfig(nodeConf.baseDirectory, "node.conf", config)
|
writeConfig(nodeConf.baseDirectory, "node.conf", config)
|
||||||
// TODO pass the version in?
|
// TODO pass the version in?
|
||||||
val node = Node(nodeConf, nodeConf.calculateServices(), MOCK_VERSION_INFO, initialiseSerialization = false)
|
val node = Node(nodeConf, nodeConf.calculateServices(), MOCK_VERSION_INFO, initialiseSerialization = false)
|
||||||
node.start()
|
node.start()
|
||||||
val nodeThread = thread(name = nodeConf.myLegalName.commonName) {
|
val nodeThread = thread(name = nodeConf.myLegalName.organisation) {
|
||||||
node.run()
|
node.run()
|
||||||
}
|
}
|
||||||
node to nodeThread
|
node to nodeThread
|
||||||
@ -882,7 +879,7 @@ class DriverDSL(
|
|||||||
callerPackage: String
|
callerPackage: String
|
||||||
): CordaFuture<Process> {
|
): CordaFuture<Process> {
|
||||||
val processFuture = executorService.fork {
|
val processFuture = executorService.fork {
|
||||||
log.info("Starting out-of-process Node ${nodeConf.myLegalName.commonName}")
|
log.info("Starting out-of-process Node ${nodeConf.myLegalName.organisation}")
|
||||||
// Write node.conf
|
// Write node.conf
|
||||||
writeConfig(nodeConf.baseDirectory, "node.conf", config)
|
writeConfig(nodeConf.baseDirectory, "node.conf", config)
|
||||||
|
|
||||||
|
@ -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.getX509Name
|
import net.corda.core.utilities.getX500Name
|
||||||
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
|
||||||
@ -127,7 +127,7 @@ class InMemoryMessagingNetwork(
|
|||||||
id: Int,
|
id: Int,
|
||||||
executor: AffinityExecutor,
|
executor: AffinityExecutor,
|
||||||
advertisedServices: List<ServiceEntry>,
|
advertisedServices: List<ServiceEntry>,
|
||||||
description: X500Name = getX509Name("In memory node $id", "London", "demo@r3.com", null),
|
description: X500Name = getX500Name(O = "In memory node $id", L = "London", C = "UK"),
|
||||||
database: CordaPersistence)
|
database: CordaPersistence)
|
||||||
: MessagingServiceBuilder<InMemoryMessaging> {
|
: MessagingServiceBuilder<InMemoryMessaging> {
|
||||||
val peerHandle = PeerHandle(id, description)
|
val peerHandle = PeerHandle(id, description)
|
||||||
|
@ -7,10 +7,10 @@ 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
|
||||||
import net.corda.testing.getTestX509Name
|
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import rx.subjects.PublishSubject
|
import rx.subjects.PublishSubject
|
||||||
import java.math.BigInteger
|
import java.math.BigInteger
|
||||||
@ -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(getTestX509Name("Bank C"), entropyToKeyPair(BigInteger.valueOf(1000)).public)
|
val BANK_C = getTestPartyAndCertificate(getX500Name(O = "Bank C", L = "London", C = "GB"), entropyToKeyPair(BigInteger.valueOf(1000)).public)
|
||||||
val BANK_D = getTestPartyAndCertificate(getTestX509Name("Bank D"), entropyToKeyPair(BigInteger.valueOf(2000)).public)
|
val BANK_D = getTestPartyAndCertificate(getX500Name(O = "Bank D", L = "London", C = "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)
|
||||||
}
|
}
|
||||||
|
@ -152,7 +152,7 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false,
|
|||||||
id,
|
id,
|
||||||
serverThread,
|
serverThread,
|
||||||
makeServiceEntries(),
|
makeServiceEntries(),
|
||||||
configuration.myLegalName,
|
myLegalName,
|
||||||
database)
|
database)
|
||||||
.start()
|
.start()
|
||||||
.getOrThrow()
|
.getOrThrow()
|
||||||
@ -303,7 +303,7 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false,
|
|||||||
val id = forcedID ?: nextNodeId++
|
val id = forcedID ?: nextNodeId++
|
||||||
val config = testNodeConfiguration(
|
val config = testNodeConfiguration(
|
||||||
baseDirectory = baseDirectory(id).createDirectories(),
|
baseDirectory = baseDirectory(id).createDirectories(),
|
||||||
myLegalName = legalName ?: getTestX509Name("Mock Company $id")).also {
|
myLegalName = legalName ?: getX500Name(O = "Mock Company $id", L = "London", C = "GB")).also {
|
||||||
whenever(it.dataSourceProperties).thenReturn(makeTestDataSourceProperties("node_${id}_net_$networkId"))
|
whenever(it.dataSourceProperties).thenReturn(makeTestDataSourceProperties("node_${id}_net_$networkId"))
|
||||||
configOverrides(it)
|
configOverrides(it)
|
||||||
}
|
}
|
||||||
|
@ -130,7 +130,7 @@ abstract class NodeBasedTest : TestDependencyInjectionBase() {
|
|||||||
clusterSize: Int,
|
clusterSize: Int,
|
||||||
serviceType: ServiceType = RaftValidatingNotaryService.type): CordaFuture<List<Node>> {
|
serviceType: ServiceType = RaftValidatingNotaryService.type): CordaFuture<List<Node>> {
|
||||||
ServiceIdentityGenerator.generateToDisk(
|
ServiceIdentityGenerator.generateToDisk(
|
||||||
(0 until clusterSize).map { baseDirectory(notaryName.appendToCommonName("-$it")) },
|
(0 until clusterSize).map { baseDirectory(getX500Name(O = "${notaryName.organisation}-$it", L = notaryName.locality, C = notaryName.country)) },
|
||||||
serviceType.id,
|
serviceType.id,
|
||||||
notaryName)
|
notaryName)
|
||||||
|
|
||||||
@ -138,19 +138,19 @@ 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(
|
||||||
getX509Name("${notaryName.commonName}-0", "London", "demo@r3.com", null),
|
getX500Name(O = "${notaryName.organisation}-0", L = notaryName.locality, C = 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.commonName}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(
|
||||||
getX509Name("${notaryName.commonName}-$it", "London", "demo@r3.com", null),
|
getX500Name(O = "${notaryName.organisation}-$it", L = notaryName.locality, C = notaryName.country),
|
||||||
advertisedServices = setOf(serviceInfo),
|
advertisedServices = setOf(serviceInfo),
|
||||||
configOverrides = mapOf(
|
configOverrides = mapOf(
|
||||||
"notaryNodeAddress" to nodeAddresses[it],
|
"notaryNodeAddress" to nodeAddresses[it],
|
||||||
"notaryClusterAddresses" to listOf(nodeAddresses[0]),
|
"notaryClusterAddresses" to listOf(nodeAddresses[0]),
|
||||||
"database" to mapOf("serverNameTablePrefix" to "${notaryName.commonName}$it".replace(Regex("[^0-9A-Za-z]+"), ""))))
|
"database" to mapOf("serverNameTablePrefix" to "${notaryName.organisation}$it".replace(Regex("[^0-9A-Za-z]+"), ""))))
|
||||||
}
|
}
|
||||||
|
|
||||||
return remainingNodesFutures.transpose().flatMap { remainingNodes ->
|
return remainingNodesFutures.transpose().flatMap { remainingNodes ->
|
||||||
@ -158,7 +158,7 @@ abstract class NodeBasedTest : TestDependencyInjectionBase() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun baseDirectory(legalName: X500Name) = tempFolder.root.toPath() / legalName.commonName.replace(WHITESPACE, "")
|
protected fun baseDirectory(legalName: X500Name) = tempFolder.root.toPath() / legalName.organisation.replace(WHITESPACE, "")
|
||||||
|
|
||||||
private fun startNodeInternal(legalName: X500Name,
|
private fun startNodeInternal(legalName: X500Name,
|
||||||
platformVersion: Int,
|
platformVersion: Int,
|
||||||
@ -187,7 +187,7 @@ abstract class NodeBasedTest : TestDependencyInjectionBase() {
|
|||||||
initialiseSerialization = false)
|
initialiseSerialization = false)
|
||||||
node.start()
|
node.start()
|
||||||
nodes += node
|
nodes += node
|
||||||
thread(name = legalName.commonName) {
|
thread(name = legalName.organisation) {
|
||||||
node.run()
|
node.run()
|
||||||
}
|
}
|
||||||
return node
|
return node
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
package net.corda.testing.node
|
package net.corda.testing.node
|
||||||
|
|
||||||
import com.codahale.metrics.MetricRegistry
|
import com.codahale.metrics.MetricRegistry
|
||||||
import net.corda.core.utilities.commonName
|
|
||||||
import net.corda.core.crypto.generateKeyPair
|
import net.corda.core.crypto.generateKeyPair
|
||||||
import net.corda.core.internal.concurrent.openFuture
|
import net.corda.core.internal.concurrent.openFuture
|
||||||
import net.corda.core.messaging.RPCOps
|
import net.corda.core.messaging.RPCOps
|
||||||
import net.corda.core.node.services.IdentityService
|
import net.corda.core.node.services.IdentityService
|
||||||
import net.corda.core.node.services.KeyManagementService
|
import net.corda.core.node.services.KeyManagementService
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
|
import net.corda.core.utilities.organisation
|
||||||
import net.corda.node.services.RPCUserServiceImpl
|
import net.corda.node.services.RPCUserServiceImpl
|
||||||
import net.corda.node.services.api.MonitoringService
|
import net.corda.node.services.api.MonitoringService
|
||||||
import net.corda.node.services.config.NodeConfiguration
|
import net.corda.node.services.config.NodeConfiguration
|
||||||
@ -21,10 +21,10 @@ import net.corda.node.utilities.AffinityExecutor.ServiceAffinityExecutor
|
|||||||
import net.corda.node.utilities.CordaPersistence
|
import net.corda.node.utilities.CordaPersistence
|
||||||
import net.corda.node.utilities.configureDatabase
|
import net.corda.node.utilities.configureDatabase
|
||||||
import net.corda.testing.freeLocalHostAndPort
|
import net.corda.testing.freeLocalHostAndPort
|
||||||
|
import net.corda.testing.node.MockServices.Companion.MOCK_VERSION_INFO
|
||||||
import java.security.KeyPair
|
import java.security.KeyPair
|
||||||
import java.security.cert.X509Certificate
|
import java.security.cert.X509Certificate
|
||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
import net.corda.testing.node.MockServices.Companion.MOCK_VERSION_INFO
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a bare-bones node which can only send and receive messages. It doesn't register with a network map service or
|
* This is a bare-bones node which can only send and receive messages. It doesn't register with a network map service or
|
||||||
@ -40,7 +40,7 @@ class SimpleNode(val config: NodeConfiguration, val address: NetworkHostAndPort
|
|||||||
val identityService: IdentityService = InMemoryIdentityService(trustRoot = trustRoot)
|
val identityService: IdentityService = InMemoryIdentityService(trustRoot = trustRoot)
|
||||||
val database: CordaPersistence = configureDatabase(config.dataSourceProperties, config.database, { NodeSchemaService() }, { InMemoryIdentityService(trustRoot = trustRoot) })
|
val database: CordaPersistence = configureDatabase(config.dataSourceProperties, config.database, { NodeSchemaService() }, { InMemoryIdentityService(trustRoot = trustRoot) })
|
||||||
val keyService: KeyManagementService = E2ETestKeyManagementService(identityService, setOf(identity))
|
val keyService: KeyManagementService = E2ETestKeyManagementService(identityService, setOf(identity))
|
||||||
val executor = ServiceAffinityExecutor(config.myLegalName.commonName, 1)
|
val executor = ServiceAffinityExecutor(config.myLegalName.organisation, 1)
|
||||||
// TODO: We should have a dummy service hub rather than change behaviour in tests
|
// TODO: We should have a dummy service hub rather than change behaviour in tests
|
||||||
val broker = ArtemisMessagingServer(config, address.port, rpcAddress.port,
|
val broker = ArtemisMessagingServer(config, address.port, rpcAddress.port,
|
||||||
MockNetworkMapCache(serviceHub = object : MockServiceHubInternal(database = database, configuration = config) {}), userService)
|
MockNetworkMapCache(serviceHub = object : MockServiceHubInternal(database = database, configuration = config) {}), userService)
|
||||||
@ -64,7 +64,7 @@ class SimpleNode(val config: NodeConfiguration, val address: NetworkHostAndPort
|
|||||||
override val protocolVersion = 0
|
override val protocolVersion = 0
|
||||||
},
|
},
|
||||||
userService)
|
userService)
|
||||||
thread(name = config.myLegalName.commonName) {
|
thread(name = config.myLegalName.organisation) {
|
||||||
network.run(broker.serverControl)
|
network.run(broker.serverControl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ 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.commonName
|
import net.corda.core.utilities.organisation
|
||||||
import net.corda.nodeapi.User
|
import net.corda.nodeapi.User
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
import org.bouncycastle.asn1.x500.X500Name
|
||||||
|
|
||||||
@ -22,7 +22,7 @@ class NodeConfig(
|
|||||||
val renderOptions: ConfigRenderOptions = ConfigRenderOptions.defaults().setOriginComments(false)
|
val renderOptions: ConfigRenderOptions = ConfigRenderOptions.defaults().setOriginComments(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
val commonName: String get() = legalName.commonName
|
val commonName: String get() = legalName.organisation
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The configuration object depends upon the networkMap,
|
* The configuration object depends upon the networkMap,
|
||||||
|
@ -4,14 +4,12 @@
|
|||||||
package net.corda.testing
|
package net.corda.testing
|
||||||
|
|
||||||
import net.corda.core.contracts.StateRef
|
import net.corda.core.contracts.StateRef
|
||||||
import net.corda.core.crypto.*
|
import net.corda.core.crypto.SecureHash
|
||||||
|
import net.corda.core.crypto.generateKeyPair
|
||||||
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.utilities.*
|
import net.corda.core.utilities.*
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
|
||||||
import net.corda.core.utilities.OpaqueBytes
|
|
||||||
import net.corda.core.utilities.loggerFor
|
|
||||||
import net.corda.finance.contracts.asset.DUMMY_CASH_ISSUER
|
import net.corda.finance.contracts.asset.DUMMY_CASH_ISSUER
|
||||||
import net.corda.node.services.config.configureDevKeyAndTrustStores
|
import net.corda.node.services.config.configureDevKeyAndTrustStores
|
||||||
import net.corda.node.services.identity.InMemoryIdentityService
|
import net.corda.node.services.identity.InMemoryIdentityService
|
||||||
@ -20,8 +18,6 @@ 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 org.bouncycastle.asn1.x500.X500Name
|
||||||
import org.bouncycastle.asn1.x500.X500NameBuilder
|
|
||||||
import org.bouncycastle.asn1.x500.style.BCStyle
|
|
||||||
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
|
||||||
@ -62,20 +58,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(getX509Name("MegaCorp", "London", "demo@r3.com", null), MEGA_CORP_PUBKEY)
|
val MEGA_CORP_IDENTITY: PartyAndCertificate get() = getTestPartyAndCertificate(getX500Name(O = "MegaCorp", L = "London", C = "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(getX509Name("MiniCorp", "London", "demo@r3.com", null), MINI_CORP_PUBKEY)
|
val MINI_CORP_IDENTITY: PartyAndCertificate get() = getTestPartyAndCertificate(getX500Name(O = "MiniCorp", L = "London", C = "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(getTestX509Name("BankOfCorda"), BOC_PUBKEY)
|
val BOC_IDENTITY: PartyAndCertificate get() = getTestPartyAndCertificate(getX500Name(O = "BankOfCorda", L = "London", C = "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(getX509Name("BigCorporation", "London", "demo@r3.com", null), BIG_CORP_PUBKEY)
|
val BIG_CORP_IDENTITY: PartyAndCertificate get() = getTestPartyAndCertificate(getX500Name(O = "BigCorporation", L = "London", C = "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
|
||||||
|
|
||||||
@ -129,21 +125,6 @@ fun configureTestSSL(legalName: X500Name = MEGA_CORP.name): SSLConfiguration = o
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a bogus X.509 for testing purposes.
|
|
||||||
*/
|
|
||||||
fun getTestX509Name(commonName: String): X500Name {
|
|
||||||
require(!commonName.startsWith("CN="))
|
|
||||||
// TODO: Consider if we want to make these more variable, i.e. different locations?
|
|
||||||
val nameBuilder = X500NameBuilder(BCStyle.INSTANCE)
|
|
||||||
nameBuilder.addRDN(BCStyle.CN, commonName)
|
|
||||||
nameBuilder.addRDN(BCStyle.O, "R3")
|
|
||||||
nameBuilder.addRDN(BCStyle.L, "New York")
|
|
||||||
nameBuilder.addRDN(BCStyle.C, "US")
|
|
||||||
return nameBuilder.build()
|
|
||||||
}
|
|
||||||
|
|
||||||
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, party.owningKey)
|
||||||
|
@ -4,13 +4,13 @@ package net.corda.testing
|
|||||||
|
|
||||||
import net.corda.core.contracts.Command
|
import net.corda.core.contracts.Command
|
||||||
import net.corda.core.contracts.TypeOnlyCommandData
|
import net.corda.core.contracts.TypeOnlyCommandData
|
||||||
import net.corda.core.utilities.CertificateAndKeyPair
|
|
||||||
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.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.identity.PartyAndCertificate
|
import net.corda.core.identity.PartyAndCertificate
|
||||||
|
import net.corda.core.utilities.CertificateAndKeyPair
|
||||||
|
import net.corda.core.utilities.getX500Name
|
||||||
import net.corda.node.utilities.X509Utilities
|
import net.corda.node.utilities.X509Utilities
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import java.math.BigInteger
|
import java.math.BigInteger
|
||||||
import java.security.KeyPair
|
import java.security.KeyPair
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
@ -25,47 +25,47 @@ 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(X500Name("CN=Notary Service,O=R3,OU=corda,L=Zurich,C=CH"), DUMMY_NOTARY_KEY.public)
|
val DUMMY_NOTARY: Party get() = Party(getX500Name(O = "Notary Service", OU = "corda", L = "Zurich", C = "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(X500Name("CN=Network Map Service,O=R3,OU=corda,L=Amsterdam,C=NL"), DUMMY_MAP_KEY.public)
|
val DUMMY_MAP: Party get() = Party(getX500Name(O = "Network Map Service", OU = "corda", L = "Amsterdam", C = "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(X500Name("CN=Bank A,O=Bank A,L=London,C=GB"), DUMMY_BANK_A_KEY.public)
|
val DUMMY_BANK_A: Party get() = Party(getX500Name(O = "Bank A", L = "London", C = "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(X500Name("CN=Bank B,O=Bank B,L=New York,C=US"), DUMMY_BANK_B_KEY.public)
|
val DUMMY_BANK_B: Party get() = Party(getX500Name(O = "Bank B", L = "New York", C = "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(X500Name("CN=Bank C,O=Bank C,L=Tokyo,C=JP"), DUMMY_BANK_C_KEY.public)
|
val DUMMY_BANK_C: Party get() = Party(getX500Name(O = "Bank C", L = "Tokyo", C = "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(X500Name("CN=Alice Corp,O=Alice Corp,L=Madrid,C=ES"), ALICE_KEY.public)
|
val ALICE: Party get() = Party(getX500Name(O = "Alice Corp", L = "Madrid", C = "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(X500Name("CN=Bob Plc,O=Bob Plc,L=Rome,C=IT"), BOB_KEY.public)
|
val BOB: Party get() = Party(getX500Name(O = "Bob Plc", L = "Rome", C = "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(X500Name("CN=Charlie Ltd,O=Charlie Ltd,L=Athens,C=GR"), CHARLIE_KEY.public)
|
val CHARLIE: Party get() = Party(getX500Name(O = "Charlie Ltd", L = "Athens", C = "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(X500Name("CN=Regulator A,OU=Corda,O=AMF,L=Paris,C=FR"), DUMMY_REGULATOR_KEY.public)
|
val DUMMY_REGULATOR: Party get() = Party(getX500Name(O = "Regulator A", OU = "Corda", L = "Paris", C = "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 {
|
||||||
// TODO: Should be identity scheme
|
// TODO: Should be identity scheme
|
||||||
val cert = X509Utilities.createSelfSignedCACertificate(X500Name("CN=Dummy CA,OU=Corda,O=R3 Ltd,L=London,C=GB"), DUMMY_CA_KEY)
|
val cert = X509Utilities.createSelfSignedCACertificate(getX500Name(CN = "Dummy CA", OU = "Corda", O = "R3 Ltd", L = "London", C = "GB"), DUMMY_CA_KEY)
|
||||||
CertificateAndKeyPair(cert, DUMMY_CA_KEY)
|
CertificateAndKeyPair(cert, DUMMY_CA_KEY)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,4 +74,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(X500Name("CN=Dummy,O=Dummy,L=Madrid,C=ES"), DUMMY_KEY_1.public)
|
val DUMMY_PARTY: Party get() = Party(getX500Name(O = "Dummy", L = "Madrid", C = "ES"), DUMMY_KEY_1.public)
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
package net.corda.testing.messaging
|
package net.corda.testing.messaging
|
||||||
|
|
||||||
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
|
||||||
import net.corda.nodeapi.config.SSLConfiguration
|
import net.corda.nodeapi.config.SSLConfiguration
|
||||||
import net.corda.testing.configureTestSSL
|
import net.corda.testing.configureTestSSL
|
||||||
import org.apache.activemq.artemis.api.core.client.*
|
import org.apache.activemq.artemis.api.core.client.*
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* As the name suggests this is a simple client for connecting to MQ brokers.
|
* As the name suggests this is a simple client for connecting to MQ brokers.
|
||||||
@ -15,7 +15,7 @@ import org.bouncycastle.asn1.x500.X500Name
|
|||||||
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 = X500Name("CN=SimpleMQClient,O=R3,OU=corda,L=London,C=GB")
|
val DEFAULT_MQ_LEGAL_NAME = getX500Name(O = "SimpleMQClient", OU = "corda", L = "London", C = "GB")
|
||||||
}
|
}
|
||||||
lateinit var sessionFactory: ClientSessionFactory
|
lateinit var sessionFactory: ClientSessionFactory
|
||||||
lateinit var session: ClientSession
|
lateinit var session: ClientSession
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
package net.corda.demobench.model
|
package net.corda.demobench.model
|
||||||
|
|
||||||
import net.corda.core.utilities.commonName
|
import net.corda.core.utilities.organisation
|
||||||
import net.corda.core.utilities.WHITESPACE
|
import net.corda.core.utilities.WHITESPACE
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
import org.bouncycastle.asn1.x500.X500Name
|
||||||
|
|
||||||
open class NetworkMapConfig(val legalName: X500Name, val p2pPort: Int) {
|
open class NetworkMapConfig(val legalName: X500Name, val p2pPort: Int) {
|
||||||
|
val key: String = legalName.organisation.toKey()
|
||||||
val key: String = legalName.commonName.toKey()
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun String.stripWhitespace() = replace(WHITESPACE, "")
|
fun String.stripWhitespace() = replace(WHITESPACE, "")
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package net.corda.demobench.model
|
package net.corda.demobench.model
|
||||||
|
|
||||||
import com.typesafe.config.*
|
import com.typesafe.config.*
|
||||||
import net.corda.core.utilities.locationOrNull
|
import net.corda.core.utilities.locality
|
||||||
import net.corda.nodeapi.User
|
import net.corda.nodeapi.User
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
import org.bouncycastle.asn1.x500.X500Name
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@ -26,7 +26,7 @@ class NodeConfig(
|
|||||||
val defaultUser = user("guest")
|
val defaultUser = user("guest")
|
||||||
}
|
}
|
||||||
|
|
||||||
val nearestCity: String = legalName.locationOrNull ?: "Unknown location"
|
val nearestCity: String = legalName.locality
|
||||||
val nodeDir: Path = baseDir.resolve(key)
|
val nodeDir: Path = baseDir.resolve(key)
|
||||||
override val pluginDir: Path = nodeDir.resolve("plugins")
|
override val pluginDir: Path = nodeDir.resolve("plugins")
|
||||||
val explorerDir: Path = baseDir.resolve("$key-explorer")
|
val explorerDir: Path = baseDir.resolve("$key-explorer")
|
||||||
|
@ -2,7 +2,7 @@ package net.corda.demobench.model
|
|||||||
|
|
||||||
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.getX509Name
|
import net.corda.core.utilities.getX500Name
|
||||||
import net.corda.demobench.plugin.PluginController
|
import net.corda.demobench.plugin.PluginController
|
||||||
import net.corda.demobench.pty.R3Pty
|
import net.corda.demobench.pty.R3Pty
|
||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
@ -54,11 +54,10 @@ class NodeController(check: atRuntime = ::checkExists) : Controller() {
|
|||||||
val location = nodeData.nearestCity.value
|
val location = nodeData.nearestCity.value
|
||||||
val config = NodeConfig(
|
val config = NodeConfig(
|
||||||
baseDir,
|
baseDir,
|
||||||
getX509Name(
|
getX500Name(
|
||||||
myLegalName = nodeData.legalName.value.trim(),
|
O = nodeData.legalName.value.trim(),
|
||||||
email = "corda@city.${location.countryCode.toLowerCase()}.example",
|
L = location.description,
|
||||||
nearestCity = location.description,
|
C = location.countryCode
|
||||||
country = location.countryCode
|
|
||||||
),
|
),
|
||||||
nodeData.p2pPort.value,
|
nodeData.p2pPort.value,
|
||||||
nodeData.rpcPort.value,
|
nodeData.rpcPort.value,
|
||||||
|
@ -4,8 +4,8 @@ import com.jediterm.terminal.ui.JediTermWidget
|
|||||||
import com.jediterm.terminal.ui.UIUtil
|
import com.jediterm.terminal.ui.UIUtil
|
||||||
import com.jediterm.terminal.ui.settings.SettingsProvider
|
import com.jediterm.terminal.ui.settings.SettingsProvider
|
||||||
import com.pty4j.PtyProcess
|
import com.pty4j.PtyProcess
|
||||||
import net.corda.core.utilities.commonName
|
|
||||||
import net.corda.core.utilities.loggerFor
|
import net.corda.core.utilities.loggerFor
|
||||||
|
import net.corda.core.utilities.organisation
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
import org.bouncycastle.asn1.x500.X500Name
|
||||||
import java.awt.Dimension
|
import java.awt.Dimension
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
@ -34,7 +34,7 @@ class R3Pty(val name: X500Name, settings: SettingsProvider, dimension: Dimension
|
|||||||
val process = PtyProcess.exec(command, environment, workingDir)
|
val process = PtyProcess.exec(command, environment, workingDir)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return PtyProcessTtyConnector(name.commonName, process, UTF_8)
|
return PtyProcessTtyConnector(name.organisation, process, UTF_8)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
process.destroyForcibly()
|
process.destroyForcibly()
|
||||||
process.waitFor(30, SECONDS)
|
process.waitFor(30, SECONDS)
|
||||||
|
@ -20,8 +20,8 @@ import net.corda.core.internal.readAllLines
|
|||||||
import net.corda.core.internal.writeLines
|
import net.corda.core.internal.writeLines
|
||||||
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.utilities.commonName
|
|
||||||
import net.corda.core.utilities.normaliseLegalName
|
import net.corda.core.utilities.normaliseLegalName
|
||||||
|
import net.corda.core.utilities.organisation
|
||||||
import net.corda.core.utilities.validateLegalName
|
import net.corda.core.utilities.validateLegalName
|
||||||
import net.corda.demobench.model.*
|
import net.corda.demobench.model.*
|
||||||
import net.corda.demobench.ui.CloseableTab
|
import net.corda.demobench.ui.CloseableTab
|
||||||
@ -267,7 +267,7 @@ class NodeTabView : Fragment() {
|
|||||||
if (countryCode != null) {
|
if (countryCode != null) {
|
||||||
nodeTab.graphic = ImageView(flags.get()[countryCode]).apply { fitWidth = 24.0; isPreserveRatio = true }
|
nodeTab.graphic = ImageView(flags.get()[countryCode]).apply { fitWidth = 24.0; isPreserveRatio = true }
|
||||||
}
|
}
|
||||||
nodeTab.text = config.legalName.commonName
|
nodeTab.text = config.legalName.organisation
|
||||||
nodeTerminalView.open(config) { exitCode ->
|
nodeTerminalView.open(config) { exitCode ->
|
||||||
Platform.runLater {
|
Platform.runLater {
|
||||||
if (exitCode == 0) {
|
if (exitCode == 0) {
|
||||||
|
@ -15,7 +15,7 @@ import javafx.scene.layout.VBox
|
|||||||
import javafx.util.Duration
|
import javafx.util.Duration
|
||||||
import net.corda.core.concurrent.match
|
import net.corda.core.concurrent.match
|
||||||
import net.corda.core.contracts.ContractState
|
import net.corda.core.contracts.ContractState
|
||||||
import net.corda.core.utilities.commonName
|
import net.corda.core.utilities.organisation
|
||||||
import net.corda.core.messaging.CordaRPCOps
|
import net.corda.core.messaging.CordaRPCOps
|
||||||
import net.corda.core.messaging.vaultTrackBy
|
import net.corda.core.messaging.vaultTrackBy
|
||||||
import net.corda.core.node.services.vault.PageSpecification
|
import net.corda.core.node.services.vault.PageSpecification
|
||||||
@ -71,7 +71,7 @@ class NodeTerminalView : Fragment() {
|
|||||||
private lateinit var swingTerminal: SwingNode
|
private lateinit var swingTerminal: SwingNode
|
||||||
|
|
||||||
fun open(config: NodeConfig, onExit: (Int) -> Unit) {
|
fun open(config: NodeConfig, onExit: (Int) -> Unit) {
|
||||||
nodeName.text = config.legalName.commonName
|
nodeName.text = config.legalName.organisation
|
||||||
|
|
||||||
swingTerminal = SwingNode()
|
swingTerminal = SwingNode()
|
||||||
swingTerminal.setOnMouseClicked {
|
swingTerminal.setOnMouseClicked {
|
||||||
|
@ -8,7 +8,7 @@ class NetworkMapConfigTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun keyValue() {
|
fun keyValue() {
|
||||||
val config = NetworkMapConfig(X500Name("CN=My\tNasty Little\rLabel\n"), 10000)
|
val config = NetworkMapConfig(X500Name("O=My\tNasty Little\rLabel\n"), 10000)
|
||||||
assertEquals("mynastylittlelabel", config.key)
|
assertEquals("mynastylittlelabel", config.key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,11 +7,12 @@ import com.typesafe.config.ConfigFactory
|
|||||||
import com.typesafe.config.ConfigValueFactory
|
import com.typesafe.config.ConfigValueFactory
|
||||||
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.testing.DUMMY_NOTARY
|
import net.corda.core.utilities.getX500Name
|
||||||
import net.corda.node.internal.NetworkMapInfo
|
import net.corda.node.internal.NetworkMapInfo
|
||||||
import net.corda.node.services.config.FullNodeConfiguration
|
import net.corda.node.services.config.FullNodeConfiguration
|
||||||
import net.corda.nodeapi.User
|
import net.corda.nodeapi.User
|
||||||
import net.corda.nodeapi.config.parseAs
|
import net.corda.nodeapi.config.parseAs
|
||||||
|
import net.corda.testing.DUMMY_NOTARY
|
||||||
import net.corda.webserver.WebServerConfig
|
import net.corda.webserver.WebServerConfig
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
import org.bouncycastle.asn1.x500.X500Name
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
@ -28,7 +29,7 @@ class NodeConfigTest {
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val baseDir: Path = Paths.get(".").toAbsolutePath()
|
private val baseDir: Path = Paths.get(".").toAbsolutePath()
|
||||||
private val myLegalName = X500Name("CN=My Name,OU=Corda QA Department,O=R3 CEV,L=New York,C=US")
|
private val myLegalName = getX500Name(OU = "Corda QA Department", O = "My Name", L = "New York", C = "US")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -145,7 +146,7 @@ class NodeConfigTest {
|
|||||||
+ "\"detectPublicIp\":false,"
|
+ "\"detectPublicIp\":false,"
|
||||||
+ "\"extraAdvertisedServiceIds\":[\"my.service\"],"
|
+ "\"extraAdvertisedServiceIds\":[\"my.service\"],"
|
||||||
+ "\"h2port\":30001,"
|
+ "\"h2port\":30001,"
|
||||||
+ "\"myLegalName\":\"CN=My Name,OU=Corda QA Department,O=R3 CEV,L=New York,C=US\","
|
+ "\"myLegalName\":\"C=US,L=New York,O=My Name,OU=Corda QA Department\","
|
||||||
+ "\"p2pAddress\":\"localhost:10001\","
|
+ "\"p2pAddress\":\"localhost:10001\","
|
||||||
+ "\"rpcAddress\":\"localhost:40002\","
|
+ "\"rpcAddress\":\"localhost:40002\","
|
||||||
+ "\"rpcUsers\":["
|
+ "\"rpcUsers\":["
|
||||||
@ -173,8 +174,8 @@ class NodeConfigTest {
|
|||||||
+ "\"detectPublicIp\":false,"
|
+ "\"detectPublicIp\":false,"
|
||||||
+ "\"extraAdvertisedServiceIds\":[\"my.service\"],"
|
+ "\"extraAdvertisedServiceIds\":[\"my.service\"],"
|
||||||
+ "\"h2port\":30001,"
|
+ "\"h2port\":30001,"
|
||||||
+ "\"myLegalName\":\"CN=My Name,OU=Corda QA Department,O=R3 CEV,L=New York,C=US\","
|
+ "\"myLegalName\":\"C=US,L=New York,O=My Name,OU=Corda QA Department\","
|
||||||
+ "\"networkMapService\":{\"address\":\"localhost:12345\",\"legalName\":\"CN=Notary Service,O=R3,OU=corda,L=Zurich,C=CH\"},"
|
+ "\"networkMapService\":{\"address\":\"localhost:12345\",\"legalName\":\"C=CH,L=Zurich,O=Notary Service,OU=corda\"},"
|
||||||
+ "\"p2pAddress\":\"localhost:10001\","
|
+ "\"p2pAddress\":\"localhost:10001\","
|
||||||
+ "\"rpcAddress\":\"localhost:40002\","
|
+ "\"rpcAddress\":\"localhost:40002\","
|
||||||
+ "\"rpcUsers\":["
|
+ "\"rpcUsers\":["
|
||||||
@ -252,7 +253,7 @@ class NodeConfigTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun createConfig(
|
private fun createConfig(
|
||||||
legalName: X500Name = X500Name("CN=Unknown,O=R3,OU=corda,L=Nowhere,C=GB"),
|
legalName: X500Name = getX500Name(O = "Unknown", OU = "corda", L = "Nowhere", C = "GB"),
|
||||||
p2pPort: Int = -1,
|
p2pPort: Int = -1,
|
||||||
rpcPort: Int = -1,
|
rpcPort: Int = -1,
|
||||||
webPort: Int = -1,
|
webPort: Int = -1,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package net.corda.demobench.model
|
package net.corda.demobench.model
|
||||||
|
|
||||||
import net.corda.core.utilities.getX509Name
|
import net.corda.core.utilities.getX500Name
|
||||||
import net.corda.nodeapi.User
|
import net.corda.nodeapi.User
|
||||||
import net.corda.testing.DUMMY_NOTARY
|
import net.corda.testing.DUMMY_NOTARY
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
@ -174,11 +174,10 @@ class NodeControllerTest {
|
|||||||
users: List<User> = listOf(user("guest"))
|
users: List<User> = listOf(user("guest"))
|
||||||
) = NodeConfig(
|
) = NodeConfig(
|
||||||
baseDir,
|
baseDir,
|
||||||
legalName = getX509Name(
|
legalName = getX500Name(
|
||||||
myLegalName = commonName,
|
O = commonName,
|
||||||
nearestCity = "New York",
|
L = "New York",
|
||||||
country = "US",
|
C = "US"
|
||||||
email = "corda@city.us.example"
|
|
||||||
),
|
),
|
||||||
p2pPort = p2pPort,
|
p2pPort = p2pPort,
|
||||||
rpcPort = rpcPort,
|
rpcPort = rpcPort,
|
||||||
|
@ -16,6 +16,7 @@ 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.OpaqueBytes
|
import net.corda.core.utilities.OpaqueBytes
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
|
import net.corda.core.utilities.getX500Name
|
||||||
import net.corda.finance.GBP
|
import net.corda.finance.GBP
|
||||||
import net.corda.finance.USD
|
import net.corda.finance.USD
|
||||||
import net.corda.finance.contracts.asset.Cash
|
import net.corda.finance.contracts.asset.Cash
|
||||||
@ -34,7 +35,6 @@ import net.corda.testing.DUMMY_NOTARY
|
|||||||
import net.corda.testing.driver.NodeHandle
|
import net.corda.testing.driver.NodeHandle
|
||||||
import net.corda.testing.driver.PortAllocation
|
import net.corda.testing.driver.PortAllocation
|
||||||
import net.corda.testing.driver.driver
|
import net.corda.testing.driver.driver
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@ -79,8 +79,8 @@ class ExplorerSimulation(val options: OptionSet) {
|
|||||||
val bob = startNode(providedName = BOB.name, rpcUsers = arrayListOf(user),
|
val bob = startNode(providedName = BOB.name, rpcUsers = arrayListOf(user),
|
||||||
advertisedServices = setOf(ServiceInfo(ServiceType.corda.getSubType("cash"))),
|
advertisedServices = setOf(ServiceInfo(ServiceType.corda.getSubType("cash"))),
|
||||||
customOverrides = mapOf("nearestCity" to "Madrid"))
|
customOverrides = mapOf("nearestCity" to "Madrid"))
|
||||||
val ukBankName = X500Name("CN=UK Bank Plc,O=UK Bank Plc,L=London,C=GB")
|
val ukBankName = getX500Name(O = "UK Bank Plc", L = "London", C = "GB")
|
||||||
val usaBankName = X500Name("CN=USA Bank Corp,O=USA Bank Corp,L=New York,C=USA")
|
val usaBankName = getX500Name(O = "USA Bank Corp", L = "New York", C = "USA")
|
||||||
val issuerGBP = startNode(providedName = ukBankName, rpcUsers = arrayListOf(manager),
|
val issuerGBP = startNode(providedName = ukBankName, rpcUsers = arrayListOf(manager),
|
||||||
advertisedServices = setOf(ServiceInfo(ServiceType.corda.getSubType("issuer.GBP"))),
|
advertisedServices = setOf(ServiceInfo(ServiceType.corda.getSubType("issuer.GBP"))),
|
||||||
customOverrides = mapOf("nearestCity" to "London"))
|
customOverrides = mapOf("nearestCity" to "London"))
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
package net.corda.explorer.formatters
|
package net.corda.explorer.formatters
|
||||||
|
|
||||||
import net.corda.core.utilities.commonName
|
import net.corda.core.utilities.organisation
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
import org.bouncycastle.asn1.x500.X500Name
|
||||||
|
|
||||||
object PartyNameFormatter {
|
object PartyNameFormatter {
|
||||||
val short = object : Formatter<X500Name> {
|
val short = object : Formatter<X500Name> {
|
||||||
override fun format(value: X500Name) = value.commonName
|
override fun format(value: X500Name) = value.organisation
|
||||||
}
|
}
|
||||||
|
|
||||||
val full = object : Formatter<X500Name> {
|
val full = object : Formatter<X500Name> {
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user