CORDA-1924: Remove references to Cordform definition and cordform-common (#3842)

This commit is contained in:
Clinton 2018-08-24 16:29:14 +01:00 committed by GitHub
parent 329c9da0a9
commit 3594ccd89b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 378 additions and 758 deletions

View File

@ -210,7 +210,6 @@ allprojects {
mavenCentral()
jcenter()
maven { url 'https://jitpack.io' }
maven { url "$artifactory_contextUrl/corda-releases" } // cordform-common
}
configurations {

View File

@ -6,6 +6,8 @@ release, see :doc:`upgrade-notes`.
Unreleased
----------
* Removed experimental feature `CordformDefinition`
* Vault query fix: support query by parent classes of Contract State classes (see https://github.com/corda/corda/issues/3714)
* Added ``registerResponderFlow`` method to ``StartedMockNode``, to support isolated testing of responder flow behaviour.

View File

@ -22,8 +22,6 @@ dependencies {
// TODO: Remove this dependency and the code that requires it
compile "commons-fileupload:commons-fileupload:$fileupload_version"
compile "net.corda.plugins:cordform-common:$gradle_plugins_version"
// TypeSafe Config: for simple and human friendly config files.
compile "com.typesafe:config:$typesafe_config_version"

View File

@ -0,0 +1,4 @@
package net.corda.nodeapi.internal
// TODO: Add to Corda node.conf to allow customisation
const val NODE_INFO_DIRECTORY = "additional-node-infos"

View File

@ -2,7 +2,6 @@ package net.corda.nodeapi.internal.network
import com.typesafe.config.Config
import com.typesafe.config.ConfigFactory
import net.corda.cordform.CordformNode
import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.Party
import net.corda.core.internal.*
@ -46,11 +45,11 @@ import kotlin.streams.toList
*/
// TODO Move this to tools:bootstrapper
class NetworkBootstrapper
@VisibleForTesting
internal constructor(private val initSerEnv: Boolean,
private val embeddedCordaJar: () -> InputStream,
private val nodeInfosGenerator: (List<Path>) -> List<Path>,
private val contractsJarConverter: (Path) -> ContractsJar) {
@VisibleForTesting
internal constructor(private val initSerEnv: Boolean,
private val embeddedCordaJar: () -> InputStream,
private val nodeInfosGenerator: (List<Path>) -> List<Path>,
private val contractsJarConverter: (Path) -> ContractsJar) {
constructor() : this(
initSerEnv = true,
@ -102,7 +101,7 @@ class NetworkBootstrapper
process.destroyForcibly()
throw IllegalStateException("Error while generating node info file. Please check the logs in $logsDir.")
}
check(process.exitValue() == 0) { "Error while generating node info file. Please check the logs in $logsDir." }
check(process.exitValue() == 0) { "Error while generating node info file. Please check the logs in $logsDir." }
return nodeDir.list { paths ->
paths.filter { it.fileName.toString().startsWith(NODE_INFO_FILE_NAME_PREFIX) }.findFirst().get()
}
@ -269,7 +268,7 @@ class NetworkBootstrapper
private fun distributeNodeInfos(nodeDirs: List<Path>, nodeInfoFiles: List<Path>) {
for (nodeDir in nodeDirs) {
val additionalNodeInfosDir = (nodeDir / CordformNode.NODE_INFO_DIRECTORY).createDirectories()
val additionalNodeInfosDir = (nodeDir / NODE_INFO_DIRECTORY).createDirectories()
for (nodeInfoFile in nodeInfoFiles) {
nodeInfoFile.copyToDirectory(additionalNodeInfosDir, REPLACE_EXISTING)
}
@ -364,10 +363,10 @@ class NetworkBootstrapper
private fun NodeInfo.notaryIdentity(): Party {
return when (legalIdentities.size) {
// Single node notaries have just one identity like all other nodes. This identity is the notary identity
// Single node notaries have just one identity like all other nodes. This identity is the notary identity
1 -> legalIdentities[0]
// Nodes which are part of a distributed notary have a second identity which is the composite identity of the
// cluster and is shared by all the other members. This is the notary identity.
// Nodes which are part of a distributed notary have a second identity which is the composite identity of the
// cluster and is shared by all the other members. This is the notary identity.
2 -> legalIdentities[1]
else -> throw IllegalArgumentException("Not sure how to get the notary identity in this scenerio: $this")
}

View File

@ -1,8 +1,8 @@
package net.corda.nodeapi.internal.network
import net.corda.cordform.CordformNode
import net.corda.core.internal.*
import net.corda.core.utilities.contextLogger
import net.corda.nodeapi.internal.NODE_INFO_DIRECTORY
import rx.Observable
import rx.Scheduler
import rx.Subscription
@ -96,10 +96,11 @@ class NodeInfoFilesCopier(scheduler: Scheduler = Schedulers.io()) : AutoCloseabl
private fun poll() {
nodeDataMapBox.locked {
for (nodeData in values) {
nodeData.nodeDir.list { paths -> paths
.filter { it.isRegularFile() }
.filter { it.fileName.toString().startsWith(NODE_INFO_FILE_NAME_PREFIX) }
.forEach { processPath(nodeData, it) }
nodeData.nodeDir.list { paths ->
paths
.filter { it.isRegularFile() }
.filter { it.fileName.toString().startsWith(NODE_INFO_FILE_NAME_PREFIX) }
.forEach { processPath(nodeData, it) }
}
}
}
@ -149,7 +150,7 @@ class NodeInfoFilesCopier(scheduler: Scheduler = Schedulers.io()) : AutoCloseabl
* Convenience holder for all the paths and files relative to a single node.
*/
private class NodeData(val nodeDir: Path) {
val additionalNodeInfoDirectory: Path = nodeDir.resolve(CordformNode.NODE_INFO_DIRECTORY)
val additionalNodeInfoDirectory: Path = nodeDir.resolve(NODE_INFO_DIRECTORY)
// Map from Path to its lastModifiedTime.
val previouslySeenFiles = mutableMapOf<Path, FileTime>()

View File

@ -1,7 +1,6 @@
package net.corda.nodeapi.internal.network
import com.typesafe.config.ConfigFactory
import net.corda.cordform.CordformNode.NODE_INFO_DIRECTORY
import net.corda.core.crypto.secureRandomBytes
import net.corda.core.crypto.sha256
import net.corda.core.identity.CordaX500Name
@ -11,6 +10,7 @@ import net.corda.core.node.NodeInfo
import net.corda.core.serialization.serialize
import net.corda.node.services.config.NotaryConfig
import net.corda.nodeapi.internal.DEV_ROOT_CA
import net.corda.nodeapi.internal.NODE_INFO_DIRECTORY
import net.corda.nodeapi.internal.SignedNodeInfo
import net.corda.nodeapi.internal.config.parseAs
import net.corda.nodeapi.internal.config.toConfig

View File

@ -1,10 +1,10 @@
package net.corda.nodeapi.internal.network
import net.corda.cordform.CordformNode
import net.corda.core.internal.div
import net.corda.core.internal.list
import net.corda.core.internal.write
import net.corda.nodeapi.eventually
import net.corda.nodeapi.internal.NODE_INFO_DIRECTORY
import org.assertj.core.api.Assertions.assertThat
import org.junit.Before
import org.junit.Rule
@ -34,12 +34,12 @@ class NodeInfoFilesCopierTest {
private val rootPath get() = folder.root.toPath()
private val scheduler = TestScheduler()
private fun nodeDir(nodeBaseDir : String) = rootPath.resolve(nodeBaseDir).resolve(ORGANIZATION.toLowerCase())
private fun nodeDir(nodeBaseDir: String) = rootPath.resolve(nodeBaseDir).resolve(ORGANIZATION.toLowerCase())
private val node1RootPath by lazy { nodeDir(NODE_1_PATH) }
private val node2RootPath by lazy { nodeDir(NODE_2_PATH) }
private val node1AdditionalNodeInfoPath by lazy { node1RootPath.resolve(CordformNode.NODE_INFO_DIRECTORY) }
private val node2AdditionalNodeInfoPath by lazy { node2RootPath.resolve(CordformNode.NODE_INFO_DIRECTORY) }
private val node1AdditionalNodeInfoPath by lazy { node1RootPath.resolve(NODE_INFO_DIRECTORY) }
private val node2AdditionalNodeInfoPath by lazy { node2RootPath.resolve(NODE_INFO_DIRECTORY) }
private lateinit var nodeInfoFilesCopier: NodeInfoFilesCopier

View File

@ -71,7 +71,6 @@ dependencies {
compile project(":confidential-identities")
compile project(':client:rpc')
compile project(':tools:shell')
compile "net.corda.plugins:cordform-common:$gradle_plugins_version"
// Log4J: logging framework (with SLF4J bindings)
compile "org.apache.logging.log4j:log4j-slf4j-impl:${log4j_version}"

View File

@ -1,6 +1,5 @@
package net.corda.node.services.network
import net.corda.cordform.CordformNode
import net.corda.core.concurrent.CordaFuture
import net.corda.core.crypto.random63BitValue
import net.corda.core.identity.CordaX500Name
@ -12,6 +11,7 @@ import net.corda.core.serialization.serialize
import net.corda.core.utilities.getOrThrow
import net.corda.core.utilities.seconds
import net.corda.node.services.config.configureDevKeyAndTrustStores
import net.corda.nodeapi.internal.NODE_INFO_DIRECTORY
import net.corda.nodeapi.internal.config.NodeSSLConfiguration
import net.corda.nodeapi.internal.network.NETWORK_PARAMS_FILE_NAME
import net.corda.nodeapi.internal.network.NETWORK_PARAMS_UPDATE_FILE_NAME
@ -235,7 +235,7 @@ class NetworkMapTest(var initFunc: (URL, NetworkMapServer) -> CompatibilityZoneP
private fun NodeHandle.onlySees(vararg nodes: NodeInfo) {
// Make sure the nodes aren't getting the node infos from their additional directories
val nodeInfosDir = baseDirectory / CordformNode.NODE_INFO_DIRECTORY
val nodeInfosDir = baseDirectory / NODE_INFO_DIRECTORY
if (nodeInfosDir.exists()) {
assertThat(nodeInfosDir.list()).isEmpty()
}

View File

@ -1,6 +1,5 @@
package net.corda.node.services.network
import net.corda.cordform.CordformNode
import net.corda.core.crypto.SecureHash
import net.corda.core.internal.*
import net.corda.core.node.NodeInfo
@ -11,6 +10,7 @@ import net.corda.core.utilities.contextLogger
import net.corda.core.utilities.debug
import net.corda.core.utilities.seconds
import net.corda.node.serialization.amqp.AMQPServerSerializationScheme
import net.corda.nodeapi.internal.NODE_INFO_DIRECTORY
import net.corda.nodeapi.internal.NodeInfoAndSigned
import net.corda.nodeapi.internal.SignedNodeInfo
import net.corda.nodeapi.internal.network.NodeInfoFilesCopier
@ -64,7 +64,8 @@ class NodeInfoWatcher(private val nodePath: Path,
}
internal data class NodeInfoFromFile(val nodeInfohash: SecureHash, val lastModified: FileTime)
private val nodeInfosDir = nodePath / CordformNode.NODE_INFO_DIRECTORY
private val nodeInfosDir = nodePath / NODE_INFO_DIRECTORY
private val nodeInfoFilesMap = HashMap<Path, NodeInfoFromFile>()
val processedNodeInfoHashes: Set<SecureHash> get() = nodeInfoFilesMap.values.map { it.nodeInfohash }.toSet()
@ -74,7 +75,7 @@ class NodeInfoWatcher(private val nodePath: Path,
}
/**
* Read all the files contained in [nodePath] / [CordformNode.NODE_INFO_DIRECTORY] and keep watching
* Read all the files contained in [nodePath] / [NODE_INFO_DIRECTORY] and keep watching
* the folder for further updates.
*
* We simply list the directory content every 5 seconds, the Java implementation of WatchService has been proven to

View File

@ -3,7 +3,6 @@ package net.corda.node.services.network
import com.google.common.jimfs.Configuration.unix
import com.google.common.jimfs.Jimfs
import com.nhaarman.mockito_kotlin.*
import net.corda.cordform.CordformNode.NODE_INFO_DIRECTORY
import net.corda.core.crypto.Crypto
import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.sign
@ -15,6 +14,7 @@ import net.corda.core.node.NodeInfo
import net.corda.core.serialization.serialize
import net.corda.core.utilities.millis
import net.corda.node.services.api.NetworkMapCacheInternal
import net.corda.nodeapi.internal.NODE_INFO_DIRECTORY
import net.corda.nodeapi.internal.NodeInfoAndSigned
import net.corda.nodeapi.internal.network.NETWORK_PARAMS_UPDATE_FILE_NAME
import net.corda.nodeapi.internal.network.NodeInfoFilesCopier

View File

@ -2,11 +2,11 @@ package net.corda.node.services.network
import com.google.common.jimfs.Configuration
import com.google.common.jimfs.Jimfs
import net.corda.cordform.CordformNode
import net.corda.core.internal.createDirectories
import net.corda.core.internal.div
import net.corda.core.internal.size
import net.corda.core.node.services.KeyManagementService
import net.corda.nodeapi.internal.NODE_INFO_DIRECTORY
import net.corda.nodeapi.internal.NodeInfoAndSigned
import net.corda.nodeapi.internal.network.NodeInfoFilesCopier
import net.corda.testing.core.ALICE_NAME
@ -51,7 +51,7 @@ class NodeInfoWatcherTest {
val identityService = makeTestIdentityService()
keyManagementService = MockKeyManagementService(identityService)
nodeInfoWatcher = NodeInfoWatcher(tempFolder.root.toPath(), scheduler)
nodeInfoPath = tempFolder.root.toPath() / CordformNode.NODE_INFO_DIRECTORY
nodeInfoPath = tempFolder.root.toPath() / NODE_INFO_DIRECTORY
}
@Test

View File

@ -7,21 +7,6 @@ apply plugin: 'net.corda.plugins.cordapp'
apply plugin: 'net.corda.plugins.cordformation'
apply plugin: 'maven-publish'
sourceSets {
integrationTest {
kotlin {
compileClasspath += main.output + test.output
runtimeClasspath += main.output + test.output
srcDir file('src/integration-test/kotlin')
}
}
}
configurations {
integrationTestCompile.extendsFrom testCompile
integrationTestRuntime.extendsFrom testRuntime
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
@ -48,13 +33,46 @@ dependencies {
}
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) {
// CordformationDefinition is an experimental feature
definitionClass = 'net.corda.bank.BankOfCordaCordform'
}
task integrationTest(type: Test, dependsOn: []) {
testClassesDirs = sourceSets.integrationTest.output.classesDirs
classpath = sourceSets.integrationTest.runtimeClasspath
nodeDefaults {
cordapp project(':finance')
}
node {
name "O=Notary Service,L=Zurich,C=CH"
notary = [validating: true]
p2pPort 10002
rpcSettings {
address "localhost:10003"
adminAddress "localhost:10004"
}
extraConfig = [h2Settings: [address: "localhost:10016"]]
}
node {
name "O=BankOfCorda,L=London,C=GB"
p2pPort 10005
rpcSettings {
address "localhost:10006"
adminAddress "localhost:10015"
}
webPort 10007
rpcUsers = [[user: "bankUser", password: "test", permissions: ["ALL"]]]
extraConfig = [
custom : [issuableCurrencies: ["USD"]],
h2Settings: [address: "localhost:10017"]
]
}
node {
name "O=BigCorporation,L=New York,C=US"
p2pPort 10008
rpcSettings {
address "localhost:10009"
adminAddress "localhost:10011"
}
webPort 10010
rpcUsers = [[user: "bigCorpUser", password: "test", permissions: ["ALL"]]]
extraConfig = [
h2Settings: [address: "localhost:10018"]
]
}
}
idea {

View File

@ -1,32 +0,0 @@
package net.corda.bank
import net.corda.client.rpc.CordaRPCClient
import net.corda.core.contracts.withoutIssuer
import net.corda.core.utilities.NetworkHostAndPort
import net.corda.finance.DOLLARS
import net.corda.finance.contracts.asset.Cash
import net.corda.finance.utils.sumCash
import net.corda.testing.core.BOC_NAME
import net.corda.testing.node.internal.demorun.nodeRunner
import org.assertj.core.api.Assertions.assertThat
import org.junit.Test
class BankOfCordaCordformTest {
@Test
fun `run demo`() {
BankOfCordaCordform().nodeRunner().scanPackages(listOf("net.corda.finance")).deployAndRunNodesAndThen {
IssueCash.requestRpcIssue(20000.DOLLARS)
CordaRPCClient(NetworkHostAndPort("localhost", BOC_RPC_PORT)).use(BOC_RPC_USER, BOC_RPC_PWD) {
assertThat(it.proxy.vaultQuery(Cash.State::class.java).states).isEmpty() // All of the issued cash is transferred
}
CordaRPCClient(NetworkHostAndPort("localhost", BIGCORP_RPC_PORT)).use(BIGCORP_RPC_USER, BIGCORP_RPC_PWD) {
val cashStates = it.proxy.vaultQuery(Cash.State::class.java).states.map { it.state.data }
val knownOwner = it.proxy.wellKnownPartyFromAnonymous(cashStates.map { it.owner }.toSet().single())
assertThat(knownOwner?.name).isEqualTo(BIGCORP_NAME)
val totalCash = cashStates.sumCash()
assertThat(totalCash.token.issuer.party.nameOrNull()).isEqualTo(BOC_NAME)
assertThat(totalCash.withoutIssuer()).isEqualTo(20000.DOLLARS)
}
}
}
}

View File

@ -1,149 +0,0 @@
package net.corda.bank
import joptsimple.OptionParser
import net.corda.bank.api.BankOfCordaClientApi
import net.corda.bank.api.BankOfCordaWebApi.IssueRequestParams
import net.corda.cordform.CordappDependency
import net.corda.cordform.CordformContext
import net.corda.cordform.CordformDefinition
import net.corda.core.contracts.Amount
import net.corda.core.identity.CordaX500Name
import net.corda.core.internal.VisibleForTesting
import net.corda.core.transactions.SignedTransaction
import net.corda.core.utilities.NetworkHostAndPort
import net.corda.node.services.Permissions.Companion.all
import net.corda.node.services.config.NotaryConfig
import net.corda.testing.node.internal.demorun.*
import net.corda.testing.core.BOC_NAME
import net.corda.testing.node.User
import java.util.*
import kotlin.system.exitProcess
val BIGCORP_NAME = CordaX500Name(organisation = "BigCorporation", locality = "New York", country = "US")
private val NOTARY_NAME = CordaX500Name(organisation = "Notary Service", locality = "Zurich", country = "CH")
const val BOC_RPC_PORT = 10006
const val BIGCORP_RPC_PORT = 10009
private const val BOC_RPC_ADMIN_PORT = 10015
private const val BOC_WEB_PORT = 10007
const val BOC_RPC_USER = "bankUser"
const val BOC_RPC_PWD = "test"
const val BIGCORP_RPC_USER = "bigCorpUser"
const val BIGCORP_RPC_PWD = "test"
class BankOfCordaCordform : CordformDefinition() {
init {
node {
name(NOTARY_NAME)
notary(NotaryConfig(validating = true))
p2pPort(10002)
rpcSettings {
address("localhost:10003")
adminAddress("localhost:10004")
}
devMode(true)
extraConfig = mapOf("h2Settings" to mapOf("address" to "localhost:10016"))
}
node {
name(BOC_NAME)
extraConfig = mapOf("custom" to mapOf("issuableCurrencies" to listOf("USD")),
"h2Settings" to mapOf("address" to "localhost:10017"))
p2pPort(10005)
rpcSettings {
address("localhost:$BOC_RPC_PORT")
adminAddress("localhost:$BOC_RPC_ADMIN_PORT")
}
webPort(BOC_WEB_PORT)
rpcUsers(User(BOC_RPC_USER, BOC_RPC_PWD, setOf(all())))
devMode(true)
}
node {
name(BIGCORP_NAME)
p2pPort(10008)
rpcSettings {
address("localhost:$BIGCORP_RPC_PORT")
adminAddress("localhost:10011")
}
webPort(10010)
rpcUsers(User(BIGCORP_RPC_USER, BIGCORP_RPC_PWD, setOf(all())))
devMode(true)
extraConfig = mapOf("h2Settings" to mapOf("address" to "localhost:10018"))
}
}
override fun setup(context: CordformContext) = Unit
override fun getCordappDependencies(): List<CordappDependency> {
return listOf(CordappDependency(":finance"))
}
}
object DeployNodes {
@JvmStatic
fun main(args: Array<String>) {
BankOfCordaCordform().nodeRunner().scanPackages(listOf("net.corda.finance")).deployAndRunNodes()
}
}
object IssueCash {
@JvmStatic
fun main(args: Array<String>) {
val parser = OptionParser()
val roleArg = parser.accepts("role").withRequiredArg().ofType(Role::class.java).describedAs("[ISSUER|ISSUE_CASH_RPC|ISSUE_CASH_WEB]")
val quantity = parser.accepts("quantity").withOptionalArg().ofType(Long::class.java)
val currency = parser.accepts("currency").withOptionalArg().ofType(String::class.java).describedAs("[GBP|USD|CHF|EUR]")
val options = try {
parser.parse(*args)
} catch (e: Exception) {
println(e.message)
printHelp(parser)
exitProcess(1)
}
val role = options.valueOf(roleArg)!!
val amount = Amount(options.valueOf(quantity), Currency.getInstance(options.valueOf(currency)))
when (role) {
Role.ISSUE_CASH_RPC -> {
println("Requesting Cash via RPC ...")
val result = requestRpcIssue(amount)
println("Success!! Your transaction receipt is ${result.tx.id}")
}
Role.ISSUE_CASH_WEB -> {
println("Requesting Cash via Web ...")
requestWebIssue(amount)
println("Successfully processed Cash Issue request")
}
}
}
@VisibleForTesting
fun requestRpcIssue(amount: Amount<Currency>): SignedTransaction {
return BankOfCordaClientApi.requestRPCIssue(NetworkHostAndPort("localhost", BOC_RPC_PORT), createParams(amount, NOTARY_NAME))
}
private fun requestWebIssue(amount: Amount<Currency>) {
BankOfCordaClientApi.requestWebIssue(NetworkHostAndPort("localhost", BOC_WEB_PORT), createParams(amount, NOTARY_NAME))
}
private fun createParams(amount: Amount<Currency>, notaryName: CordaX500Name): IssueRequestParams {
return IssueRequestParams(amount, BIGCORP_NAME, "1", BOC_NAME, notaryName)
}
private fun printHelp(parser: OptionParser) {
println("""
Usage: bank-of-corda --role ISSUER
bank-of-corda --role (ISSUE_CASH_RPC|ISSUE_CASH_WEB) --quantity <quantity> --currency <currency>
Please refer to the documentation in docs/build/index.html for more info.
""".trimIndent())
parser.printHelpOn(System.out)
}
enum class Role {
ISSUE_CASH_RPC,
ISSUE_CASH_WEB,
}
}

View File

@ -0,0 +1,77 @@
package net.corda.bank
import joptsimple.OptionParser
import net.corda.bank.api.BankOfCordaClientApi
import net.corda.bank.api.BankOfCordaWebApi
import net.corda.core.contracts.Amount
import net.corda.core.identity.CordaX500Name
import net.corda.core.internal.VisibleForTesting
import net.corda.core.transactions.SignedTransaction
import net.corda.core.utilities.NetworkHostAndPort
import net.corda.testing.core.BOC_NAME
import java.util.*
import kotlin.system.exitProcess
object IssueCash {
private val NOTARY_NAME = CordaX500Name(organisation = "Notary Service", locality = "Zurich", country = "CH")
private val BIGCORP_NAME = CordaX500Name(organisation = "BigCorporation", locality = "New York", country = "US")
private const val BOC_RPC_PORT = 10006
private const val BOC_WEB_PORT = 10007
@JvmStatic
fun main(args: Array<String>) {
val parser = OptionParser()
val roleArg = parser.accepts("role").withRequiredArg().ofType(Role::class.java).describedAs("[ISSUER|ISSUE_CASH_RPC|ISSUE_CASH_WEB]")
val quantity = parser.accepts("quantity").withOptionalArg().ofType(Long::class.java)
val currency = parser.accepts("currency").withOptionalArg().ofType(String::class.java).describedAs("[GBP|USD|CHF|EUR]")
val options = try {
parser.parse(*args)
} catch (e: Exception) {
println(e.message)
printHelp(parser)
exitProcess(1)
}
val role = options.valueOf(roleArg)!!
val amount = Amount(options.valueOf(quantity), Currency.getInstance(options.valueOf(currency)))
when (role) {
Role.ISSUE_CASH_RPC -> {
println("Requesting Cash via RPC ...")
val result = requestRpcIssue(amount)
println("Success!! Your transaction receipt is ${result.tx.id}")
}
Role.ISSUE_CASH_WEB -> {
println("Requesting Cash via Web ...")
requestWebIssue(amount)
println("Successfully processed Cash Issue request")
}
}
}
@VisibleForTesting
fun requestRpcIssue(amount: Amount<Currency>): SignedTransaction {
return BankOfCordaClientApi.requestRPCIssue(NetworkHostAndPort("localhost", BOC_RPC_PORT), createParams(amount, NOTARY_NAME))
}
private fun requestWebIssue(amount: Amount<Currency>) {
BankOfCordaClientApi.requestWebIssue(NetworkHostAndPort("localhost", BOC_WEB_PORT), createParams(amount, NOTARY_NAME))
}
private fun createParams(amount: Amount<Currency>, notaryName: CordaX500Name): BankOfCordaWebApi.IssueRequestParams {
return BankOfCordaWebApi.IssueRequestParams(amount, BIGCORP_NAME, "1", BOC_NAME, notaryName)
}
private fun printHelp(parser: OptionParser) {
println("""
Usage: bank-of-corda --role ISSUER
bank-of-corda --role (ISSUE_CASH_RPC|ISSUE_CASH_WEB) --quantity <quantity> --currency <currency>
Please refer to the documentation in docs/build/index.html for more info.
""".trimIndent())
parser.printHelpOn(System.out)
}
enum class Role {
ISSUE_CASH_RPC,
ISSUE_CASH_WEB,
}
}

View File

@ -1,7 +1,5 @@
package net.corda.bank.api
import net.corda.bank.BOC_RPC_PWD
import net.corda.bank.BOC_RPC_USER
import net.corda.bank.api.BankOfCordaWebApi.IssueRequestParams
import net.corda.client.rpc.CordaRPCClient
import net.corda.core.messaging.startFlow
@ -16,6 +14,9 @@ import net.corda.testing.http.HttpApi
* Interface for communicating with Bank of Corda node
*/
object BankOfCordaClientApi {
const val BOC_RPC_USER = "bankUser"
const val BOC_RPC_PWD = "test"
/**
* HTTP API
*/
@ -40,7 +41,8 @@ object BankOfCordaClientApi {
// Resolve parties via RPC
val issueToParty = rpc.wellKnownPartyFromX500Name(params.issueToPartyName)
?: throw IllegalStateException("Unable to locate ${params.issueToPartyName} in Network Map Service")
val notaryLegalIdentity = rpc.notaryIdentities().firstOrNull { it.name == params.notaryName } ?: throw IllegalStateException("Couldn't locate notary ${params.notaryName} in NetworkMapCache")
val notaryLegalIdentity = rpc.notaryIdentities().firstOrNull { it.name == params.notaryName }
?: throw IllegalStateException("Couldn't locate notary ${params.notaryName} in NetworkMapCache")
val anonymous = true
val issuerBankPartyRef = OpaqueBytes.of(params.issuerBankPartyRef.toByte())

View File

@ -49,19 +49,229 @@ publishing {
task deployNodes(dependsOn: ['deployNodesSingle', 'deployNodesRaft', 'deployNodesBFT', 'deployNodesCustom'])
task deployNodesSingle(type: Cordform, dependsOn: 'jar') {
definitionClass = 'net.corda.notarydemo.SingleNotaryCordform'
directory file("$buildDir/nodes/nodesSingle")
nodeDefaults {
extraConfig = [h2Settings: [address: "localhost:0"]]
}
node {
name "O=Alice Corp,L=Madrid,C=ES"
p2pPort 10002
rpcSettings {
address "localhost:10003"
adminAddress "localhost:10103"
}
rpcUsers = [[user: "demou", password: "demop", permissions: ["ALL"]]]
}
node {
name "O=Bob Plc,L=Rome,C=IT"
p2pPort 10005
rpcSettings {
address "localhost:10006"
adminAddress "localhost:10106"
}
}
node {
name "O=Notary Service,L=Zurich,C=CH"
p2pPort 10009
rpcSettings {
address "localhost:10010"
adminAddress "localhost:10110"
}
notary = [validating: true]
}
}
task deployNodesCustom(type: Cordform, dependsOn: 'jar') {
definitionClass = 'net.corda.notarydemo.CustomNotaryCordform'
directory file("$buildDir/nodes/nodesCustom")
nodeDefaults {
extraConfig = [h2Settings: [address: "localhost:0"]]
}
node {
name "O=Alice Corp,L=Madrid,C=ES"
p2pPort 10002
rpcSettings {
address "localhost:10003"
adminAddress "localhost:10103"
}
rpcUsers = [[user: "demou", password: "demop", permissions: ["ALL"]]]
}
node {
name "O=Bob Plc,L=Rome,C=IT"
p2pPort 10005
rpcSettings {
address "localhost:10006"
adminAddress "localhost:10106"
}
}
node {
name "O=Notary Service,L=Zurich,C=CH"
p2pPort 10009
rpcSettings {
address "localhost:10010"
adminAddress "localhost:10110"
}
notary = [validating: true, "custom": true]
}
}
task deployNodesRaft(type: Cordform, dependsOn: 'jar') {
definitionClass = 'net.corda.notarydemo.RaftNotaryCordform'
directory file("$buildDir/nodes/nodesRaft")
nodeDefaults {
extraConfig = [h2Settings: [address: "localhost:0"]]
}
node {
name "O=Alice Corp,L=Madrid,C=ES"
p2pPort 10002
rpcSettings {
address "localhost:10003"
adminAddress "localhost:10103"
}
rpcUsers = [[user: "demou", password: "demop", permissions: ["ALL"]]]
}
node {
name "O=Bob Plc,L=Rome,C=IT"
p2pPort 10005
rpcSettings {
address "localhost:10006"
adminAddress "localhost:10106"
}
}
node {
name "O=Notary Service 0,L=Zurich,C=CH"
p2pPort 10009
rpcSettings {
address "localhost:10010"
adminAddress "localhost:10110"
}
notary = [
validating: true,
serviceLegalName: "O=Raft,L=Zurich,C=CH",
raft: [
nodeAddress: "localhost:10008"
]
]
}
node {
name "O=Notary Service 1,L=Zurich,C=CH"
p2pPort 10013
rpcSettings {
address "localhost:10014"
adminAddress "localhost:10114"
}
notary = [
validating: true,
serviceLegalName: "O=Raft,L=Zurich,C=CH",
raft: [
nodeAddress: "localhost:10012",
clusterAddresses: ["localhost:10008"]
]
]
}
node {
name "O=Notary Service 2,L=Zurich,C=CH"
p2pPort 10017
rpcSettings {
address "localhost:10018"
adminAddress "localhost:10118"
}
notary = [
validating: true,
serviceLegalName: "O=Raft,L=Zurich,C=CH",
raft: [
nodeAddress: "localhost:10016",
clusterAddresses: ["localhost:10008"]
]
]
}
}
task deployNodesBFT(type: Cordform, dependsOn: 'jar') {
definitionClass = 'net.corda.notarydemo.BFTNotaryCordform'
def clusterAddresses = ["localhost:11000", "localhost:11010", "localhost:11020", "localhost:11030"]
directory file("$buildDir/nodes/nodesBFT")
nodeDefaults {
extraConfig = [h2Settings: [address: "localhost:0"]]
}
node {
name "O=Alice Corp,L=Madrid,C=ES"
p2pPort 10002
rpcSettings {
address "localhost:10003"
adminAddress "localhost:10103"
}
rpcUsers = [[user: "demou", password: "demop", permissions: ["ALL"]]]
}
node {
name "O=Bob Plc,L=Rome,C=IT"
p2pPort 10005
rpcSettings {
address "localhost:10006"
adminAddress "localhost:10106"
}
}
node {
name "O=Notary Service 0,L=Zurich,C=CH"
p2pPort 10009
rpcSettings {
address "localhost:10010"
adminAddress "localhost:10110"
}
notary = [
validating: false,
serviceLegalName: "O=BFT,L=Zurich,C=CH",
bftSMaRt: [
replicaId: 0,
clusterAddresses: clusterAddresses
]
]
}
node {
name "O=Notary Service 1,L=Zurich,C=CH"
p2pPort 10013
rpcSettings {
address "localhost:10014"
adminAddress "localhost:10114"
}
notary = [
validating: false,
serviceLegalName: "O=BFT,L=Zurich,C=CH",
bftSMaRt: [
replicaId: 0,
clusterAddresses: clusterAddresses
]
]
}
node {
name "O=Notary Service 2,L=Zurich,C=CH"
p2pPort 10017
rpcSettings {
address "localhost:10018"
adminAddress "localhost:10118"
}
notary = [
validating: false,
serviceLegalName: "O=BFT,L=Zurich,C=CH",
bftSMaRt: [
replicaId: 0,
clusterAddresses: clusterAddresses
]
]
}
node {
name "O=Notary Service 3,L=Zurich,C=CH"
p2pPort 10021
rpcSettings {
address "localhost:10022"
adminAddress "localhost:10122"
}
notary = [
validating: false,
serviceLegalName: "O=BFT,L=Zurich,C=CH",
bftSMaRt: [
replicaId: 0,
clusterAddresses: clusterAddresses
]
]
}
}
task notarise(type: JavaExec) {

View File

@ -1,93 +0,0 @@
package net.corda.notarydemo
import net.corda.cordform.CordformContext
import net.corda.cordform.CordformDefinition
import net.corda.cordform.CordformNode
import net.corda.core.identity.CordaX500Name
import net.corda.core.utilities.NetworkHostAndPort
import net.corda.node.services.config.BFTSMaRtConfiguration
import net.corda.node.services.config.NotaryConfig
import net.corda.node.services.transactions.minCorrectReplicas
import net.corda.nodeapi.internal.DevIdentityGenerator
import net.corda.testing.node.internal.demorun.*
import net.corda.testing.core.ALICE_NAME
import net.corda.testing.core.BOB_NAME
import java.nio.file.Paths
fun main(args: Array<String>) = BFTNotaryCordform().nodeRunner().deployAndRunNodes()
private const val clusterSize = 4 // Minimum size that tolerates a faulty replica.
private val notaryNames = createNotaryNames(clusterSize)
// This is not the intended final design for how to use CordformDefinition, please treat this as experimental and DO
// NOT use this as a design to copy.
class BFTNotaryCordform : CordformDefinition() {
private val clusterName = CordaX500Name("BFT", "Zurich", "CH")
init {
nodesDirectory = Paths.get("build", "nodes", "nodesBFT")
node {
name(ALICE_NAME)
p2pPort(10002)
rpcSettings {
address("localhost:10003")
adminAddress("localhost:10103")
}
rpcUsers(notaryDemoUser)
devMode(true)
extraConfig = mapOf("h2Settings" to mapOf("address" to "localhost:0"))
}
node {
name(BOB_NAME)
p2pPort(10005)
rpcSettings {
address("localhost:10006")
adminAddress("localhost:10106")
}
devMode(true)
extraConfig = mapOf("h2Settings" to mapOf("address" to "localhost:0"))
}
val clusterAddresses = (0 until clusterSize).map { NetworkHostAndPort("localhost", 11000 + it * 10) }
fun notaryNode(replicaId: Int, configure: CordformNode.() -> Unit) = node {
name(notaryNames[replicaId])
notary(NotaryConfig(validating = false, serviceLegalName = clusterName, bftSMaRt = BFTSMaRtConfiguration(replicaId, clusterAddresses)))
extraConfig = mapOf("h2Settings" to mapOf("address" to "localhost:0"))
configure()
}
notaryNode(0) {
p2pPort(10009)
rpcSettings {
address("localhost:10010")
adminAddress("localhost:10110")
}
devMode(true)
}
notaryNode(1) {
p2pPort(10013)
rpcSettings {
address("localhost:10014")
adminAddress("localhost:10114")
}
devMode(true)
}
notaryNode(2) {
p2pPort(10017)
rpcSettings {
address("localhost:10018")
adminAddress("localhost:10118")
}
devMode(true)
}
notaryNode(3) {
p2pPort(10021)
rpcSettings {
address("localhost:10022")
adminAddress("localhost:10122")
}
devMode(true)
}
}
override fun setup(context: CordformContext) {
}
}

View File

@ -1,9 +0,0 @@
package net.corda.notarydemo
import net.corda.testing.node.internal.demorun.nodeRunner
fun main(args: Array<String>) {
listOf(SingleNotaryCordform(), RaftNotaryCordform(), BFTNotaryCordform()).map { it.nodeRunner() }.forEach {
it.clean()
}
}

View File

@ -1,52 +0,0 @@
package net.corda.notarydemo
import net.corda.cordform.CordformContext
import net.corda.cordform.CordformDefinition
import net.corda.node.services.config.NotaryConfig
import net.corda.testing.node.internal.demorun.*
import net.corda.testing.core.ALICE_NAME
import net.corda.testing.core.BOB_NAME
import net.corda.testing.core.DUMMY_NOTARY_NAME
import java.nio.file.Paths
fun main(args: Array<String>) = CustomNotaryCordform().nodeRunner().deployAndRunNodes()
class CustomNotaryCordform : CordformDefinition() {
init {
nodesDirectory = Paths.get("build", "nodes", "nodesCustom")
node {
name(ALICE_NAME)
p2pPort(10002)
rpcSettings {
address("localhost:10003")
adminAddress("localhost:10103")
}
rpcUsers(notaryDemoUser)
devMode(true)
extraConfig = mapOf("h2Settings" to mapOf("address" to "localhost:0"))
}
node {
name(BOB_NAME)
p2pPort(10005)
rpcSettings {
address("localhost:10006")
adminAddress("localhost:10106")
}
devMode(true)
extraConfig = mapOf("h2Settings" to mapOf("address" to "localhost:0"))
}
node {
name(DUMMY_NOTARY_NAME)
p2pPort(10009)
rpcSettings {
address("localhost:10010")
adminAddress("localhost:10110")
}
notary(NotaryConfig(validating = true, custom = true))
devMode(true)
extraConfig = mapOf("h2Settings" to mapOf("address" to "localhost:0"))
}
}
override fun setup(context: CordformContext) {}
}

View File

@ -17,7 +17,7 @@ import java.util.concurrent.Future
fun main(args: Array<String>) {
val address = NetworkHostAndPort("localhost", 10003)
println("Connecting to the recipient node ($address)")
CordaRPCClient(address).start(notaryDemoUser.username, notaryDemoUser.password).use {
CordaRPCClient(address).start("demou", "demop").use {
NotaryDemoClientApi(it.proxy).notarise(10)
}
}

View File

@ -1,86 +0,0 @@
package net.corda.notarydemo
import net.corda.cordform.CordformContext
import net.corda.cordform.CordformDefinition
import net.corda.cordform.CordformNode
import net.corda.core.identity.CordaX500Name
import net.corda.core.utilities.NetworkHostAndPort
import net.corda.node.services.config.NotaryConfig
import net.corda.node.services.config.RaftConfig
import net.corda.nodeapi.internal.DevIdentityGenerator
import net.corda.testing.node.internal.demorun.*
import net.corda.testing.core.ALICE_NAME
import net.corda.testing.core.BOB_NAME
import java.nio.file.Paths
fun main(args: Array<String>) = RaftNotaryCordform().nodeRunner().deployAndRunNodes()
internal fun createNotaryNames(clusterSize: Int) = (0 until clusterSize).map { CordaX500Name("Notary Service $it", "Zurich", "CH") }
private val notaryNames = createNotaryNames(3)
// This is not the intended final design for how to use CordformDefinition, please treat this as experimental and DO
// NOT use this as a design to copy.
class RaftNotaryCordform : CordformDefinition() {
private val clusterName = CordaX500Name("Raft", "Zurich", "CH")
init {
nodesDirectory = Paths.get("build", "nodes", "nodesRaft")
node {
name(ALICE_NAME)
p2pPort(10002)
rpcSettings {
address("localhost:10003")
adminAddress("localhost:10103")
}
rpcUsers(notaryDemoUser)
devMode(true)
extraConfig = mapOf("h2Settings" to mapOf("address" to "localhost:0"))
}
node {
name(BOB_NAME)
p2pPort(10005)
rpcSettings {
address("localhost:10006")
adminAddress("localhost:10106")
}
devMode(true)
extraConfig = mapOf("h2Settings" to mapOf("address" to "localhost:0"))
}
fun notaryNode(index: Int, nodePort: Int, clusterPort: Int? = null, configure: CordformNode.() -> Unit) = node {
name(notaryNames[index])
val clusterAddresses = if (clusterPort != null) listOf(NetworkHostAndPort("localhost", clusterPort)) else emptyList()
notary(NotaryConfig(validating = true, serviceLegalName = clusterName, raft = RaftConfig(NetworkHostAndPort("localhost", nodePort), clusterAddresses)))
extraConfig = mapOf("h2Settings" to mapOf("address" to "localhost:0"))
configure()
devMode(true)
}
notaryNode(0, 10008) {
p2pPort(10009)
rpcSettings {
address("localhost:10010")
adminAddress("localhost:10110")
}
devMode(true)
}
notaryNode(1, 10012, 10008) {
p2pPort(10013)
rpcSettings {
address("localhost:10014")
adminAddress("localhost:10114")
}
devMode(true)
}
notaryNode(2, 10016, 10008) {
p2pPort(10017)
rpcSettings {
address("localhost:10018")
adminAddress("localhost:10118")
}
devMode(true)
}
}
override fun setup(context: CordformContext) {
}
}

View File

@ -1,58 +0,0 @@
package net.corda.notarydemo
import net.corda.cordform.CordformContext
import net.corda.cordform.CordformDefinition
import net.corda.node.services.Permissions.Companion.all
import net.corda.node.services.config.NotaryConfig
import net.corda.testing.core.ALICE_NAME
import net.corda.testing.core.BOB_NAME
import net.corda.testing.core.DUMMY_NOTARY_NAME
import net.corda.testing.node.User
import net.corda.testing.node.internal.demorun.*
import java.nio.file.Paths
fun main(args: Array<String>) = SingleNotaryCordform().nodeRunner().deployAndRunNodes()
val notaryDemoUser = User("demou", "demop", setOf(all()))
// This is not the intended final design for how to use CordformDefinition, please treat this as experimental and DO
// NOT use this as a design to copy.
class SingleNotaryCordform : CordformDefinition() {
init {
nodesDirectory = Paths.get("build", "nodes", "nodesSingle")
node {
name(ALICE_NAME)
p2pPort(10002)
rpcSettings {
address("localhost:10003")
adminAddress("localhost:10103")
}
rpcUsers(notaryDemoUser)
devMode(true)
extraConfig = mapOf("h2Settings" to mapOf("address" to "localhost:0"))
}
node {
name(BOB_NAME)
p2pPort(10005)
rpcSettings {
address("localhost:10006")
adminAddress("localhost:10106")
}
devMode(true)
extraConfig = mapOf("h2Settings" to mapOf("address" to "localhost:0"))
}
node {
name(DUMMY_NOTARY_NAME)
p2pPort(10009)
rpcSettings {
address("localhost:10010")
adminAddress("localhost:10110")
}
notary(NotaryConfig(validating = true))
devMode(true)
extraConfig = mapOf("h2Settings" to mapOf("address" to "localhost:0"))
}
}
override fun setup(context: CordformContext) {}
}

View File

@ -26,7 +26,6 @@ sourceSets {
dependencies {
compile project(':test-utils')
compile "net.corda.plugins:cordform-common:$gradle_plugins_version"
// Integration test helpers
testCompile "org.assertj:assertj-core:$assertj_version"

View File

@ -1,14 +1,11 @@
package net.corda.testing.node.internal
import com.google.common.collect.HashMultimap
import com.google.common.util.concurrent.ThreadFactoryBuilder
import com.typesafe.config.Config
import com.typesafe.config.ConfigFactory
import com.typesafe.config.ConfigRenderOptions
import com.typesafe.config.ConfigValueFactory
import net.corda.client.rpc.internal.createCordaRPCClientWithInternalSslAndClassLoader
import net.corda.cordform.CordformContext
import net.corda.cordform.CordformNode
import net.corda.core.concurrent.CordaFuture
import net.corda.core.concurrent.firstOf
import net.corda.core.identity.CordaX500Name
@ -33,7 +30,6 @@ import net.corda.node.utilities.registration.NodeRegistrationHelper
import net.corda.nodeapi.internal.DevIdentityGenerator
import net.corda.nodeapi.internal.SignedNodeInfo
import net.corda.nodeapi.internal.addShutdownHook
import net.corda.nodeapi.internal.config.parseAs
import net.corda.nodeapi.internal.config.toConfig
import net.corda.nodeapi.internal.crypto.X509KeyStore
import net.corda.nodeapi.internal.crypto.X509Utilities
@ -52,8 +48,6 @@ import net.corda.testing.internal.setGlobalSerialization
import net.corda.testing.node.ClusterSpec
import net.corda.testing.node.NotarySpec
import net.corda.testing.node.User
import net.corda.testing.node.internal.DriverDSLImpl.ClusterType.NON_VALIDATING_RAFT
import net.corda.testing.node.internal.DriverDSLImpl.ClusterType.VALIDATING_RAFT
import net.corda.testing.node.internal.DriverDSLImpl.Companion.cordappsInCurrentAndAdditionalPackages
import okhttp3.OkHttpClient
import okhttp3.Request
@ -309,97 +303,6 @@ class DriverDSLImpl(
NON_VALIDATING_BFT(false, CordaX500Name("BFT", "Zurich", "CH"))
}
// TODO remove this
internal fun startCordformNodes(cordforms: List<CordformNode>): CordaFuture<*> {
check(notarySpecs.isEmpty()) { "Specify notaries in the CordformDefinition" }
check(compatibilityZone == null) { "Cordform nodes cannot be run with compatibilityZoneURL" }
val clusterNodes = HashMultimap.create<ClusterType, CordaX500Name>()
val notaryInfos = ArrayList<NotaryInfo>()
// Go though the node definitions and pick out the notaries so that we can generate their identities to be used
// in the network parameters
for (cordform in cordforms) {
if (cordform.notary == null) continue
val name = CordaX500Name.parse(cordform.name)
val notaryConfig = ConfigFactory.parseMap(cordform.notary).parseAs<NotaryConfig>()
// We need to first group the nodes that form part of a cluster. We assume for simplicity that nodes of the
// same cluster type and validating flag are part of the same cluster.
when {
notaryConfig.raft != null -> {
val key = if (notaryConfig.validating) VALIDATING_RAFT else NON_VALIDATING_RAFT
clusterNodes.put(key, name)
}
notaryConfig.bftSMaRt != null -> clusterNodes.put(ClusterType.NON_VALIDATING_BFT, name)
else -> {
// We have all we need here to generate the identity for single node notaries
val identity = DevIdentityGenerator.installKeyStoreWithNodeIdentity(baseDirectory(name), legalName = name)
notaryInfos += NotaryInfo(identity, notaryConfig.validating)
}
}
}
clusterNodes.asMap().forEach { type, nodeNames ->
val identity = if (type == ClusterType.NON_VALIDATING_RAFT || type == ClusterType.VALIDATING_RAFT) {
DevIdentityGenerator.generateDistributedNotarySingularIdentity(
dirs = nodeNames.map { baseDirectory(it) },
notaryName = type.clusterName
)
} else {
DevIdentityGenerator.generateDistributedNotaryCompositeIdentity(
dirs = nodeNames.map { baseDirectory(it) },
notaryName = type.clusterName
)
}
notaryInfos += NotaryInfo(identity, type.validating)
}
val localNetworkMap = LocalNetworkMap(notaryInfos)
return cordforms.map {
val startedNode = startCordformNode(it, localNetworkMap)
if (it.webAddress != null) {
// Start a webserver if an address for it was specified
startedNode.flatMap { startWebserver(it) }
} else {
startedNode
}
}.transpose()
}
// TODO remove this
private fun startCordformNode(cordform: CordformNode, localNetworkMap: LocalNetworkMap): CordaFuture<NodeHandle> {
val name = CordaX500Name.parse(cordform.name)
// TODO We shouldn't have to allocate an RPC or web address if they're not specified. We're having to do this because of startNodeInternal
val rpcAddress = if (cordform.rpcAddress == null) {
val overrides = mutableMapOf<String, Any>("rpcSettings.address" to portAllocation.nextHostAndPort().toString())
cordform.config.apply {
overrides += "rpcSettings.adminAddress" to portAllocation.nextHostAndPort().toString()
}
overrides
} else {
val overrides = mutableMapOf<String, Any>()
cordform.config.apply {
overrides += "rpcSettings.adminAddress" to portAllocation.nextHostAndPort().toString()
}
overrides
}
val webAddress = cordform.webAddress?.let { NetworkHostAndPort.parse(it) } ?: portAllocation.nextHostAndPort()
val notary = if (cordform.notary != null) mapOf("notary" to cordform.notary) else emptyMap()
val rpcUsers = cordform.rpcUsers
val rawConfig = cordform.config + rpcAddress + notary + mapOf(
"rpcUsers" to if (rpcUsers.isEmpty()) defaultRpcUserList else rpcUsers
)
val typesafe = ConfigHelper.loadConfig(
baseDirectory = baseDirectory(name),
allowMissingConfig = true,
configOverrides = rawConfig.toNodeOnly()
)
val config = NodeConfig(typesafe).checkAndOverrideForInMemoryDB()
return startNodeInternal(config, webAddress, null, "512m", localNetworkMap, emptySet())
}
@Suppress("DEPRECATION")
private fun queryWebserver(handle: NodeHandle, process: Process): WebserverHandle {
val protocol = if ((handle as NodeHandleInternal).useHTTPS) "https://" else "http://"
@ -993,7 +896,7 @@ private class NetworkVisibilityController {
}
}
interface InternalDriverDSL : DriverDSL, CordformContext {
interface InternalDriverDSL : DriverDSL {
private companion object {
private val DEFAULT_POLL_INTERVAL = 500.millis
private const val DEFAULT_WARN_COUNT = 120
@ -1001,7 +904,7 @@ interface InternalDriverDSL : DriverDSL, CordformContext {
val shutdownManager: ShutdownManager
override fun baseDirectory(nodeName: String): Path = baseDirectory(CordaX500Name.parse(nodeName))
fun baseDirectory(nodeName: String): Path = baseDirectory(CordaX500Name.parse(nodeName))
/**
* Polls a function until it returns a non-null value. Note that there is no timeout on the polling.
@ -1205,4 +1108,5 @@ private fun Config.toNodeOnly(): Config {
return if (hasPath("webAddress")) withoutPath("webAddress").withoutPath("useHTTPS") else this
}
internal fun DriverParameters.cordappsForAllNodes(): Set<TestCorDapp> = cordappsForAllNodes ?: cordappsInCurrentAndAdditionalPackages(extraCordappPackagesToScan)
internal fun DriverParameters.cordappsForAllNodes(): Set<TestCorDapp> = cordappsForAllNodes
?: cordappsInCurrentAndAdditionalPackages(extraCordappPackagesToScan)

View File

@ -1,78 +0,0 @@
package net.corda.testing.node.internal.demorun
import net.corda.cordform.CordformDefinition
import net.corda.cordform.CordformNode
import net.corda.core.internal.deleteRecursively
import net.corda.core.utilities.NetworkHostAndPort
import net.corda.core.utilities.getOrThrow
import net.corda.testing.driver.JmxPolicy
import net.corda.testing.driver.PortAllocation
import net.corda.testing.node.internal.DriverDSLImpl.Companion.cordappsInCurrentAndAdditionalPackages
import net.corda.testing.node.internal.internalDriver
/**
* Creates a demo runner for this cordform definition
*/
fun CordformDefinition.nodeRunner() = CordformNodeRunner(this)
/**
* A node runner creates and runs nodes for a given [[CordformDefinition]].
*/
class CordformNodeRunner(private val cordformDefinition: CordformDefinition) {
private var extraPackagesToScan = emptyList<String>()
/**
* Builder method to sets the extra cordapp scan packages
*/
fun scanPackages(packages: List<String>): CordformNodeRunner {
extraPackagesToScan = packages
return this
}
fun clean() {
System.err.println("Deleting: ${cordformDefinition.nodesDirectory}")
cordformDefinition.nodesDirectory.deleteRecursively()
}
/**
* Deploy the nodes specified in the given [CordformDefinition]. This will block until all the nodes and webservers
* have terminated.
*/
fun deployAndRunNodes() {
runNodes(waitForAllNodesToFinish = true) { }
}
/**
* Deploy the nodes specified in the given [CordformDefinition] and then execute the given [block] once all the nodes
* and webservers are up. After execution all these processes will be terminated.
*/
fun deployAndRunNodesAndThen(block: () -> Unit) {
runNodes(waitForAllNodesToFinish = false, block = block)
}
private fun runNodes(waitForAllNodesToFinish: Boolean, block: () -> Unit) {
clean()
val nodes = cordformDefinition.nodeConfigurers.map { configurer -> CordformNode().also { configurer.accept(it) } }
val maxPort = nodes
.flatMap { listOf(it.p2pAddress, it.rpcAddress, it.webAddress) }
.mapNotNull { address -> address?.let { NetworkHostAndPort.parse(it).port } }
.max()!!
internalDriver(
jmxPolicy = JmxPolicy(true),
driverDirectory = cordformDefinition.nodesDirectory,
// Notaries are manually specified in Cordform so we don't want the driver automatically starting any
notarySpecs = emptyList(),
// Start from after the largest port used to prevent port clash
portAllocation = PortAllocation.Incremental(maxPort + 1),
waitForAllNodesToFinish = waitForAllNodesToFinish,
cordappsForAllNodes = cordappsInCurrentAndAdditionalPackages(extraPackagesToScan)
) {
cordformDefinition.setup(this)
startCordformNodes(nodes).getOrThrow() // Only proceed once everything is up and running
println("All nodes and webservers are ready...")
block()
}
}
}

View File

@ -1,34 +0,0 @@
@file:JvmName("CordformUtils")
package net.corda.testing.node.internal.demorun
import net.corda.cordform.CordformDefinition
import net.corda.cordform.CordformNode
import net.corda.cordform.RpcSettings
import net.corda.cordform.SslOptions
import net.corda.core.identity.CordaX500Name
import net.corda.node.services.config.NotaryConfig
import net.corda.nodeapi.internal.config.toConfig
import net.corda.testing.node.User
fun CordformDefinition.node(configure: CordformNode.() -> Unit) {
addNode { cordformNode -> cordformNode.configure() }
}
fun CordformNode.name(name: CordaX500Name) = name(name.toString())
fun CordformNode.rpcUsers(vararg users: User) {
rpcUsers = users.map { it.toConfig().root().unwrapped() }
}
fun CordformNode.notary(notaryConfig: NotaryConfig) {
notary = notaryConfig.toConfig().root().unwrapped()
}
fun CordformNode.rpcSettings(configure: RpcSettings.() -> Unit) {
RpcSettings().also(configure).also(this::rpcSettings)
}
fun RpcSettings.ssl(configure: SslOptions.() -> Unit) {
SslOptions().also(configure).also(this::ssl)
}

View File

@ -56,8 +56,6 @@ dependencies {
// Controls FX: more java FX components http://fxexperience.com/controlsfx/
compile "org.controlsfx:controlsfx:$controlsfx_version"
compile "net.corda.plugins:cordform-common:$gradle_plugins_version"
compile project(':client:rpc')
compile project(':finance')