Merged in irsdemowindows (pull request #125)

IRS Demo support on Windows - Replaced shell scripts with Kotlin demo runner.
This commit is contained in:
Clinton Alexander 2016-06-09 09:59:53 +01:00
commit ff467beaec
5 changed files with 456 additions and 174 deletions

View File

@ -12,23 +12,35 @@ so far. We have:
The demos create node data directories in the root of the project. If something goes wrong with them, blow away the
directories and try again.
.. warning:: Corda is developed on MacOS and works best on UNIX systems. The trader demo is easily run on Windows but
you won't get the nice coloured output. The IRS demo relies on a shell script wrapper and isn't so easily run on
Windows currently: we will fix this soon.
.. note:: Corda is developed on MacOS and works best on UNIX systems. Both demos are easily run on Windows but
you won't get the nice coloured output.
Trader demo
-----------
.. note:: On Windows, use the same commands, but run the batch file instead of the shell file (add .bat to the command)
Open two terminals, and in the first run:
Open two terminals, and in the first run:::
.. note:: If you are planning to use non-default configuration you will need to run with --role=SetupA and --role=SetupB
beforehand with the same parameters you plan to supply to the respective nodes.
gradle installDist && ./build/install/r3prototyping/bin/trader-demo --role=BUYER
**Windows**::
gradlew.bat & .\build\install\r3prototyping\bin\trader-demo --role=BUYER
**Other**::
Other: ./gradlew installDist && ./build/install/r3prototyping/bin/trader-demo --role=BUYER
It will compile things, if necessary, then create a directory named trader-demo/buyer with a bunch of files inside and
start the node. You should see it waiting for a trade to begin.
In the second terminal, run::
In the second terminal, run:
**Windows**::
.\build\install\r3prototyping\bin\trader-demo --role=SELLER
**Other**::
./build/install/r3prototyping/bin/trader-demo --role=SELLER
@ -41,26 +53,48 @@ If it doesn't work, jump on the mailing list and let us know.
IRS demo
--------
.. warning:: This demo currently works best on MacOS or Linux
Open three terminals. In the first run:
Open three terminals. In the first run:::
**Windows**::
./scripts/irs-demo.sh nodeA
gradlew.bat installDist & .\build\install\r3prototyping\bin\irsdemo.bat --role=NodeA
And in the second run:::
**Other**::
./scripts/irs-demo.sh nodeB
./gradlew installDist && ./build/install/r3prototyping/bin/irsdemo --role=NodeA
And in the second run:
**Windows**::
.\build\install\r3prototyping\bin\irsdemo.bat --role=NodeB
**Other**::
./build/install/r3prototyping/bin/irsdemo --role=NodeB
The node in the first terminal will complain that it didn't know about nodeB, so restart it. It'll then find the
location and identity keys of nodeA and be happy. NodeB also doubles up as the interest rates oracle and you should
see some rates data get loaded.
Now in the third terminal run:::
Now in the third terminal run:
./scripts/irs-demo.sh trade trade1
**Windows**::
.\build\install\r3prototyping\bin\irsdemo.bat --role=Trade trade1
**Other**::
./build/install/r3prototyping/bin/irsdemo --role=Trade trade1
You should see some activity in the other two terminals as they set up the deal. You can now run this command in
a separate window to roll the fake clock forward and trigger lots of fixing events. Things go fast so make sure you
can see the other terminals whilst you run this command!::
can see the other terminals whilst you run this command!:
./scripts/irs-demo.sh date 2017-01-30
**Windows**::
.\build\install\r3prototyping\bin\irsdemo.bat --role=Date 2017-01-30
**Other**::
./build/install/r3prototyping/bin/irsdemo --role=Date 2017-01-30

View File

@ -1,69 +0,0 @@
#!/bin/bash
mode=$1
if [ ! -e ./gradlew ]; then
echo "Run from the root directory please"
exit 1
fi
if [ ! -d build/install/r3prototyping ] && [[ "$SKIP_INSTALL" == "" ]]; then
./gradlew installDist
fi
if [[ "$mode" == "nodeA" ]]; then
if [ ! -d nodeA ]; then
mkdir nodeA
echo "myLegalName = Bank A" >nodeA/config
fi
RC=83
while [ $RC -eq 83 ]
do
build/install/r3prototyping/bin/irsdemo --dir=nodeA --network-address=localhost \
--fake-trade-with-address=localhost:31340 --fake-trade-with-identity=nodeB/identity-public \
--network-map-identity-file=nodeA/identity-public --network-map-address=localhost
RC=$?
done
elif [[ "$mode" == "nodeB" ]]; then
if [ ! -d nodeB ]; then
mkdir nodeB
echo "myLegalName = Bank B" >nodeB/config
fi
# enable job control
set -o monitor
RC=83
while [ $RC -eq 83 ]
do
build/install/r3prototyping/bin/irsdemo --dir=nodeB --network-address=localhost:31340 \
--fake-trade-with-address=localhost --fake-trade-with-identity=nodeA/identity-public \
--network-map-identity-file=nodeA/identity-public --network-map-address=localhost &
while ! curl -F rates=@scripts/example.rates.txt http://localhost:31341/upload/interest-rates; do
echo "Retry to upload interest rates to oracle after 5 seconds"
sleep 5
done
fg %1
RC=$?
done
elif [[ "$mode" == "trade" && "$2" != "" ]]; then
tradeID=$2
echo "Uploading tradeID ${tradeID}"
sed "s/tradeXXX/${tradeID}/g" scripts/example-irs-trade.json | curl -H "Content-Type: application/json" -d @- http://localhost:31338/api/irs/deals
elif [[ "$mode" == "date" && "$2" != "" ]]; then
demodate=$2
echo "Setting demo date to ${demodate}"
echo "\"$demodate\"" | curl -H "Content-Type: application/json" -X PUT -d @- http://localhost:31338/api/irs/demodate
else
echo "Run like this, one in each tab:"
echo
echo " scripts/irs-demo.sh nodeA"
echo " scripts/irs-demo.sh nodeB"
echo
echo "To upload a trade as e.g. trade10"
echo " scripts/irs-demo.sh trade trade10"
echo
echo "To set the demo date, and post fixings in the interval, to e.g. 2017-01-30"
echo " scripts/irs-demo.sh date 2017-01-30"
fi

View File

@ -1,46 +1,91 @@
package com.r3corda.demos
import com.google.common.net.HostAndPort
import com.typesafe.config.ConfigFactory
import com.r3corda.core.crypto.Party
import com.r3corda.core.logElapsedTime
import com.r3corda.node.internal.Node
import com.r3corda.node.services.config.NodeConfiguration
import com.r3corda.node.services.config.NodeConfigurationFromConfig
import com.r3corda.core.node.NodeInfo
import com.r3corda.node.services.network.NetworkMapService
import com.r3corda.node.services.clientapi.NodeInterestRates
import com.r3corda.node.services.transactions.NotaryService
import com.r3corda.core.node.services.ServiceType
import com.r3corda.node.services.messaging.ArtemisMessagingService
import com.r3corda.core.serialization.deserialize
import com.r3corda.core.utilities.BriefLogFormatter
import com.r3corda.demos.api.InterestRateSwapAPI
import com.r3corda.demos.protocols.AutoOfferProtocol
import com.r3corda.demos.protocols.ExitServerProtocol
import com.r3corda.demos.protocols.UpdateBusinessDayProtocol
import com.r3corda.node.internal.Node
import com.r3corda.node.services.clientapi.NodeInterestRates
import com.r3corda.node.services.config.NodeConfiguration
import com.r3corda.node.services.config.NodeConfigurationFromConfig
import com.r3corda.node.services.messaging.ArtemisMessagingService
import com.r3corda.node.services.network.NetworkMapService
import com.r3corda.node.internal.AbstractNode
import com.r3corda.node.internal.testing.MockNetwork
import com.r3corda.node.services.network.InMemoryMessagingNetwork
import com.r3corda.node.services.transactions.SimpleNotaryService
import com.typesafe.config.ConfigFactory
import joptsimple.OptionParser
import joptsimple.OptionSet
import joptsimple.OptionSpec
import java.io.DataOutputStream
import java.io.File
import java.net.HttpURLConnection
import java.net.URL
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import java.util.*
import kotlin.concurrent.fixedRateTimer
import kotlin.system.exitProcess
import org.apache.commons.io.IOUtils
import java.io.FileNotFoundException
// IRS DEMO
//
// TODO: Please see TBD
// Please see docs/build/html/running-the-trading-demo.html
//
// TODO: TBD
//
// The different roles in the scenario this program can adopt are:
enum class IRSDemoRole {
SetupNodeA,
SetupNodeB,
NodeA,
NodeB,
Trade,
Date
}
private class NodeParams() {
var id: Int = -1
var dir : Path = Paths.get("")
var address : String = ""
var mapAddress: String = ""
var identityFile: Path = Paths.get("")
var tradeWithAddrs: List<String> = listOf()
var tradeWithIdentities: List<Path> = listOf()
var uploadRates: Boolean = false
var defaultLegalName: String = ""
}
private class DemoArgs() {
lateinit var roleArg: OptionSpec<IRSDemoRole>
lateinit var networkAddressArg: OptionSpec<String>
lateinit var dirArg: OptionSpec<String>
lateinit var networkMapIdentityFile: OptionSpec<String>
lateinit var networkMapNetAddr: OptionSpec<String>
lateinit var fakeTradeWithAddr: OptionSpec<String>
lateinit var fakeTradeWithIdentityFile: OptionSpec<String>
lateinit var nonOptions: OptionSpec<String>
}
private class NotSetupException: Throwable {
constructor(message: String): super(message) {}
}
fun main(args: Array<String>) {
val parser = OptionParser()
val networkAddressArg = parser.accepts("network-address").withRequiredArg().required()
val dirArg = parser.accepts("directory").withRequiredArg().defaultsTo("nodedata")
val networkMapIdentityFile = parser.accepts("network-map-identity-file").withRequiredArg()
val networkMapNetAddr = parser.accepts("network-map-address").requiredIf(networkMapIdentityFile).withRequiredArg()
// Use these to list one or more peers (again, will be superseded by discovery implementation)
val fakeTradeWithAddr = parser.accepts("fake-trade-with-address").withRequiredArg().required()
val fakeTradeWithIdentityFile = parser.accepts("fake-trade-with-identity-file").withRequiredArg().required()
val demoArgs = setupArgs(parser)
val options = try {
parser.parse(*args)
} catch (e: Exception) {
@ -52,112 +97,384 @@ fun main(args: Array<String>) {
// Suppress the Artemis MQ noise, and activate the demo logging.
BriefLogFormatter.initVerbose("+demo.irsdemo", "+api-call", "+platform.deal", "-org.apache.activemq")
val dir = Paths.get(options.valueOf(dirArg))
val configFile = dir.resolve("config")
val role = options.valueOf(demoArgs.roleArg)!!
if(role == IRSDemoRole.SetupNodeA) {
val nodeParams = configureNodeParams(IRSDemoRole.NodeA, demoArgs, options)
setup(nodeParams)
} else if(role == IRSDemoRole.SetupNodeB) {
val nodeParams = configureNodeParams(IRSDemoRole.NodeB, demoArgs, options)
setup(nodeParams)
} else if(role == IRSDemoRole.Trade) {
val tradeIdArgs = options.valuesOf(demoArgs.nonOptions)
if (tradeIdArgs.size > 0) {
val tradeId = tradeIdArgs[0]
val host = if (options.has(demoArgs.networkAddressArg)) {
options.valueOf(demoArgs.networkAddressArg)
} else {
"http://localhost:" + (Node.DEFAULT_PORT + 1)
}
if (!Files.exists(dir)) {
Files.createDirectory(dir)
}
if (runTrade(tradeId, host)) {
exitProcess(0)
} else {
exitProcess(1)
}
} else {
println("Please provide a trade ID")
exitProcess(1)
}
} else if(role == IRSDemoRole.Date) {
val dateStrArgs = options.valuesOf(demoArgs.nonOptions)
if (dateStrArgs.size > 0) {
val dateStr = dateStrArgs[0]
val host = if (options.has(demoArgs.networkAddressArg)) {
options.valueOf(demoArgs.networkAddressArg)
} else {
"http://localhost:" + (Node.DEFAULT_PORT + 1)
}
val config = loadConfigFile(configFile)
val advertisedServices: Set<ServiceType>
val myNetAddr = HostAndPort.fromString(options.valueOf(networkAddressArg)).withDefaultPort(Node.DEFAULT_PORT)
val networkMapId = if (options.valueOf(networkMapNetAddr).equals(options.valueOf(networkAddressArg))) {
// This node provides network map and notary services
advertisedServices = setOf(NetworkMapService.Type, SimpleNotaryService.Type)
null
runDateChange(dateStr, host)
} else {
println("Please provide a date")
exitProcess(1)
}
} else {
advertisedServices = setOf(NodeInterestRates.Type)
// If these directory and identity file arguments aren't specified then we can assume a default setup and
// create everything that is needed without needing to run setup.
if(!options.has(demoArgs.dirArg) && !options.has(demoArgs.fakeTradeWithIdentityFile)) {
createNodeConfig(createNodeAParams());
createNodeConfig(createNodeBParams());
}
try {
nodeInfo(options.valueOf(networkMapNetAddr), options.valueOf(networkMapIdentityFile), setOf(NetworkMapService.Type, SimpleNotaryService.Type))
} catch (e: Exception) {
null
runNode(configureNodeParams(role, demoArgs, options))
} catch (e: NotSetupException) {
println(e.message)
exitProcess(1)
}
exitProcess(0)
}
}
private fun setupArgs(parser: OptionParser): DemoArgs {
val args = DemoArgs()
args.roleArg = parser.accepts("role").withRequiredArg().ofType(IRSDemoRole::class.java).required()
args.networkAddressArg = parser.accepts("network-address").withOptionalArg()
args.dirArg = parser.accepts("directory").withOptionalArg()
args.networkMapIdentityFile = parser.accepts("network-map-identity-file").withOptionalArg()
args.networkMapNetAddr = parser.accepts("network-map-address").withRequiredArg().defaultsTo("localhost")
// Use these to list one or more peers (again, will be superseded by discovery implementation)
args.fakeTradeWithAddr = parser.accepts("fake-trade-with-address").withOptionalArg()
args.fakeTradeWithIdentityFile = parser.accepts("fake-trade-with-identity-file").withOptionalArg()
args.nonOptions = parser.nonOptions().ofType(String::class.java)
return args
}
private fun setup(params: NodeParams) {
createNodeConfig(params)
}
private fun runDateChange(date: String, host: String) : Boolean {
val url = URL(host + "/api/irs/demodate")
if(putJson(url, "\"" + date + "\"")) {
println("Date changed")
return true
} else {
println("Date failed to change")
return false
}
}
private fun runTrade(tradeId: String, host: String) : Boolean {
println("Uploading tradeID " + tradeId)
val fileContents = IOUtils.toString(NodeParams::class.java.getResourceAsStream("example-irs-trade.json"))
val tradeFile = fileContents.replace("tradeXXX", tradeId)
val url = URL(host + "/api/irs/deals")
if(postJson(url, tradeFile)) {
println("Trade sent")
return true
} else {
println("Trade failed to send")
return false
}
}
private fun configureNodeParams(role: IRSDemoRole, args: DemoArgs, options: OptionSet): NodeParams {
val nodeParams = when (role) {
IRSDemoRole.NodeA -> createNodeAParams()
IRSDemoRole.NodeB -> createNodeBParams()
else -> {
throw IllegalArgumentException()
}
}
val node = logElapsedTime("Node startup") { Node(dir, myNetAddr, config, networkMapId,
advertisedServices, DemoClock(),
listOf(InterestRateSwapAPI::class.java)).start() }
// TODO: This should all be replaced by the identity service being updated
// as the network map changes.
val hostAndPortStrings = options.valuesOf(fakeTradeWithAddr)
val identityFiles = options.valuesOf(fakeTradeWithIdentityFile)
if (hostAndPortStrings.size != identityFiles.size) {
throw IllegalArgumentException("Different number of peer addresses (${hostAndPortStrings.size}) and identities (${identityFiles.size})")
nodeParams.mapAddress = options.valueOf(args.networkMapNetAddr)
if (options.has(args.dirArg)) {
nodeParams.dir = Paths.get(options.valueOf(args.dirArg))
}
for ((hostAndPortString, identityFile) in hostAndPortStrings.zip(identityFiles)) {
try {
val peerId = nodeInfo(hostAndPortString, identityFile)
node.services.identityService.registerIdentity(peerId.identity)
} catch (e: Exception) {
println("Could not load peer identity file \"$identityFile\".")
}
if (options.has(args.networkAddressArg)) {
nodeParams.address = options.valueOf(args.networkAddressArg)
}
nodeParams.identityFile = if (options.has(args.networkMapIdentityFile)) {
Paths.get(options.valueOf(args.networkMapIdentityFile))
} else {
nodeParams.dir.resolve(AbstractNode.PUBLIC_IDENTITY_FILE_NAME)
}
if (options.has(args.fakeTradeWithIdentityFile)) {
nodeParams.tradeWithIdentities = options.valuesOf(args.fakeTradeWithIdentityFile).map { Paths.get(it) }
}
if (options.has(args.fakeTradeWithAddr)) {
nodeParams.tradeWithAddrs = options.valuesOf(args.fakeTradeWithAddr)
}
return nodeParams
}
private fun runNode(nodeParams : NodeParams) : Unit {
val node = startNode(nodeParams)
// Register handlers for the demo
AutoOfferProtocol.Handler.register(node)
UpdateBusinessDayProtocol.Handler.register(node)
ExitServerProtocol.Handler.register(node)
if(nodeParams.uploadRates) {
runUploadRates()
}
try {
while (true) Thread.sleep(Long.MAX_VALUE)
} catch(e: InterruptedException) {
node.stop()
}
exitProcess(0)
}
fun nodeInfo(hostAndPortString: String, identityFile: String, advertisedServices: Set<ServiceType> = emptySet()): NodeInfo {
try {
val addr = HostAndPort.fromString(hostAndPortString).withDefaultPort(Node.DEFAULT_PORT)
val path = Paths.get(identityFile)
val party = Files.readAllBytes(path).deserialize<Party>()
return NodeInfo(ArtemisMessagingService.makeRecipient(addr), party, advertisedServices)
} catch (e: Exception) {
println("Could not find identify file $identityFile. If the file has just been created as part of starting the demo, please restart this node")
throw e
private fun runUploadRates() {
val fileContents = IOUtils.toString(NodeParams::class.java.getResource("example.rates.txt"))
var timer : Timer? = null
timer = fixedRateTimer("upload-rates", false, 0, 5000, {
try {
val url = URL("http://localhost:31341/upload/interest-rates")
if(uploadFile(url, fileContents)) {
timer!!.cancel()
println("Rates uploaded successfully")
} else {
print("Could not upload rates. Retrying in 5 seconds. ")
}
} catch (e: Exception) {
println("Could not upload rates due to exception. Retrying in 5 seconds")
}
})
}
// Todo: Use a simpler library function for this and handle timeout exceptions
private fun sendJson(url: URL, data: String, method: String) : Boolean {
val connection = url.openConnection() as HttpURLConnection
connection.doOutput = true
connection.useCaches = false
connection.requestMethod = method
connection.connectTimeout = 5000
connection.readTimeout = 5000
connection.setRequestProperty("Connection", "Keep-Alive")
connection.setRequestProperty("Cache-Control", "no-cache")
connection.setRequestProperty("Content-Type", "application/json")
connection.setRequestProperty("Content-Length", data.length.toString())
val outStream = DataOutputStream(connection.outputStream)
outStream.writeBytes(data)
outStream.close()
return when(connection.responseCode) {
200 -> true
201 -> true
else -> {
println("Failed to " + method + " data. Status Code: " + connection.responseCode + ". Mesage: " + connection.responseMessage)
false
}
}
}
private fun loadConfigFile(configFile: Path): NodeConfiguration {
fun askAdminToEditConfig(configFile: Path?) {
println()
println("This is the first run, so you should edit the config file in $configFile and then start the node again.")
println()
exitProcess(1)
private fun putJson(url: URL, data: String) : Boolean {
return sendJson(url, data, "PUT")
}
private fun postJson(url: URL, data: String) : Boolean {
return sendJson(url, data, "POST")
}
// Todo: Use a simpler library function for this and handle timeout exceptions
private fun uploadFile(url: URL, file: String) : Boolean {
val boundary = "===" + System.currentTimeMillis() + "==="
val hyphens = "--"
val clrf = "\r\n"
val connection = url.openConnection() as HttpURLConnection
connection.doOutput = true
connection.doInput = true
connection.useCaches = false
connection.requestMethod = "POST"
connection.connectTimeout = 5000
connection.readTimeout = 5000
connection.setRequestProperty("Connection", "Keep-Alive")
connection.setRequestProperty("Cache-Control", "no-cache")
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary)
val request = DataOutputStream(connection.outputStream)
request.writeBytes(hyphens + boundary + clrf)
request.writeBytes("Content-Disposition: form-data; name=\"rates\" filename=\"example.rates.txt\"" + clrf)
request.writeBytes(clrf)
request.writeBytes(file)
request.writeBytes(clrf)
request.writeBytes(hyphens + boundary + hyphens + clrf)
if (connection.responseCode == 200) {
return true
} else {
println("Could not upload file. Status Code: " + connection + ". Mesage: " + connection.responseMessage)
return false
}
}
private fun createNodeAParams() : NodeParams {
val params = NodeParams()
params.id = 0
params.dir = Paths.get("nodeA")
params.address = "localhost"
params.tradeWithAddrs = listOf("localhost:31340")
params.tradeWithIdentities = listOf(getRoleDir(IRSDemoRole.NodeB).resolve(AbstractNode.PUBLIC_IDENTITY_FILE_NAME))
params.defaultLegalName = "Bank A"
return params
}
private fun createNodeBParams() : NodeParams {
val params = NodeParams()
params.id = 1
params.dir = Paths.get("nodeB")
params.address = "localhost:31340"
params.tradeWithAddrs = listOf("localhost")
params.tradeWithIdentities = listOf(getRoleDir(IRSDemoRole.NodeA).resolve(AbstractNode.PUBLIC_IDENTITY_FILE_NAME))
params.defaultLegalName = "Bank B"
params.uploadRates = true
return params
}
private fun createNodeConfig(params: NodeParams) : NodeConfiguration {
if (!Files.exists(params.dir)) {
Files.createDirectory(params.dir)
}
val defaultLegalName = "Global MegaCorp, Ltd."
if (!Files.exists(configFile)) {
createDefaultConfigFile(configFile, defaultLegalName)
askAdminToEditConfig(configFile)
val configFile = params.dir.resolve("config").toFile()
val config = loadConfigFile(configFile, params.defaultLegalName)
if(!Files.exists(params.dir.resolve(AbstractNode.PUBLIC_IDENTITY_FILE_NAME))) {
createIdentities(params, config)
}
System.setProperty("config.file", configFile.toAbsolutePath().toString())
val config = NodeConfigurationFromConfig(ConfigFactory.load())
// Make sure admin did actually edit at least the legal name.
if (config.myLegalName == defaultLegalName)
askAdminToEditConfig(configFile)
return config
}
private fun createDefaultConfigFile(configFile: Path?, defaultLegalName: String) {
Files.write(configFile,
"""
# Node configuration: give the buyer node the name 'Bank of Zurich' (no quotes)
# The seller node can be named whatever you like.
private fun getNodeConfig(params: NodeParams): NodeConfiguration {
if(!Files.exists(params.dir)) {
throw NotSetupException("Missing config directory. Please run node setup before running the node")
}
myLegalName = $defaultLegalName
if(!Files.exists(params.dir.resolve(AbstractNode.PUBLIC_IDENTITY_FILE_NAME))) {
throw NotSetupException("Missing identity file. Please run node setup before running the node")
}
val configFile = params.dir.resolve("config").toFile()
return loadConfigFile(configFile, params.defaultLegalName)
}
private fun startNode(params : NodeParams) : Node {
val config = getNodeConfig(params)
val advertisedServices: Set<ServiceType>
val myNetAddr = HostAndPort.fromString(params.address).withDefaultPort(Node.DEFAULT_PORT)
val networkMapId = if (params.mapAddress.equals(params.address)) {
// This node provides network map and notary services
advertisedServices = setOf(NetworkMapService.Type, SimpleNotaryService.Type)
null
} else {
advertisedServices = setOf(NodeInterestRates.Type)
nodeInfo(params.mapAddress, params.identityFile, setOf(NetworkMapService.Type, SimpleNotaryService.Type))
}
val node = logElapsedTime("Node startup") { Node(params.dir, myNetAddr, config, networkMapId,
advertisedServices, DemoClock(),
listOf(InterestRateSwapAPI::class.java)).start() }
// TODO: This should all be replaced by the identity service being updated
// as the network map changes.
if (params.tradeWithAddrs.size != params.tradeWithIdentities.size) {
throw IllegalArgumentException("Different number of peer addresses (${params.tradeWithAddrs.size}) and identities (${params.tradeWithIdentities.size})")
}
for ((hostAndPortString, identityFile) in params.tradeWithAddrs.zip(params.tradeWithIdentities)) {
val peerId = nodeInfo(hostAndPortString, identityFile)
node.services.identityService.registerIdentity(peerId.identity)
}
return node
}
private fun getRoleDir(role: IRSDemoRole) : Path {
when(role) {
IRSDemoRole.NodeA -> return Paths.get("nodeA")
IRSDemoRole.NodeB -> return Paths.get("nodeB")
else -> {
throw IllegalArgumentException()
}
}
}
private fun nodeInfo(hostAndPortString: String, identityFile: Path, advertisedServices: Set<ServiceType> = emptySet()): NodeInfo {
try {
val addr = HostAndPort.fromString(hostAndPortString).withDefaultPort(Node.DEFAULT_PORT)
val path = identityFile
val party = Files.readAllBytes(path).deserialize<Party>()
return NodeInfo(ArtemisMessagingService.makeRecipient(addr), party, advertisedServices)
} catch (e: Exception) {
println("Could not find identify file $identityFile.")
throw e
}
}
private fun nodeInfo(handle: InMemoryMessagingNetwork.Handle, identityFile: Path, advertisedServices: Set<ServiceType> = emptySet()): NodeInfo {
try {
val path = identityFile
val party = Files.readAllBytes(path).deserialize<Party>()
return NodeInfo(handle, party, advertisedServices)
} catch (e: Exception) {
println("Could not find identify file $identityFile.")
throw e
}
}
private fun loadConfigFile(configFile: File, defaultLegalName: String): NodeConfiguration {
if (!configFile.exists()) {
createDefaultConfigFile(configFile, defaultLegalName)
println("Default config created at $configFile.")
}
val config = ConfigFactory.parseFile(configFile).withFallback(ConfigFactory.load())
return NodeConfigurationFromConfig(config)
}
private fun createIdentities(params: NodeParams, nodeConf: NodeConfiguration) {
val mockNetwork = MockNetwork(false)
val node = MockNetwork.MockNode(params.dir, nodeConf, mockNetwork, null, setOf(NetworkMapService.Type, SimpleNotaryService.Type), params.id, null)
node.start()
node.stop()
}
private fun createDefaultConfigFile(configFile: File, legalName: String) {
configFile.writeBytes(
"""
myLegalName = $legalName
""".trimIndent().toByteArray())
}
private fun printHelp() {
println("""
Please refer to the documentation that doesn't yet exist to learn how to run the demo.
Please refer to the documentation in docs/build/index.html to learn how to run the demo.
""".trimIndent())
}

View File

@ -3,7 +3,7 @@
"fixedRatePayer": "Bank A",
"notional": {
"quantity": 2500000000,
"token": "USD"
"token": "EUR"
},
"paymentFrequency": "SemiAnnual",
"effectiveDate": "2016-03-11",
@ -28,7 +28,7 @@
"floatingRatePayer": "Bank B",
"notional": {
"quantity": 2500000000,
"token": "USD"
"token": "EUR"
},
"paymentFrequency": "Quarterly",
"effectiveDate": "2016-03-11",