From 9b6f1c2e9ef65fdc183a9a331c1e0d0b533b0b5f Mon Sep 17 00:00:00 2001 From: Anthony Nixon Date: Fri, 7 Feb 2020 12:53:13 +0000 Subject: [PATCH 1/2] blacklist tested java --- .../.idea/runConfigurations/Debug_CorDapp.xml | 14 -- .../runConfigurations/Run_Contract_Tests.xml | 23 --- .../runConfigurations/Run_Flow_Tests.xml | 23 --- .../.idea/runConfigurations/Unit_tests.xml | 21 --- .../runConfigurations/Upload_blacklist.xml | 15 -- blacklist/README.md | 11 +- blacklist/build.gradle | 128 ++++------------ blacklist/clients-java/build.gradle | 43 ++++++ .../examples/attachments/client/Client.java | 97 ++++++++++++ .../attachments/webserver/Controller.java | 27 ++++ .../webserver/NodeRPCConnection.java | 48 ++++++ .../attachments/webserver/Starter.java | 23 +++ .../src/main/resources/static/app.js | 3 + .../src/main/resources/static/index.html | 10 ++ blacklist/clients-kotlin/build.gradle | 43 ++++++ .../examples/attachments}/client/Client.kt | 2 +- .../attachments/webserver/Controller.kt | 25 +++ .../webserver/NodeRPCConnection.kt | 52 +++++++ .../examples/attachments/webserver/Server.kt | 22 +++ .../src/main/resources/static/app.js | 3 + .../src/main/resources/static/index.html | 10 ++ blacklist/contracts-java/build.gradle | 31 ++++ .../corda/examples/attachments/Constants.java | 28 ++++ .../contracts/AgreementContract.java | 123 +++++++++++++++ .../attachments/states/AgreementState.java | 42 +++++ .../src/main/resources/blacklist.jar | Bin .../src/main/resources/log4j2.xml | 0 .../attachments/contracts/ContractTests.java | 99 ++++++++++++ .../attachments/states/StateTests.java | 41 +++++ blacklist/contracts-kotlin/build.gradle | 35 +++++ .../corda/examples/attachments/Constants.kt | 19 +++ .../contracts}/AgreementContract.kt | 6 +- .../attachments/states}/AgreementState.kt | 4 +- .../src/main/resources/blacklist.jar | Bin 0 -> 460 bytes .../src/main/resources/log4j2.xml | 31 ++++ .../attachments/contracts}/ContractTests.kt | 12 +- .../examples/attachments/states/StateTests.kt | 34 +++++ blacklist/repositories.gradle | 8 - blacklist/settings.gradle | 7 + .../corda/examples/attachments/Constants.kt | 10 -- .../examples/attachments/tests/Constants.kt | 12 -- blacklist/workflows-java/build.gradle | 119 +++++++++++++++ .../examples/attachments/DriverBasedTest.java | 49 ++++++ .../corda/examples/attachments/AgreeFlow.java | 40 +++++ .../examples/attachments/ProposeFlow.java | 60 ++++++++ .../corda/examples/attachments/FlowTests.java | 143 ++++++++++++++++++ .../examples/attachments/NodeDriver.java | 45 ++++++ .../src/test/resources/invalid.jar | Bin blacklist/workflows-kotlin/build.gradle | 116 ++++++++++++++ .../examples/attachments/DriverBasedTest.kt | 47 ++++++ .../attachments}/ReachAgreementFlow.kt | 8 +- .../corda/examples/attachments}/FlowTests.kt | 10 +- .../corda/examples/attachments}/NodeDriver.kt | 5 +- .../src/test/resources/invalid.jar | Bin 0 -> 1198 bytes 54 files changed, 1571 insertions(+), 256 deletions(-) delete mode 100644 blacklist/.idea/runConfigurations/Debug_CorDapp.xml delete mode 100644 blacklist/.idea/runConfigurations/Run_Contract_Tests.xml delete mode 100644 blacklist/.idea/runConfigurations/Run_Flow_Tests.xml delete mode 100644 blacklist/.idea/runConfigurations/Unit_tests.xml delete mode 100644 blacklist/.idea/runConfigurations/Upload_blacklist.xml create mode 100644 blacklist/clients-java/build.gradle create mode 100644 blacklist/clients-java/src/main/java/net/corda/examples/attachments/client/Client.java create mode 100644 blacklist/clients-java/src/main/java/net/corda/examples/attachments/webserver/Controller.java create mode 100644 blacklist/clients-java/src/main/java/net/corda/examples/attachments/webserver/NodeRPCConnection.java create mode 100644 blacklist/clients-java/src/main/java/net/corda/examples/attachments/webserver/Starter.java create mode 100644 blacklist/clients-java/src/main/resources/static/app.js create mode 100644 blacklist/clients-java/src/main/resources/static/index.html create mode 100644 blacklist/clients-kotlin/build.gradle rename blacklist/{src/test/kotlin/net/corda/examples/attachments/tests => clients-kotlin/src/main/kotlin/net/corda/examples/attachments}/client/Client.kt (98%) create mode 100644 blacklist/clients-kotlin/src/main/kotlin/net/corda/examples/attachments/webserver/Controller.kt create mode 100644 blacklist/clients-kotlin/src/main/kotlin/net/corda/examples/attachments/webserver/NodeRPCConnection.kt create mode 100644 blacklist/clients-kotlin/src/main/kotlin/net/corda/examples/attachments/webserver/Server.kt create mode 100644 blacklist/clients-kotlin/src/main/resources/static/app.js create mode 100644 blacklist/clients-kotlin/src/main/resources/static/index.html create mode 100644 blacklist/contracts-java/build.gradle create mode 100644 blacklist/contracts-java/src/main/java/net/corda/examples/attachments/Constants.java create mode 100644 blacklist/contracts-java/src/main/java/net/corda/examples/attachments/contracts/AgreementContract.java create mode 100644 blacklist/contracts-java/src/main/java/net/corda/examples/attachments/states/AgreementState.java rename blacklist/{ => contracts-java}/src/main/resources/blacklist.jar (100%) rename blacklist/{ => contracts-java}/src/main/resources/log4j2.xml (100%) create mode 100644 blacklist/contracts-java/src/test/java/net/corda/examples/attachments/contracts/ContractTests.java create mode 100644 blacklist/contracts-java/src/test/java/net/corda/examples/attachments/states/StateTests.java create mode 100644 blacklist/contracts-kotlin/build.gradle create mode 100644 blacklist/contracts-kotlin/src/main/kotlin/net/corda/examples/attachments/Constants.kt rename blacklist/{src/main/kotlin/net/corda/examples/attachments/contract => contracts-kotlin/src/main/kotlin/net/corda/examples/attachments/contracts}/AgreementContract.kt (95%) rename blacklist/{src/main/kotlin/net/corda/examples/attachments/state => contracts-kotlin/src/main/kotlin/net/corda/examples/attachments/states}/AgreementState.kt (75%) create mode 100644 blacklist/contracts-kotlin/src/main/resources/blacklist.jar create mode 100644 blacklist/contracts-kotlin/src/main/resources/log4j2.xml rename blacklist/{src/test/kotlin/net/corda/examples/attachments/tests/contract => contracts-kotlin/src/test/kotlin/net/corda/examples/attachments/contracts}/ContractTests.kt (85%) create mode 100644 blacklist/contracts-kotlin/src/test/kotlin/net/corda/examples/attachments/states/StateTests.kt delete mode 100644 blacklist/repositories.gradle delete mode 100644 blacklist/src/main/kotlin/net/corda/examples/attachments/Constants.kt delete mode 100644 blacklist/src/test/kotlin/net/corda/examples/attachments/tests/Constants.kt create mode 100644 blacklist/workflows-java/build.gradle create mode 100644 blacklist/workflows-java/src/integrationTest/java/net/corda/examples/attachments/DriverBasedTest.java create mode 100644 blacklist/workflows-java/src/main/java/net/corda/examples/attachments/AgreeFlow.java create mode 100644 blacklist/workflows-java/src/main/java/net/corda/examples/attachments/ProposeFlow.java create mode 100644 blacklist/workflows-java/src/test/java/net/corda/examples/attachments/FlowTests.java create mode 100644 blacklist/workflows-java/src/test/java/net/corda/examples/attachments/NodeDriver.java rename blacklist/{ => workflows-java}/src/test/resources/invalid.jar (100%) create mode 100644 blacklist/workflows-kotlin/build.gradle create mode 100644 blacklist/workflows-kotlin/src/integrationTest/kotlin/net/corda/examples/attachments/DriverBasedTest.kt rename blacklist/{src/main/kotlin/net/corda/examples/attachments/flow => workflows-kotlin/src/main/kotlin/net/corda/examples/attachments}/ReachAgreementFlow.kt (89%) rename blacklist/{src/test/kotlin/net/corda/examples/attachments/tests/flow => workflows-kotlin/src/test/kotlin/net/corda/examples/attachments}/FlowTests.kt (93%) rename blacklist/{src/test/kotlin/net/corda/examples/attachments/tests => workflows-kotlin/src/test/kotlin/net/corda/examples/attachments}/NodeDriver.kt (91%) create mode 100644 blacklist/workflows-kotlin/src/test/resources/invalid.jar diff --git a/blacklist/.idea/runConfigurations/Debug_CorDapp.xml b/blacklist/.idea/runConfigurations/Debug_CorDapp.xml deleted file mode 100644 index 99ec0b2da..000000000 --- a/blacklist/.idea/runConfigurations/Debug_CorDapp.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - \ No newline at end of file diff --git a/blacklist/.idea/runConfigurations/Run_Contract_Tests.xml b/blacklist/.idea/runConfigurations/Run_Contract_Tests.xml deleted file mode 100644 index ccd8a0cd7..000000000 --- a/blacklist/.idea/runConfigurations/Run_Contract_Tests.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/blacklist/.idea/runConfigurations/Run_Flow_Tests.xml b/blacklist/.idea/runConfigurations/Run_Flow_Tests.xml deleted file mode 100644 index a859aa081..000000000 --- a/blacklist/.idea/runConfigurations/Run_Flow_Tests.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/blacklist/.idea/runConfigurations/Unit_tests.xml b/blacklist/.idea/runConfigurations/Unit_tests.xml deleted file mode 100644 index 0d8cb29ee..000000000 --- a/blacklist/.idea/runConfigurations/Unit_tests.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/blacklist/.idea/runConfigurations/Upload_blacklist.xml b/blacklist/.idea/runConfigurations/Upload_blacklist.xml deleted file mode 100644 index 5f121c8e3..000000000 --- a/blacklist/.idea/runConfigurations/Upload_blacklist.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - \ No newline at end of file diff --git a/blacklist/README.md b/blacklist/README.md index 29d0a6cd4..449a874c2 100644 --- a/blacklist/README.md +++ b/blacklist/README.md @@ -35,8 +35,13 @@ Before attempting to reach any agreements, you must upload the blacklist as an a be able to *initiate* an agreement. The blacklist can be uploaded via RPC by running the following command from the project's root folder: -* Unix/Mac OSX: `./gradlew uploadBlacklist` -* Windows: `gradlew uploadBlacklist` +Java version +* Unix/Mac OSX: ` ./gradlew clients-java:uploadBlacklist` +* Windows: `gradlew clients-java:uploadBlacklist` + +Kotlin version +* Unix/Mac OSX: `./gradlew clients-kotlin:uploadBlacklist` +* Windows: `gradlew clinets-kotlin:uploadBlacklist` Or by running the `Upload blacklist` run configuration from IntelliJ. @@ -52,7 +57,7 @@ the shell of Monogram Bank: start ProposeFlow agreementTxt: "A and B agree Y", counterparty: "Hiseville Deposit Bank", untrustedPartiesAttachment: "4CEC607599723D7E0393EB5F05F24562732CD1B217DEAEDEABD4C25AFE5B333A" -If you now run `run vaultQuery contractStateType: net.corda.examples.attachments.state.AgreementState` on either the +If you now run `run vaultQuery contractStateType: net.corda.examples.attachments.states.AgreementState` on either the Monogram Bank or Hiseville Deposit Bank node, you should see the agreement stored: data: ! diff --git a/blacklist/build.gradle b/blacklist/build.gradle index 7b59bda44..f438347eb 100644 --- a/blacklist/build.gradle +++ b/blacklist/build.gradle @@ -1,4 +1,5 @@ buildscript { + ext.kotlin_version = '1.3.31' Properties constants = new Properties() file("$projectDir/../constants.properties").withInputStream { constants.load(it) } @@ -12,6 +13,8 @@ buildscript { log4j_version = constants.getProperty("log4jVersion") slf4j_version = constants.getProperty("slf4jVersion") corda_platform_version = constants.getProperty("platformVersion") + spring_boot_version = '2.0.2.RELEASE' + ext.spring_boot_gradle_plugin_version = '2.0.2.RELEASE' } repositories { @@ -26,114 +29,39 @@ buildscript { classpath "net.corda.plugins:cordapp:$corda_gradle_plugins_version" classpath "net.corda.plugins:cordformation:$corda_gradle_plugins_version" classpath "net.corda.plugins:quasar-utils:$corda_gradle_plugins_version" + classpath "org.springframework.boot:spring-boot-gradle-plugin:$spring_boot_gradle_plugin_version" } } -apply from: 'repositories.gradle' +allprojects { -apply plugin: 'kotlin' -apply plugin: 'net.corda.plugins.cordapp' -apply plugin: 'net.corda.plugins.cordformation' -apply plugin: 'net.corda.plugins.quasar-utils' - -cordapp { - targetPlatformVersion corda_platform_version.toInteger() - minimumPlatformVersion corda_platform_version.toInteger() - contract { - name "Blacklist" - vendor "Corda Open Source" - licence "Apache License, Version 2.0" - versionId 1 - } - workflow { - name "Blacklist" - vendor "Corda Open Source" - licence "Apache License, Version 2.0" - versionId 1 - } -} - -dependencies { - compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version" - testCompile "junit:junit:$junit_version" - - // This is for the deployNodes task only. - cordaRuntime "org.apache.logging.log4j:log4j-slf4j-impl:$log4j_version" - - // Corda dependencies. - cordaCompile "$corda_release_group:corda-core:$corda_release_version" - cordaCompile "$corda_release_group:corda-jackson:$corda_release_version" - cordaCompile "$corda_release_group:corda-rpc:$corda_release_version" - cordaCompile "$corda_release_group:corda-node-api:$corda_release_version" - cordaRuntime "$corda_release_group:corda:$corda_release_version" - - testCompile "$corda_release_group:corda-node-driver:$corda_release_version" - - // CorDapp dependencies. -} - -jar { - // CorDapps do not configure the Node's logging! - exclude '**/log4j2*.xml' -} - -tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile) { - kotlinOptions { - languageVersion = "1.2" - apiVersion = "1.2" - jvmTarget = "1.8" - javaParameters = true // Useful for reflection. + repositories { + mavenLocal() + jcenter() + mavenCentral() + maven { url 'https://jitpack.io' } + maven { url 'https://ci-artifactory.corda.r3cev.com/artifactory/corda' } + maven { url 'https://repo.gradle.org/gradle/libs-releases' } } -} -task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) { - node { - name "O=Notary,L=London,C=GB" - notary = [validating : true] - p2pPort 10002 - rpcSettings { - address("localhost:10003") - adminAddress("localhost:10043") - } - projectCordapp { - deploy = false - } - } - node { - name "O=Monogram Bank,L=London,C=GB" - p2pPort 10006 - rpcSettings { - address("localhost:10007") - adminAddress("localhost:10047") + configurations { + compile { + // We want to use SLF4J's version of these bindings: jcl-over-slf4j + // Remove any transitive dependency on Apache's version. + exclude group: 'commons-logging', module: 'commons-logging' } - cordapps = [] - rpcUsers = [[ user: "user1", "password": "test", "permissions": ["ALL"]]] } - node { - name "O=Hiseville Deposit Bank,L=Sao Paulo,C=BR" - p2pPort 10009 - rpcSettings { - address("localhost:10010") - adminAddress("localhost:10050") - } - cordapps = [] - rpcUsers = [[ user: "user1", "password": "test", "permissions": ["ALL"]]] + + tasks.withType(JavaCompile) { + options.compilerArgs << "-parameters" // Required for shell commands. } - node { - name "O=George State Bank,L=New York,C=US" - p2pPort 10012 - rpcSettings { - address("localhost:10013") - adminAddress("localhost:10053") + + tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile) { + kotlinOptions { + languageVersion = "1.2" + apiVersion = "1.2" + jvmTarget = "1.8" + javaParameters = true // Useful for reflection. } - cordapps = [] - rpcUsers = [[ user: "user1", "password": "test", "permissions": ["ALL"]]] } -} - -task uploadBlacklist(type: JavaExec, dependsOn: compileTestKotlin) { - classpath = sourceSets.test.runtimeClasspath - main = 'net.corda.examples.attachments.tests.client.ClientKt' - args 'localhost:10007', 'localhost:10010', 'localhost:10013' -} +} \ No newline at end of file diff --git a/blacklist/clients-java/build.gradle b/blacklist/clients-java/build.gradle new file mode 100644 index 000000000..6faf48538 --- /dev/null +++ b/blacklist/clients-java/build.gradle @@ -0,0 +1,43 @@ +apply plugin: 'org.springframework.boot' +apply plugin: 'java' + +sourceSets { + main { + resources { + srcDir rootProject.file("config/dev") + } + } +} + +dependencies { + // Corda dependencies. + compile "$corda_release_group:corda-rpc:$corda_release_version" + + // CorDapp dependencies. + compile project(":contracts-java") + compile project(":workflows-java") + + compile("org.springframework.boot:spring-boot-starter-websocket:$spring_boot_version") { + exclude group: "org.springframework.boot", module: "spring-boot-starter-logging" + } + + compile "org.apache.logging.log4j:log4j-slf4j-impl:${log4j_version}" + compile "org.apache.logging.log4j:log4j-web:${log4j_version}" + compile "org.slf4j:jul-to-slf4j:$slf4j_version" +} + +springBoot { + mainClassName = "net.corda.examples.attachments.webserver.Server" +} + +task runWebServer(type: JavaExec, dependsOn: assemble) { + classpath = sourceSets.main.runtimeClasspath + main = 'net.corda.examples.attachments.webserver.Starter' + args '--server.port=10050', '--config.rpc.host=localhost', '--config.rpc.port=10006', '--config.rpc.username=user1', '--config.rpc.password=test' +} + +task uploadBlacklist(type: JavaExec, dependsOn: assemble) { + classpath = sourceSets.main.runtimeClasspath + main = 'net.corda.examples.attachments.client.Client' + args 'localhost:10006', 'localhost:10009', 'localhost:10012' +} diff --git a/blacklist/clients-java/src/main/java/net/corda/examples/attachments/client/Client.java b/blacklist/clients-java/src/main/java/net/corda/examples/attachments/client/Client.java new file mode 100644 index 000000000..ed363cf40 --- /dev/null +++ b/blacklist/clients-java/src/main/java/net/corda/examples/attachments/client/Client.java @@ -0,0 +1,97 @@ +package net.corda.examples.attachments.client; + +import kotlin.text.Charsets; +import net.corda.client.rpc.CordaRPCClient; +import net.corda.client.rpc.CordaRPCConnection; +import net.corda.core.crypto.SecureHash; +import net.corda.core.messaging.CordaRPCOps; +import net.corda.core.utilities.NetworkHostAndPort; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.*; +import java.nio.file.FileAlreadyExistsException; +import java.util.List; +import java.util.jar.JarInputStream; +import java.util.stream.Collectors; + +import static net.corda.examples.attachments.Constants.*; + +public class Client { + + private static class Companion { + static Logger logger = LoggerFactory.getLogger(Client.class); + } + + /** + * Uploads the jar of blacklisted counterparties with whom agreements cannot be struck to the node. + */ + public static void main(String[] args) throws IOException { + if (args.length == 0) { + String message = "Usage: uploadBlacklist ..."; + throw new IllegalArgumentException(message.toString()); + } + + for (String arg : args) { + NetworkHostAndPort nodeAddress = NetworkHostAndPort.parse(arg); + CordaRPCConnection rpcConnection = new CordaRPCClient(nodeAddress).start("user1", "test"); + CordaRPCOps proxy = rpcConnection.getProxy(); + + SecureHash attachmentHash = BLACKLIST_JAR_HASH; + + // take relative path using substring of constant BLACKLIST_JAR_PATH, check if node contains blacklist already + if (!proxy.attachmentExists(attachmentHash)) { + System.out.println("Working Directory = " + + System.getProperty("user.dir")); + attachmentHash = uploadAttachment(proxy, BLACKLIST_JAR_PATH); + Companion.logger.info("Blacklist uploaded to node at " + nodeAddress); + } else { + Companion.logger.info("Node already contains Blacklist, skipping upload at " + nodeAddress); + } + + JarInputStream attachmentJar = downloadAttachment(proxy, attachmentHash); + Companion.logger.info("Blacklist downloaded from node at " + nodeAddress); + + checkAttachment(attachmentJar, ATTACTMENT_FILE_NAME, ATTACHMENT_EXPECTED_CONTENTS); + Companion.logger.info("Attachment contents checked on node at " + nodeAddress); + } + + } + + /** + * Uploads the attachment at [attachmentPath] to the node. + */ + private static SecureHash uploadAttachment(CordaRPCOps proxy, String attachmentPath) throws FileNotFoundException, FileAlreadyExistsException { + FileInputStream attachmentUploadInputStream = new FileInputStream(new File(attachmentPath)); + return proxy.uploadAttachment(attachmentUploadInputStream); + } + + /** + * Downloads the attachment with hash [attachmentHash] from the node. + */ + private static JarInputStream downloadAttachment(CordaRPCOps proxy, SecureHash attachmentHash) throws IOException { + InputStream attachmentDownloadInputStream = proxy.openAttachment(attachmentHash); + return new JarInputStream(attachmentDownloadInputStream); + } + + /** + * Checks the [expectedFileName] and [expectedContents] of the downloaded [attachmentJar]. + */ + private static void checkAttachment(JarInputStream attachmentJar, String expectedFileName, List expectedContents) throws IOException { + String name = attachmentJar.getNextEntry().getName(); + while (!name.equals(expectedFileName)) { + name = attachmentJar.getNextEntry().getName(); + } + + BufferedInputStream bisAttachmentJar = new BufferedInputStream(attachmentJar, (8*1024)); + InputStreamReader isrAttachmentJar = new InputStreamReader(bisAttachmentJar, Charsets.UTF_8); + BufferedReader brAttachmentJar = new BufferedReader(isrAttachmentJar); + + List contents = brAttachmentJar.lines().collect(Collectors.toList()); + + if (!contents.equals(expectedContents)) { + throw new IllegalArgumentException("Downloaded JAR did not have the expected contents."); + } + + } +} diff --git a/blacklist/clients-java/src/main/java/net/corda/examples/attachments/webserver/Controller.java b/blacklist/clients-java/src/main/java/net/corda/examples/attachments/webserver/Controller.java new file mode 100644 index 000000000..fcbe49898 --- /dev/null +++ b/blacklist/clients-java/src/main/java/net/corda/examples/attachments/webserver/Controller.java @@ -0,0 +1,27 @@ +package net.corda.examples.attachments.webserver; + +import net.corda.core.messaging.CordaRPCOps; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * Define your API endpoints here. + */ +@RestController +@RequestMapping("/") // The paths for HTTP requests are relative to this base path. +public class Controller { + private final CordaRPCOps proxy; + private final static Logger logger = LoggerFactory.getLogger(Controller.class); + + public Controller(NodeRPCConnection rpc) { + this.proxy = rpc.proxy; + } + + @GetMapping(value = "/templateendpoint", produces = "text/plain") + private String templateendpoint() { + return "Define an endpoint here."; + } +} \ No newline at end of file diff --git a/blacklist/clients-java/src/main/java/net/corda/examples/attachments/webserver/NodeRPCConnection.java b/blacklist/clients-java/src/main/java/net/corda/examples/attachments/webserver/NodeRPCConnection.java new file mode 100644 index 000000000..76b4fd445 --- /dev/null +++ b/blacklist/clients-java/src/main/java/net/corda/examples/attachments/webserver/NodeRPCConnection.java @@ -0,0 +1,48 @@ +package net.corda.examples.attachments.webserver; + +import net.corda.client.rpc.CordaRPCClient; +import net.corda.client.rpc.CordaRPCConnection; +import net.corda.core.messaging.CordaRPCOps; +import net.corda.core.utilities.NetworkHostAndPort; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; + +/** + * Wraps an RPC connection to a Corda node. + * + * The RPC connection is configured using command line arguments. + */ +@Component +public class NodeRPCConnection implements AutoCloseable { + // The host of the node we are connecting to. + @Value("${config.rpc.host}") + private String host; + // The RPC port of the node we are connecting to. + @Value("${config.rpc.username}") + private String username; + // The username for logging into the RPC client. + @Value("${config.rpc.password}") + private String password; + // The password for logging into the RPC client. + @Value("${config.rpc.port}") + private int rpcPort; + + private CordaRPCConnection rpcConnection; + CordaRPCOps proxy; + + @PostConstruct + public void initialiseNodeRPCConnection() { + NetworkHostAndPort rpcAddress = new NetworkHostAndPort(host, rpcPort); + CordaRPCClient rpcClient = new CordaRPCClient(rpcAddress); + rpcConnection = rpcClient.start(username, password); + proxy = rpcConnection.getProxy(); + } + + @PreDestroy + public void close() { + rpcConnection.notifyServerAndClose(); + } +} \ No newline at end of file diff --git a/blacklist/clients-java/src/main/java/net/corda/examples/attachments/webserver/Starter.java b/blacklist/clients-java/src/main/java/net/corda/examples/attachments/webserver/Starter.java new file mode 100644 index 000000000..b278f622f --- /dev/null +++ b/blacklist/clients-java/src/main/java/net/corda/examples/attachments/webserver/Starter.java @@ -0,0 +1,23 @@ +package net.corda.examples.attachments.webserver; + +import org.springframework.boot.Banner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +import static org.springframework.boot.WebApplicationType.SERVLET; + +/** + * Our Spring Boot application. + */ +@SpringBootApplication +public class Starter { + /** + * Starts our Spring Boot application. + */ + public static void main(String[] args) { + SpringApplication app = new SpringApplication(Starter.class); + app.setBannerMode(Banner.Mode.OFF); + app.setWebApplicationType(SERVLET); + app.run(args); + } +} \ No newline at end of file diff --git a/blacklist/clients-java/src/main/resources/static/app.js b/blacklist/clients-java/src/main/resources/static/app.js new file mode 100644 index 000000000..c58d2de8c --- /dev/null +++ b/blacklist/clients-java/src/main/resources/static/app.js @@ -0,0 +1,3 @@ +"use strict"; + +// Define your client-side logic here. \ No newline at end of file diff --git a/blacklist/clients-java/src/main/resources/static/index.html b/blacklist/clients-java/src/main/resources/static/index.html new file mode 100644 index 000000000..758501dd0 --- /dev/null +++ b/blacklist/clients-java/src/main/resources/static/index.html @@ -0,0 +1,10 @@ + + + + + Example front-end. + + +
Define your front-end here.
+ + \ No newline at end of file diff --git a/blacklist/clients-kotlin/build.gradle b/blacklist/clients-kotlin/build.gradle new file mode 100644 index 000000000..15343ff02 --- /dev/null +++ b/blacklist/clients-kotlin/build.gradle @@ -0,0 +1,43 @@ +apply plugin: 'org.springframework.boot' +apply plugin: 'kotlin' + +sourceSets { + main { + resources { + srcDir rootProject.file("config/dev") + } + } +} + +dependencies { + // Corda dependencies. + compile "$corda_release_group:corda-rpc:$corda_release_version" + + // CorDapp dependencies. + compile project(":contracts-kotlin") + compile project(":workflows-kotlin") + + compile("org.springframework.boot:spring-boot-starter-websocket:$spring_boot_version") { + exclude group: "org.springframework.boot", module: "spring-boot-starter-logging" + } + + compile "org.apache.logging.log4j:log4j-slf4j-impl:${log4j_version}" + compile "org.apache.logging.log4j:log4j-web:${log4j_version}" + compile "org.slf4j:jul-to-slf4j:$slf4j_version" +} + +springBoot { + mainClassName = "net.corda.examples.attachments.webserver.Server" +} + +task runWebServer(type: JavaExec, dependsOn: assemble) { + classpath = sourceSets.main.runtimeClasspath + main = 'net.corda.examples.attachments.webserver.Starter' + args '--server.port=10050', '--config.rpc.host=localhost', '--config.rpc.port=10006', '--config.rpc.username=user1', '--config.rpc.password=test' +} + +task uploadBlacklist(type: JavaExec, dependsOn: assemble) { + classpath = sourceSets.main.runtimeClasspath + main = 'net.corda.examples.attachments.client.ClientKt' + args 'localhost:10006', 'localhost:10009', 'localhost:10012' +} diff --git a/blacklist/src/test/kotlin/net/corda/examples/attachments/tests/client/Client.kt b/blacklist/clients-kotlin/src/main/kotlin/net/corda/examples/attachments/client/Client.kt similarity index 98% rename from blacklist/src/test/kotlin/net/corda/examples/attachments/tests/client/Client.kt rename to blacklist/clients-kotlin/src/main/kotlin/net/corda/examples/attachments/client/Client.kt index 35babbb03..125656453 100644 --- a/blacklist/src/test/kotlin/net/corda/examples/attachments/tests/client/Client.kt +++ b/blacklist/clients-kotlin/src/main/kotlin/net/corda/examples/attachments/client/Client.kt @@ -1,4 +1,4 @@ -package net.corda.examples.attachments.tests.client +package net.corda.examples.attachments.client import net.corda.client.rpc.CordaRPCClient import net.corda.core.crypto.SecureHash diff --git a/blacklist/clients-kotlin/src/main/kotlin/net/corda/examples/attachments/webserver/Controller.kt b/blacklist/clients-kotlin/src/main/kotlin/net/corda/examples/attachments/webserver/Controller.kt new file mode 100644 index 000000000..dda7dc778 --- /dev/null +++ b/blacklist/clients-kotlin/src/main/kotlin/net/corda/examples/attachments/webserver/Controller.kt @@ -0,0 +1,25 @@ +package net.corda.examples.attachments.webserver + +import org.slf4j.LoggerFactory +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RestController + +/** + * Define your API endpoints here. + */ +@RestController +@RequestMapping("/") // The paths for HTTP requests are relative to this base path. +class Controller(rpc: NodeRPCConnection) { + + companion object { + private val logger = LoggerFactory.getLogger(RestController::class.java) + } + + private val proxy = rpc.proxy + + @GetMapping(value = ["/templateendpoint"], produces = arrayOf("text/plain")) + private fun templateendpoint(): String { + return "Define an endpoint here." + } +} \ No newline at end of file diff --git a/blacklist/clients-kotlin/src/main/kotlin/net/corda/examples/attachments/webserver/NodeRPCConnection.kt b/blacklist/clients-kotlin/src/main/kotlin/net/corda/examples/attachments/webserver/NodeRPCConnection.kt new file mode 100644 index 000000000..e1d6acb34 --- /dev/null +++ b/blacklist/clients-kotlin/src/main/kotlin/net/corda/examples/attachments/webserver/NodeRPCConnection.kt @@ -0,0 +1,52 @@ +package net.corda.examples.attachments.webserver + +import net.corda.client.rpc.CordaRPCClient +import net.corda.client.rpc.CordaRPCConnection +import net.corda.core.messaging.CordaRPCOps +import net.corda.core.utilities.NetworkHostAndPort +import org.springframework.beans.factory.annotation.Value +import org.springframework.stereotype.Component +import javax.annotation.PostConstruct +import javax.annotation.PreDestroy + +private const val CORDA_USER_NAME = "config.rpc.username" +private const val CORDA_USER_PASSWORD = "config.rpc.password" +private const val CORDA_NODE_HOST = "config.rpc.host" +private const val CORDA_RPC_PORT = "config.rpc.port" + +/** + * Wraps an RPC connection to a Corda node. + * + * The RPC connection is configured using command line arguments. + * + * @param host The host of the node we are connecting to. + * @param rpcPort The RPC port of the node we are connecting to. + * @param username The username for logging into the RPC client. + * @param password The password for logging into the RPC client. + * @property proxy The RPC proxy. + */ +@Component +open class NodeRPCConnection( + @Value("\${$CORDA_NODE_HOST}") private val host: String, + @Value("\${$CORDA_USER_NAME}") private val username: String, + @Value("\${$CORDA_USER_PASSWORD}") private val password: String, + @Value("\${$CORDA_RPC_PORT}") private val rpcPort: Int): AutoCloseable { + + lateinit var rpcConnection: CordaRPCConnection + private set + lateinit var proxy: CordaRPCOps + private set + + @PostConstruct + fun initialiseNodeRPCConnection() { + val rpcAddress = NetworkHostAndPort(host, rpcPort) + val rpcClient = CordaRPCClient(rpcAddress) + val rpcConnection = rpcClient.start(username, password) + proxy = rpcConnection.proxy + } + + @PreDestroy + override fun close() { + rpcConnection.notifyServerAndClose() + } +} \ No newline at end of file diff --git a/blacklist/clients-kotlin/src/main/kotlin/net/corda/examples/attachments/webserver/Server.kt b/blacklist/clients-kotlin/src/main/kotlin/net/corda/examples/attachments/webserver/Server.kt new file mode 100644 index 000000000..04672c6c3 --- /dev/null +++ b/blacklist/clients-kotlin/src/main/kotlin/net/corda/examples/attachments/webserver/Server.kt @@ -0,0 +1,22 @@ +package net.corda.examples.attachments.webserver + +import org.springframework.boot.Banner +import org.springframework.boot.SpringApplication +import org.springframework.boot.WebApplicationType.SERVLET +import org.springframework.boot.autoconfigure.SpringBootApplication + +/** + * Our Spring Boot application. + */ +@SpringBootApplication +private open class Starter + +/** + * Starts our Spring Boot application. + */ +fun main(args: Array) { + val app = SpringApplication(Starter::class.java) + app.setBannerMode(Banner.Mode.OFF) + app.webApplicationType = SERVLET + app.run(*args) +} diff --git a/blacklist/clients-kotlin/src/main/resources/static/app.js b/blacklist/clients-kotlin/src/main/resources/static/app.js new file mode 100644 index 000000000..c58d2de8c --- /dev/null +++ b/blacklist/clients-kotlin/src/main/resources/static/app.js @@ -0,0 +1,3 @@ +"use strict"; + +// Define your client-side logic here. \ No newline at end of file diff --git a/blacklist/clients-kotlin/src/main/resources/static/index.html b/blacklist/clients-kotlin/src/main/resources/static/index.html new file mode 100644 index 000000000..758501dd0 --- /dev/null +++ b/blacklist/clients-kotlin/src/main/resources/static/index.html @@ -0,0 +1,10 @@ + + + + + Example front-end. + + +
Define your front-end here.
+ + \ No newline at end of file diff --git a/blacklist/contracts-java/build.gradle b/blacklist/contracts-java/build.gradle new file mode 100644 index 000000000..77d851a50 --- /dev/null +++ b/blacklist/contracts-java/build.gradle @@ -0,0 +1,31 @@ +apply plugin: 'java' +apply plugin: 'net.corda.plugins.cordapp' + +jar { + // CorDapps do not configure a Node's logging. + exclude '**/log4j2*.xml' +} + +cordapp { + targetPlatformVersion corda_platform_version.toInteger() + minimumPlatformVersion corda_platform_version.toInteger() + contract { + name "Blacklist" + vendor "Corda Open Source" + licence "Apache License, Version 2.0" + versionId 1 + } +} + +dependencies { + testImplementation "junit:junit:$junit_version" + testImplementation "$corda_release_group:corda-node-driver:$corda_release_version" + testCompile "$corda_release_group:corda-node-driver:$corda_release_version" + + // Corda dependencies. + cordaCompile "$corda_release_group:corda-core:$corda_release_version" + cordaCompile "$corda_release_group:corda-jackson:$corda_release_version" + cordaCompile "$corda_release_group:corda-rpc:$corda_release_version" + cordaRuntime "$corda_release_group:corda:$corda_release_version" + +} \ No newline at end of file diff --git a/blacklist/contracts-java/src/main/java/net/corda/examples/attachments/Constants.java b/blacklist/contracts-java/src/main/java/net/corda/examples/attachments/Constants.java new file mode 100644 index 000000000..ee32077f6 --- /dev/null +++ b/blacklist/contracts-java/src/main/java/net/corda/examples/attachments/Constants.java @@ -0,0 +1,28 @@ +package net.corda.examples.attachments; + +import net.corda.core.crypto.SecureHash; + +import java.util.Arrays; +import java.util.List; + +public interface Constants { + String BLACKLIST_JAR_PATH = "../contracts-java/src/main/resources/blacklist.jar"; + SecureHash BLACKLIST_JAR_HASH = SecureHash.parse("4CEC607599723D7E0393EB5F05F24562732CD1B217DEAEDEABD4C25AFE5B333A"); + String ATTACTMENT_FILE_NAME = "blacklist.txt"; + List ATTACHMENT_EXPECTED_CONTENTS = Arrays.asList( + "Crossland Savings", + "TCF National Bank Wisconsin", + "George State Bank", + "The James Polk Stone Community Bank", + "Tifton Banking Company" + ); + List BLACKLISTED_PARTIES = Arrays.asList( + "Crossland Savings", + "TCF National Bank Wisconsin", + "George State Bank", + "The James Polk Stone Community Bank", + "Tifton Banking Company" + ); + // This jar exists, but does not meet the constraints imposed by AttachmentContract. + String INCORRECT_JAR_PATH = "src/test/resources/invalid.jar"; +} \ No newline at end of file diff --git a/blacklist/contracts-java/src/main/java/net/corda/examples/attachments/contracts/AgreementContract.java b/blacklist/contracts-java/src/main/java/net/corda/examples/attachments/contracts/AgreementContract.java new file mode 100644 index 000000000..096de191b --- /dev/null +++ b/blacklist/contracts-java/src/main/java/net/corda/examples/attachments/contracts/AgreementContract.java @@ -0,0 +1,123 @@ +package net.corda.examples.attachments.contracts; + +import kotlin.text.Charsets; +import net.corda.core.contracts.*; +import net.corda.core.crypto.SecureHash; +import net.corda.core.identity.AbstractParty; +import net.corda.core.identity.Party; +import net.corda.core.transactions.LedgerTransaction; +import net.corda.examples.attachments.states.AgreementState; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.security.PublicKey; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.jar.JarInputStream; +import java.util.stream.Collectors; + +public class AgreementContract implements Contract { + public static final String AGREEMENT_CONTRACT_ID = "net.corda.examples.attachments.contracts.AgreementContract"; + private static SecureHash BLACKLIST_JAR_HASH = SecureHash.parse("4CEC607599723D7E0393EB5F05F24562732CD1B217DEAEDEABD4C25AFE5B333A"); + + @Override + public void verify(LedgerTransaction tx) { + // Constraints on the inputs, outputs and commands. + ContractsDSL.requireThat(req -> { + req.using("The transaction should have no inputs", + tx.getInputStates().isEmpty()); + req.using("The transaction should have an AgreementState output", + tx.outputsOfType(AgreementState.class).size() == 1); + req.using("The transaction should have no other outputs", + tx.getOutputs().size() == 1); + req.using("The transaction should have an Agree command", + tx.commandsOfType(Commands.Agree.class).size() == 1); + req.using("The transaction should have no other commands", + tx.getCommands().size() == 1); + return null; + }); + + // Constraints on the included attachments. + List nonContractAttachments = tx.getAttachments() + .stream() + .filter(p -> !(p instanceof ContractAttachment)) + .map(p -> (Attachment) p) + .collect(Collectors.toList()); + + Attachment attached = nonContractAttachments.get(0); + + ContractsDSL.requireThat(req -> { + req.using("The transaction should have a single non-contract attachment", + nonContractAttachments.size() == 1); + + // TODO: Switch to constraint on the jar's signer. + // In the future, Corda will support singing of jars. We will then be able to restrict + // the attachments used to just those signed by party X. + req.using("The jar's hash should be correct", attached.getId().equals(BLACKLIST_JAR_HASH)); + return null; + }); + + // Extract the blacklisted company names from the JAR. + List blacklistedCompanies = new ArrayList<>(); + JarInputStream attachmentJar = attached.openAsJAR(); + try { + while (!attachmentJar.getNextEntry().getName().equals("blacklist.txt")) { + // Calling 'getNextEntry()' causes us to scroll through the JAR. + } + InputStreamReader isrBlacklist = new InputStreamReader(attachmentJar, Charsets.UTF_8); + BufferedReader brBlacklist = new BufferedReader(isrBlacklist, (8 * 1024)); // Note - changed BIR to BR + + String company = brBlacklist.readLine(); + + while (company != null) { + blacklistedCompanies.add(company); + company = brBlacklist.readLine(); + } + } catch (IOException e) { + System.out.println("error reading blacklist.txt"); + } + + // Constraints on the blacklisted parties + AgreementState agreement = tx.outputsOfType(AgreementState.class).get(0); + + List participants = new ArrayList<>(); + List participantsOrgs = new ArrayList<>(); + for (AbstractParty p : agreement.getParticipants()) { + Party participant = (Party) p; + participantsOrgs.add(participant.getName().getOrganisation()); + participants.add(participant); + } + + // overlap is whether any participants in the transaction belong to a blacklisted org. + Set overlap = new HashSet<>(blacklistedCompanies); + overlap.retainAll(new HashSet<>(participantsOrgs)); // intersection + + ContractsDSL.requireThat(req -> { + req.using("The agreement involved blacklisted parties" + overlap.toString(), + overlap.isEmpty()); + return null; + }); + + // Constraints on the signers. + Command command = tx.getCommand(0); + List particpantKeys = new ArrayList<>(); + for (Party p : participants) { + particpantKeys.add(p.getOwningKey()); + } + + ContractsDSL.requireThat(req -> { + req.using("All the parties to the agreement are signers", + command.getSigners().containsAll(particpantKeys)); + return null; + }); + + + } + + public interface Commands extends CommandData { + class Agree extends TypeOnlyCommandData implements Commands {} + } +} diff --git a/blacklist/contracts-java/src/main/java/net/corda/examples/attachments/states/AgreementState.java b/blacklist/contracts-java/src/main/java/net/corda/examples/attachments/states/AgreementState.java new file mode 100644 index 000000000..830cb6bb5 --- /dev/null +++ b/blacklist/contracts-java/src/main/java/net/corda/examples/attachments/states/AgreementState.java @@ -0,0 +1,42 @@ +package net.corda.examples.attachments.states; + +import net.corda.core.contracts.BelongsToContract; +import net.corda.core.contracts.ContractState; +import net.corda.core.identity.AbstractParty; +import net.corda.core.identity.Party; +import net.corda.core.serialization.ConstructorForDeserialization; +import net.corda.core.serialization.CordaSerializable; +import net.corda.examples.attachments.contracts.AgreementContract; +import org.jetbrains.annotations.NotNull; + +import java.util.Arrays; +import java.util.List; + +@CordaSerializable +@BelongsToContract(AgreementContract.class) +public class AgreementState implements ContractState { + private final Party partyA; + private final Party partyB; + private final String txt; + + public Party getPartyA() { + return partyA; + } + public Party getPartyB() { return partyB; } + public String getTxt() { + return txt; + } + + @ConstructorForDeserialization + public AgreementState(Party partyA, Party partyB, String txt) { + this.partyA = partyA; + this.partyB = partyB; + this.txt = txt; + } + + @NotNull + @Override + public List getParticipants() { + return Arrays.asList(partyA, partyB); + } +} diff --git a/blacklist/src/main/resources/blacklist.jar b/blacklist/contracts-java/src/main/resources/blacklist.jar similarity index 100% rename from blacklist/src/main/resources/blacklist.jar rename to blacklist/contracts-java/src/main/resources/blacklist.jar diff --git a/blacklist/src/main/resources/log4j2.xml b/blacklist/contracts-java/src/main/resources/log4j2.xml similarity index 100% rename from blacklist/src/main/resources/log4j2.xml rename to blacklist/contracts-java/src/main/resources/log4j2.xml diff --git a/blacklist/contracts-java/src/test/java/net/corda/examples/attachments/contracts/ContractTests.java b/blacklist/contracts-java/src/test/java/net/corda/examples/attachments/contracts/ContractTests.java new file mode 100644 index 000000000..7dee81ee0 --- /dev/null +++ b/blacklist/contracts-java/src/test/java/net/corda/examples/attachments/contracts/ContractTests.java @@ -0,0 +1,99 @@ +package net.corda.examples.attachments.contracts; + +import net.corda.core.crypto.SecureHash; +import net.corda.core.identity.CordaX500Name; +import net.corda.core.identity.Party; +import net.corda.examples.attachments.states.AgreementState; +import net.corda.testing.core.TestIdentity; +import net.corda.testing.node.MockServices; +import org.junit.Test; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.security.KeyPair; +import java.security.PublicKey; + +import static java.util.Arrays.asList; +import static net.corda.core.crypto.CryptoUtils.generateKeyPair; +import static net.corda.examples.attachments.Constants.BLACKLISTED_PARTIES; +import static net.corda.examples.attachments.Constants.BLACKLIST_JAR_PATH; +import static net.corda.examples.attachments.contracts.AgreementContract.AGREEMENT_CONTRACT_ID; +import static net.corda.testing.core.TestUtils.getTestPartyAndCertificate; +import static net.corda.testing.node.MockServicesKt.makeTestIdentityService; +import static net.corda.testing.node.NodeTestUtils.ledger; + + +public class ContractTests { + static private final MockServices ledgerServices = new MockServices(asList("net.corda.examples.attachments.contracts"), new TestIdentity(new CordaX500Name("TestIdentity", "", "GB")), makeTestIdentityService()); + static private final CordaX500Name megaCorpName = new CordaX500Name("MegaCorp", "London", "GB"); + static private final CordaX500Name miniCorpName = new CordaX500Name("MiniCorp", "London", "GB"); + static private final TestIdentity megaCorp = new TestIdentity(megaCorpName); + static private final TestIdentity miniCorp = new TestIdentity(miniCorpName); + + static private final String agreementTxt = megaCorpName + " agrees with " + miniCorpName + " that..."; + static private final File validAttachment = new File(BLACKLIST_JAR_PATH); + static private final KeyPair blacklistedPartyKeyPair = generateKeyPair(); + static private final PublicKey blacklistedPartyPubKey = blacklistedPartyKeyPair.getPublic(); + static private final CordaX500Name blacklistedPartyName = new CordaX500Name(BLACKLISTED_PARTIES.get(0), "London", "GB"); + static private final Party blacklistedParty = getTestPartyAndCertificate(blacklistedPartyName, blacklistedPartyPubKey).getParty(); + + @Test + public void agreementTransactionContainsOneNonContractAttachment() { + ledger(ledgerServices, (ledger -> { + // We upload a test attachment to the ledger. + FileInputStream attachmentInputStream = null; + try { + attachmentInputStream = new FileInputStream(validAttachment); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + SecureHash attachmentHash = ledger.attachment(attachmentInputStream); + + ledger.transaction(tx -> { + tx.output(AGREEMENT_CONTRACT_ID, new AgreementState(megaCorp.getParty(), miniCorp.getParty(), agreementTxt)); + tx.command(asList(megaCorp.getPublicKey(), miniCorp.getPublicKey()), new AgreementContract.Commands.Agree()); + tx.fails(); + tx.attachment(attachmentHash); + tx.verifies(); + return null; + }); + return null; + })); + } + + @Test + public void nonContractAttachmentMustNotBlacklistAnyOfTheParticipants() { + ledger(ledgerServices, (ledger -> { + // We upload a test attachment to the ledger. + FileInputStream attachmentInputStream = null; + try { + attachmentInputStream = new FileInputStream(validAttachment); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + SecureHash attachmentHash = ledger.attachment(attachmentInputStream); + + ledger.transaction(tx -> { + tx.output(AGREEMENT_CONTRACT_ID, new AgreementState(megaCorp.getParty(), blacklistedParty, agreementTxt)); + tx.command(asList(megaCorp.getPublicKey(), blacklistedPartyPubKey), new AgreementContract.Commands.Agree()); + tx.attachment(attachmentHash); + tx.fails(); + + return null; + }); + + ledger.transaction(tx -> { + tx.output(AGREEMENT_CONTRACT_ID, new AgreementState(megaCorp.getParty(), miniCorp.getParty(), agreementTxt)); + tx.command(asList(megaCorp.getPublicKey(), miniCorp.getPublicKey()), new AgreementContract.Commands.Agree()); + tx.attachment(attachmentHash); + tx.verifies(); + + return null; + }); + + + return null; + })); + } +} diff --git a/blacklist/contracts-java/src/test/java/net/corda/examples/attachments/states/StateTests.java b/blacklist/contracts-java/src/test/java/net/corda/examples/attachments/states/StateTests.java new file mode 100644 index 000000000..9327531c4 --- /dev/null +++ b/blacklist/contracts-java/src/test/java/net/corda/examples/attachments/states/StateTests.java @@ -0,0 +1,41 @@ +package net.corda.examples.attachments.states; + +import net.corda.core.contracts.ContractState; +import net.corda.core.identity.CordaX500Name; +import net.corda.core.identity.Party; +import net.corda.testing.core.TestIdentity; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class StateTests { + private final Party alice = new TestIdentity(new CordaX500Name("Alice", "", "GB")).getParty(); + private final Party bob = new TestIdentity(new CordaX500Name("Bob", "", "GB")).getParty(); + + @Test + public void agreementStateHasParamsOfCorrectTypeInConstructor() { + new AgreementState(alice, bob, "this is an agreement txt"); + } + + @Test + public void tokenStateHasGettersForPartyAPartyBandTxt() { + AgreementState agreementState = new AgreementState(alice, bob, "this is an agreement txt"); + assertEquals(alice, agreementState.getPartyA()); + assertEquals(bob, agreementState.getPartyB()); + assertEquals("this is an agreement txt", agreementState.getTxt()); + } + + @Test + public void agreementStateImplementsContractState() { + assertTrue(new AgreementState(alice, bob, "this is an agreement txt") instanceof ContractState); + } + + @Test + public void agreementStateHasTwoParticipantsPartyAPartyB() { + AgreementState agreementState = new AgreementState(alice, bob, "this is an agreement txt"); + assertEquals(2, agreementState.getParticipants().size()); + assertTrue(agreementState.getParticipants().contains(alice)); + assertTrue(agreementState.getParticipants().contains(bob)); + } +} \ No newline at end of file diff --git a/blacklist/contracts-kotlin/build.gradle b/blacklist/contracts-kotlin/build.gradle new file mode 100644 index 000000000..eba56b818 --- /dev/null +++ b/blacklist/contracts-kotlin/build.gradle @@ -0,0 +1,35 @@ +apply plugin: 'kotlin' +apply plugin: 'net.corda.plugins.cordapp' + +jar { + // CorDapps do not configure a Node's logging. + exclude '**/log4j2*.xml' +} + +cordapp { + targetPlatformVersion corda_platform_version.toInteger() + minimumPlatformVersion corda_platform_version.toInteger() + contract { + name "Blacklist" + vendor "Corda Open Source" + licence "Apache License, Version 2.0" + versionId 1 + } +} + +tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile) { + kotlinOptions { + languageVersion = "1.2" + apiVersion = "1.2" + jvmTarget = "1.8" + javaParameters = true // Useful for reflection. + } +} + +dependencies { + compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" + + // Corda dependencies. + cordaCompile "$corda_release_group:corda-core:$corda_release_version" + testCompile "$corda_release_group:corda-node-driver:$corda_release_version" +} \ No newline at end of file diff --git a/blacklist/contracts-kotlin/src/main/kotlin/net/corda/examples/attachments/Constants.kt b/blacklist/contracts-kotlin/src/main/kotlin/net/corda/examples/attachments/Constants.kt new file mode 100644 index 000000000..21a6f72d0 --- /dev/null +++ b/blacklist/contracts-kotlin/src/main/kotlin/net/corda/examples/attachments/Constants.kt @@ -0,0 +1,19 @@ +package net.corda.examples.attachments + +const val BLACKLIST_JAR_PATH = "../contracts-kotlin/src/main/resources/blacklist.jar" +const val ATTACHMENT_FILE_NAME = "blacklist.txt" +val ATTACHMENT_EXPECTED_CONTENTS = listOf( + "Crossland Savings", + "TCF National Bank Wisconsin", + "George State Bank", + "The James Polk Stone Community Bank", + "Tifton Banking Company") +val BLACKLISTED_PARTIES = listOf( + "Crossland Savings", + "TCF National Bank Wisconsin", + "George State Bank", + "The James Polk Stone Community Bank", + "Tifton Banking Company" +) +// This jar exists, but does not meet the constraints imposed by AttachmentContract. +const val INCORRECT_JAR_PATH = "src/test/resources/invalid.jar" \ No newline at end of file diff --git a/blacklist/src/main/kotlin/net/corda/examples/attachments/contract/AgreementContract.kt b/blacklist/contracts-kotlin/src/main/kotlin/net/corda/examples/attachments/contracts/AgreementContract.kt similarity index 95% rename from blacklist/src/main/kotlin/net/corda/examples/attachments/contract/AgreementContract.kt rename to blacklist/contracts-kotlin/src/main/kotlin/net/corda/examples/attachments/contracts/AgreementContract.kt index 7d6a06be3..d80f1f108 100644 --- a/blacklist/src/main/kotlin/net/corda/examples/attachments/contract/AgreementContract.kt +++ b/blacklist/contracts-kotlin/src/main/kotlin/net/corda/examples/attachments/contracts/AgreementContract.kt @@ -1,4 +1,4 @@ -package net.corda.examples.attachments.contract +package net.corda.examples.attachments.contracts import net.corda.core.contracts.Contract import net.corda.core.contracts.ContractAttachment @@ -6,11 +6,11 @@ import net.corda.core.contracts.TypeOnlyCommandData import net.corda.core.contracts.requireThat import net.corda.core.crypto.SecureHash import net.corda.core.transactions.LedgerTransaction -import net.corda.examples.attachments.state.AgreementState +import net.corda.examples.attachments.states.AgreementState open class AgreementContract : Contract { companion object { - const val AGREEMENT_CONTRACT_ID = "net.corda.examples.attachments.contract.AgreementContract" + const val AGREEMENT_CONTRACT_ID = "net.corda.examples.attachments.contracts.AgreementContract" val BLACKLIST_JAR_HASH = SecureHash.parse("4CEC607599723D7E0393EB5F05F24562732CD1B217DEAEDEABD4C25AFE5B333A") } diff --git a/blacklist/src/main/kotlin/net/corda/examples/attachments/state/AgreementState.kt b/blacklist/contracts-kotlin/src/main/kotlin/net/corda/examples/attachments/states/AgreementState.kt similarity index 75% rename from blacklist/src/main/kotlin/net/corda/examples/attachments/state/AgreementState.kt rename to blacklist/contracts-kotlin/src/main/kotlin/net/corda/examples/attachments/states/AgreementState.kt index c6b4ef857..6c87e1c39 100644 --- a/blacklist/src/main/kotlin/net/corda/examples/attachments/state/AgreementState.kt +++ b/blacklist/contracts-kotlin/src/main/kotlin/net/corda/examples/attachments/states/AgreementState.kt @@ -1,9 +1,9 @@ -package net.corda.examples.attachments.state +package net.corda.examples.attachments.states import net.corda.core.contracts.BelongsToContract import net.corda.core.contracts.ContractState import net.corda.core.identity.Party -import net.corda.examples.attachments.contract.AgreementContract +import net.corda.examples.attachments.contracts.AgreementContract @BelongsToContract(AgreementContract::class) data class AgreementState(val partyA: Party, val partyB: Party, val txt: String) : ContractState { diff --git a/blacklist/contracts-kotlin/src/main/resources/blacklist.jar b/blacklist/contracts-kotlin/src/main/resources/blacklist.jar new file mode 100644 index 0000000000000000000000000000000000000000..f847c28d1bcb11cdea66bb3be029270f8fb9b606 GIT binary patch literal 460 zcmWIWW@h1H0DPK@}|KD3%A^nWk=gt{hL$z0x;b-L9Zd~Z@ma@3myzx?Wt;r6hElIa^u88XuMM{V* zR8KE_rL#7a$LV6xKgZLB`Co!xYhQ2QUnhB-Gr*gXNsbv;cz{BMfdS}Yh9!+47Dni> rLP7^EWFUs(3Ik+A6M=@Jg$U3{P>5g{$;t+D0TU3e0MdLQM=<~ZQpkW5 literal 0 HcmV?d00001 diff --git a/blacklist/contracts-kotlin/src/main/resources/log4j2.xml b/blacklist/contracts-kotlin/src/main/resources/log4j2.xml new file mode 100644 index 000000000..aaabc5aa3 --- /dev/null +++ b/blacklist/contracts-kotlin/src/main/resources/log4j2.xml @@ -0,0 +1,31 @@ + + + + build/logs + blacklist-${hostName} + + + + + + + [%-5level] %d{HH:mm:ss.SSS} [%t] %c{1}.%M - %msg%n + > + + + + + + + + + + + + + + + + + diff --git a/blacklist/src/test/kotlin/net/corda/examples/attachments/tests/contract/ContractTests.kt b/blacklist/contracts-kotlin/src/test/kotlin/net/corda/examples/attachments/contracts/ContractTests.kt similarity index 85% rename from blacklist/src/test/kotlin/net/corda/examples/attachments/tests/contract/ContractTests.kt rename to blacklist/contracts-kotlin/src/test/kotlin/net/corda/examples/attachments/contracts/ContractTests.kt index be3bfef37..9b5ebc66b 100644 --- a/blacklist/src/test/kotlin/net/corda/examples/attachments/tests/contract/ContractTests.kt +++ b/blacklist/contracts-kotlin/src/test/kotlin/net/corda/examples/attachments/contracts/ContractTests.kt @@ -1,12 +1,12 @@ -package net.corda.examples.attachments.tests.contract +package net.corda.examples.attachments.contracts import net.corda.core.crypto.generateKeyPair import net.corda.core.identity.CordaX500Name +import net.corda.examples.attachments.BLACKLISTED_PARTIES import net.corda.examples.attachments.BLACKLIST_JAR_PATH -import net.corda.examples.attachments.contract.AgreementContract -import net.corda.examples.attachments.contract.AgreementContract.Companion.AGREEMENT_CONTRACT_ID -import net.corda.examples.attachments.state.AgreementState -import net.corda.examples.attachments.tests.BLACKLISTED_PARTIES +import net.corda.examples.attachments.contracts.AgreementContract +import net.corda.examples.attachments.contracts.AgreementContract.Companion.AGREEMENT_CONTRACT_ID +import net.corda.examples.attachments.states.AgreementState import net.corda.testing.core.TestIdentity import net.corda.testing.core.getTestPartyAndCertificate import net.corda.testing.node.MockServices @@ -16,7 +16,7 @@ import org.junit.Test import java.io.File class ContractTests { - private val ledgerServices = MockServices(listOf("net.corda.examples.attachments.contract"), identityService = makeTestIdentityService(), initialIdentity = TestIdentity(CordaX500Name("TestIdentity", "", "GB"))) + private val ledgerServices = MockServices(listOf("net.corda.examples.attachments.contracts"), identityService = makeTestIdentityService(), initialIdentity = TestIdentity(CordaX500Name("TestIdentity", "", "GB"))) private val megaCorpName = CordaX500Name("MegaCorp", "London", "GB") private val miniCorpName = CordaX500Name("MiniCorp", "London", "GB") private val megaCorp = TestIdentity(megaCorpName) diff --git a/blacklist/contracts-kotlin/src/test/kotlin/net/corda/examples/attachments/states/StateTests.kt b/blacklist/contracts-kotlin/src/test/kotlin/net/corda/examples/attachments/states/StateTests.kt new file mode 100644 index 000000000..1f5de1985 --- /dev/null +++ b/blacklist/contracts-kotlin/src/test/kotlin/net/corda/examples/attachments/states/StateTests.kt @@ -0,0 +1,34 @@ +package net.corda.examples.attachments.states + +import net.corda.core.identity.CordaX500Name +import net.corda.testing.core.TestIdentity +import org.junit.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue + +class StateTests { + + private val alice = TestIdentity(CordaX500Name("Alice", "", "GB")).party + private val bob = TestIdentity(CordaX500Name("Bob", "", "GB")).party + + @Test + fun `agreementStateHasParamsOfCorrectTypeInConstructor`() { + AgreementState(alice, bob, "this is an agreement txt") + } + + @Test + fun `agreementStateHasGettersForPartyAPartyBTxt`() { + val agreementState = AgreementState(alice, bob, "this is an agreement txt") + assertEquals(alice, agreementState.partyA) + assertEquals(bob, agreementState.partyB) + assertEquals("this is an agreement txt", agreementState.txt) + } + + @Test + fun `agreementStateHasTwoParticipantsPartyAPartyB`() { + val agreementState = AgreementState(alice, bob, "this is an agreement txt") + assertEquals(2, agreementState.participants.size) + assertTrue(agreementState.participants.contains(alice)) + assertTrue(agreementState.participants.contains(bob)) + } +} \ No newline at end of file diff --git a/blacklist/repositories.gradle b/blacklist/repositories.gradle deleted file mode 100644 index 2874c2ab4..000000000 --- a/blacklist/repositories.gradle +++ /dev/null @@ -1,8 +0,0 @@ -repositories { - mavenLocal() - mavenCentral() - jcenter() - maven { url 'https://jitpack.io' } - maven { url 'https://ci-artifactory.corda.r3cev.com/artifactory/corda' } - maven { url 'https://repo.gradle.org/gradle/libs-releases' } -} diff --git a/blacklist/settings.gradle b/blacklist/settings.gradle index e69de29bb..2bb92f868 100644 --- a/blacklist/settings.gradle +++ b/blacklist/settings.gradle @@ -0,0 +1,7 @@ +include 'workflows-kotlin' +include 'contracts-kotlin' +include 'workflows-java' +include 'contracts-java' +include 'clients-java' +include 'clients-kotlin' + diff --git a/blacklist/src/main/kotlin/net/corda/examples/attachments/Constants.kt b/blacklist/src/main/kotlin/net/corda/examples/attachments/Constants.kt deleted file mode 100644 index 8f0a6ffcb..000000000 --- a/blacklist/src/main/kotlin/net/corda/examples/attachments/Constants.kt +++ /dev/null @@ -1,10 +0,0 @@ -package net.corda.examples.attachments - -const val BLACKLIST_JAR_PATH = "src/main/resources/blacklist.jar" -const val ATTACHMENT_FILE_NAME = "blacklist.txt" -val ATTACHMENT_EXPECTED_CONTENTS = listOf( - "Crossland Savings", - "TCF National Bank Wisconsin", - "George State Bank", - "The James Polk Stone Community Bank", - "Tifton Banking Company") \ No newline at end of file diff --git a/blacklist/src/test/kotlin/net/corda/examples/attachments/tests/Constants.kt b/blacklist/src/test/kotlin/net/corda/examples/attachments/tests/Constants.kt deleted file mode 100644 index 67dae0404..000000000 --- a/blacklist/src/test/kotlin/net/corda/examples/attachments/tests/Constants.kt +++ /dev/null @@ -1,12 +0,0 @@ -package net.corda.examples.attachments.tests - -// These blacklisted parties are named in the file blacklisted.txt file in blacklist.jar. -val BLACKLISTED_PARTIES = listOf( - "Crossland Savings", - "TCF National Bank Wisconsin", - "George State Bank", - "The James Polk Stone Community Bank", - "Tifton Banking Company" -) -// This jar exists, but does not meet the constraints imposed by AttachmentContract. -const val INCORRECT_JAR_PATH = "src/test/resources/invalid.jar" \ No newline at end of file diff --git a/blacklist/workflows-java/build.gradle b/blacklist/workflows-java/build.gradle new file mode 100644 index 000000000..9729d4651 --- /dev/null +++ b/blacklist/workflows-java/build.gradle @@ -0,0 +1,119 @@ +apply plugin: 'java' +apply plugin: 'net.corda.plugins.cordapp' +apply plugin: 'net.corda.plugins.quasar-utils' +apply plugin: 'net.corda.plugins.cordformation' + +jar { + // CorDapps do not configure a Node's logging. + exclude '**/log4j2*.xml' +} + +cordapp { + targetPlatformVersion corda_platform_version.toInteger() + minimumPlatformVersion corda_platform_version.toInteger() + workflow { + name "Blacklist" + vendor "Corda Open Source" + licence "Apache License, Version 2.0" + versionId 1 + } +} + +dependencies { + testCompile "junit:junit:$junit_version" + + // Corda dependencies. + cordaCompile "$corda_release_group:corda-core:$corda_release_version" + cordaCompile "$corda_release_group:corda-jackson:$corda_release_version" + cordaCompile "$corda_release_group:corda-rpc:$corda_release_version" + cordaCompile "$corda_release_group:corda-node-api:$corda_release_version" + + testCompile "$corda_release_group:corda-node-driver:$corda_release_version" + // Needed by deployNodes task. + cordaRuntime "$corda_release_group:corda:$corda_release_version" + + // CorDapp dependencies. + cordapp project(":contracts-java") +} + +sourceSets { + main { + resources { + srcDir rootProject.file("config/dev") + } + } + test { + resources { + srcDir rootProject.file("config/test") + } + } + integrationTest { + java { + compileClasspath += main.output + test.output + runtimeClasspath += main.output + test.output + srcDir file('src/integrationTest/java') + } + } +} + +configurations { + integrationTestCompile.extendsFrom testCompile + integrationTestRuntime.extendsFrom testRuntime +} + +task integrationTest(type: Test, dependsOn: []) { + testClassesDirs = sourceSets.integrationTest.output.classesDirs + classpath = sourceSets.integrationTest.runtimeClasspath +} + +task uploadBlacklist(type: JavaExec, dependsOn: assemble) { + classpath = sourceSets.test.runtimeClasspath + main = 'net.corda.examples.attachments.Client' + args 'localhost:10006', 'localhost:10009', 'localhost:10012' +} + +tasks.withType(JavaCompile) { + options.compilerArgs << "-parameters" // Required for shell commands. +} + +task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) { + nodeDefaults { + cordapp project(':contracts-java') + } + node { + name "O=Notary,L=London,C=GB" + notary = [validating : false] + p2pPort 10002 + rpcSettings { + address("localhost:10003") + adminAddress("localhost:10043") + } + } + node { + name "O=Monogram Bank,L=London,C=GB" + p2pPort 10005 + rpcSettings { + address("localhost:10006") + adminAddress("localhost:10046") + } + rpcUsers = [[ user: "user1", "password": "test", "permissions": ["ALL"]]] + } + node { + name "O=Hiseville Deposit Bank,L=Sao Paulo,C=BR" + p2pPort 10008 + rpcSettings { + address("localhost:10009") + adminAddress("localhost:10049") + } + rpcUsers = [[ user: "user1", "password": "test", "permissions": ["ALL"]]] + } + node { + name "O=George State Bank,L=New York,C=US" + p2pPort 10011 + rpcSettings { + address("localhost:10012") + adminAddress("localhost:10052") + } + rpcUsers = [[ user: "user1", "password": "test", "permissions": ["ALL"]]] + } +} \ No newline at end of file diff --git a/blacklist/workflows-java/src/integrationTest/java/net/corda/examples/attachments/DriverBasedTest.java b/blacklist/workflows-java/src/integrationTest/java/net/corda/examples/attachments/DriverBasedTest.java new file mode 100644 index 000000000..da5c1a348 --- /dev/null +++ b/blacklist/workflows-java/src/integrationTest/java/net/corda/examples/attachments/DriverBasedTest.java @@ -0,0 +1,49 @@ +package net.corda.examples.attachments; + +import com.google.common.collect.ImmutableList; +import net.corda.core.concurrent.CordaFuture; +import net.corda.core.identity.CordaX500Name; +import net.corda.testing.core.TestIdentity; +import net.corda.testing.driver.DriverParameters; +import net.corda.testing.driver.NodeHandle; +import net.corda.testing.driver.NodeParameters; +import net.corda.testing.driver.PortAllocation; +import org.junit.Test; + +import java.util.List; + +import static net.corda.testing.driver.Driver.driver; +import static org.junit.Assert.assertEquals; + +public class DriverBasedTest { + private final TestIdentity bankA = new TestIdentity(new CordaX500Name("BankA", "", "GB")); + private final TestIdentity bankB = new TestIdentity(new CordaX500Name("BankB", "", "US")); + + @Test + public void nodeTest() { + driver(new DriverParameters().withIsDebug(true).withStartNodesInProcess(true), dsl -> { + // Start a pair of nodes and wait for them both to be ready. + List> handleFutures = ImmutableList.of( + dsl.startNode(new NodeParameters().withProvidedName(bankA.getName())), + dsl.startNode(new NodeParameters().withProvidedName(bankB.getName())) + ); + + try { + NodeHandle partyAHandle = handleFutures.get(0).get(); + NodeHandle partyBHandle = handleFutures.get(1).get(); + + // From each node, make an RPC call to retrieve another node's name from the network map, to verify that the + // nodes have started and can communicate. + + // This is a very basic test: in practice tests would be starting flows, and verifying the states in the vault + // and other important metrics to ensure that your CorDapp is working as intended. + assertEquals(partyAHandle.getRpc().wellKnownPartyFromX500Name(bankB.getName()).getName(), bankB.getName()); + assertEquals(partyBHandle.getRpc().wellKnownPartyFromX500Name(bankA.getName()).getName(), bankA.getName()); + } catch (Exception e) { + throw new RuntimeException("Caught exception during test: ", e); + } + + return null; + }); + } +} \ No newline at end of file diff --git a/blacklist/workflows-java/src/main/java/net/corda/examples/attachments/AgreeFlow.java b/blacklist/workflows-java/src/main/java/net/corda/examples/attachments/AgreeFlow.java new file mode 100644 index 000000000..5eb7aa1f7 --- /dev/null +++ b/blacklist/workflows-java/src/main/java/net/corda/examples/attachments/AgreeFlow.java @@ -0,0 +1,40 @@ +package net.corda.examples.attachments; + +import co.paralleluniverse.fibers.Suspendable; +import net.corda.core.crypto.SecureHash; +import net.corda.core.flows.*; +import net.corda.core.transactions.SignedTransaction; +import net.corda.examples.attachments.states.AgreementState; +import org.jetbrains.annotations.NotNull; + +import java.security.SignatureException; + +@InitiatedBy(ProposeFlow.class) +public class AgreeFlow extends FlowLogic { + FlowSession counterPartySession = null; + + public AgreeFlow(FlowSession counterPartySession) { + this.counterPartySession = counterPartySession; + } + + @Suspendable + @Override + public SignedTransaction call() throws FlowException { + FlowLogic signTransactionFlow = new SignTransactionFlow(counterPartySession) { + @Override + protected void checkTransaction(@NotNull SignedTransaction stx) throws FlowException { + // We ensure that the transaction contains an AgreementContract + try { + if (stx.toLedgerTransaction(getServiceHub(), false).outputsOfType(AgreementState.class).isEmpty()) { + throw new FlowException("Agreement transaction did not contain an output AgreementState."); + } + } catch (SignatureException e) { + e.printStackTrace(); + } + } + }; + + final SecureHash txId = subFlow(signTransactionFlow).getId(); + return subFlow(new ReceiveFinalityFlow(counterPartySession, txId)); + } +} diff --git a/blacklist/workflows-java/src/main/java/net/corda/examples/attachments/ProposeFlow.java b/blacklist/workflows-java/src/main/java/net/corda/examples/attachments/ProposeFlow.java new file mode 100644 index 000000000..999bbd56c --- /dev/null +++ b/blacklist/workflows-java/src/main/java/net/corda/examples/attachments/ProposeFlow.java @@ -0,0 +1,60 @@ +package net.corda.examples.attachments; + +import co.paralleluniverse.fibers.Suspendable; +import com.google.common.collect.ImmutableSet; +import net.corda.core.crypto.SecureHash; +import net.corda.core.flows.*; +import net.corda.core.identity.Party; +import net.corda.core.transactions.SignedTransaction; +import net.corda.core.transactions.TransactionBuilder; +import net.corda.examples.attachments.contracts.AgreementContract; +import net.corda.examples.attachments.states.AgreementState; + +import java.security.PublicKey; +import java.util.Arrays; +import java.util.List; + +import static net.corda.examples.attachments.contracts.AgreementContract.AGREEMENT_CONTRACT_ID; + +@InitiatingFlow +@StartableByRPC +public class ProposeFlow extends FlowLogic { + private static String agreementTxt; + private static SecureHash untrustedPartiesAttachment; + private static Party counterparty; + + public ProposeFlow(String agreementTxt, SecureHash untrustedPartiesAttachment, Party counterparty) { + this.agreementTxt = agreementTxt; + this.untrustedPartiesAttachment = untrustedPartiesAttachment; + this.counterparty = counterparty; + } + + Party getFirstNotary() throws FlowException { + List notaries = getServiceHub().getNetworkMapCache().getNotaryIdentities(); + if (notaries.isEmpty()) throw new FlowException("No available notary"); + return notaries.get(0); + } + + @Override + @Suspendable + public SignedTransaction call() throws FlowException { + final Party notary = getFirstNotary(); + + final AgreementState agreementState = new AgreementState(getOurIdentity(), counterparty, agreementTxt); + final AgreementContract.Commands.Agree agreeCmd = new AgreementContract.Commands.Agree(); + final List agreeCmdRequiredSigners = Arrays.asList(getOurIdentity().getOwningKey(), counterparty.getOwningKey()); + + final TransactionBuilder txBuilder = new TransactionBuilder(notary) + .addOutputState(agreementState, AGREEMENT_CONTRACT_ID) + .addCommand(agreeCmd, agreeCmdRequiredSigners) + .addAttachment(untrustedPartiesAttachment); + + final SignedTransaction partSignedTx = getServiceHub().signInitialTransaction(txBuilder); + + final FlowSession counterpartySession = initiateFlow(counterparty); + final SignedTransaction signedTx = subFlow( + new CollectSignaturesFlow(partSignedTx, ImmutableSet.of(counterpartySession))); + + return subFlow(new FinalityFlow(signedTx, counterpartySession)); + } +} diff --git a/blacklist/workflows-java/src/test/java/net/corda/examples/attachments/FlowTests.java b/blacklist/workflows-java/src/test/java/net/corda/examples/attachments/FlowTests.java new file mode 100644 index 000000000..7e9b9aa98 --- /dev/null +++ b/blacklist/workflows-java/src/test/java/net/corda/examples/attachments/FlowTests.java @@ -0,0 +1,143 @@ +package net.corda.examples.attachments; + +import com.google.common.collect.ImmutableList; +import net.corda.core.concurrent.CordaFuture; +import net.corda.core.contracts.Attachment; +import net.corda.core.contracts.StateAndRef; +import net.corda.core.contracts.TransactionVerificationException; +import net.corda.core.crypto.SecureHash; +import net.corda.core.identity.Party; +import net.corda.core.transactions.SignedTransaction; +import net.corda.examples.attachments.states.AgreementState; +import net.corda.testing.node.MockNetwork; +import net.corda.testing.node.MockNetworkParameters; +import net.corda.testing.node.StartedMockNode; +import net.corda.testing.node.TestCordapp; +import org.hamcrest.core.IsInstanceOf; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.List; +import java.util.concurrent.ExecutionException; + +import static net.corda.examples.attachments.Constants.BLACKLIST_JAR_PATH; +import static net.corda.examples.attachments.Constants.INCORRECT_JAR_PATH; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +public class FlowTests { + private MockNetwork network; + private StartedMockNode a; + private StartedMockNode b; + private Party aIdentity; + private Party bIdentity; + private String agreementTxt; + private SecureHash blacklistAttachment; + private SecureHash incorrectAttachment; + + @Before + public void setup() throws FileNotFoundException { + network = new MockNetwork(new MockNetworkParameters().withCordappsForAllNodes(ImmutableList.of( + TestCordapp.findCordapp("net.corda.examples.attachments.contracts")))); + a = network.createNode(); + b = network.createNode(); + aIdentity = a.getInfo().getLegalIdentities().get(0); + bIdentity = b.getInfo().getLegalIdentities().get(0); + + agreementTxt = aIdentity.getName() + " agrees with " + bIdentity.getName() + " that..."; + + // We upload the valid attachment to the first node, who will propagate it to the other node as part of the + // flow. + FileInputStream attachmentInputStream = new FileInputStream(new File(BLACKLIST_JAR_PATH)); + + a.transaction(() -> { + try { + blacklistAttachment = a.getServices().getAttachments().importAttachment(attachmentInputStream, "user", "blacklist"); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + }); + + // We upload the invalid attachment to the first node, who will propagate it to the other node as part of the + // flow. + FileInputStream incorrectAttachmentInputStream = new FileInputStream(new File(INCORRECT_JAR_PATH)); + + a.transaction(() -> { + try { + incorrectAttachment = a.getServices().getAttachments().importAttachment(incorrectAttachmentInputStream, "user", "blacklist"); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + }); + + b.registerInitiatedFlow(AgreeFlow.class); + network.runNetwork(); + } + + @After + public void tearDown() { + network.stopNodes(); + } + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test + public void flowRejectsAttachmentsThatDoNotMeetTheConstraintsOfAttachmentContract() throws ExecutionException, InterruptedException { + thrown.expectCause(IsInstanceOf.instanceOf(TransactionVerificationException.class)); + + // The attachment being passed to the propose flow is INVALID, will be rejected. + ProposeFlow flow = new ProposeFlow(agreementTxt, incorrectAttachment, bIdentity); + CordaFuture future = a.startFlow(flow); + network.runNetwork(); + future.get(); + } + + @Test + public void flowRecordsTheCorrectTransactionInBothPartiesTransactionStorages() throws ExecutionException, InterruptedException { + reachAgreement(); + + // We check the recorded agreement in both vaults. + for (StartedMockNode node : ImmutableList.of(a, b)) { + node.transaction(() -> { + List> agreements = node.getServices().getVaultService().queryBy(AgreementState.class).getStates(); + assertEquals(1, agreements.size()); + + AgreementState recordedState = agreements.get(0).getState().getData(); + assertEquals(aIdentity, recordedState.getPartyA()); + assertEquals(bIdentity, recordedState.getPartyB()); + assertEquals(agreementTxt, recordedState.getTxt()); + + return null; + }); + } + } + + @Test + public void flowPropagatesTheAttachmentToBsAttachmentStorage() throws ExecutionException, InterruptedException { + reachAgreement(); + + b.transaction(() -> { + Attachment blacklist = b.getServices().getAttachments().openAttachment(blacklistAttachment); + assertNotNull(blacklist); + + return null; + }); + } + + private SignedTransaction reachAgreement() throws ExecutionException, InterruptedException { + ProposeFlow flow = new ProposeFlow(agreementTxt, blacklistAttachment, bIdentity); + CordaFuture future = a.startFlow(flow); + network.runNetwork(); + return (SignedTransaction) future.get(); + } +} diff --git a/blacklist/workflows-java/src/test/java/net/corda/examples/attachments/NodeDriver.java b/blacklist/workflows-java/src/test/java/net/corda/examples/attachments/NodeDriver.java new file mode 100644 index 000000000..36487579f --- /dev/null +++ b/blacklist/workflows-java/src/test/java/net/corda/examples/attachments/NodeDriver.java @@ -0,0 +1,45 @@ +package net.corda.examples.attachments; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import net.corda.core.identity.CordaX500Name; +import net.corda.testing.driver.DriverParameters; +import net.corda.testing.driver.NodeParameters; +import net.corda.testing.node.User; + +import java.util.List; + +import static net.corda.testing.driver.Driver.driver; + +/** + * Allows you to run your nodes through an IDE (as opposed to using deployNodes). Do not use in a production + * environment. + * + */ +public class NodeDriver { + public static void main(String[] args) { + final List rpcUsers = + ImmutableList.of(new User("user1", "test", ImmutableSet.of("ALL"))); + + driver(new DriverParameters().withStartNodesInProcess(true).withWaitForAllNodesToFinish(true), dsl -> { + try { + dsl.startNode(new NodeParameters() + .withProvidedName(new CordaX500Name("Monogram Bank", "London", "GB")) + .withRpcUsers(rpcUsers)).get(); + dsl.startNode(new NodeParameters() + .withProvidedName(new CordaX500Name("Hiseville Deposit Bank", "Sao Paulo", "BR")) + .withRpcUsers(rpcUsers)).get(); + dsl.startNode(new NodeParameters() + .withProvidedName(new CordaX500Name("George State Bank", "New York", "US")) + .withRpcUsers(rpcUsers)).get(); + } catch (Throwable e) { + System.err.println("Encountered exception in node startup: " + e.getMessage()); + e.printStackTrace(); + } + + return null; + } + ); + } +} + diff --git a/blacklist/src/test/resources/invalid.jar b/blacklist/workflows-java/src/test/resources/invalid.jar similarity index 100% rename from blacklist/src/test/resources/invalid.jar rename to blacklist/workflows-java/src/test/resources/invalid.jar diff --git a/blacklist/workflows-kotlin/build.gradle b/blacklist/workflows-kotlin/build.gradle new file mode 100644 index 000000000..fae6d5539 --- /dev/null +++ b/blacklist/workflows-kotlin/build.gradle @@ -0,0 +1,116 @@ +apply plugin: 'kotlin' +apply plugin: 'net.corda.plugins.cordapp' +apply plugin: 'net.corda.plugins.quasar-utils' +apply plugin: 'net.corda.plugins.cordformation' + +jar { + // CorDapps do not configure a Node's logging. + exclude '**/log4j2*.xml' +} + +cordapp { + targetPlatformVersion corda_platform_version.toInteger() + minimumPlatformVersion corda_platform_version.toInteger() + workflow { + name "Blacklist" + vendor "Corda Open Source" + licence "Apache License, Version 2.0" + versionId 1 + } +} + +dependencies { + testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version" + testCompile "junit:junit:$junit_version" + + // Corda dependencies. + cordaCompile "$corda_release_group:corda-core:$corda_release_version" + cordaCompile "$corda_release_group:corda-jackson:$corda_release_version" + cordaCompile "$corda_release_group:corda-rpc:$corda_release_version" + cordaCompile "$corda_release_group:corda-node-api:$corda_release_version" + + testCompile "$corda_release_group:corda-node-driver:$corda_release_version" + // Needed by deployNodes task. + cordaRuntime "$corda_release_group:corda:$corda_release_version" + + // CorDapp dependencies. + cordapp project(":contracts-kotlin") +} + +sourceSets { + main { + resources { + srcDir rootProject.file("config/dev") + } + } + test { + resources { + srcDir rootProject.file("config/test") + } + } + integrationTest { + kotlin { + compileClasspath += main.output + test.output + runtimeClasspath += main.output + test.output + srcDir file('src/integrationTest/kotlin') + } + } +} + +configurations { + integrationTestCompile.extendsFrom testCompile + integrationTestRuntime.extendsFrom testRuntime +} + +task integrationTest(type: Test, dependsOn: []) { + testClassesDirs = sourceSets.integrationTest.output.classesDirs + classpath = sourceSets.integrationTest.runtimeClasspath +} + +task uploadBlacklist(type: JavaExec, dependsOn: compileTestKotlin) { + classpath = sourceSets.test.runtimeClasspath + main = 'net.corda.examples.attachments.ClientKt' + args 'localhost:10007', 'localhost:10010', 'localhost:10013' +} + +task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) { + nodeDefaults { + cordapp project(':contracts-kotlin') + } + node { + name "O=Notary,L=London,C=GB" + notary = [validating : false] + p2pPort 10002 + rpcSettings { + address("localhost:10003") + adminAddress("localhost:10043") + } + } + node { + name "O=Monogram Bank,L=London,C=GB" + p2pPort 10005 + rpcSettings { + address("localhost:10006") + adminAddress("localhost:10046") + } + rpcUsers = [[ user: "user1", "password": "test", "permissions": ["ALL"]]] + } + node { + name "O=Hiseville Deposit Bank,L=Sao Paulo,C=BR" + p2pPort 10008 + rpcSettings { + address("localhost:10009") + adminAddress("localhost:10049") + } + rpcUsers = [[ user: "user1", "password": "test", "permissions": ["ALL"]]] + } + node { + name "O=George State Bank,L=New York,C=US" + p2pPort 10011 + rpcSettings { + address("localhost:10012") + adminAddress("localhost:10052") + } + rpcUsers = [[ user: "user1", "password": "test", "permissions": ["ALL"]]] + } +} \ No newline at end of file diff --git a/blacklist/workflows-kotlin/src/integrationTest/kotlin/net/corda/examples/attachments/DriverBasedTest.kt b/blacklist/workflows-kotlin/src/integrationTest/kotlin/net/corda/examples/attachments/DriverBasedTest.kt new file mode 100644 index 000000000..fa4622940 --- /dev/null +++ b/blacklist/workflows-kotlin/src/integrationTest/kotlin/net/corda/examples/attachments/DriverBasedTest.kt @@ -0,0 +1,47 @@ +package net.corda.examples.attachments + +import net.corda.core.identity.CordaX500Name +import net.corda.core.utilities.getOrThrow +import net.corda.testing.core.TestIdentity +import net.corda.testing.driver.DriverDSL +import net.corda.testing.driver.DriverParameters +import net.corda.testing.driver.NodeHandle +import net.corda.testing.driver.driver +import org.junit.Test +import java.util.concurrent.Future +import kotlin.test.assertEquals + +class DriverBasedTest { + private val bankA = TestIdentity(CordaX500Name("BankA", "", "GB")) + private val bankB = TestIdentity(CordaX500Name("BankB", "", "US")) + + @Test + fun `node test`() = withDriver { + // Start a pair of nodes and wait for them both to be ready. + val (partyAHandle, partyBHandle) = startNodes(bankA, bankB) + + // From each node, make an RPC call to retrieve another node's name from the network map, to verify that the + // nodes have started and can communicate. + + // This is a very basic test: in practice tests would be starting flows, and verifying the states in the vault + // and other important metrics to ensure that your CorDapp is working as intended. + assertEquals(bankB.name, partyAHandle.resolveName(bankB.name)) + assertEquals(bankA.name, partyBHandle.resolveName(bankA.name)) + } + + // Runs a test inside the Driver DSL, which provides useful functions for starting nodes, etc. + private fun withDriver(test: DriverDSL.() -> Unit) = driver( + DriverParameters(isDebug = true, startNodesInProcess = true) + ) { test() } + + // Makes an RPC call to retrieve another node's name from the network map. + private fun NodeHandle.resolveName(name: CordaX500Name) = rpc.wellKnownPartyFromX500Name(name)!!.name + + // Resolves a list of futures to a list of the promised values. + private fun List>.waitForAll(): List = map { it.getOrThrow() } + + // Starts multiple nodes simultaneously, then waits for them all to be ready. + private fun DriverDSL.startNodes(vararg identities: TestIdentity) = identities + .map { startNode(providedName = it.name) } + .waitForAll() +} \ No newline at end of file diff --git a/blacklist/src/main/kotlin/net/corda/examples/attachments/flow/ReachAgreementFlow.kt b/blacklist/workflows-kotlin/src/main/kotlin/net/corda/examples/attachments/ReachAgreementFlow.kt similarity index 89% rename from blacklist/src/main/kotlin/net/corda/examples/attachments/flow/ReachAgreementFlow.kt rename to blacklist/workflows-kotlin/src/main/kotlin/net/corda/examples/attachments/ReachAgreementFlow.kt index 6708cff34..7e0c36b14 100644 --- a/blacklist/src/main/kotlin/net/corda/examples/attachments/flow/ReachAgreementFlow.kt +++ b/blacklist/workflows-kotlin/src/main/kotlin/net/corda/examples/attachments/ReachAgreementFlow.kt @@ -1,4 +1,4 @@ -package net.corda.examples.attachments.flow +package net.corda.examples.attachments import co.paralleluniverse.fibers.Suspendable import net.corda.core.contracts.requireThat @@ -7,9 +7,9 @@ import net.corda.core.flows.* import net.corda.core.identity.Party import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.TransactionBuilder -import net.corda.examples.attachments.contract.AgreementContract -import net.corda.examples.attachments.contract.AgreementContract.Companion.AGREEMENT_CONTRACT_ID -import net.corda.examples.attachments.state.AgreementState +import net.corda.examples.attachments.contracts.AgreementContract +import net.corda.examples.attachments.contracts.AgreementContract.Companion.AGREEMENT_CONTRACT_ID +import net.corda.examples.attachments.states.AgreementState @InitiatingFlow @StartableByRPC diff --git a/blacklist/src/test/kotlin/net/corda/examples/attachments/tests/flow/FlowTests.kt b/blacklist/workflows-kotlin/src/test/kotlin/net/corda/examples/attachments/FlowTests.kt similarity index 93% rename from blacklist/src/test/kotlin/net/corda/examples/attachments/tests/flow/FlowTests.kt rename to blacklist/workflows-kotlin/src/test/kotlin/net/corda/examples/attachments/FlowTests.kt index 5026d908d..cee194ed0 100644 --- a/blacklist/src/test/kotlin/net/corda/examples/attachments/tests/flow/FlowTests.kt +++ b/blacklist/workflows-kotlin/src/test/kotlin/net/corda/examples/attachments/FlowTests.kt @@ -1,4 +1,4 @@ -package net.corda.examples.attachments.tests.flow +package net.corda.examples.attachments import net.corda.core.contracts.TransactionVerificationException import net.corda.core.crypto.SecureHash @@ -6,11 +6,7 @@ import net.corda.core.identity.Party import net.corda.core.node.services.queryBy import net.corda.core.transactions.SignedTransaction import net.corda.core.utilities.getOrThrow -import net.corda.examples.attachments.BLACKLIST_JAR_PATH -import net.corda.examples.attachments.flow.AgreeFlow -import net.corda.examples.attachments.flow.ProposeFlow -import net.corda.examples.attachments.state.AgreementState -import net.corda.examples.attachments.tests.INCORRECT_JAR_PATH +import net.corda.examples.attachments.states.AgreementState import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetworkParameters import net.corda.testing.node.StartedMockNode @@ -36,7 +32,7 @@ class FlowTests { @Before fun setup() { network = MockNetwork(MockNetworkParameters(cordappsForAllNodes = listOf( - TestCordapp.findCordapp("net.corda.examples.attachments.contract")))) + TestCordapp.findCordapp("net.corda.examples.attachments.contracts")))) a = network.createNode() b = network.createNode() aIdentity = a.info.legalIdentities.first() diff --git a/blacklist/src/test/kotlin/net/corda/examples/attachments/tests/NodeDriver.kt b/blacklist/workflows-kotlin/src/test/kotlin/net/corda/examples/attachments/NodeDriver.kt similarity index 91% rename from blacklist/src/test/kotlin/net/corda/examples/attachments/tests/NodeDriver.kt rename to blacklist/workflows-kotlin/src/test/kotlin/net/corda/examples/attachments/NodeDriver.kt index a1c4c43f7..03233bf36 100644 --- a/blacklist/src/test/kotlin/net/corda/examples/attachments/tests/NodeDriver.kt +++ b/blacklist/workflows-kotlin/src/test/kotlin/net/corda/examples/attachments/NodeDriver.kt @@ -1,4 +1,4 @@ -package net.corda.examples.attachments.tests +package net.corda.examples.attachments import net.corda.core.identity.CordaX500Name import net.corda.core.utilities.getOrThrow @@ -29,8 +29,5 @@ fun main(args: Array) { startNode(providedName = CordaX500Name("Hiseville Deposit Bank", "Sao Paulo", "BR"), rpcUsers = listOf(user)), startNode(providedName = CordaX500Name("George State Bank", "New York", "US"), rpcUsers = listOf(user))).map { it.getOrThrow() } - startWebserver(nodeA) - startWebserver(nodeB) - startWebserver(nodeC) } } \ No newline at end of file diff --git a/blacklist/workflows-kotlin/src/test/resources/invalid.jar b/blacklist/workflows-kotlin/src/test/resources/invalid.jar new file mode 100644 index 0000000000000000000000000000000000000000..f49523a053afd305a03254c4c2d7b22cbd5ab6d4 GIT binary patch literal 1198 zcmWIWW@Zs#-~d9iRv&K$B*4ocz>t)an4F!HSzMx5Qc)5b!NYK@{6VBe@BPTHj3NxW zXAg2UJMgev_+96^Zz(sIt%&2o=L=S{m8&1kVf}w^ZH4qRUY|Q>Yz@_3RfeCDYrAow zyIacQV)MpJ(X}Q!l(r<@*100CR}?8BwopC2@RiQmP#&j?MgJU67v_Hneyx4IeSe+g zan1m5c8jVC+q`%SVuqu(*y}-bpdI{k4y?|AN36dSY@1@nilv> z=o58V)4HrhP;uR)IrCRfj|iABdDZmUQIlp&ikOrkI{)qKN0F0eNk`3z5}7n3?#zJ+ zArmG?#v~T~Q~-~)Ogza%5IC_XJSCv|Ye z6?PX(q6RvC#}9C*Gct)XBYc6J7I_(Xz$p<(I4o%dG0{>F2Ry?Bc!P|=m2eTp{B_(2 zGzKXdbHI}^#0Z2-kkf_)ic4M~8-bCe(H(^_5!r8iC?>9EWWY#axXnR!nIwuiu}nyw Z(~C!scVr`3*+2ox3WViA%N3bHJOFP`ZlC}F literal 0 HcmV?d00001 From e205a67c254740a3dbe790af7a2474ab07bf62bb Mon Sep 17 00:00:00 2001 From: Anthony Nixon Date: Thu, 20 Feb 2020 00:42:31 +0000 Subject: [PATCH 2/2] README now instructs how to deployNodes and reminds user that nodes must be active before uploading blacklist - webservers removed --- blacklist/README.md | 17 ++++++ .../attachments/webserver/Controller.java | 27 ---------- .../webserver/NodeRPCConnection.java | 48 ----------------- .../attachments/webserver/Starter.java | 23 -------- .../src/main/resources/static/app.js | 3 -- .../src/main/resources/static/index.html | 10 ---- .../attachments/webserver/Controller.kt | 25 --------- .../webserver/NodeRPCConnection.kt | 52 ------------------- .../examples/attachments/webserver/Server.kt | 22 -------- .../src/main/resources/static/app.js | 3 -- .../src/main/resources/static/index.html | 10 ---- 11 files changed, 17 insertions(+), 223 deletions(-) delete mode 100644 blacklist/clients-java/src/main/java/net/corda/examples/attachments/webserver/Controller.java delete mode 100644 blacklist/clients-java/src/main/java/net/corda/examples/attachments/webserver/NodeRPCConnection.java delete mode 100644 blacklist/clients-java/src/main/java/net/corda/examples/attachments/webserver/Starter.java delete mode 100644 blacklist/clients-java/src/main/resources/static/app.js delete mode 100644 blacklist/clients-java/src/main/resources/static/index.html delete mode 100644 blacklist/clients-kotlin/src/main/kotlin/net/corda/examples/attachments/webserver/Controller.kt delete mode 100644 blacklist/clients-kotlin/src/main/kotlin/net/corda/examples/attachments/webserver/NodeRPCConnection.kt delete mode 100644 blacklist/clients-kotlin/src/main/kotlin/net/corda/examples/attachments/webserver/Server.kt delete mode 100644 blacklist/clients-kotlin/src/main/resources/static/app.js delete mode 100644 blacklist/clients-kotlin/src/main/resources/static/index.html diff --git a/blacklist/README.md b/blacklist/README.md index 449a874c2..c8720fd1a 100644 --- a/blacklist/README.md +++ b/blacklist/README.md @@ -29,7 +29,24 @@ See https://docs.corda.net/getting-set-up.html. See https://docs.corda.net/tutorial-cordapp.html#running-the-example-cordapp. +Java nodes +``` +./gradlew workflows-java:deployNodes +``` +``` +./workflows-java/build/nodes/runnodes +``` + +Kotlin nodes +``` +./gradlew workflows-kotlin:deployNodes +``` +``` +./workflows-kotlin/build/nodes/runnodes +``` + ## Uploading the blacklist: +Note: The nodes must be running before attempting this step Before attempting to reach any agreements, you must upload the blacklist as an attachment to each node that you want to be able to *initiate* an agreement. The blacklist can be uploaded via RPC by running the following command from the diff --git a/blacklist/clients-java/src/main/java/net/corda/examples/attachments/webserver/Controller.java b/blacklist/clients-java/src/main/java/net/corda/examples/attachments/webserver/Controller.java deleted file mode 100644 index fcbe49898..000000000 --- a/blacklist/clients-java/src/main/java/net/corda/examples/attachments/webserver/Controller.java +++ /dev/null @@ -1,27 +0,0 @@ -package net.corda.examples.attachments.webserver; - -import net.corda.core.messaging.CordaRPCOps; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -/** - * Define your API endpoints here. - */ -@RestController -@RequestMapping("/") // The paths for HTTP requests are relative to this base path. -public class Controller { - private final CordaRPCOps proxy; - private final static Logger logger = LoggerFactory.getLogger(Controller.class); - - public Controller(NodeRPCConnection rpc) { - this.proxy = rpc.proxy; - } - - @GetMapping(value = "/templateendpoint", produces = "text/plain") - private String templateendpoint() { - return "Define an endpoint here."; - } -} \ No newline at end of file diff --git a/blacklist/clients-java/src/main/java/net/corda/examples/attachments/webserver/NodeRPCConnection.java b/blacklist/clients-java/src/main/java/net/corda/examples/attachments/webserver/NodeRPCConnection.java deleted file mode 100644 index 76b4fd445..000000000 --- a/blacklist/clients-java/src/main/java/net/corda/examples/attachments/webserver/NodeRPCConnection.java +++ /dev/null @@ -1,48 +0,0 @@ -package net.corda.examples.attachments.webserver; - -import net.corda.client.rpc.CordaRPCClient; -import net.corda.client.rpc.CordaRPCConnection; -import net.corda.core.messaging.CordaRPCOps; -import net.corda.core.utilities.NetworkHostAndPort; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; - -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; - -/** - * Wraps an RPC connection to a Corda node. - * - * The RPC connection is configured using command line arguments. - */ -@Component -public class NodeRPCConnection implements AutoCloseable { - // The host of the node we are connecting to. - @Value("${config.rpc.host}") - private String host; - // The RPC port of the node we are connecting to. - @Value("${config.rpc.username}") - private String username; - // The username for logging into the RPC client. - @Value("${config.rpc.password}") - private String password; - // The password for logging into the RPC client. - @Value("${config.rpc.port}") - private int rpcPort; - - private CordaRPCConnection rpcConnection; - CordaRPCOps proxy; - - @PostConstruct - public void initialiseNodeRPCConnection() { - NetworkHostAndPort rpcAddress = new NetworkHostAndPort(host, rpcPort); - CordaRPCClient rpcClient = new CordaRPCClient(rpcAddress); - rpcConnection = rpcClient.start(username, password); - proxy = rpcConnection.getProxy(); - } - - @PreDestroy - public void close() { - rpcConnection.notifyServerAndClose(); - } -} \ No newline at end of file diff --git a/blacklist/clients-java/src/main/java/net/corda/examples/attachments/webserver/Starter.java b/blacklist/clients-java/src/main/java/net/corda/examples/attachments/webserver/Starter.java deleted file mode 100644 index b278f622f..000000000 --- a/blacklist/clients-java/src/main/java/net/corda/examples/attachments/webserver/Starter.java +++ /dev/null @@ -1,23 +0,0 @@ -package net.corda.examples.attachments.webserver; - -import org.springframework.boot.Banner; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -import static org.springframework.boot.WebApplicationType.SERVLET; - -/** - * Our Spring Boot application. - */ -@SpringBootApplication -public class Starter { - /** - * Starts our Spring Boot application. - */ - public static void main(String[] args) { - SpringApplication app = new SpringApplication(Starter.class); - app.setBannerMode(Banner.Mode.OFF); - app.setWebApplicationType(SERVLET); - app.run(args); - } -} \ No newline at end of file diff --git a/blacklist/clients-java/src/main/resources/static/app.js b/blacklist/clients-java/src/main/resources/static/app.js deleted file mode 100644 index c58d2de8c..000000000 --- a/blacklist/clients-java/src/main/resources/static/app.js +++ /dev/null @@ -1,3 +0,0 @@ -"use strict"; - -// Define your client-side logic here. \ No newline at end of file diff --git a/blacklist/clients-java/src/main/resources/static/index.html b/blacklist/clients-java/src/main/resources/static/index.html deleted file mode 100644 index 758501dd0..000000000 --- a/blacklist/clients-java/src/main/resources/static/index.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - Example front-end. - - -
Define your front-end here.
- - \ No newline at end of file diff --git a/blacklist/clients-kotlin/src/main/kotlin/net/corda/examples/attachments/webserver/Controller.kt b/blacklist/clients-kotlin/src/main/kotlin/net/corda/examples/attachments/webserver/Controller.kt deleted file mode 100644 index dda7dc778..000000000 --- a/blacklist/clients-kotlin/src/main/kotlin/net/corda/examples/attachments/webserver/Controller.kt +++ /dev/null @@ -1,25 +0,0 @@ -package net.corda.examples.attachments.webserver - -import org.slf4j.LoggerFactory -import org.springframework.web.bind.annotation.GetMapping -import org.springframework.web.bind.annotation.RequestMapping -import org.springframework.web.bind.annotation.RestController - -/** - * Define your API endpoints here. - */ -@RestController -@RequestMapping("/") // The paths for HTTP requests are relative to this base path. -class Controller(rpc: NodeRPCConnection) { - - companion object { - private val logger = LoggerFactory.getLogger(RestController::class.java) - } - - private val proxy = rpc.proxy - - @GetMapping(value = ["/templateendpoint"], produces = arrayOf("text/plain")) - private fun templateendpoint(): String { - return "Define an endpoint here." - } -} \ No newline at end of file diff --git a/blacklist/clients-kotlin/src/main/kotlin/net/corda/examples/attachments/webserver/NodeRPCConnection.kt b/blacklist/clients-kotlin/src/main/kotlin/net/corda/examples/attachments/webserver/NodeRPCConnection.kt deleted file mode 100644 index e1d6acb34..000000000 --- a/blacklist/clients-kotlin/src/main/kotlin/net/corda/examples/attachments/webserver/NodeRPCConnection.kt +++ /dev/null @@ -1,52 +0,0 @@ -package net.corda.examples.attachments.webserver - -import net.corda.client.rpc.CordaRPCClient -import net.corda.client.rpc.CordaRPCConnection -import net.corda.core.messaging.CordaRPCOps -import net.corda.core.utilities.NetworkHostAndPort -import org.springframework.beans.factory.annotation.Value -import org.springframework.stereotype.Component -import javax.annotation.PostConstruct -import javax.annotation.PreDestroy - -private const val CORDA_USER_NAME = "config.rpc.username" -private const val CORDA_USER_PASSWORD = "config.rpc.password" -private const val CORDA_NODE_HOST = "config.rpc.host" -private const val CORDA_RPC_PORT = "config.rpc.port" - -/** - * Wraps an RPC connection to a Corda node. - * - * The RPC connection is configured using command line arguments. - * - * @param host The host of the node we are connecting to. - * @param rpcPort The RPC port of the node we are connecting to. - * @param username The username for logging into the RPC client. - * @param password The password for logging into the RPC client. - * @property proxy The RPC proxy. - */ -@Component -open class NodeRPCConnection( - @Value("\${$CORDA_NODE_HOST}") private val host: String, - @Value("\${$CORDA_USER_NAME}") private val username: String, - @Value("\${$CORDA_USER_PASSWORD}") private val password: String, - @Value("\${$CORDA_RPC_PORT}") private val rpcPort: Int): AutoCloseable { - - lateinit var rpcConnection: CordaRPCConnection - private set - lateinit var proxy: CordaRPCOps - private set - - @PostConstruct - fun initialiseNodeRPCConnection() { - val rpcAddress = NetworkHostAndPort(host, rpcPort) - val rpcClient = CordaRPCClient(rpcAddress) - val rpcConnection = rpcClient.start(username, password) - proxy = rpcConnection.proxy - } - - @PreDestroy - override fun close() { - rpcConnection.notifyServerAndClose() - } -} \ No newline at end of file diff --git a/blacklist/clients-kotlin/src/main/kotlin/net/corda/examples/attachments/webserver/Server.kt b/blacklist/clients-kotlin/src/main/kotlin/net/corda/examples/attachments/webserver/Server.kt deleted file mode 100644 index 04672c6c3..000000000 --- a/blacklist/clients-kotlin/src/main/kotlin/net/corda/examples/attachments/webserver/Server.kt +++ /dev/null @@ -1,22 +0,0 @@ -package net.corda.examples.attachments.webserver - -import org.springframework.boot.Banner -import org.springframework.boot.SpringApplication -import org.springframework.boot.WebApplicationType.SERVLET -import org.springframework.boot.autoconfigure.SpringBootApplication - -/** - * Our Spring Boot application. - */ -@SpringBootApplication -private open class Starter - -/** - * Starts our Spring Boot application. - */ -fun main(args: Array) { - val app = SpringApplication(Starter::class.java) - app.setBannerMode(Banner.Mode.OFF) - app.webApplicationType = SERVLET - app.run(*args) -} diff --git a/blacklist/clients-kotlin/src/main/resources/static/app.js b/blacklist/clients-kotlin/src/main/resources/static/app.js deleted file mode 100644 index c58d2de8c..000000000 --- a/blacklist/clients-kotlin/src/main/resources/static/app.js +++ /dev/null @@ -1,3 +0,0 @@ -"use strict"; - -// Define your client-side logic here. \ No newline at end of file diff --git a/blacklist/clients-kotlin/src/main/resources/static/index.html b/blacklist/clients-kotlin/src/main/resources/static/index.html deleted file mode 100644 index 758501dd0..000000000 --- a/blacklist/clients-kotlin/src/main/resources/static/index.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - Example front-end. - - -
Define your front-end here.
- - \ No newline at end of file