diff --git a/fabcar/java/.gitignore b/fabcar/java/.gitignore new file mode 100755 index 0000000000..5fbd19f554 --- /dev/null +++ b/fabcar/java/.gitignore @@ -0,0 +1,5 @@ +/bin/ +/target/ +.settings/ +.classpath +.project \ No newline at end of file diff --git a/fabcar/java/pom.xml b/fabcar/java/pom.xml new file mode 100644 index 0000000000..db663c5ddc --- /dev/null +++ b/fabcar/java/pom.xml @@ -0,0 +1,56 @@ + + 4.0.0 + fabcar-java + fabcar-java + 1.4.0-SNAPSHOT + + + + maven-compiler-plugin + 3.8.0 + + 1.8 + 1.8 + + + + + + + hyperledger + Hyperledger Nexus + https://nexus.hyperledger.org/content/repositories/snapshots + + + + + org.hyperledger.fabric + fabric-gateway-java + 1.4.0-SNAPSHOT + + + org.junit.platform + junit-platform-launcher + 1.4.2 + + + org.junit.jupiter + junit-jupiter-engine + 5.4.1 + test + + + org.junit.vintage + junit-vintage-engine + 5.4.2 + + + org.assertj + assertj-core + 3.12.2 + test + + + \ No newline at end of file diff --git a/fabcar/java/src/main/java/org/example/ClientApp.java b/fabcar/java/src/main/java/org/example/ClientApp.java new file mode 100755 index 0000000000..c69f52beee --- /dev/null +++ b/fabcar/java/src/main/java/org/example/ClientApp.java @@ -0,0 +1,52 @@ +/* +SPDX-License-Identifier: Apache-2.0 +*/ + +package org.example; + +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.hyperledger.fabric.gateway.Contract; +import org.hyperledger.fabric.gateway.Gateway; +import org.hyperledger.fabric.gateway.Network; +import org.hyperledger.fabric.gateway.Wallet; + +public class ClientApp { + + public static void main(String[] args) throws Exception { + // Load a file system based wallet for managing identities. + Path walletPath = Paths.get("wallet"); + Wallet wallet = Wallet.createFileSystemWallet(walletPath); + + // load a CCP + Path networkConfigPath = Paths.get("..", "..", "first-network", "connection-org1.yaml"); + + Gateway.Builder builder = Gateway.createBuilder(); + builder.identity(wallet, "user1").networkConfig(networkConfigPath).discovery(true); + + // create a gateway connection + try (Gateway gateway = builder.connect()) { + + // get the network and contract + Network network = gateway.getNetwork("mychannel"); + Contract contract = network.getContract("fabcar"); + + byte[] result; + + result = contract.evaluateTransaction("queryAllCars"); + System.out.println(new String(result)); + + contract.submitTransaction("createCar", "CAR10", "VW", "Polo", "Grey", "Mary"); + + result = contract.evaluateTransaction("queryCar", "CAR10"); + System.out.println(new String(result)); + + contract.submitTransaction("changeCarOwner", "CAR10", "Archie"); + + result = contract.evaluateTransaction("queryCar", "CAR10"); + System.out.println(new String(result)); + } + } + +} diff --git a/fabcar/java/src/main/java/org/example/EnrollAdmin.java b/fabcar/java/src/main/java/org/example/EnrollAdmin.java new file mode 100644 index 0000000000..4d4db12271 --- /dev/null +++ b/fabcar/java/src/main/java/org/example/EnrollAdmin.java @@ -0,0 +1,50 @@ +/* +SPDX-License-Identifier: Apache-2.0 +*/ + +package org.example; + +import java.nio.file.Paths; +import java.util.Properties; + +import org.hyperledger.fabric.gateway.Wallet; +import org.hyperledger.fabric.gateway.Wallet.Identity; +import org.hyperledger.fabric.sdk.Enrollment; +import org.hyperledger.fabric.sdk.security.CryptoSuite; +import org.hyperledger.fabric.sdk.security.CryptoSuiteFactory; +import org.hyperledger.fabric_ca.sdk.EnrollmentRequest; +import org.hyperledger.fabric_ca.sdk.HFCAClient; + +public class EnrollAdmin { + + public static void main(String[] args) throws Exception { + + // Create a CA client for interacting with the CA. + Properties props = new Properties(); + props.put("pemFile", + "../../first-network/crypto-config/peerOrganizations/org1.example.com/ca/ca.org1.example.com-cert.pem"); + props.put("allowAllHostNames", "true"); + HFCAClient caClient = HFCAClient.createNewInstance("https://localhost:7054", props); + CryptoSuite cryptoSuite = CryptoSuiteFactory.getDefault().getCryptoSuite(); + caClient.setCryptoSuite(cryptoSuite); + + // Create a wallet for managing identities + Wallet wallet = Wallet.createFileSystemWallet(Paths.get("wallet")); + + // Check to see if we've already enrolled the admin user. + boolean adminExists = wallet.exists("admin"); + if (adminExists) { + System.out.println("An identity for the admin user \"admin\" already exists in the wallet"); + return; + } + + // Enroll the admin user, and import the new identity into the wallet. + final EnrollmentRequest enrollmentRequestTLS = new EnrollmentRequest(); + enrollmentRequestTLS.addHost("localhost"); + enrollmentRequestTLS.setProfile("tls"); + Enrollment enrollment = caClient.enroll("admin", "adminpw", enrollmentRequestTLS); + Identity user = Identity.createIdentity("Org1MSP", enrollment.getCert(), enrollment.getKey()); + wallet.put("admin", user); + System.out.println("Successfully enrolled user \"admin\" and imported it into the wallet"); + } +} diff --git a/fabcar/java/src/main/java/org/example/RegisterUser.java b/fabcar/java/src/main/java/org/example/RegisterUser.java new file mode 100644 index 0000000000..d972a01be2 --- /dev/null +++ b/fabcar/java/src/main/java/org/example/RegisterUser.java @@ -0,0 +1,107 @@ +/* +SPDX-License-Identifier: Apache-2.0 +*/ + +package org.example; + +import java.nio.file.Paths; +import java.security.PrivateKey; +import java.util.Properties; +import java.util.Set; + +import org.hyperledger.fabric.gateway.Wallet; +import org.hyperledger.fabric.gateway.Wallet.Identity; +import org.hyperledger.fabric.sdk.Enrollment; +import org.hyperledger.fabric.sdk.User; +import org.hyperledger.fabric.sdk.security.CryptoSuite; +import org.hyperledger.fabric.sdk.security.CryptoSuiteFactory; +import org.hyperledger.fabric_ca.sdk.HFCAClient; +import org.hyperledger.fabric_ca.sdk.RegistrationRequest; + +public class RegisterUser { + + public static void main(String[] args) throws Exception { + + // Create a CA client for interacting with the CA. + Properties props = new Properties(); + props.put("pemFile", + "../../first-network/crypto-config/peerOrganizations/org1.example.com/ca/ca.org1.example.com-cert.pem"); + props.put("allowAllHostNames", "true"); + HFCAClient caClient = HFCAClient.createNewInstance("https://localhost:7054", props); + CryptoSuite cryptoSuite = CryptoSuiteFactory.getDefault().getCryptoSuite(); + caClient.setCryptoSuite(cryptoSuite); + + // Create a wallet for managing identities + Wallet wallet = Wallet.createFileSystemWallet(Paths.get("wallet")); + + // Check to see if we've already enrolled the user. + boolean userExists = wallet.exists("user1"); + if (userExists) { + System.out.println("An identity for the user \"user1\" already exists in the wallet"); + return; + } + + userExists = wallet.exists("admin"); + if (!userExists) { + System.out.println("\"admin\" needs to be enrolled and added to the wallet first"); + return; + } + + Identity adminIdentity = wallet.get("admin"); + User admin = new User() { + + @Override + public String getName() { + return "admin"; + } + + @Override + public Set getRoles() { + return null; + } + + @Override + public String getAccount() { + return null; + } + + @Override + public String getAffiliation() { + return "org1.department1"; + } + + @Override + public Enrollment getEnrollment() { + return new Enrollment() { + + @Override + public PrivateKey getKey() { + return adminIdentity.getPrivateKey(); + } + + @Override + public String getCert() { + return adminIdentity.getCertificate(); + } + }; + } + + @Override + public String getMspId() { + return "Org1MSP"; + } + + }; + + // Register the user, enroll the user, and import the new identity into the wallet. + RegistrationRequest registrationRequest = new RegistrationRequest("user1"); + registrationRequest.setAffiliation("org1.department1"); + registrationRequest.setEnrollmentID("user1"); + String enrollmentSecret = caClient.register(registrationRequest, admin); + Enrollment enrollment = caClient.enroll("user1", enrollmentSecret); + Identity user = Identity.createIdentity("Org1MSP", enrollment.getCert(), enrollment.getKey()); + wallet.put("user1", user); + System.out.println("Successfully enrolled user \"user1\" and imported it into the wallet"); + } + +} diff --git a/fabcar/java/src/test/java/org/example/ClientTest.java b/fabcar/java/src/test/java/org/example/ClientTest.java new file mode 100644 index 0000000000..4bf2d83829 --- /dev/null +++ b/fabcar/java/src/test/java/org/example/ClientTest.java @@ -0,0 +1,17 @@ +/* +SPDX-License-Identifier: Apache-2.0 +*/ + +package org.example; + +import org.junit.Test; + +public class ClientTest { + + @Test + public void testFabCar() throws Exception { + EnrollAdmin.main(null); + RegisterUser.main(null); + ClientApp.main(null); + } +} diff --git a/fabcar/java/wallet/.gitkeep b/fabcar/java/wallet/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/fabcar/javascript/enrollAdmin.js b/fabcar/javascript/enrollAdmin.js index 8d2a86aa2d..695d9ea57e 100644 --- a/fabcar/javascript/enrollAdmin.js +++ b/fabcar/javascript/enrollAdmin.js @@ -18,8 +18,7 @@ async function main() { // Create a new CA client for interacting with the CA. const caInfo = ccp.certificateAuthorities['ca.org1.example.com']; - const caTLSCACertsPath = path.resolve(__dirname, '..', '..', 'first-network', caInfo.tlsCACerts.path); - const caTLSCACerts = fs.readFileSync(caTLSCACertsPath); + const caTLSCACerts = caInfo.tlsCACerts.pem; const ca = new FabricCAServices(caInfo.url, { trustedRoots: caTLSCACerts, verify: false }, caInfo.caName); // Create a new file system based wallet for managing identities. diff --git a/fabcar/startFabric.sh b/fabcar/startFabric.sh index 6fe36dc86b..115abf89b6 100755 --- a/fabcar/startFabric.sh +++ b/fabcar/startFabric.sh @@ -259,4 +259,19 @@ TypeScript: return all cars, but you can update the application to evaluate other transactions: node dist/query +Java: + + Start by changing into the "java" directory: + cd java + + Then, install dependencies and run the test using: + mvn test + + The test will invoke the sample client app which perform the following: + - Enroll admin and user1 and import them into the wallet (if they don't already exist there) + - Submit a transaction to create a new car + - Evaluate a transaction (query) to return details of this car + - Submit a transaction to change the owner of this car + - Evaluate a transaction (query) to return the updated details of this car + EOF diff --git a/fabcar/typescript/src/enrollAdmin.ts b/fabcar/typescript/src/enrollAdmin.ts index 7e8df7cd12..7325ee2ddd 100644 --- a/fabcar/typescript/src/enrollAdmin.ts +++ b/fabcar/typescript/src/enrollAdmin.ts @@ -16,8 +16,7 @@ async function main() { // Create a new CA client for interacting with the CA. const caInfo = ccp.certificateAuthorities['ca.org1.example.com']; - const caTLSCACertsPath = path.resolve(__dirname, '..', '..', '..', 'first-network', caInfo.tlsCACerts.path); - const caTLSCACerts = fs.readFileSync(caTLSCACertsPath); + const caTLSCACerts = caInfo.tlsCACerts.pem; const ca = new FabricCAServices(caInfo.url, { trustedRoots: caTLSCACerts, verify: false }, caInfo.caName); // Create a new file system based wallet for managing identities. diff --git a/first-network/byfn.sh b/first-network/byfn.sh index 08ad46c2de..f91f261d9a 100755 --- a/first-network/byfn.sh +++ b/first-network/byfn.sh @@ -367,6 +367,8 @@ function generateCerts() { exit 1 fi echo + echo "Generate CCP files for Org1 and Org2" + ./ccp-generate.sh } # The `configtxgen tool is used to create four artifacts: orderer **bootstrap diff --git a/first-network/ccp-generate.sh b/first-network/ccp-generate.sh new file mode 100755 index 0000000000..11d3715523 --- /dev/null +++ b/first-network/ccp-generate.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +function one_line_pem { + echo "`awk 'NF {sub(/\\n/, ""); printf "%s\\\\\\\n",$0;}' $1`" +} + +function json_ccp { + local PP=$(one_line_pem $5) + local CP=$(one_line_pem $6) + sed -e "s/\${ORG}/$1/" \ + -e "s/\${P0PORT}/$2/" \ + -e "s/\${P1PORT}/$3/" \ + -e "s/\${CAPORT}/$4/" \ + -e "s#\${PEERPEM}#$PP#" \ + -e "s#\${CAPEM}#$CP#" \ + ccp-template.json +} + +function yaml_ccp { + local PP=$(one_line_pem $5) + local CP=$(one_line_pem $6) + sed -e "s/\${ORG}/$1/" \ + -e "s/\${P0PORT}/$2/" \ + -e "s/\${P1PORT}/$3/" \ + -e "s/\${CAPORT}/$4/" \ + -e "s#\${PEERPEM}#$PP#" \ + -e "s#\${CAPEM}#$CP#" \ + ccp-template.yaml | sed -e $'s/\\\\n/\\\n /g' +} + +ORG=1 +P0PORT=7051 +P1PORT=8051 +CAPORT=7054 +PEERPEM=crypto-config/peerOrganizations/org1.example.com/tlsca/tlsca.org1.example.com-cert.pem +CAPEM=crypto-config/peerOrganizations/org1.example.com/ca/ca.org1.example.com-cert.pem + +echo "$(json_ccp $ORG $P0PORT $P1PORT $CAPORT $PEERPEM $CAPEM)" > connection-org1.json +echo "$(yaml_ccp $ORG $P0PORT $P1PORT $CAPORT $PEERPEM $CAPEM)" > connection-org1.yaml + +ORG=2 +P0PORT=9051 +P1PORT=10051 +CAPORT=8054 +PEERPEM=crypto-config/peerOrganizations/org2.example.com/tlsca/tlsca.org2.example.com-cert.pem +CAPEM=crypto-config/peerOrganizations/org2.example.com/ca/ca.org2.example.com-cert.pem + +echo "$(json_ccp $ORG $P0PORT $P1PORT $CAPORT $PEERPEM $CAPEM)" > connection-org2.json +echo "$(yaml_ccp $ORG $P0PORT $P1PORT $CAPORT $PEERPEM $CAPEM)" > connection-org2.yaml diff --git a/first-network/ccp-template.json b/first-network/ccp-template.json new file mode 100644 index 0000000000..243f0ccdcd --- /dev/null +++ b/first-network/ccp-template.json @@ -0,0 +1,60 @@ +{ + "name": "first-network-org${ORG}", + "version": "1.0.0", + "client": { + "organization": "Org${ORG}", + "connection": { + "timeout": { + "peer": { + "endorser": "300" + } + } + } + }, + "organizations": { + "Org${ORG}": { + "mspid": "Org${ORG}MSP", + "peers": [ + "peer0.org${ORG}.example.com", + "peer1.org${ORG}.example.com" + ], + "certificateAuthorities": [ + "ca.org${ORG}.example.com" + ] + } + }, + "peers": { + "peer0.org${ORG}.example.com": { + "url": "grpcs://localhost:${P0PORT}", + "tlsCACerts": { + "pem": "${PEERPEM}" + }, + "grpcOptions": { + "ssl-target-name-override": "peer0.org${ORG}.example.com", + "hostnameOverride": "peer0.org${ORG}.example.com" + } + }, + "peer1.org${ORG}.example.com": { + "url": "grpcs://localhost:${P1PORT}", + "tlsCACerts": { + "pem": "${PEERPEM}" + }, + "grpcOptions": { + "ssl-target-name-override": "peer1.org${ORG}.example.com", + "hostnameOverride": "peer1.org${ORG}.example.com" + } + } + }, + "certificateAuthorities": { + "ca.org${ORG}.example.com": { + "url": "https://localhost:${CAPORT}", + "caName": "ca-org${ORG}", + "tlsCACerts": { + "pem": "${CAPEM}" + }, + "httpOptions": { + "verify": false + } + } + } +} diff --git a/first-network/ccp-template.yaml b/first-network/ccp-template.yaml new file mode 100644 index 0000000000..35333d9975 --- /dev/null +++ b/first-network/ccp-template.yaml @@ -0,0 +1,43 @@ +--- +name: first-network-org${ORG} +version: 1.0.0 +client: + organization: Org${ORG} + connection: + timeout: + peer: + endorser: '300' +organizations: + Org${ORG}: + mspid: Org${ORG}MSP + peers: + - peer0.org${ORG}.example.com + - peer1.org${ORG}.example.com + certificateAuthorities: + - ca.org${ORG}.example.com +peers: + peer0.org${ORG}.example.com: + url: grpcs://localhost:${P0PORT} + tlsCACerts: + pem: | + ${PEERPEM} + grpcOptions: + ssl-target-name-override: peer0.org${ORG}.example.com + hostnameOverride: peer0.org${ORG}.example.com + peer1.org${ORG}.example.com: + url: grpcs://localhost:${P1PORT} + tlsCACerts: + pem: | + ${PEERPEM} + grpcOptions: + ssl-target-name-override: peer1.org${ORG}.example.com + hostnameOverride: peer1.org${ORG}.example.com +certificateAuthorities: + ca.org${ORG}.example.com: + url: https://localhost:${CAPORT} + caName: ca-org${ORG} + tlsCACerts: + pem: | + ${CAPEM} + httpOptions: + verify: false diff --git a/first-network/connection-org1.json b/first-network/connection-org1.json deleted file mode 100644 index d9f460eb9d..0000000000 --- a/first-network/connection-org1.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "name": "first-network-org1", - "version": "1.0.0", - "client": { - "organization": "Org1", - "connection": { - "timeout": { - "peer": { - "endorser": "300" - } - } - } - }, - "organizations": { - "Org1": { - "mspid": "Org1MSP", - "peers": [ - "peer0.org1.example.com", - "peer1.org1.example.com" - ], - "certificateAuthorities": [ - "ca.org1.example.com" - ] - } - }, - "peers": { - "peer0.org1.example.com": { - "url": "grpcs://localhost:7051", - "tlsCACerts": { - "path": "crypto-config/peerOrganizations/org1.example.com/tlsca/tlsca.org1.example.com-cert.pem" - }, - "grpcOptions": { - "ssl-target-name-override": "peer0.org1.example.com" - } - }, - "peer1.org1.example.com": { - "url": "grpcs://localhost:8051", - "tlsCACerts": { - "path": "crypto-config/peerOrganizations/org1.example.com/tlsca/tlsca.org1.example.com-cert.pem" - }, - "grpcOptions": { - "ssl-target-name-override": "peer1.org1.example.com" - } - } - }, - "certificateAuthorities": { - "ca.org1.example.com": { - "url": "https://localhost:7054", - "caName": "ca-org1", - "tlsCACerts": { - "path": "crypto-config/peerOrganizations/org1.example.com/tlsca/tlsca.org1.example.com-cert.pem" - }, - "httpOptions": { - "verify": false - } - } - } -} diff --git a/first-network/connection-org1.yaml b/first-network/connection-org1.yaml deleted file mode 100644 index daa9ad6422..0000000000 --- a/first-network/connection-org1.yaml +++ /dev/null @@ -1,38 +0,0 @@ ---- -name: first-network-org1 -version: 1.0.0 -client: - organization: Org1 - connection: - timeout: - peer: - endorser: '300' -organizations: - Org1: - mspid: Org1MSP - peers: - - peer0.org1.example.com - - peer1.org1.example.com - certificateAuthorities: - - ca.org1.example.com -peers: - peer0.org1.example.com: - url: grpcs://localhost:7051 - tlsCACerts: - path: crypto-config/peerOrganizations/org1.example.com/tlsca/tlsca.org1.example.com-cert.pem - grpcOptions: - ssl-target-name-override: peer0.org1.example.com - peer1.org1.example.com: - url: grpcs://localhost:8051 - tlsCACerts: - path: crypto-config/peerOrganizations/org1.example.com/tlsca/tlsca.org1.example.com-cert.pem - grpcOptions: - ssl-target-name-override: peer1.org1.example.com -certificateAuthorities: - ca.org1.example.com: - url: https://localhost:7054 - caName: ca-org1 - tlsCACerts: - path: crypto-config/peerOrganizations/org1.example.com/tlsca/tlsca.org1.example.com-cert.pem - httpOptions: - verify: false diff --git a/first-network/connection-org2.json b/first-network/connection-org2.json deleted file mode 100644 index 49f9106d6c..0000000000 --- a/first-network/connection-org2.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "name": "first-network-org2", - "version": "1.0.0", - "client": { - "organization": "Org2", - "connection": { - "timeout": { - "peer": { - "endorser": "300" - } - } - } - }, - "organizations": { - "Org2": { - "mspid": "Org2MSP", - "peers": [ - "peer0.org2.example.com", - "peer1.org2.example.com" - ], - "certificateAuthorities": [ - "ca.org2.example.com" - ] - } - }, - "peers": { - "peer0.org2.example.com": { - "url": "grpcs://localhost:9051", - "tlsCACerts": { - "path": "crypto-config/peerOrganizations/org2.example.com/tlsca/tlsca.org2.example.com-cert.pem" - }, - "grpcOptions": { - "ssl-target-name-override": "peer0.org2.example.com" - } - }, - "peer1.org2.example.com": { - "url": "grpcs://localhost:10051", - "tlsCACerts": { - "path": "crypto-config/peerOrganizations/org2.example.com/tlsca/tlsca.org2.example.com-cert.pem" - }, - "grpcOptions": { - "ssl-target-name-override": "peer1.org2.example.com" - } - } - }, - "certificateAuthorities": { - "ca.org2.example.com": { - "url": "https://localhost:8054", - "caName": "ca-org2", - "tlsCACerts": { - "path": "crypto-config/peerOrganizations/org2.example.com/tlsca/tlsca.org2.example.com-cert.pem" - }, - "httpOptions": { - "verify": false - } - } - } -} diff --git a/first-network/connection-org2.yaml b/first-network/connection-org2.yaml deleted file mode 100644 index b21c879fd8..0000000000 --- a/first-network/connection-org2.yaml +++ /dev/null @@ -1,38 +0,0 @@ ---- -name: first-network-org2 -version: 1.0.0 -client: - organization: Org2 - connection: - timeout: - peer: - endorser: '300' -organizations: - Org2: - mspid: Org2MSP - peers: - - peer0.org2.example.com - - peer1.org2.example.com - certificateAuthorities: - - ca.org2.example.com -peers: - peer0.org2.example.com: - url: grpcs://localhost:9051 - tlsCACerts: - path: crypto-config/peerOrganizations/org2.example.com/tlsca/tlsca.org2.example.com-cert.pem - grpcOptions: - ssl-target-name-override: peer0.org2.example.com - peer1.org2.example.com: - url: grpcs://localhost:10051 - tlsCACerts: - path: crypto-config/peerOrganizations/org2.example.com/tlsca/tlsca.org2.example.com-cert.pem - grpcOptions: - ssl-target-name-override: peer1.org2.example.com -certificateAuthorities: - ca.org2.example.com: - url: https://localhost:8054 - caName: ca-org2 - tlsCACerts: - path: crypto-config/peerOrganizations/org2.example.com/tlsca/tlsca.org2.example.com-cert.pem - httpOptions: - verify: false