[FAB-17461] Move off_chain_data sample to test network (#122)

Signed-off-by: NIKHIL E GUPTA <negupta@us.ibm.com>

Co-authored-by: NIKHIL E GUPTA <negupta@us.ibm.com>
This commit is contained in:
nikhil550 2020-03-20 10:23:54 -04:00 committed by GitHub
parent 121a44a1d1
commit faac18e6da
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 167 additions and 165 deletions

View file

@ -1,28 +1,32 @@
# Off Chain data
This sample demonstrates how you can use [Peer channel-based event services](https://hyperledger-fabric.readthedocs.io/en/release-1.4/peer_event_services.html)
This sample demonstrates how you can use [Peer channel-based event services](https://hyperledger-fabric.readthedocs.io/en/release-2.0/peer_event_services.html)
to replicate the data on your blockchain network to an off chain database.
Using an off chain database allows you to analyze the data from your network or
build a dashboard without degrading the performance of your application.
This sample uses the [Fabric network event listener](https://fabric-sdk-node.github.io/release-1.4/tutorial-listening-to-events.html) from the Node.JS Fabric SDK to write data to local instance of
This sample uses the [Fabric network event listener](https://hyperledger.github.io/fabric-sdk-node/release-1.4/tutorial-channel-events.html) from the Node.JS Fabric SDK to write data to local instance of
CouchDB.
## Getting started
This sample uses Node Fabric SDK application code similar to the `fabcar` sample
to connect to a network created using the `first-network` sample.
to connect to a running instance of the Fabric test network. Make sure that you
are running the following commands from the `off_chain_data` directory.
### Install dependencies
### Starting the Network
You need to install Node.js version 8.9.x to use the sample application code.
Execute the following commands to install the required dependencies:
Use the following command to start the sample network:
```
cd fabric-samples/off_chain_data
npm install
./startFabric.sh
```
This command will deploy an instance of the Fabric test network. The network
consists of an ordering service, two peer organizations with one peers each, and
a CA for each org. The command also creates a channel named `mychannel`. The
marbles chaincode will be installed on both peers and deployed to the channel.
### Configuration
The configuration for the listener is stored in the `config.json` file:
@ -51,29 +55,24 @@ If you set the "use_couchdb" option to true in `config.json`, you can run the
following command start a local instance of CouchDB using docker:
```
docker run --publish 5990:5984 --detach --name offchaindb hyperledger/fabric-couchdb
docker run --publish 5990:5984 --detach --name offchaindb couchdb
docker start offchaindb
```
### Starting the Network
### Install dependencies
Use the following command to start the sample network:
You need to install Node.js version 8.9.x to use the sample application code.
Execute the following commands to install the required dependencies:
```
./startFabric.sh
npm install
```
This command uses the `first-network` sample to deploy a fabric network with an
ordering service, two peer organizations with two peers each, and a channel
named `mychannel`. The marbles chaincode will be installed on all four peers and
instantiated on the channel.
### Starting the Channel Event Listener
Once the network has started, we can use the Node.js SDK to create the user and
certificates our listener application will use to interact with the network. Run
the following command to enroll the admin user:
After we have installed the application dependencies, we can use the Node.js SDK
to create the identity our listener application will use to interact with the
network. Run the following command to enroll the admin user:
```
node enrollAdmin.js
```
@ -358,18 +357,16 @@ database:
## Clean up
If you are finished using the sample application, you can bring down the network
and any accompanying artifacts.
and any accompanying artifacts by running the following command:
```
./network-clean.sh
```
* Change to `fabric-samples/first-network` directory.
* To stop the network, run `./byfn.sh down`.
* Change back to `fabric-samples/off_chain_data` directory.
Running the script will complete the following actions:
* Bring down the Fabric test network.
* Takes down the local CouchDB database.
* Remove the certificates you generated by deleting the `wallet` folder.
* Delete `nextblock.txt` so you can start with the first block next time you
operate the listener. You can also reset the `nextMarbleNumber` in
`addMarbles.json` to 100.
* To take down the local CouchDB database, first stop and then remove the
docker container:
```
docker stop offchaindb
docker rm offchaindb
```
operate the listener.
* Removes `addMarbles.json`.

View file

@ -69,7 +69,7 @@ async function main() {
// Parse the connection profile. This would be the path to the file downloaded
// from the IBM Blockchain Platform operational console.
const ccpPath = path.resolve(__dirname, '..', 'first-network', 'connection-org1.json');
const ccpPath = path.resolve(__dirname, '..', 'test-network','organizations','peerOrganizations','org1.example.com', 'connection-org1.json');
const ccp = JSON.parse(fs.readFileSync(ccpPath, 'utf8'));
// Configure a wallet. This wallet must already be primed with an identity that
@ -80,7 +80,7 @@ async function main() {
// Create a new gateway, and connect to the gateway peer node(s). The identity
// specified must already exist in the specified wallet.
const gateway = new Gateway();
await gateway.connect(ccp, { wallet, identity: 'user1', discovery: { enabled: true, asLocalhost: true } });
await gateway.connect(ccp, { wallet, identity: 'appUser', discovery: { enabled: true, asLocalhost: true } });
// Get the network channel that the smart contract is deployed to.
const network = await gateway.getNetwork(channelid);

View file

@ -98,20 +98,20 @@ async function main() {
console.log(`Wallet path: ${walletPath}`);
// Check to see if we've already enrolled the user.
const userExists = await wallet.get('user1');
const userExists = await wallet.get('appUser');
if (!userExists) {
console.log('An identity for the user "user1" does not exist in the wallet');
console.log('An identity for the user "appUser" does not exist in the wallet');
console.log('Run the enrollUser.js application before retrying');
return;
}
// Parse the connection profile. This would be the path to the file downloaded
// from the IBM Blockchain Platform operational console.
const ccpPath = path.resolve(__dirname, '..', 'first-network', 'connection-org1.json');
const ccpPath = path.resolve(__dirname, '..', 'test-network','organizations','peerOrganizations','org1.example.com', 'connection-org1.json');
const ccp = JSON.parse(fs.readFileSync(ccpPath, 'utf8'));
// Create a new gateway for connecting to our peer node.
const gateway = new Gateway();
await gateway.connect(ccp, { wallet, identity: 'user1', discovery: { enabled: true, asLocalhost: true } });
await gateway.connect(ccp, { wallet, identity: 'appUser', discovery: { enabled: true, asLocalhost: true } });
// Get the network (channel) our contract is deployed to.
const network = await gateway.getNetwork('mychannel');

View file

@ -36,7 +36,7 @@ async function main() {
// Parse the connection profile. This would be the path to the file downloaded
// from the IBM Blockchain Platform operational console.
const ccpPath = path.resolve(__dirname, '..', 'first-network', 'connection-org1.json');
const ccpPath = path.resolve(__dirname, '..', 'test-network','organizations','peerOrganizations','org1.example.com', 'connection-org1.json');
const ccp = JSON.parse(fs.readFileSync(ccpPath, 'utf8'));
// Configure a wallet. This wallet must already be primed with an identity that
@ -47,7 +47,7 @@ async function main() {
// Create a new gateway, and connect to the gateway peer node(s). The identity
// specified must already exist in the specified wallet.
const gateway = new Gateway();
await gateway.connect(ccp, { wallet, identity: 'user1', discovery: { enabled: true, asLocalhost: true } });
await gateway.connect(ccp, { wallet, identity: 'appUser', discovery: { enabled: true, asLocalhost: true } });
// Get the network channel that the smart contract is deployed to.
const network = await gateway.getNetwork(channelid);

View file

@ -1,6 +1,4 @@
/*
* Copyright IBM Corp. All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
@ -15,7 +13,7 @@ const path = require('path');
async function main() {
try {
// load the network configuration
const ccpPath = path.resolve(__dirname, '..', 'first-network', 'connection-org1.json');
const ccpPath = path.resolve(__dirname, '..', 'test-network', 'organizations', 'peerOrganizations', 'org1.example.com', 'connection-org1.json');
let ccp = JSON.parse(fs.readFileSync(ccpPath, 'utf8'));
// Create a new CA client for interacting with the CA.

20
off_chain_data/network-clean.sh Executable file
View file

@ -0,0 +1,20 @@
#!/bin/bash
#
# Copyright IBM Corp All Rights Reserved
#
# SPDX-License-Identifier: Apache-2.0
#
# Exit on first error
set -ex
# Bring the test network down
pushd ../test-network
./network.sh down
popd
# clean out any old identites in the wallets
rm -rf wallet
rm -rf addMarbles.json mychannel_marbles.log mychannel__lifecycle.log nextblock.txt
docker stop offchaindb
docker rm offchaindb

View file

@ -1,6 +1,4 @@
/*
* Copyright IBM Corp. All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
@ -15,7 +13,7 @@ const path = require('path');
async function main() {
try {
// load the network configuration
const ccpPath = path.resolve(__dirname, '..', 'first-network', 'connection-org1.json');
const ccpPath = path.resolve(__dirname, '..', 'test-network','organizations','peerOrganizations','org1.example.com', 'connection-org1.json');
const ccp = JSON.parse(fs.readFileSync(ccpPath, 'utf8'));
// Create a new CA client for interacting with the CA.
@ -28,9 +26,9 @@ async function main() {
console.log(`Wallet path: ${walletPath}`);
// Check to see if we've already enrolled the user.
const userExists = await wallet.get('user1');
const userExists = await wallet.get('appUser');
if (userExists) {
console.log('An identity for the user "user1" already exists in the wallet');
console.log('An identity for the user "appUser" already exists in the wallet');
return;
}
@ -49,11 +47,11 @@ async function main() {
// Register the user, enroll the user, and import the new identity into the wallet.
const secret = await ca.register({
affiliation: 'org1.department1',
enrollmentID: 'user1',
enrollmentID: 'appUser',
role: 'client'
}, adminUser);
const enrollment = await ca.enroll({
enrollmentID: 'user1',
enrollmentID: 'appUser',
enrollmentSecret: secret
});
const x509Identity = {
@ -64,11 +62,11 @@ async function main() {
mspId: 'Org1MSP',
type: 'X.509',
};
await wallet.put('user1', x509Identity);
console.log('Successfully registered and enrolled admin user "user1" and imported it into the wallet');
await wallet.put('appUser', x509Identity);
console.log('Successfully registered and enrolled admin user "appUser" and imported it into the wallet');
} catch (error) {
console.error(`Failed to register user "user1": ${error}`);
console.error(`Failed to register user "appUser": ${error}`);
process.exit(1);
}
}

View file

@ -7,98 +7,64 @@
# Exit on first error
set -e pipefail
# don't rewrite paths for Windows Git Bash users
export MSYS_NO_PATHCONV=1
starttime=$(date +%s)
CC_SRC_LANGUAGE=golang
CC_RUNTIME_LANGUAGE=golang
CC_SRC_PATH=github.com/hyperledger/fabric-samples/chaincode/marbles02/go
CC_SRC_PATH=../chaincode/marbles02/go
echo Vendoring Go dependencies ...
pushd ../chaincode/marbles02/go
GO111MODULE=on go mod vendor
popd
echo Finished vendoring Go dependencies
# clean the keystore
rm -rf ./hfc-key-store
# launch network; create channel and join peer to channel
pushd ../first-network
echo y | ./byfn.sh down
echo y | ./byfn.sh up -a -n -s couchdb
popd
pushd ../test-network
./network.sh down
./network.sh up createChannel -ca -s couchdb
CONFIG_ROOT=/opt/gopath/src/github.com/hyperledger/fabric/peer
ORG1_MSPCONFIGPATH=${CONFIG_ROOT}/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
ORG1_TLS_ROOTCERT_FILE=${CONFIG_ROOT}/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
ORG2_MSPCONFIGPATH=${CONFIG_ROOT}/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
ORG2_TLS_ROOTCERT_FILE=${CONFIG_ROOT}/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
ORDERER_TLS_ROOTCERT_FILE=${CONFIG_ROOT}/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
export PATH=${PWD}/../bin:${PWD}:$PATH
export FABRIC_CFG_PATH=${PWD}/../config
# import environment variables
. scripts/envVar.sh
echo "Packaging the marbles smart contract"
docker exec \
cli \
peer lifecycle chaincode package marbles.tar.gz \
--path $CC_SRC_PATH \
--lang $CC_RUNTIME_LANGUAGE \
--label marblesv1
setGlobals 1
peer lifecycle chaincode package marbles.tar.gz \
--path $CC_SRC_PATH \
--lang $CC_RUNTIME_LANGUAGE \
--label marblesv1
echo "Installing smart contract on peer0.org1.example.com"
docker exec \
-e CORE_PEER_LOCALMSPID=Org1MSP \
-e CORE_PEER_ADDRESS=peer0.org1.example.com:7051 \
-e CORE_PEER_MSPCONFIGPATH=${ORG1_MSPCONFIGPATH} \
-e CORE_PEER_TLS_ROOTCERT_FILE=${ORG1_TLS_ROOTCERT_FILE} \
cli \
peer lifecycle chaincode install marbles.tar.gz
echo "Installing smart contract on peer1.org1.example.com"
docker exec \
-e CORE_PEER_LOCALMSPID=Org1MSP \
-e CORE_PEER_ADDRESS=peer1.org1.example.com:8051 \
-e CORE_PEER_MSPCONFIGPATH=${ORG1_MSPCONFIGPATH} \
-e CORE_PEER_TLS_ROOTCERT_FILE=${ORG1_TLS_ROOTCERT_FILE} \
cli \
peer lifecycle chaincode install marbles.tar.gz
peer lifecycle chaincode install marbles.tar.gz
echo "Installing smart contract on peer0.org2.example.com"
docker exec \
-e CORE_PEER_LOCALMSPID=Org2MSP \
-e CORE_PEER_ADDRESS=peer0.org2.example.com:9051 \
-e CORE_PEER_MSPCONFIGPATH=${ORG2_MSPCONFIGPATH} \
-e CORE_PEER_TLS_ROOTCERT_FILE=${ORG2_TLS_ROOTCERT_FILE} \
cli \
peer lifecycle chaincode install marbles.tar.gz
echo "Installing smart contract on peer1.org2.example.com"
docker exec \
-e CORE_PEER_LOCALMSPID=Org2MSP \
-e CORE_PEER_ADDRESS=peer1.org2.example.com:10051 \
-e CORE_PEER_MSPCONFIGPATH=${ORG2_MSPCONFIGPATH} \
-e CORE_PEER_TLS_ROOTCERT_FILE=${ORG2_TLS_ROOTCERT_FILE} \
cli \
peer lifecycle chaincode install marbles.tar.gz
setGlobals 2
peer lifecycle chaincode install marbles.tar.gz
echo "Query the chaincode package id"
docker exec \
-e CORE_PEER_LOCALMSPID=Org1MSP \
-e CORE_PEER_ADDRESS=peer0.org1.example.com:7051 \
-e CORE_PEER_MSPCONFIGPATH=${ORG1_MSPCONFIGPATH} \
-e CORE_PEER_TLS_ROOTCERT_FILE=${ORG1_TLS_ROOTCERT_FILE} \
cli \
/bin/bash -c "peer lifecycle chaincode queryinstalled > log"
PACKAGE_ID=`docker exec cli sed -nr '/Label: marblesv1/s/Package ID: (.*), Label: marblesv1/\1/p;' log`
setGlobals 1
peer lifecycle chaincode queryinstalled >&log.txt
PACKAGE_ID=$(sed -n "/marblesv1/{s/^Package ID: //; s/, Label:.*$//; p;}" log.txt)
echo "Approving the chaincode definition for org1.example.com"
docker exec \
-e CORE_PEER_LOCALMSPID=Org1MSP \
-e CORE_PEER_ADDRESS=peer0.org1.example.com:7051 \
-e CORE_PEER_MSPCONFIGPATH=${ORG1_MSPCONFIGPATH} \
-e CORE_PEER_TLS_ROOTCERT_FILE=${ORG1_TLS_ROOTCERT_FILE} \
cli \
peer lifecycle chaincode approveformyorg \
-o orderer.example.com:7050 \
peer lifecycle chaincode approveformyorg \
-o localhost:7050 \
--ordererTLSHostnameOverride orderer.example.com \
--channelID mychannel \
--name marbles \
--version 1.0 \
@ -107,17 +73,15 @@ docker exec \
--sequence 1 \
--package-id $PACKAGE_ID \
--tls \
--cafile ${ORDERER_TLS_ROOTCERT_FILE}
--cafile ${ORDERER_CA}
echo "Approving the chaincode definition for org2.example.com"
docker exec \
-e CORE_PEER_LOCALMSPID=Org2MSP \
-e CORE_PEER_ADDRESS=peer0.org2.example.com:9051 \
-e CORE_PEER_MSPCONFIGPATH=${ORG2_MSPCONFIGPATH} \
-e CORE_PEER_TLS_ROOTCERT_FILE=${ORG2_TLS_ROOTCERT_FILE} \
cli \
peer lifecycle chaincode approveformyorg \
-o orderer.example.com:7050 \
setGlobals 2
peer lifecycle chaincode approveformyorg \
-o localhost:7050 \
--ordererTLSHostnameOverride orderer.example.com \
--channelID mychannel \
--name marbles \
--version 1.0 \
@ -126,19 +90,38 @@ docker exec \
--sequence 1 \
--package-id $PACKAGE_ID \
--tls \
--cafile ${ORDERER_TLS_ROOTCERT_FILE}
--cafile ${ORDERER_CA}
echo "Waiting for the approvals to be committed ..."
echo "Checking if the chaincode definition is ready to commit"
sleep 10
peer lifecycle chaincode checkcommitreadiness \
--channelID mychannel \
--name marbles \
--version 1.0 \
--sequence 1 \
--output json \
--init-required \
--signature-policy AND"('Org1MSP.member','Org2MSP.member')" >&log.txt
rc=0
for var in "\"Org1MSP\": true" "\"Org2MSP\": true"
do
grep "$var" log.txt &>/dev/null || let rc=1
done
if test $rc -eq 0; then
echo "Chaincode definition is ready to commit"
else
sleep 10
fi
parsePeerConnectionParameters 1 2
echo "Commit the chaincode definition to the channel"
docker exec \
-e CORE_PEER_LOCALMSPID=Org1MSP \
-e CORE_PEER_MSPCONFIGPATH=${ORG1_MSPCONFIGPATH} \
cli \
peer lifecycle chaincode commit \
-o orderer.example.com:7050 \
peer lifecycle chaincode commit \
-o localhost:7050 \
--ordererTLSHostnameOverride orderer.example.com \
--channelID mychannel \
--name marbles \
--version 1.0 \
@ -146,35 +129,41 @@ docker exec \
--signature-policy AND"('Org1MSP.member','Org2MSP.member')" \
--sequence 1 \
--tls \
--cafile ${ORDERER_TLS_ROOTCERT_FILE} \
--peerAddresses peer0.org1.example.com:7051 \
--tlsRootCertFiles ${ORG1_TLS_ROOTCERT_FILE} \
--peerAddresses peer0.org2.example.com:9051 \
--tlsRootCertFiles ${ORG2_TLS_ROOTCERT_FILE}
--cafile ${ORDERER_CA} \
$PEER_CONN_PARMS
echo "Waiting for the chaincode to be committed ..."
echo "Check if the chaincode has been committed to the channel ..."
sleep 10
peer lifecycle chaincode querycommitted \
--channelID mychannel \
--name marbles >&log.txt
EXPECTED_RESULT="Version: 1.0, Sequence: 1, Endorsement Plugin: escc, Validation Plugin: vscc"
VALUE=$(grep -o "Version: 1.0, Sequence: 1, Endorsement Plugin: escc, Validation Plugin: vscc" log.txt)
echo "$VALUE"
if [ "$VALUE" = "Version: 1.0, Sequence: 1, Endorsement Plugin: escc, Validation Plugin: vscc" ] ; then
echo "chaincode has been committed"
else
sleep 10
fi
echo "invoke the marbles chaincode init function ... "
docker exec \
-e CORE_PEER_LOCALMSPID=Org1MSP \
-e CORE_PEER_ADDRESS=peer0.org1.example.com:7051 \
cli \
peer chaincode invoke \
-o orderer.example.com:7050 \
-C mychannel \
-n marbles \
--isInit \
-c '{"Args":["Init"]}' \
--tls \
--cafile ${ORDERER_TLS_ROOTCERT_FILE} \
--peerAddresses peer0.org1.example.com:7051 \
--tlsRootCertFiles ${ORG1_TLS_ROOTCERT_FILE} \
--peerAddresses peer0.org2.example.com:9051 \
--tlsRootCertFiles ${ORG2_TLS_ROOTCERT_FILE}
sleep 10
peer chaincode invoke \
-o localhost:7050 \
--ordererTLSHostnameOverride orderer.example.com \
-C mychannel \
-n marbles \
--isInit \
-c '{"Args":["Init"]}' \
--tls \
--cafile ${ORDERER_CA} \
$PEER_CONN_PARMS
rm log.txt
popd
cat <<EOF

View file

@ -36,7 +36,7 @@ async function main() {
// Parse the connection profile. This would be the path to the file downloaded
// from the IBM Blockchain Platform operational console.
const ccpPath = path.resolve(__dirname, '..', 'first-network', 'connection-org1.json');
const ccpPath = path.resolve(__dirname, '..', 'test-network','organizations','peerOrganizations','org1.example.com', 'connection-org1.json');
const ccp = JSON.parse(fs.readFileSync(ccpPath, 'utf8'));
// Configure a wallet. This wallet must already be primed with an identity that
@ -47,7 +47,7 @@ async function main() {
// Create a new gateway, and connect to the gateway peer node(s). The identity
// specified must already exist in the specified wallet.
const gateway = new Gateway();
await gateway.connect(ccp, { wallet, identity: 'user1', discovery: { enabled: true, asLocalhost: true } });
await gateway.connect(ccp, { wallet, identity: 'appUser', discovery: { enabled: true, asLocalhost: true } });
// Get the network channel that the smart contract is deployed to.
const network = await gateway.getNetwork(channelid);