mirror of
https://github.com/corda/corda.git
synced 2024-12-25 15:41:10 +00:00
Refactoring related to BFT notary demo (#680)
* Fix: Add missing @StartableByRPC to fix the Raft notary demo * Make loadConfig take a Config object, for cordformation Node * Unduplicate User.toMap * Unduplicate WHITESPACE regex, choose possessive form * Use slash to make a Path * Remove Companion where redundant * Remove unused code
This commit is contained in:
parent
42d0a3c638
commit
d3bb040355
@ -46,9 +46,3 @@ class NodeConfig(
|
|||||||
return if (obj == null) config else body(config, obj).atPath(path)
|
return if (obj == null) config else body(config, obj).atPath(path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun User.toMap(): Map<String, Any> = mapOf(
|
|
||||||
"username" to username,
|
|
||||||
"password" to password,
|
|
||||||
"permissions" to permissions
|
|
||||||
)
|
|
||||||
|
@ -136,7 +136,8 @@ fun <A> ListenableFuture<out A>.toObservable(): Observable<A> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Allows you to write code like: Paths.get("someDir") / "subdir" / "filename" but using the Paths API to avoid platform separator problems. */
|
/** Allows you to write code like: Paths.get("someDir") / "subdir" / "filename" but using the Paths API to avoid platform separator problems. */
|
||||||
operator fun Path.div(other: String): Path = resolve(other)
|
operator fun Path.div(other: String) = resolve(other)
|
||||||
|
operator fun String.div(other: String) = Paths.get(this) / other
|
||||||
|
|
||||||
fun Path.createDirectory(vararg attrs: FileAttribute<*>): Path = Files.createDirectory(this, *attrs)
|
fun Path.createDirectory(vararg attrs: FileAttribute<*>): Path = Files.createDirectory(this, *attrs)
|
||||||
fun Path.createDirectories(vararg attrs: FileAttribute<*>): Path = Files.createDirectories(this, *attrs)
|
fun Path.createDirectories(vararg attrs: FileAttribute<*>): Path = Files.createDirectories(this, *attrs)
|
||||||
|
@ -24,12 +24,14 @@ fun validateLegalName(normalizedLegalName: String) {
|
|||||||
rules.forEach { it.validate(normalizedLegalName) }
|
rules.forEach { it.validate(normalizedLegalName) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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.
|
||||||
*/
|
*/
|
||||||
fun normaliseLegalName(legalName: String): String {
|
fun normaliseLegalName(legalName: String): String {
|
||||||
val trimmedLegalName = legalName.trim().replace(Regex("\\s+"), " ")
|
val trimmedLegalName = legalName.trim().replace(WHITESPACE, " ")
|
||||||
return Normalizer.normalize(trimmedLegalName, Normalizer.Form.NFKC)
|
return Normalizer.normalize(trimmedLegalName, Normalizer.Form.NFKC)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ class PartialMerkleTreeTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `building Merkle tree - no hashes`() {
|
fun `building Merkle tree - no hashes`() {
|
||||||
assertFailsWith<MerkleTreeException> { MerkleTree.Companion.getMerkleTree(emptyList()) }
|
assertFailsWith<MerkleTreeException> { MerkleTree.getMerkleTree(emptyList()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -71,7 +71,7 @@ class SecureHashGenerator : Generator<SecureHash>(SecureHash::class.java) {
|
|||||||
|
|
||||||
class StateRefGenerator : Generator<StateRef>(StateRef::class.java) {
|
class StateRefGenerator : Generator<StateRef>(StateRef::class.java) {
|
||||||
override fun generate(random: SourceOfRandomness, status: GenerationStatus): StateRef {
|
override fun generate(random: SourceOfRandomness, status: GenerationStatus): StateRef {
|
||||||
return StateRef(SecureHash.Companion.sha256(random.nextBytes(16)), random.nextInt(0, 10))
|
return StateRef(SecureHash.sha256(random.nextBytes(16)), random.nextInt(0, 10))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ class ObligationTests {
|
|||||||
val defaultRef = OpaqueBytes(ByteArray(1, { 1 }))
|
val defaultRef = OpaqueBytes(ByteArray(1, { 1 }))
|
||||||
val defaultIssuer = MEGA_CORP.ref(defaultRef)
|
val defaultIssuer = MEGA_CORP.ref(defaultRef)
|
||||||
val oneMillionDollars = 1000000.DOLLARS `issued by` defaultIssuer
|
val oneMillionDollars = 1000000.DOLLARS `issued by` defaultIssuer
|
||||||
val trustedCashContract = nonEmptySetOf(SecureHash.Companion.randomSHA256() as SecureHash)
|
val trustedCashContract = nonEmptySetOf(SecureHash.randomSHA256() as SecureHash)
|
||||||
val megaIssuedDollars = nonEmptySetOf(Issued(defaultIssuer, USD))
|
val megaIssuedDollars = nonEmptySetOf(Issued(defaultIssuer, USD))
|
||||||
val megaIssuedPounds = nonEmptySetOf(Issued(defaultIssuer, GBP))
|
val megaIssuedPounds = nonEmptySetOf(Issued(defaultIssuer, GBP))
|
||||||
val fivePm = TEST_TX_TIME.truncatedTo(ChronoUnit.DAYS).plus(17, ChronoUnit.HOURS)
|
val fivePm = TEST_TX_TIME.truncatedTo(ChronoUnit.DAYS).plus(17, ChronoUnit.HOURS)
|
||||||
@ -759,7 +759,7 @@ class ObligationTests {
|
|||||||
|
|
||||||
// States must not be nettable if the cash contract differs
|
// States must not be nettable if the cash contract differs
|
||||||
assertNotEquals(fiveKDollarsFromMegaToMega.bilateralNetState,
|
assertNotEquals(fiveKDollarsFromMegaToMega.bilateralNetState,
|
||||||
fiveKDollarsFromMegaToMega.copy(template = megaCorpDollarSettlement.copy(acceptableContracts = nonEmptySetOf(SecureHash.Companion.randomSHA256()))).bilateralNetState)
|
fiveKDollarsFromMegaToMega.copy(template = megaCorpDollarSettlement.copy(acceptableContracts = nonEmptySetOf(SecureHash.randomSHA256()))).bilateralNetState)
|
||||||
|
|
||||||
// States must not be nettable if the trusted issuers differ
|
// States must not be nettable if the trusted issuers differ
|
||||||
val miniCorpIssuer = nonEmptySetOf(Issued(MINI_CORP.ref(1), USD))
|
val miniCorpIssuer = nonEmptySetOf(Issued(MINI_CORP.ref(1), USD))
|
||||||
|
@ -40,7 +40,7 @@ class IssuerFlowTest {
|
|||||||
bankClientNode = net.createPartyNode(notaryNode.info.address, MEGA_CORP.name)
|
bankClientNode = net.createPartyNode(notaryNode.info.address, MEGA_CORP.name)
|
||||||
|
|
||||||
// using default IssueTo Party Reference
|
// using default IssueTo Party Reference
|
||||||
val issueToPartyAndRef = bankClientNode.info.legalIdentity.ref(OpaqueBytes.Companion.of(123))
|
val issueToPartyAndRef = bankClientNode.info.legalIdentity.ref(OpaqueBytes.of(123))
|
||||||
val (issuer, issuerResult) = runIssuerAndIssueRequester(bankOfCordaNode, bankClientNode, 1000000.DOLLARS, issueToPartyAndRef)
|
val (issuer, issuerResult) = runIssuerAndIssueRequester(bankOfCordaNode, bankClientNode, 1000000.DOLLARS, issueToPartyAndRef)
|
||||||
assertEquals(issuerResult.get(), issuer.get().resultFuture.get())
|
assertEquals(issuerResult.get(), issuer.get().resultFuture.get())
|
||||||
|
|
||||||
@ -62,7 +62,7 @@ class IssuerFlowTest {
|
|||||||
bankOfCordaNode = net.createPartyNode(notaryNode.info.address, BOC.name)
|
bankOfCordaNode = net.createPartyNode(notaryNode.info.address, BOC.name)
|
||||||
|
|
||||||
// using default IssueTo Party Reference
|
// using default IssueTo Party Reference
|
||||||
val issueToPartyAndRef = bankOfCordaNode.info.legalIdentity.ref(OpaqueBytes.Companion.of(123))
|
val issueToPartyAndRef = bankOfCordaNode.info.legalIdentity.ref(OpaqueBytes.of(123))
|
||||||
val (issuer, issuerResult) = runIssuerAndIssueRequester(bankOfCordaNode, bankOfCordaNode, 1000000.DOLLARS, issueToPartyAndRef)
|
val (issuer, issuerResult) = runIssuerAndIssueRequester(bankOfCordaNode, bankOfCordaNode, 1000000.DOLLARS, issueToPartyAndRef)
|
||||||
assertEquals(issuerResult.get(), issuer.get().resultFuture.get())
|
assertEquals(issuerResult.get(), issuer.get().resultFuture.get())
|
||||||
|
|
||||||
@ -80,7 +80,7 @@ class IssuerFlowTest {
|
|||||||
bankClientNode = net.createPartyNode(notaryNode.info.address, MEGA_CORP.name)
|
bankClientNode = net.createPartyNode(notaryNode.info.address, MEGA_CORP.name)
|
||||||
|
|
||||||
// using default IssueTo Party Reference
|
// using default IssueTo Party Reference
|
||||||
val issueToPartyAndRef = bankClientNode.info.legalIdentity.ref(OpaqueBytes.Companion.of(123))
|
val issueToPartyAndRef = bankClientNode.info.legalIdentity.ref(OpaqueBytes.of(123))
|
||||||
|
|
||||||
// this test exercises the Cashflow issue and move subflows to ensure consistent spending of issued states
|
// this test exercises the Cashflow issue and move subflows to ensure consistent spending of issued states
|
||||||
val amount = 10000.DOLLARS
|
val amount = 10000.DOLLARS
|
||||||
|
@ -18,6 +18,11 @@ data class User(
|
|||||||
val password: String,
|
val password: String,
|
||||||
val permissions: Set<String>) {
|
val permissions: Set<String>) {
|
||||||
override fun toString(): String = "${javaClass.simpleName}($username, permissions=$permissions)"
|
override fun toString(): String = "${javaClass.simpleName}($username, permissions=$permissions)"
|
||||||
|
fun toMap() = mapOf(
|
||||||
|
"username" to username,
|
||||||
|
"password" to password,
|
||||||
|
"permissions" to permissions
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Records the protocol version in which this RPC was added. */
|
/** Records the protocol version in which this RPC was added. */
|
||||||
|
@ -12,12 +12,10 @@ import org.bouncycastle.asn1.x500.X500Name
|
|||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.nio.file.Paths
|
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.reflect.full.primaryConstructor
|
import kotlin.reflect.full.primaryConstructor
|
||||||
import kotlin.test.assertEquals
|
|
||||||
|
|
||||||
class ConfigParsingTest {
|
class ConfigParsingTest {
|
||||||
@Test
|
@Test
|
||||||
@ -70,7 +68,7 @@ class ConfigParsingTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `Path`() {
|
fun `Path`() {
|
||||||
val path = Paths.get("tmp") / "test"
|
val path = "tmp" / "test"
|
||||||
testPropertyType<PathData, PathListData, Path>(path, path / "file", valuesToString = true)
|
testPropertyType<PathData, PathListData, Path>(path, path / "file", valuesToString = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,9 +65,7 @@ data class CmdLineOptions(val baseDirectory: Path,
|
|||||||
val isVersion: Boolean,
|
val isVersion: Boolean,
|
||||||
val noLocalShell: Boolean,
|
val noLocalShell: Boolean,
|
||||||
val sshdServer: Boolean) {
|
val sshdServer: Boolean) {
|
||||||
fun loadConfig(allowMissingConfig: Boolean = false, configOverrides: Map<String, Any?> = emptyMap()): FullNodeConfiguration {
|
fun loadConfig() = ConfigHelper
|
||||||
return ConfigHelper
|
.loadConfig(baseDirectory, configFile)
|
||||||
.loadConfig(baseDirectory, configFile, allowMissingConfig, configOverrides)
|
|
||||||
.parseAs<FullNodeConfiguration>()
|
.parseAs<FullNodeConfiguration>()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -18,9 +18,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.*
|
import net.corda.core.utilities.*
|
||||||
import net.corda.node.LOGS_DIRECTORY_NAME
|
import net.corda.node.LOGS_DIRECTORY_NAME
|
||||||
import net.corda.node.services.config.ConfigHelper
|
import net.corda.node.services.config.*
|
||||||
import net.corda.node.services.config.FullNodeConfiguration
|
|
||||||
import net.corda.node.services.config.VerifierType
|
|
||||||
import net.corda.node.services.network.NetworkMapService
|
import net.corda.node.services.network.NetworkMapService
|
||||||
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
|
||||||
@ -491,9 +489,9 @@ class DriverDSL(
|
|||||||
val webAddress = portAllocation.nextHostAndPort()
|
val webAddress = portAllocation.nextHostAndPort()
|
||||||
val debugPort = if (isDebug) debugPortAllocation.nextPort() else null
|
val debugPort = if (isDebug) debugPortAllocation.nextPort() else null
|
||||||
// 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 ?: X509Utilities.getDevX509Name("${pickA(name).commonName}-${p2pAddress.port}")
|
val name = providedName ?: X509Utilities.getDevX509Name("${oneOf(names).commonName}-${p2pAddress.port}")
|
||||||
val baseDirectory = driverDirectory / name.commonName
|
val baseDirectory = driverDirectory / name.commonName
|
||||||
val configOverrides = mapOf(
|
val configOverrides = configOf(
|
||||||
"myLegalName" to name.toString(),
|
"myLegalName" to name.toString(),
|
||||||
"p2pAddress" to p2pAddress.toString(),
|
"p2pAddress" to p2pAddress.toString(),
|
||||||
"rpcAddress" to rpcAddress.toString(),
|
"rpcAddress" to rpcAddress.toString(),
|
||||||
@ -511,13 +509,7 @@ class DriverDSL(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"useTestClock" to useTestClock,
|
"useTestClock" to useTestClock,
|
||||||
"rpcUsers" to rpcUsers.map {
|
"rpcUsers" to rpcUsers.map { it.toMap() },
|
||||||
mapOf(
|
|
||||||
"username" to it.username,
|
|
||||||
"password" to it.password,
|
|
||||||
"permissions" to it.permissions
|
|
||||||
)
|
|
||||||
},
|
|
||||||
"verifierType" to verifierType.name
|
"verifierType" to verifierType.name
|
||||||
) + customOverrides
|
) + customOverrides
|
||||||
|
|
||||||
@ -612,7 +604,7 @@ class DriverDSL(
|
|||||||
val config = ConfigHelper.loadConfig(
|
val config = ConfigHelper.loadConfig(
|
||||||
baseDirectory = baseDirectory,
|
baseDirectory = baseDirectory,
|
||||||
allowMissingConfig = true,
|
allowMissingConfig = true,
|
||||||
configOverrides = mapOf(
|
configOverrides = configOf(
|
||||||
"myLegalName" to dedicatedNetworkMapLegalName.toString(),
|
"myLegalName" to dedicatedNetworkMapLegalName.toString(),
|
||||||
// TODO: remove the webAddress as NMS doesn't need to run a web server. This will cause all
|
// TODO: remove the webAddress as NMS doesn't need to run a web server. This will cause all
|
||||||
// node port numbers to be shifted, so all demos and docs need to be updated accordingly.
|
// node port numbers to be shifted, so all demos and docs need to be updated accordingly.
|
||||||
@ -635,13 +627,13 @@ class DriverDSL(
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val name = arrayOf(
|
private val names = arrayOf(
|
||||||
ALICE.name,
|
ALICE.name,
|
||||||
BOB.name,
|
BOB.name,
|
||||||
DUMMY_BANK_A.name
|
DUMMY_BANK_A.name
|
||||||
)
|
)
|
||||||
|
|
||||||
fun <A> pickA(array: Array<A>): A = array[Math.abs(Random().nextInt()) % array.size]
|
private fun <A> oneOf(array: Array<A>) = array[Random().nextInt(array.size)]
|
||||||
|
|
||||||
private fun startNode(
|
private fun startNode(
|
||||||
executorService: ListeningScheduledExecutorService,
|
executorService: ListeningScheduledExecutorService,
|
||||||
|
@ -18,21 +18,23 @@ import net.corda.nodeapi.config.SSLConfiguration
|
|||||||
import org.bouncycastle.asn1.x500.X500Name
|
import org.bouncycastle.asn1.x500.X500Name
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
|
|
||||||
|
fun configOf(vararg pairs: Pair<String, Any?>) = ConfigFactory.parseMap(mapOf(*pairs))
|
||||||
|
operator fun Config.plus(overrides: Map<String, Any?>) = ConfigFactory.parseMap(overrides).withFallback(this)
|
||||||
|
|
||||||
object ConfigHelper {
|
object ConfigHelper {
|
||||||
private val log = loggerFor<ConfigHelper>()
|
private val log = loggerFor<ConfigHelper>()
|
||||||
|
|
||||||
fun loadConfig(baseDirectory: Path,
|
fun loadConfig(baseDirectory: Path,
|
||||||
configFile: Path = baseDirectory / "node.conf",
|
configFile: Path = baseDirectory / "node.conf",
|
||||||
allowMissingConfig: Boolean = false,
|
allowMissingConfig: Boolean = false,
|
||||||
configOverrides: Map<String, Any?> = emptyMap()): Config {
|
configOverrides: Config = ConfigFactory.empty()): Config {
|
||||||
val parseOptions = ConfigParseOptions.defaults()
|
val parseOptions = ConfigParseOptions.defaults()
|
||||||
val defaultConfig = ConfigFactory.parseResources("reference.conf", parseOptions.setAllowMissing(false))
|
val defaultConfig = ConfigFactory.parseResources("reference.conf", parseOptions.setAllowMissing(false))
|
||||||
val appConfig = ConfigFactory.parseFile(configFile.toFile(), parseOptions.setAllowMissing(allowMissingConfig))
|
val appConfig = ConfigFactory.parseFile(configFile.toFile(), parseOptions.setAllowMissing(allowMissingConfig))
|
||||||
val overrideConfig = ConfigFactory.parseMap(configOverrides + mapOf(
|
val finalConfig = configOf(
|
||||||
// Add substitution values here
|
// Add substitution values here
|
||||||
"basedir" to baseDirectory.toString())
|
"basedir" to baseDirectory.toString())
|
||||||
)
|
.withFallback(configOverrides)
|
||||||
val finalConfig = overrideConfig
|
|
||||||
.withFallback(appConfig)
|
.withFallback(appConfig)
|
||||||
.withFallback(defaultConfig)
|
.withFallback(defaultConfig)
|
||||||
.resolve()
|
.resolve()
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
package net.corda.node.services.config
|
||||||
|
|
||||||
|
import com.typesafe.config.ConfigFactory
|
||||||
|
import net.corda.nodeapi.config.toProperties
|
||||||
|
import org.junit.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
class ConfigOperatorTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `config plus behaves the same as map plus`() {
|
||||||
|
val config = arrayOf("x" to "y1", "a" to "b", "z" to "Z")
|
||||||
|
val overrides = arrayOf("x" to "y2", "c" to "d", "z" to null)
|
||||||
|
val old = ConfigFactory.parseMap(mapOf(*config) + mapOf(*overrides))
|
||||||
|
val new = configOf(*config) + mapOf(*overrides)
|
||||||
|
listOf(old, new).map { it.toProperties() }.forEach { c ->
|
||||||
|
assertEquals("y2", c["x"])
|
||||||
|
assertEquals("b", c["a"])
|
||||||
|
assertEquals("d", c["c"])
|
||||||
|
assertEquals(null, c["z"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -8,7 +8,6 @@ import net.corda.core.utilities.DUMMY_NOTARY
|
|||||||
import net.corda.node.driver.driver
|
import net.corda.node.driver.driver
|
||||||
import net.corda.node.services.transactions.SimpleNotaryService
|
import net.corda.node.services.transactions.SimpleNotaryService
|
||||||
import net.corda.nodeapi.User
|
import net.corda.nodeapi.User
|
||||||
import java.nio.file.Paths
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This file is exclusively for being able to run your nodes through an IDE (as opposed to running deployNodes)
|
* This file is exclusively for being able to run your nodes through an IDE (as opposed to running deployNodes)
|
||||||
@ -16,8 +15,8 @@ import java.nio.file.Paths
|
|||||||
*/
|
*/
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
val demoUser = listOf(User("demo", "demo", setOf("StartFlow.net.corda.flows.FinalityFlow")))
|
val demoUser = listOf(User("demo", "demo", setOf("StartFlow.net.corda.flows.FinalityFlow")))
|
||||||
driver(isDebug = true, driverDirectory = Paths.get("build") / "attachment-demo-nodes") {
|
driver(isDebug = true, driverDirectory = "build" / "attachment-demo-nodes") {
|
||||||
startNode(DUMMY_NOTARY.name, setOf(ServiceInfo(SimpleNotaryService.Companion.type)))
|
startNode(DUMMY_NOTARY.name, setOf(ServiceInfo(SimpleNotaryService.type)))
|
||||||
startNode(DUMMY_BANK_A.name, rpcUsers = demoUser)
|
startNode(DUMMY_BANK_A.name, rpcUsers = demoUser)
|
||||||
startNode(DUMMY_BANK_B.name, rpcUsers = demoUser)
|
startNode(DUMMY_BANK_B.name, rpcUsers = demoUser)
|
||||||
waitForAllNodesToFinish()
|
waitForAllNodesToFinish()
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import net.corda.plugins.Cordform
|
||||||
|
|
||||||
apply plugin: 'java'
|
apply plugin: 'java'
|
||||||
apply plugin: 'kotlin'
|
apply plugin: 'kotlin'
|
||||||
apply plugin: 'idea'
|
apply plugin: 'idea'
|
||||||
@ -68,7 +70,7 @@ task generateNotaryIdentity(type: JavaExec, dependsOn: 'cleanNodes') {
|
|||||||
args = [nodeDirs, notaryType, notaryName]
|
args = [nodeDirs, notaryType, notaryName]
|
||||||
}
|
}
|
||||||
|
|
||||||
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar', 'generateNotaryIdentity']) {
|
task deployNodes(type: Cordform, dependsOn: ['jar', generateNotaryIdentity]) {
|
||||||
directory deployTo
|
directory deployTo
|
||||||
networkMap "CN=Notary 1,O=R3,OU=corda,L=London,C=UK"
|
networkMap "CN=Notary 1,O=R3,OU=corda,L=London,C=UK"
|
||||||
node {
|
node {
|
||||||
@ -80,7 +82,7 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar', 'generateN
|
|||||||
cordapps = []
|
cordapps = []
|
||||||
rpcUsers = [['username': "demo", 'password': "demo", 'permissions': [
|
rpcUsers = [['username': "demo", 'password': "demo", 'permissions': [
|
||||||
'StartFlow.net.corda.notarydemo.flows.DummyIssueAndMove',
|
'StartFlow.net.corda.notarydemo.flows.DummyIssueAndMove',
|
||||||
'StartFlow.net.corda.flows.NotaryFlow$Client'
|
'StartFlow.net.corda.notarydemo.flows.RPCStartableNotaryFlowClient'
|
||||||
]]]
|
]]]
|
||||||
}
|
}
|
||||||
node {
|
node {
|
||||||
@ -126,4 +128,3 @@ task notarise(type: JavaExec) {
|
|||||||
classpath = sourceSets.main.runtimeClasspath
|
classpath = sourceSets.main.runtimeClasspath
|
||||||
main = 'net.corda.notarydemo.NotaryDemoKt'
|
main = 'net.corda.notarydemo.NotaryDemoKt'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@ import net.corda.core.div
|
|||||||
import net.corda.core.utilities.ALICE
|
import net.corda.core.utilities.ALICE
|
||||||
import net.corda.core.utilities.BOB
|
import net.corda.core.utilities.BOB
|
||||||
import net.corda.core.utilities.DUMMY_NOTARY
|
import net.corda.core.utilities.DUMMY_NOTARY
|
||||||
import net.corda.flows.NotaryFlow
|
|
||||||
import net.corda.node.driver.NetworkMapStartStrategy
|
import net.corda.node.driver.NetworkMapStartStrategy
|
||||||
import net.corda.node.driver.PortAllocation
|
import net.corda.node.driver.PortAllocation
|
||||||
import net.corda.node.driver.driver
|
import net.corda.node.driver.driver
|
||||||
@ -14,14 +13,14 @@ import net.corda.node.services.startFlowPermission
|
|||||||
import net.corda.node.services.transactions.RaftValidatingNotaryService
|
import net.corda.node.services.transactions.RaftValidatingNotaryService
|
||||||
import net.corda.nodeapi.User
|
import net.corda.nodeapi.User
|
||||||
import net.corda.notarydemo.flows.DummyIssueAndMove
|
import net.corda.notarydemo.flows.DummyIssueAndMove
|
||||||
|
import net.corda.notarydemo.flows.RPCStartableNotaryFlowClient
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
import org.bouncycastle.asn1.x500.X500Name
|
||||||
import java.nio.file.Paths
|
|
||||||
|
|
||||||
/** Creates and starts all nodes required for the demo. */
|
/** Creates and starts all nodes required for the demo. */
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
val demoUser = listOf(User("demo", "demo", setOf(startFlowPermission<DummyIssueAndMove>(), startFlowPermission<NotaryFlow.Client>())))
|
val demoUser = listOf(User("demo", "demo", setOf(startFlowPermission<DummyIssueAndMove>(), startFlowPermission<RPCStartableNotaryFlowClient>())))
|
||||||
val networkMap = NetworkMapStartStrategy.Nominated(DUMMY_NOTARY.name.appendToCommonName("1"), HostAndPort.fromParts("localhost", 10009))
|
val networkMap = NetworkMapStartStrategy.Nominated(DUMMY_NOTARY.name.appendToCommonName("1"), HostAndPort.fromParts("localhost", 10009))
|
||||||
driver(isDebug = true, driverDirectory = Paths.get("build") / "notary-demo-nodes", networkMapStartStrategy = networkMap, portAllocation = PortAllocation.Incremental(10001)) {
|
driver(isDebug = true, driverDirectory = "build" / "notary-demo-nodes", networkMapStartStrategy = networkMap, portAllocation = PortAllocation.Incremental(10001)) {
|
||||||
startNode(ALICE.name, rpcUsers = demoUser)
|
startNode(ALICE.name, rpcUsers = demoUser)
|
||||||
startNode(BOB.name)
|
startNode(BOB.name)
|
||||||
startNotaryCluster(X500Name("CN=Raft,O=R3,OU=corda,L=Zurich,C=CH"), clusterSize = 3, type = RaftValidatingNotaryService.type)
|
startNotaryCluster(X500Name("CN=Raft,O=R3,OU=corda,L=Zurich,C=CH"), clusterSize = 3, type = RaftValidatingNotaryService.type)
|
||||||
|
@ -2,23 +2,16 @@ package net.corda.notarydemo
|
|||||||
|
|
||||||
import com.google.common.net.HostAndPort
|
import com.google.common.net.HostAndPort
|
||||||
import com.google.common.util.concurrent.Futures
|
import com.google.common.util.concurrent.Futures
|
||||||
import joptsimple.OptionParser
|
|
||||||
import net.corda.client.rpc.CordaRPCClient
|
import net.corda.client.rpc.CordaRPCClient
|
||||||
import net.corda.client.rpc.notUsed
|
import net.corda.client.rpc.notUsed
|
||||||
import net.corda.core.crypto.toStringShort
|
import net.corda.core.crypto.toStringShort
|
||||||
import net.corda.core.div
|
|
||||||
import net.corda.core.getOrThrow
|
import net.corda.core.getOrThrow
|
||||||
import net.corda.core.messaging.CordaRPCOps
|
import net.corda.core.messaging.CordaRPCOps
|
||||||
import net.corda.core.messaging.startFlow
|
import net.corda.core.messaging.startFlow
|
||||||
import net.corda.core.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
import net.corda.core.utilities.BOB
|
import net.corda.core.utilities.BOB
|
||||||
import net.corda.flows.NotaryFlow
|
|
||||||
import net.corda.nodeapi.config.SSLConfiguration
|
|
||||||
import net.corda.notarydemo.flows.DummyIssueAndMove
|
import net.corda.notarydemo.flows.DummyIssueAndMove
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
import net.corda.notarydemo.flows.RPCStartableNotaryFlowClient
|
||||||
import java.nio.file.Path
|
|
||||||
import java.nio.file.Paths
|
|
||||||
import kotlin.system.exitProcess
|
|
||||||
|
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
val host = HostAndPort.fromString("localhost:10003")
|
val host = HostAndPort.fromString("localhost:10003")
|
||||||
@ -85,28 +78,7 @@ private class NotaryDemoClientApi(val rpc: CordaRPCOps) {
|
|||||||
private fun notariseTransactions(transactions: List<SignedTransaction>): List<String> {
|
private fun notariseTransactions(transactions: List<SignedTransaction>): List<String> {
|
||||||
// TODO: Remove this suppress when we upgrade to kotlin 1.1 or when JetBrain fixes the bug.
|
// TODO: Remove this suppress when we upgrade to kotlin 1.1 or when JetBrain fixes the bug.
|
||||||
@Suppress("UNSUPPORTED_FEATURE")
|
@Suppress("UNSUPPORTED_FEATURE")
|
||||||
val signatureFutures = transactions.map { rpc.startFlow(NotaryFlow::Client, it).returnValue }
|
val signatureFutures = transactions.map { rpc.startFlow(::RPCStartableNotaryFlowClient, it).returnValue }
|
||||||
return Futures.allAsList(signatureFutures).getOrThrow().map { it.map { it.by.toStringShort() }.joinToString() }
|
return Futures.allAsList(signatureFutures).getOrThrow().map { it.map { it.by.toStringShort() }.joinToString() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getCertPath(args: Array<String>): String? {
|
|
||||||
val parser = OptionParser()
|
|
||||||
val certsPath = parser.accepts("certificates").withRequiredArg()
|
|
||||||
val options = try {
|
|
||||||
parser.parse(*args)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
println(e.message)
|
|
||||||
exitProcess(1)
|
|
||||||
}
|
|
||||||
return options.valueOf(certsPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Take this out once we have a dedicated RPC port and allow SSL on it to be optional.
|
|
||||||
private fun sslConfigFor(nodename: String, certsPath: String?): SSLConfiguration {
|
|
||||||
return object : SSLConfiguration {
|
|
||||||
override val keyStorePassword: String = "cordacadevpass"
|
|
||||||
override val trustStorePassword: String = "trustpass"
|
|
||||||
override val certificatesDirectory: Path = if (certsPath != null) Paths.get(certsPath) else Paths.get("build") / "nodes" / nodename / "certificates"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -4,9 +4,11 @@ import co.paralleluniverse.fibers.Suspendable
|
|||||||
import net.corda.core.contracts.DummyContract
|
import net.corda.core.contracts.DummyContract
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.flows.FlowLogic
|
import net.corda.core.flows.FlowLogic
|
||||||
|
import net.corda.core.flows.StartableByRPC
|
||||||
import net.corda.core.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
@StartableByRPC
|
||||||
class DummyIssueAndMove(private val notary: Party, private val counterpartyNode: Party) : FlowLogic<SignedTransaction>() {
|
class DummyIssueAndMove(private val notary: Party, private val counterpartyNode: Party) : FlowLogic<SignedTransaction>() {
|
||||||
@Suspendable
|
@Suspendable
|
||||||
override fun call(): SignedTransaction {
|
override fun call(): SignedTransaction {
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
package net.corda.notarydemo.flows
|
||||||
|
|
||||||
|
import net.corda.core.flows.StartableByRPC
|
||||||
|
import net.corda.core.transactions.SignedTransaction
|
||||||
|
import net.corda.flows.NotaryFlow
|
||||||
|
|
||||||
|
@StartableByRPC
|
||||||
|
class RPCStartableNotaryFlowClient(stx: SignedTransaction) : NotaryFlow.Client(stx)
|
@ -11,7 +11,6 @@ import net.corda.node.services.startFlowPermission
|
|||||||
import net.corda.node.services.transactions.SimpleNotaryService
|
import net.corda.node.services.transactions.SimpleNotaryService
|
||||||
import net.corda.nodeapi.User
|
import net.corda.nodeapi.User
|
||||||
import net.corda.testing.BOC
|
import net.corda.testing.BOC
|
||||||
import java.nio.file.Paths
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This file is exclusively for being able to run your nodes through an IDE (as opposed to running deployNodes)
|
* This file is exclusively for being able to run your nodes through an IDE (as opposed to running deployNodes)
|
||||||
@ -22,7 +21,7 @@ fun main(args: Array<String>) {
|
|||||||
startFlowPermission<IssuerFlow.IssuanceRequester>(),
|
startFlowPermission<IssuerFlow.IssuanceRequester>(),
|
||||||
startFlowPermission<net.corda.traderdemo.flow.SellerFlow>())
|
startFlowPermission<net.corda.traderdemo.flow.SellerFlow>())
|
||||||
val demoUser = listOf(User("demo", "demo", permissions))
|
val demoUser = listOf(User("demo", "demo", permissions))
|
||||||
driver(driverDirectory = Paths.get("build") / "trader-demo-nodes", isDebug = true) {
|
driver(driverDirectory = "build" / "trader-demo-nodes", isDebug = true) {
|
||||||
val user = User("user1", "test", permissions = setOf(startFlowPermission<IssuerFlow.IssuanceRequester>()))
|
val user = User("user1", "test", permissions = setOf(startFlowPermission<IssuerFlow.IssuanceRequester>()))
|
||||||
startNode(DUMMY_NOTARY.name, setOf(ServiceInfo(SimpleNotaryService.type)))
|
startNode(DUMMY_NOTARY.name, setOf(ServiceInfo(SimpleNotaryService.type)))
|
||||||
startNode(DUMMY_BANK_A.name, rpcUsers = demoUser)
|
startNode(DUMMY_BANK_A.name, rpcUsers = demoUser)
|
||||||
|
@ -12,6 +12,8 @@ import net.corda.node.driver.addressMustNotBeBound
|
|||||||
import net.corda.node.internal.Node
|
import net.corda.node.internal.Node
|
||||||
import net.corda.node.services.config.ConfigHelper
|
import net.corda.node.services.config.ConfigHelper
|
||||||
import net.corda.node.services.config.FullNodeConfiguration
|
import net.corda.node.services.config.FullNodeConfiguration
|
||||||
|
import net.corda.node.services.config.configOf
|
||||||
|
import net.corda.node.services.config.plus
|
||||||
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.nodeapi.User
|
import net.corda.nodeapi.User
|
||||||
@ -141,18 +143,12 @@ abstract class NodeBasedTest {
|
|||||||
val config = ConfigHelper.loadConfig(
|
val config = ConfigHelper.loadConfig(
|
||||||
baseDirectory = baseDirectory,
|
baseDirectory = baseDirectory,
|
||||||
allowMissingConfig = true,
|
allowMissingConfig = true,
|
||||||
configOverrides = mapOf(
|
configOverrides = configOf(
|
||||||
"myLegalName" to legalName.toString(),
|
"myLegalName" to legalName.toString(),
|
||||||
"p2pAddress" to localPort[0].toString(),
|
"p2pAddress" to localPort[0].toString(),
|
||||||
"rpcAddress" to localPort[1].toString(),
|
"rpcAddress" to localPort[1].toString(),
|
||||||
"extraAdvertisedServiceIds" to advertisedServices.map { it.toString() },
|
"extraAdvertisedServiceIds" to advertisedServices.map { it.toString() },
|
||||||
"rpcUsers" to rpcUsers.map {
|
"rpcUsers" to rpcUsers.map { it.toMap() }
|
||||||
mapOf(
|
|
||||||
"username" to it.username,
|
|
||||||
"password" to it.password,
|
|
||||||
"permissions" to it.permissions
|
|
||||||
)
|
|
||||||
}
|
|
||||||
) + configOverrides
|
) + configOverrides
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package net.corda.demobench.model
|
package net.corda.demobench.model
|
||||||
|
|
||||||
import net.corda.core.crypto.commonName
|
import net.corda.core.crypto.commonName
|
||||||
|
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) {
|
||||||
@ -9,7 +10,5 @@ open class NetworkMapConfig(val legalName: X500Name, val p2pPort: Int) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val WHITESPACE = "\\s++".toRegex()
|
fun String.stripWhitespace() = replace(WHITESPACE, "")
|
||||||
|
fun String.toKey() = stripWhitespace().toLowerCase()
|
||||||
fun String.stripWhitespace() = this.replace(WHITESPACE, "")
|
|
||||||
fun String.toKey() = this.stripWhitespace().toLowerCase()
|
|
||||||
|
@ -5,12 +5,6 @@ package net.corda.demobench.model
|
|||||||
import net.corda.nodeapi.User
|
import net.corda.nodeapi.User
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
fun User.toMap(): Map<String, Any> = mapOf(
|
|
||||||
"username" to username,
|
|
||||||
"password" to password,
|
|
||||||
"permissions" to permissions
|
|
||||||
)
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
fun toUser(map: Map<String, Any>) = User(
|
fun toUser(map: Map<String, Any>) = User(
|
||||||
map.getOrElse("username", { "none" }) as String,
|
map.getOrElse("username", { "none" }) as String,
|
||||||
|
Loading…
Reference in New Issue
Block a user