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:
Andrzej Cichocki 2017-05-16 11:30:50 +01:00 committed by GitHub
parent 42d0a3c638
commit d3bb040355
23 changed files with 86 additions and 101 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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