8.0 KiB
Running our CorDapp
Now that we've written a CorDapp, it's time to test it by running it on some real Corda nodes.
Deploying our CorDapp
Let's take a look at the nodes we're going to deploy. Open the project's build file under java-source/build.gradle
or kotlin-source/build.gradle
and scroll down to the task deployNodes
section. This section defines four nodes - the Controller, and NodeA, NodeB and NodeC:
'build']) {
task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ["./build/nodes"
directory "CN=Controller,O=R3,OU=corda,L=London,C=GB"
networkMap
node {"CN=Controller,O=R3,OU=corda,L=London,C=GB"
name "corda.notary.validating"]
advertisedServices = [10002
p2pPort 10003
rpcPort 10004
webPort
cordapps = []
}
node {"CN=NodeA,O=NodeA,L=London,C=GB"
name
advertisedServices = []10005
p2pPort 10006
rpcPort 10007
webPort
cordapps = []"user1", "password": "test", "permissions": []]]
rpcUsers = [[ user:
}
node {"CN=NodeB,O=NodeB,L=New York,C=US"
name
advertisedServices = []10008
p2pPort 10009
rpcPort 10010
webPort
cordapps = []"user1", "password": "test", "permissions": []]]
rpcUsers = [[ user:
}
node {"CN=NodeC,O=NodeC,L=Paris,C=FR"
name
advertisedServices = []10011
p2pPort 10012
rpcPort 10013
webPort
cordapps = []"user1", "password": "test", "permissions": []]]
rpcUsers = [[ user:
} }
We have three standard nodes, plus a special Controller node that is running the network map service, and is also advertising a validating notary service. Feel free to add additional node definitions here to expand the size of the test network.
We can run this deployNodes
task using Gradle. For each node definition, Gradle will:
- Package the project's source files into a CorDapp jar
- Create a new node in
build/nodes
with our CorDapp already installed
We can do that now by running the following commands from the root of the project:
// On Windows
gradlew clean deployNodes
// On Mac
/gradlew clean deployNodes .
Running the nodes
Running deployNodes
will build the nodes under both java-source/build/nodes
and kotlin-source/build/nodes
. If we navigate to one of these folders, we'll see four node folder. Each node folder has the following structure:
.|____corda.jar // The runnable node |____corda-webserver.jar // The node's webserver |____dependencies |____node.conf // The node's configuration file |____plugins |____java/kotlin-source-0.1.jar // Our IOU CorDapp
Let's start the nodes by running the following commands from the root of the project:
// On Windows for a Java CorDapp
-source/build/nodes/runnodes.bat
java
// On Windows for a Kotlin CorDapp
-source/build/nodes/runnodes.bat
kotlin
// On Mac for a Java CorDapp
-source/build/nodes/runnodes
java
// On Mac for a Kotlin CorDapp
-source/build/nodes/runnodes kotlin
This will start a terminal window for each node, and an additional terminal window for each node's webserver - eight terminal windows in all. Give each node a moment to start - you'll know it's ready when its terminal windows displays the message, "Welcome to the Corda interactive shell.".
Interacting with the nodes
Now that our nodes are running, let's order one of them to create an IOU by kicking off our IOUFlow
. In a larger app, we'd generally provide a web API sitting on top of our node. Here, for simplicity, we'll be interacting with the node via its built-in CRaSH shell.
Go to the terminal window displaying the CRaSH shell of Node A. Typing help
will display a list of the available commands.
We want to create an IOU of 100 with Node B. We start the IOUFlow
by typing:
99, arg1: "NodeB" start IOUFlow arg0:
99, otherParty: "NodeB" start IOUFlow iouValue:
Node A and Node B will automatically agree an IOU.
If the flow worked, it should have led to the recording of a new IOU in the vaults of both Node A and Node B. Equally importantly, Node C - although it sits on the same network - should not be aware of this transaction.
We can check the flow has worked by using an RPC operation to check the contents of each node's vault. Typing run
will display a list of the available commands. We can examine the contents of a node's vault by running:
run vaultAndUpdates
And we can also examine a node's transaction storage, by running:
run verifiedTransactions
The vaults of Node A and Node B should both display the following output:
first:- state:
data:99
value: "CN=NodeA,O=NodeA,L=London,C=GB"
lender: "CN=NodeB,O=NodeB,L=New York,C=US"
borrower:
contract:"559322B95BCF7913E3113962DC3F3CBD71C818C66977721580C045DC41C813A5"
legalContractReference:
participants:- "CN=NodeA,O=NodeA,L=London,C=GB"
- "CN=NodeB,O=NodeB,L=New York,C=US"
"CN=Controller,O=R3,OU=corda,L=London,C=GB,OU=corda.notary.validating"
notary:
encumbrance: null
ref:"656A1BF64D5AEEC6F6C944E287F34EF133336F5FC2C5BFB9A0BFAE25E826125F"
txhash: 0
index: "(observable)" second:
But the vault of Node C should output nothing!
first: []"(observable)" second:
Conclusion
We have written a simple CorDapp that allows IOUs to be issued onto the ledger. Like all CorDapps, our CorDapp is made up of three key parts:
- The
IOUState
, representing IOUs on the ledger - The
IOUContract
, controlling the evolution of IOUs over time - The
IOUFlow
, orchestrating the process of agreeing the creation of an IOU on-ledger
Together, these three parts completely determine how IOUs are created and evolved on the ledger.
Next steps
There are a number of improvements we could make to this CorDapp:
- We could require signatures from the lender as well the borrower, to give both parties a say in the creation of a new
IOUState
- We should add unit tests, using the contract-test and flow-test frameworks
- We should change
IOUState.value
from an integer to a proper amount of a given currency - We could add an API, to make it easier to interact with the CorDapp
We will explore some of these improvements in future tutorials. But you should now be ready to develop your own CorDapps. There's a more fleshed-out version of the IOU CorDapp with an API and web front-end, and a set of example CorDapps in the main Corda repo, under samples
. An explanation of how to run these samples here <running-the-demos>
.
As you write CorDapps, you can learn more about the API available here <api>
.
If you get stuck at any point, please reach out on Slack, Discourse, or Stack Overflow.