customize off chain data: use custom listener as docker container

This commit is contained in:
chhaileng 2020-09-03 11:17:32 +00:00
parent c02c49be55
commit dbabd42c9e
27 changed files with 5089 additions and 0 deletions

View file

@ -0,0 +1,4 @@
{
"nextMarbleNumber": 120,
"numberMarblesToAdd": 20
}

View file

@ -0,0 +1,87 @@
/*
* Copyright IBM Corp. All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
/*
*
* addMarbles.js will add random sample data to blockchain.
*
* $ node addMarbles.js
*
* addMarbles will add 10 marbles by default with a starting marble name of "marble100".
* Additional marbles will be added by incrementing the number at the end of the marble name.
*
* The properties for adding marbles are stored in addMarbles.json. This file will be created
* during the first execution of the utility if it does not exist. The utility can be run
* multiple times without changing the properties. The nextMarbleNumber will be incremented and
* stored in the JSON file.
*
* {
* "nextMarbleNumber": 100,
* "numberMarblesToAdd": 10
* }
*
*/
'use strict';
const { Wallets, Gateway } = require('fabric-network');
const fs = require('fs');
const path = require('path');
const addMarblesConfigFile = path.resolve(__dirname, 'addMarbles.json');
const colors=[ 'blue', 'red', 'yellow', 'green', 'white', 'purple' ];
const owners=[ 'tom', 'fred', 'julie', 'james', 'janet', 'henry', 'alice', 'marie', 'sam', 'debra', 'nancy'];
const sizes=[ 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 ];
const docType='marble'
const config = require('./config.json');
const channelid = config.channelid;
async function main() {
try {
// 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, '..', '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
// the application can use to interact with the peer node.
const walletPath = path.resolve(__dirname, 'wallet');
const wallet = await Wallets.newFileSystemWallet(walletPath);
// 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: 'appUser', discovery: { enabled: true, asLocalhost: true } });
// Get the network channel that the smart contract is deployed to.
const network = await gateway.getNetwork(channelid);
// Get the smart contract from the network channel.
const contract = network.getContract('marbles');
var randomColor = Math.floor(Math.random() * (6));
var randomOwner = Math.floor(Math.random() * (11));
var randomSize = Math.floor(Math.random() * (10));
// Submit the 'initMarble' transaction to the smart contract, and wait for it
// to be committed to the ledger.
var counter = Math.floor(Math.random() * (10000));
await contract.submitTransaction('initMarble', docType+counter, colors[randomColor], ''+sizes[randomSize], owners[randomOwner]);
console.log("Adding marble: " + docType + counter + " owner:" + owners[randomOwner] + " color:" + colors[randomColor] + " size:" + '' + sizes[randomSize] );
await gateway.disconnect();
} catch (error) {
console.error(`Failed to submit transaction: ${error}`);
process.exit(1);
}
}
main();

View file

@ -0,0 +1,55 @@
/*
* Copyright IBM Corp. All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
'use strict';
const FabricCAServices = require('fabric-ca-client');
const { Wallets, X509WalletMixin } = require('fabric-network');
const fs = require('fs');
const path = require('path');
async function main() {
try {
// load the network configuration
const ccpPath = path.resolve(__dirname, 'files', 'connection-org1.json');
let ccp = JSON.parse(fs.readFileSync(ccpPath, 'utf8'));
// Create a new CA client for interacting with the CA.
const caURL = ccp.certificateAuthorities['ca.org1.example.com'].url;
const ca = new FabricCAServices(caURL);
// Create a new file system based wallet for managing identities.
const walletPath = path.join(process.cwd(), 'wallet');
const wallet = await Wallets.newFileSystemWallet(walletPath);
console.log(`Wallet path: ${walletPath}`);
// Check to see if we've already enrolled the admin user.
const adminExists = await wallet.get('admin');
if (adminExists) {
console.log('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.
const enrollment = await ca.enroll({ enrollmentID: 'admin', enrollmentSecret: 'adminpw' });
const x509Identity = {
credentials: {
certificate: enrollment.certificate,
privateKey: enrollment.key.toBytes(),
},
mspId: 'Org1MSP',
type: 'X.509',
};
await wallet.put('admin', x509Identity);
console.log('Successfully enrolled admin user "admin" and imported it into the wallet');
} catch (error) {
console.error(`Failed to enroll admin user "admin": ${error}`);
process.exit(1);
}
}
main();

View file

@ -0,0 +1,11 @@
FROM node:8.17.0
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
CMD ["node", "blockEventListener.js"]

View file

@ -0,0 +1,87 @@
/*
* Copyright IBM Corp. All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
/*
*
* addMarbles.js will add random sample data to blockchain.
*
* $ node addMarbles.js
*
* addMarbles will add 10 marbles by default with a starting marble name of "marble100".
* Additional marbles will be added by incrementing the number at the end of the marble name.
*
* The properties for adding marbles are stored in addMarbles.json. This file will be created
* during the first execution of the utility if it does not exist. The utility can be run
* multiple times without changing the properties. The nextMarbleNumber will be incremented and
* stored in the JSON file.
*
* {
* "nextMarbleNumber": 100,
* "numberMarblesToAdd": 10
* }
*
*/
'use strict';
const { Wallets, Gateway } = require('fabric-network');
const fs = require('fs');
const path = require('path');
const addMarblesConfigFile = path.resolve(__dirname, 'addMarbles.json');
const colors=[ 'blue', 'red', 'yellow', 'green', 'white', 'purple' ];
const owners=[ 'tom', 'fred', 'julie', 'james', 'janet', 'henry', 'alice', 'marie', 'sam', 'debra', 'nancy'];
const sizes=[ 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 ];
const docType='marble'
const config = require('./config.json');
const channelid = config.channelid;
async function main() {
try {
// 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, '..', '..', '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
// the application can use to interact with the peer node.
const walletPath = path.resolve(__dirname, 'wallet');
const wallet = await Wallets.newFileSystemWallet(walletPath);
// 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: 'listenerUser', discovery: { enabled: true, asLocalhost: true } });
// Get the network channel that the smart contract is deployed to.
const network = await gateway.getNetwork(channelid);
// Get the smart contract from the network channel.
const contract = network.getContract('marbles');
var randomColor = Math.floor(Math.random() * (6));
var randomOwner = Math.floor(Math.random() * (11));
var randomSize = Math.floor(Math.random() * (10));
// Submit the 'initMarble' transaction to the smart contract, and wait for it
// to be committed to the ledger.
var counter = Math.floor(Math.random() * (10000));
await contract.submitTransaction('initMarble', docType+counter, colors[randomColor], ''+sizes[randomSize], owners[randomOwner]);
console.log("Adding marble: " + docType + counter + " owner:" + owners[randomOwner] + " color:" + colors[randomColor] + " size:" + '' + sizes[randomSize] );
await gateway.disconnect();
} catch (error) {
console.error(`Failed to submit transaction: ${error}`);
process.exit(1);
}
}
main();

View file

@ -0,0 +1,183 @@
/*
* Copyright IBM Corp. All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
/*
blockEventListener.js is an nodejs application to listen for block events from
a specified channel.
Configuration is stored in config.json:
{
"peer_name": "peer0.org1.example.com",
"channelid": "mychannel",
"use_couchdb":false,
"couchdb_address": "http://admin:adminpw@localhost:5990"
}
peer_name: target peer for the listener
channelid: channel name for block events
use_couchdb: if set to true, events will be stored in a local couchdb
couchdb_address: local address for an off chain couchdb database
Note: If use_couchdb is set to false, only a local log of events will be stored.
Usage:
node bockEventListener.js
The block event listener will log events received to the console and write event blocks to
a log file based on the channelid and chaincode name.
The event listener stores the next block to retrieve in a file named nextblock.txt. This file
is automatically created and initialized to zero if it does not exist.
*/
'use strict';
const { Wallets, Gateway } = require('fabric-network');
const fs = require('fs');
const path = require('path');
const couchdbutil = require('./couchdbutil.js');
const blockProcessing = require('./blockProcessing.js');
const config = require('./config.json');
const channelid = config.channelid;
const peer_name = config.peer_name;
const use_couchdb = config.use_couchdb;
const couchdb_address = config.couchdb_address;
const configPath = path.resolve(__dirname, 'nextblock.txt');
const nano = require('nano')(couchdb_address);
// simple map to hold blocks for processing
class BlockMap {
constructor() {
this.list = []
}
get(key) {
key = parseInt(key, 10).toString();
return this.list[`block${key}`];
}
set(key, value) {
this.list[`block${key}`] = value;
}
remove(key) {
key = parseInt(key, 10).toString();
delete this.list[`block${key}`];
}
}
let ProcessingMap = new BlockMap()
async function main() {
try {
// initialize the next block to be 0
let nextBlock = 0;
// check to see if there is a next block already defined
if (fs.existsSync(configPath)) {
// read file containing the next block to read
nextBlock = fs.readFileSync(configPath, 'utf8');
} else {
// store the next block as 0
fs.writeFileSync(configPath, parseInt(nextBlock, 10))
}
// Create a new file system based wallet for managing identities.
const walletPath = path.join(process.cwd(), 'wallet');
const wallet = await Wallets.newFileSystemWallet(walletPath);
console.log(`Wallet path: ${walletPath}`);
// Check to see if we've already enrolled the user.
const userExists = await wallet.get('listenerUser');
if (!userExists) {
console.log('An identity for the user "listenerUser" 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, 'files', '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: 'listenerUser', discovery: { enabled: true, asLocalhost: false } });
// Get the network (channel) our contract is deployed to.
const network = await gateway.getNetwork('mychannel');
const listener = await network.addBlockListener(
async (event) => {
// Add the block to the processing map by block number
const blockNum = event.blockNumber.low;
const block = event.blockData;
await ProcessingMap.set(block.header.number, block);
console.log(`Added block ${blockNum} to ProcessingMap`)
},
// set the starting block for the listener
{ filtered: false, startBlock: parseInt(nextBlock, 10) }
);
console.log(`Listening for block events, nextblock: ${nextBlock}`);
// start processing, looking for entries in the ProcessingMap
processPendingBlocks(ProcessingMap);
} catch (error) {
console.error(`Failed to evaluate transaction: ${error}`);
process.exit(1);
}
}
// listener function to check for blocks in the ProcessingMap
async function processPendingBlocks(ProcessingMap) {
setTimeout(async () => {
// get the next block number from nextblock.txt
let nextBlockNumber = fs.readFileSync(configPath, 'utf8');
let processBlock;
do {
// get the next block to process from the ProcessingMap
processBlock = ProcessingMap.get(nextBlockNumber)
if (processBlock == undefined) {
break;
}
console.log("call block processing event")
try {
await blockProcessing.processBlockEvent(channelid, processBlock, use_couchdb, nano)
} catch (error) {
console.error(`Failed to process block: ${error}`);
}
// if successful, remove the block from the ProcessingMap
ProcessingMap.remove(nextBlockNumber);
// increment the next block number to the next block
fs.writeFileSync(configPath, parseInt(nextBlockNumber, 10) + 1)
// retrive the next block number to process
nextBlockNumber = fs.readFileSync(configPath, 'utf8');
} while (true);
processPendingBlocks(ProcessingMap);
}, 250);
}
main();

View file

@ -0,0 +1,216 @@
/*
* Copyright IBM Corp. All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
'use strict';
const fs = require('fs');
const path = require('path');
const couchdbutil = require('./couchdbutil.js');
const configPath = path.resolve(__dirname, 'nextblock.txt');
exports.processBlockEvent = async function (channelname, block, use_couchdb, nano) {
return new Promise((async (resolve, reject) => {
// reject the block if the block number is not defined
if (block.header.number == undefined) {
reject(new Error('Undefined block number'));
}
const blockNumber = block.header.number
console.log(`------------------------------------------------`);
console.log(`Block Number: ${blockNumber}`);
// reject if the data is not set
if (block.data.data == undefined) {
reject(new Error('Data block is not defined'));
}
const dataArray = block.data.data;
// transaction filter for each transaction in dataArray
const txSuccess = block.metadata.metadata[2];
for (var dataItem in dataArray) {
// reject if a timestamp is not set
if (dataArray[dataItem].payload.header.channel_header.timestamp == undefined) {
reject(new Error('Transaction timestamp is not defined'));
}
// tx may be rejected at commit stage by peers
// only valid transactions (code=0) update the word state and off-chain db
// filter through valid tx, refer below for list of error codes
// https://github.com/hyperledger/fabric-sdk-node/blob/release-1.4/fabric-client/lib/protos/peer/transaction.proto
if (txSuccess[dataItem] !== 0) {
continue;
}
const timestamp = dataArray[dataItem].payload.header.channel_header.timestamp;
// continue to next tx if no actions are set
if (dataArray[dataItem].payload.data.actions == undefined) {
continue;
}
// actions are stored as an array. In Fabric 1.4.3 only one
// action exists per tx so we may simply use actions[0]
// in case Fabric adds support for multiple actions
// a for loop is used for demonstration
const actions = dataArray[dataItem].payload.data.actions;
// iterate through all actions
for (var actionItem in actions) {
// reject if a chaincode id is not defined
if (actions[actionItem].payload.chaincode_proposal_payload.input.chaincode_spec.chaincode_id.name == undefined) {
reject(new Error('Chaincode name is not defined'));
}
const chaincodeID = actions[actionItem].payload.chaincode_proposal_payload.input.chaincode_spec.chaincode_id.name
// reject if there is no readwrite set
if (actions[actionItem].payload.action.proposal_response_payload.extension.results.ns_rwset == undefined) {
reject(new Error('No readwrite set is defined'));
}
const rwSet = actions[actionItem].payload.action.proposal_response_payload.extension.results.ns_rwset
for (var record in rwSet) {
// ignore lscc events
if (rwSet[record].namespace != 'lscc') {
// create object to store properties
const writeObject = new Object();
writeObject.blocknumber = blockNumber;
writeObject.chaincodeid = chaincodeID;
writeObject.timestamp = timestamp;
writeObject.values = rwSet[record].rwset.writes;
console.log(`Transaction Timestamp: ${writeObject.timestamp}`);
console.log(`ChaincodeID: ${writeObject.chaincodeid}`);
console.log(writeObject.values);
const logfilePath = path.resolve(__dirname, 'nextblock.txt');
// send the object to a log file
fs.appendFileSync(channelname + '_' + chaincodeID + '.log', JSON.stringify(writeObject) + "\n");
// if couchdb is configured, then write to couchdb
if (use_couchdb) {
try {
await writeValuesToCouchDBP(nano, channelname, writeObject);
} catch (error) {
}
}
}
};
};
};
// update the nextblock.txt file to retrieve the next block
fs.writeFileSync(configPath, parseInt(blockNumber, 10) + 1)
resolve(true);
}));
}
async function writeValuesToCouchDBP(nano, channelname, writeObject) {
return new Promise((async (resolve, reject) => {
try {
// define the database for saving block events by key - this emulates world state
const dbname = channelname + '_' + writeObject.chaincodeid;
// define the database for saving all block events - this emulates history
const historydbname = channelname + '_' + writeObject.chaincodeid + '_history';
// set values to the array of values received
const values = writeObject.values;
try {
for (var sequence in values) {
let keyvalue =
values[
sequence
];
if (
keyvalue.is_delete ==
true
) {
await couchdbutil.deleteRecord(
nano,
dbname,
keyvalue.key
);
} else {
if (
isJSON(
keyvalue.value
)
) {
// insert or update value by key - this emulates world state behavior
await couchdbutil.writeToCouchDB(
nano,
dbname,
keyvalue.key,
JSON.parse(
keyvalue.value
)
);
}
}
// add additional fields for history
keyvalue.timestamp =
writeObject.timestamp;
keyvalue.blocknumber = parseInt(
writeObject.blocknumber,
10
);
keyvalue.sequence = parseInt(
sequence,
10
);
await couchdbutil.writeToCouchDB(
nano,
historydbname,
null,
keyvalue
);
}
} catch (error) {
console.log(error);
reject(error);
}
} catch (error) {
console.error(`Failed to write to couchdb: ${error}`);
reject(error);
}
resolve(true);
}));
}
function isJSON(value) {
try {
JSON.parse(value);
} catch (e) {
return false;
}
return true;
}

View file

@ -0,0 +1,7 @@
{
"peer_name": "peer0.org1.example.com",
"channelid": "mychannel",
"use_couchdb":true,
"create_history_log":true,
"couchdb_address": "http://admin:adminpw@offchaindb:5984"
}

View file

@ -0,0 +1,111 @@
/*
* Copyright IBM Corp. All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
'use strict';
exports.createDatabaseIfNotExists = function (nano, dbname) {
return new Promise((async (resolve, reject) => {
await nano.db.get(dbname, async function (err, body) {
if (err) {
if (err.statusCode == 404) {
await nano.db.create(dbname, function (err, body) {
if (!err) {
resolve(true);
} else {
reject(err);
}
});
} else {
reject(err);
}
} else {
resolve(true);
}
});
}));
}
exports.writeToCouchDB = async function (nano, dbname, key, value) {
return new Promise((async (resolve, reject) => {
try {
await this.createDatabaseIfNotExists(nano, dbname);
} catch (error) {
}
const db = nano.use(dbname);
// If a key is not specified, then this is an insert
if (key == null) {
db.insert(value, async function (err, body, header) {
if (err) {
reject(err);
}
}
);
} else {
// If a key is specified, then attempt to retrieve the record by key
db.get(key, async function (err, body) {
// parse the value
const updateValue = value;
// if the record was found, then update the revision to allow the update
if (err == null) {
updateValue._rev = body._rev
}
// update or insert the value
db.insert(updateValue, key, async function (err, body, header) {
if (err) {
reject(err);
}
});
});
}
resolve(true);
}));
}
exports.deleteRecord = async function (nano, dbname, key) {
return new Promise((async (resolve, reject) => {
try {
await this.createDatabaseIfNotExists(nano, dbname);
} catch (error) {
}
const db = nano.use(dbname);
// If a key is specified, then attempt to retrieve the record by key
db.get(key, async function (err, body) {
// if the record was found, then update the revision to allow the update
if (err == null) {
let revision = body._rev
// update or insert the value
db.destroy(key, revision, async function (err, body, header) {
if (err) {
reject(err);
}
});
}
});
resolve(true);
}));
}

View file

@ -0,0 +1,26 @@
version: '2'
networks:
net_test:
external: true
services:
offchaindb:
container_name: offchaindb
image: couchdb:3.1
environment:
- COUCHDB_USER=admin
- COUCHDB_PASSWORD=adminpw
ports:
- "5990:5984"
networks:
- net_test
offchainlistener:
container_name: block-listener
restart: always
build: .
networks:
- net_test
depends_on:
- offchaindb

View file

@ -0,0 +1,55 @@
/*
* Copyright IBM Corp. All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
'use strict';
const FabricCAServices = require('fabric-ca-client');
const { Wallets, X509WalletMixin } = require('fabric-network');
const fs = require('fs');
const path = require('path');
async function main() {
try {
// load the network configuration
const ccpPath = path.resolve(__dirname, 'files', 'connection-org1.json');
let ccp = JSON.parse(fs.readFileSync(ccpPath, 'utf8'));
// Create a new CA client for interacting with the CA.
const caURL = ccp.certificateAuthorities['ca.org1.example.com'].url;
const ca = new FabricCAServices(caURL);
// Create a new file system based wallet for managing identities.
const walletPath = path.join(process.cwd(), 'wallet');
const wallet = await Wallets.newFileSystemWallet(walletPath);
console.log(`Wallet path: ${walletPath}`);
// Check to see if we've already enrolled the admin user.
const adminExists = await wallet.get('admin');
if (adminExists) {
console.log('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.
const enrollment = await ca.enroll({ enrollmentID: 'admin', enrollmentSecret: 'adminpw' });
const x509Identity = {
credentials: {
certificate: enrollment.certificate,
privateKey: enrollment.key.toBytes(),
},
mspId: 'Org1MSP',
type: 'X.509',
};
await wallet.put('admin', x509Identity);
console.log('Successfully enrolled admin user "admin" and imported it into the wallet');
} catch (error) {
console.error(`Failed to enroll admin user "admin": ${error}`);
process.exit(1);
}
}
main();

View file

@ -0,0 +1,49 @@
{
"name": "test-network-org1",
"version": "1.0.0",
"client": {
"organization": "Org1",
"connection": {
"timeout": {
"peer": {
"endorser": "300"
}
}
}
},
"organizations": {
"Org1": {
"mspid": "Org1MSP",
"peers": [
"peer0.org1.example.com"
],
"certificateAuthorities": [
"ca.org1.example.com"
]
}
},
"peers": {
"peer0.org1.example.com": {
"url": "grpcs://localhost:7051",
"tlsCACerts": {
"pem": "-----BEGIN CERTIFICATE-----\nMIICJjCCAc2gAwIBAgIURi+1fFD+OW/8hkW3oGqvmyrKe5cwCgYIKoZIzj0EAwIw\ncDELMAkGA1UEBhMCVVMxFzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMQ8wDQYDVQQH\nEwZEdXJoYW0xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2Nh\nLm9yZzEuZXhhbXBsZS5jb20wHhcNMjAwOTAyMTIzOTAwWhcNMzUwODMwMTIzOTAw\nWjBwMQswCQYDVQQGEwJVUzEXMBUGA1UECBMOTm9ydGggQ2Fyb2xpbmExDzANBgNV\nBAcTBkR1cmhhbTEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEcMBoGA1UEAxMT\nY2Eub3JnMS5leGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABA8o\nTFVDKJAYRFhme5CIe4NoUC6dBA2n0wu00gdU4wxYN3t5jgvNfND9rbz69IxcTx25\nA56qWnG6M8TxP3oCKyOjRTBDMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAG\nAQH/AgEBMB0GA1UdDgQWBBTwjphcJEd3xvAI/OpZXDCd/aoMxDAKBggqhkjOPQQD\nAgNHADBEAiAu63pJTw5kr7ua/MDVIcZ+eoqVDbyRVku5yp8ETwyxiwIgGfiyOJEm\nMIeKkhyNrYSwqCLUR0wUp+H9dagC9X18MDI=\n-----END CERTIFICATE-----\n"
},
"grpcOptions": {
"ssl-target-name-override": "peer0.org1.example.com",
"hostnameOverride": "peer0.org1.example.com"
}
}
},
"certificateAuthorities": {
"ca.org1.example.com": {
"url": "https://localhost:7054",
"caName": "ca-org1",
"tlsCACerts": {
"pem": ["-----BEGIN CERTIFICATE-----\nMIICJjCCAc2gAwIBAgIURi+1fFD+OW/8hkW3oGqvmyrKe5cwCgYIKoZIzj0EAwIw\ncDELMAkGA1UEBhMCVVMxFzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMQ8wDQYDVQQH\nEwZEdXJoYW0xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2Nh\nLm9yZzEuZXhhbXBsZS5jb20wHhcNMjAwOTAyMTIzOTAwWhcNMzUwODMwMTIzOTAw\nWjBwMQswCQYDVQQGEwJVUzEXMBUGA1UECBMOTm9ydGggQ2Fyb2xpbmExDzANBgNV\nBAcTBkR1cmhhbTEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEcMBoGA1UEAxMT\nY2Eub3JnMS5leGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABA8o\nTFVDKJAYRFhme5CIe4NoUC6dBA2n0wu00gdU4wxYN3t5jgvNfND9rbz69IxcTx25\nA56qWnG6M8TxP3oCKyOjRTBDMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAG\nAQH/AgEBMB0GA1UdDgQWBBTwjphcJEd3xvAI/OpZXDCd/aoMxDAKBggqhkjOPQQD\nAgNHADBEAiAu63pJTw5kr7ua/MDVIcZ+eoqVDbyRVku5yp8ETwyxiwIgGfiyOJEm\nMIeKkhyNrYSwqCLUR0wUp+H9dagC9X18MDI=\n-----END CERTIFICATE-----\n"]
},
"httpOptions": {
"verify": false
}
}
}
}

View file

@ -0,0 +1,49 @@
{
"name": "test-network-org1",
"version": "1.0.0",
"client": {
"organization": "Org1",
"connection": {
"timeout": {
"peer": {
"endorser": "300"
}
}
}
},
"organizations": {
"Org1": {
"mspid": "Org1MSP",
"peers": [
"peer0.org1.example.com"
],
"certificateAuthorities": [
"ca.org1.example.com"
]
}
},
"peers": {
"peer0.org1.example.com": {
"url": "grpcs://peer0.org1.example.com:7051",
"tlsCACerts": {
"pem": "-----BEGIN CERTIFICATE-----\nMIICJjCCAc2gAwIBAgIURi+1fFD+OW/8hkW3oGqvmyrKe5cwCgYIKoZIzj0EAwIw\ncDELMAkGA1UEBhMCVVMxFzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMQ8wDQYDVQQH\nEwZEdXJoYW0xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2Nh\nLm9yZzEuZXhhbXBsZS5jb20wHhcNMjAwOTAyMTIzOTAwWhcNMzUwODMwMTIzOTAw\nWjBwMQswCQYDVQQGEwJVUzEXMBUGA1UECBMOTm9ydGggQ2Fyb2xpbmExDzANBgNV\nBAcTBkR1cmhhbTEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEcMBoGA1UEAxMT\nY2Eub3JnMS5leGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABA8o\nTFVDKJAYRFhme5CIe4NoUC6dBA2n0wu00gdU4wxYN3t5jgvNfND9rbz69IxcTx25\nA56qWnG6M8TxP3oCKyOjRTBDMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAG\nAQH/AgEBMB0GA1UdDgQWBBTwjphcJEd3xvAI/OpZXDCd/aoMxDAKBggqhkjOPQQD\nAgNHADBEAiAu63pJTw5kr7ua/MDVIcZ+eoqVDbyRVku5yp8ETwyxiwIgGfiyOJEm\nMIeKkhyNrYSwqCLUR0wUp+H9dagC9X18MDI=\n-----END CERTIFICATE-----\n"
},
"grpcOptions": {
"ssl-target-name-override": "peer0.org1.example.com",
"hostnameOverride": "peer0.org1.example.com"
}
}
},
"certificateAuthorities": {
"ca.org1.example.com": {
"url": "https://ca_org{ORG}:7054",
"caName": "ca-org1",
"tlsCACerts": {
"pem": ["-----BEGIN CERTIFICATE-----\nMIICJjCCAc2gAwIBAgIURi+1fFD+OW/8hkW3oGqvmyrKe5cwCgYIKoZIzj0EAwIw\ncDELMAkGA1UEBhMCVVMxFzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMQ8wDQYDVQQH\nEwZEdXJoYW0xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2Nh\nLm9yZzEuZXhhbXBsZS5jb20wHhcNMjAwOTAyMTIzOTAwWhcNMzUwODMwMTIzOTAw\nWjBwMQswCQYDVQQGEwJVUzEXMBUGA1UECBMOTm9ydGggQ2Fyb2xpbmExDzANBgNV\nBAcTBkR1cmhhbTEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEcMBoGA1UEAxMT\nY2Eub3JnMS5leGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABA8o\nTFVDKJAYRFhme5CIe4NoUC6dBA2n0wu00gdU4wxYN3t5jgvNfND9rbz69IxcTx25\nA56qWnG6M8TxP3oCKyOjRTBDMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAG\nAQH/AgEBMB0GA1UdDgQWBBTwjphcJEd3xvAI/OpZXDCd/aoMxDAKBggqhkjOPQQD\nAgNHADBEAiAu63pJTw5kr7ua/MDVIcZ+eoqVDbyRVku5yp8ETwyxiwIgGfiyOJEm\nMIeKkhyNrYSwqCLUR0wUp+H9dagC9X18MDI=\n-----END CERTIFICATE-----\n"]
},
"httpOptions": {
"verify": false
}
}
}
}

View file

@ -0,0 +1,49 @@
{
"name": "test-network-org2",
"version": "1.0.0",
"client": {
"organization": "Org2",
"connection": {
"timeout": {
"peer": {
"endorser": "300"
}
}
}
},
"organizations": {
"Org2": {
"mspid": "Org2MSP",
"peers": [
"peer0.org2.example.com"
],
"certificateAuthorities": [
"ca.org2.example.com"
]
}
},
"peers": {
"peer0.org2.example.com": {
"url": "grpcs://localhost:9051",
"tlsCACerts": {
"pem": "-----BEGIN CERTIFICATE-----\nMIICHzCCAcWgAwIBAgIUGt1JOlE1zJ31uO7t8ed5n4d7V0YwCgYIKoZIzj0EAwIw\nbDELMAkGA1UEBhMCVUsxEjAQBgNVBAgTCUhhbXBzaGlyZTEQMA4GA1UEBxMHSHVy\nc2xleTEZMBcGA1UEChMQb3JnMi5leGFtcGxlLmNvbTEcMBoGA1UEAxMTY2Eub3Jn\nMi5leGFtcGxlLmNvbTAeFw0yMDA5MDIxMjM5MDBaFw0zNTA4MzAxMjM5MDBaMGwx\nCzAJBgNVBAYTAlVLMRIwEAYDVQQIEwlIYW1wc2hpcmUxEDAOBgNVBAcTB0h1cnNs\nZXkxGTAXBgNVBAoTEG9yZzIuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2NhLm9yZzIu\nZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATrGlQj2uW/FXjr\nZcrSzHMY4yHNyeEmfMJfKWyzrOpHIbVcUDfvmOlyUwmWN9hNrELw8V8I+I1LKdtx\nE4mcha0To0UwQzAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAd\nBgNVHQ4EFgQUa06sGaGWJeWPZK42DmgCaXrkrCMwCgYIKoZIzj0EAwIDSAAwRQIh\nAMvQVC/bz0fchGBLzJaaUan3EnHyCsgJ+3jXefKwRT4aAiArRMyTkFJtcUP428YR\n/4qB0m37B+GiMHgrjZCGBNmVDA==\n-----END CERTIFICATE-----\n"
},
"grpcOptions": {
"ssl-target-name-override": "peer0.org2.example.com",
"hostnameOverride": "peer0.org2.example.com"
}
}
},
"certificateAuthorities": {
"ca.org2.example.com": {
"url": "https://localhost:8054",
"caName": "ca-org2",
"tlsCACerts": {
"pem": ["-----BEGIN CERTIFICATE-----\nMIICHzCCAcWgAwIBAgIUGt1JOlE1zJ31uO7t8ed5n4d7V0YwCgYIKoZIzj0EAwIw\nbDELMAkGA1UEBhMCVUsxEjAQBgNVBAgTCUhhbXBzaGlyZTEQMA4GA1UEBxMHSHVy\nc2xleTEZMBcGA1UEChMQb3JnMi5leGFtcGxlLmNvbTEcMBoGA1UEAxMTY2Eub3Jn\nMi5leGFtcGxlLmNvbTAeFw0yMDA5MDIxMjM5MDBaFw0zNTA4MzAxMjM5MDBaMGwx\nCzAJBgNVBAYTAlVLMRIwEAYDVQQIEwlIYW1wc2hpcmUxEDAOBgNVBAcTB0h1cnNs\nZXkxGTAXBgNVBAoTEG9yZzIuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2NhLm9yZzIu\nZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATrGlQj2uW/FXjr\nZcrSzHMY4yHNyeEmfMJfKWyzrOpHIbVcUDfvmOlyUwmWN9hNrELw8V8I+I1LKdtx\nE4mcha0To0UwQzAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAd\nBgNVHQ4EFgQUa06sGaGWJeWPZK42DmgCaXrkrCMwCgYIKoZIzj0EAwIDSAAwRQIh\nAMvQVC/bz0fchGBLzJaaUan3EnHyCsgJ+3jXefKwRT4aAiArRMyTkFJtcUP428YR\n/4qB0m37B+GiMHgrjZCGBNmVDA==\n-----END CERTIFICATE-----\n"]
},
"httpOptions": {
"verify": false
}
}
}
}

View file

@ -0,0 +1,49 @@
{
"name": "test-network-org2",
"version": "1.0.0",
"client": {
"organization": "Org2",
"connection": {
"timeout": {
"peer": {
"endorser": "300"
}
}
}
},
"organizations": {
"Org2": {
"mspid": "Org2MSP",
"peers": [
"peer0.org2.example.com"
],
"certificateAuthorities": [
"ca.org2.example.com"
]
}
},
"peers": {
"peer0.org2.example.com": {
"url": "grpcs://peer0.org2.example.com:9051",
"tlsCACerts": {
"pem": "-----BEGIN CERTIFICATE-----\nMIICHzCCAcWgAwIBAgIUGt1JOlE1zJ31uO7t8ed5n4d7V0YwCgYIKoZIzj0EAwIw\nbDELMAkGA1UEBhMCVUsxEjAQBgNVBAgTCUhhbXBzaGlyZTEQMA4GA1UEBxMHSHVy\nc2xleTEZMBcGA1UEChMQb3JnMi5leGFtcGxlLmNvbTEcMBoGA1UEAxMTY2Eub3Jn\nMi5leGFtcGxlLmNvbTAeFw0yMDA5MDIxMjM5MDBaFw0zNTA4MzAxMjM5MDBaMGwx\nCzAJBgNVBAYTAlVLMRIwEAYDVQQIEwlIYW1wc2hpcmUxEDAOBgNVBAcTB0h1cnNs\nZXkxGTAXBgNVBAoTEG9yZzIuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2NhLm9yZzIu\nZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATrGlQj2uW/FXjr\nZcrSzHMY4yHNyeEmfMJfKWyzrOpHIbVcUDfvmOlyUwmWN9hNrELw8V8I+I1LKdtx\nE4mcha0To0UwQzAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAd\nBgNVHQ4EFgQUa06sGaGWJeWPZK42DmgCaXrkrCMwCgYIKoZIzj0EAwIDSAAwRQIh\nAMvQVC/bz0fchGBLzJaaUan3EnHyCsgJ+3jXefKwRT4aAiArRMyTkFJtcUP428YR\n/4qB0m37B+GiMHgrjZCGBNmVDA==\n-----END CERTIFICATE-----\n"
},
"grpcOptions": {
"ssl-target-name-override": "peer0.org2.example.com",
"hostnameOverride": "peer0.org2.example.com"
}
}
},
"certificateAuthorities": {
"ca.org2.example.com": {
"url": "https://ca_org{ORG}:8054",
"caName": "ca-org2",
"tlsCACerts": {
"pem": ["-----BEGIN CERTIFICATE-----\nMIICHzCCAcWgAwIBAgIUGt1JOlE1zJ31uO7t8ed5n4d7V0YwCgYIKoZIzj0EAwIw\nbDELMAkGA1UEBhMCVUsxEjAQBgNVBAgTCUhhbXBzaGlyZTEQMA4GA1UEBxMHSHVy\nc2xleTEZMBcGA1UEChMQb3JnMi5leGFtcGxlLmNvbTEcMBoGA1UEAxMTY2Eub3Jn\nMi5leGFtcGxlLmNvbTAeFw0yMDA5MDIxMjM5MDBaFw0zNTA4MzAxMjM5MDBaMGwx\nCzAJBgNVBAYTAlVLMRIwEAYDVQQIEwlIYW1wc2hpcmUxEDAOBgNVBAcTB0h1cnNs\nZXkxGTAXBgNVBAoTEG9yZzIuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2NhLm9yZzIu\nZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATrGlQj2uW/FXjr\nZcrSzHMY4yHNyeEmfMJfKWyzrOpHIbVcUDfvmOlyUwmWN9hNrELw8V8I+I1LKdtx\nE4mcha0To0UwQzAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAd\nBgNVHQ4EFgQUa06sGaGWJeWPZK42DmgCaXrkrCMwCgYIKoZIzj0EAwIDSAAwRQIh\nAMvQVC/bz0fchGBLzJaaUan3EnHyCsgJ+3jXefKwRT4aAiArRMyTkFJtcUP428YR\n/4qB0m37B+GiMHgrjZCGBNmVDA==\n-----END CERTIFICATE-----\n"]
},
"httpOptions": {
"verify": false
}
}
}
}

3783
off_chain_data/listener/package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,45 @@
{
"name": "offchaindata",
"version": "1.0.0",
"description": "Offchain Data application implemented in JavaScript",
"engines": {
"node": ">=8",
"npm": ">=5"
},
"scripts": {
"lint": "eslint .",
"pretest": "npm run lint",
"test": "nyc mocha --recursive"
},
"engineStrict": true,
"author": "Hyperledger",
"license": "Apache-2.0",
"dependencies": {
"fabric-ca-client": "^2.1.0",
"fabric-network": "^2.1.0"
},
"devDependencies": {
"chai": "^4.2.0",
"eslint": "^5.9.0",
"mocha": "^5.2.0",
"nyc": "^13.1.0",
"sinon": "^7.1.1",
"sinon-chai": "^3.3.0"
},
"nyc": {
"exclude": [
"coverage/**",
"test/**"
],
"reporter": [
"text-summary",
"html"
],
"all": true,
"check-coverage": true,
"statements": 100,
"branches": 100,
"functions": 100,
"lines": 100
}
}

View file

@ -0,0 +1,75 @@
/*
* Copyright IBM Corp. All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
'use strict';
const { Wallets, Gateway, X509WalletMixin } = require('fabric-network');
const FabricCAServices = require('fabric-ca-client');
const fs = require('fs');
const path = require('path');
async function main() {
try {
// load the network configuration
const ccpPath = path.resolve(__dirname, 'files', 'connection-org1.json');
const ccp = JSON.parse(fs.readFileSync(ccpPath, 'utf8'));
// Create a new CA client for interacting with the CA.
const caURL = ccp.certificateAuthorities['ca.org1.example.com'].url;
const ca = new FabricCAServices(caURL);
// Create a new file system based wallet for managing identities.
const walletPath = path.join(process.cwd(), 'wallet');
const wallet = await Wallets.newFileSystemWallet(walletPath);
console.log(`Wallet path: ${walletPath}`);
// Check to see if we've already enrolled the user.
const userExists = await wallet.get('listenerUser');
if (userExists) {
console.log('An identity for the user "listenerUser" already exists in the wallet');
return;
}
// Check to see if we've already enrolled the admin user.
const adminIdentity = await wallet.get('admin');
if (!adminIdentity) {
console.log('An identity for the admin user "admin" does not exist in the wallet');
console.log('Run the enrollAdmin.js application before retrying');
return;
}
// build a user object for authenticating with the CA
const provider = wallet.getProviderRegistry().getProvider(adminIdentity.type);
const adminUser = await provider.getUserContext(adminIdentity, 'admin');
// Register the user, enroll the user, and import the new identity into the wallet.
const secret = await ca.register({
affiliation: 'org1.department1',
enrollmentID: 'listenerUser',
role: 'client'
}, adminUser);
const enrollment = await ca.enroll({
enrollmentID: 'listenerUser',
enrollmentSecret: secret
});
const x509Identity = {
credentials: {
certificate: enrollment.certificate,
privateKey: enrollment.key.toBytes(),
},
mspId: 'Org1MSP',
type: 'X.509',
};
await wallet.put('listenerUser', x509Identity);
console.log('Successfully registered and enrolled admin user "listenerUser" and imported it into the wallet');
} catch (error) {
console.error(`Failed to register user "listenerUser": ${error}`);
process.exit(1);
}
}
main();

View file

@ -0,0 +1 @@
{"credentials":{"certificate":"-----BEGIN CERTIFICATE-----\nMIIB8jCCAZmgAwIBAgIUZK86p6mQmWUJzhv4EoY5EeGObM4wCgYIKoZIzj0EAwIw\ncDELMAkGA1UEBhMCVVMxFzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMQ8wDQYDVQQH\nEwZEdXJoYW0xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2Nh\nLm9yZzEuZXhhbXBsZS5jb20wHhcNMjAwOTAyMTI0MDAwWhcNMjEwOTAyMTI0NTAw\nWjAhMQ8wDQYDVQQLEwZjbGllbnQxDjAMBgNVBAMTBWFkbWluMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAE8ANxIy5O+BU02DiF5KRMKdSmQHntJNLjKIuTMWAoZjNp\nB+ylEP4h8174OSL122lOz+j+U1NKWWSANn9MsYn2qqNgMF4wDgYDVR0PAQH/BAQD\nAgeAMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFKt5l3uuPT/Q5CnezAQKaMhCEvSy\nMB8GA1UdIwQYMBaAFPCOmFwkR3fG8Aj86llcMJ39qgzEMAoGCCqGSM49BAMCA0cA\nMEQCIEpd5ipyrnWYEknfg/ydYSGTwug/SS3smTDaK0R9rZI4AiAtBO9WnfsGgBGd\ntNpJg18QdM8TH6OJglypwI2Q0H/A+Q==\n-----END CERTIFICATE-----\n","privateKey":"-----BEGIN PRIVATE KEY-----\r\nMIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgHLXHn0jU6ZRzkdtb\r\nMaZ1VnlruDE0crtGAyaVQ6INEpOhRANCAATwA3EjLk74FTTYOIXkpEwp1KZAee0k\r\n0uMoi5MxYChmM2kH7KUQ/iHzXvg5IvXbaU7P6P5TU0pZZIA2f0yxifaq\r\n-----END PRIVATE KEY-----\r\n"},"mspId":"Org1MSP","type":"X.509","version":1}

View file

@ -0,0 +1 @@
{"credentials":{"certificate":"-----BEGIN CERTIFICATE-----\nMIICjDCCAjSgAwIBAgIUOAhHDicFm3H63ACoYBVis78SoREwCgYIKoZIzj0EAwIw\ncDELMAkGA1UEBhMCVVMxFzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMQ8wDQYDVQQH\nEwZEdXJoYW0xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2Nh\nLm9yZzEuZXhhbXBsZS5jb20wHhcNMjAwOTAyMTI0MDAwWhcNMjEwOTAyMTI0NTAw\nWjBJMTAwDQYDVQQLEwZjbGllbnQwCwYDVQQLEwRvcmcxMBIGA1UECxMLZGVwYXJ0\nbWVudDExFTATBgNVBAMTDGxpc3RlbmVyVXNlcjBZMBMGByqGSM49AgEGCCqGSM49\nAwEHA0IABMvQv3LC0SBoUd0Qzulpi5smB5sX5++vK98irqcRYmcr8l3smHCDmbS4\n0/VYvp6QnQSC18zyHOf5Wt0ZS6cPzrOjgdIwgc8wDgYDVR0PAQH/BAQDAgeAMAwG\nA1UdEwEB/wQCMAAwHQYDVR0OBBYEFDZjFQb5/b8qp8nj9z6fLZ2hqjcNMB8GA1Ud\nIwQYMBaAFPCOmFwkR3fG8Aj86llcMJ39qgzEMG8GCCoDBAUGBwgBBGN7ImF0dHJz\nIjp7ImhmLkFmZmlsaWF0aW9uIjoib3JnMS5kZXBhcnRtZW50MSIsImhmLkVucm9s\nbG1lbnRJRCI6Imxpc3RlbmVyVXNlciIsImhmLlR5cGUiOiJjbGllbnQifX0wCgYI\nKoZIzj0EAwIDRgAwQwIgVZo7YqK1DCyPPSu/nfz8VWqP+g9fYrkUPqvig/AfDb8C\nH3rP+wzF09o0ddH91+TUegflXFceRaPB8uXgz07sYLE=\n-----END CERTIFICATE-----\n","privateKey":"-----BEGIN PRIVATE KEY-----\r\nMIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgyn/2qcvazRXWCnLk\r\nNNx51uBeDAck6w2z0VgLAGBPOpahRANCAATL0L9ywtEgaFHdEM7paYubJgebF+fv\r\nryvfIq6nEWJnK/Jd7Jhwg5m0uNP1WL6ekJ0EgtfM8hzn+VrdGUunD86z\r\n-----END PRIVATE KEY-----\r\n"},"mspId":"Org1MSP","type":"X.509","version":1}

View file

@ -16,5 +16,12 @@ popd
rm -rf wallet rm -rf wallet
rm -rf addMarbles.json mychannel_marbles.log mychannel__lifecycle.log nextblock.txt rm -rf addMarbles.json mychannel_marbles.log mychannel__lifecycle.log nextblock.txt
pushd listener
docker-compose down
rm -rf wallet
rm -rf mychannel_marbles.log mychannel__lifecycle.log nextblock.txt
rm files/*
popd
docker stop offchaindb docker stop offchaindb
docker rm offchaindb docker rm offchaindb

View file

@ -25,6 +25,36 @@ pushd ../test-network
./network.sh down ./network.sh down
./network.sh up createChannel -ca -s couchdb ./network.sh up createChannel -ca -s couchdb
# COPY CPP to my working dir
cp organizations/peerOrganizations/org1.example.com/connection-org1.json ../off_chain_data/listener/files/
cp organizations/peerOrganizations/org2.example.com/connection-org2.json ../off_chain_data/listener/files/
cp organizations/peerOrganizations/org1.example.com/connection-org1-for-docker.json ../off_chain_data/listener/files/
cp organizations/peerOrganizations/org2.example.com/connection-org2-for-docker.json ../off_chain_data/listener/files/
#echo Starting offchain database
#docker run --publish 5990:5984 --detach -e COUCHDB_USER=admin -e COUCHDB_PASSWORD=adminpw --name offchaindb couchdb
popd
pushd listener
node enrollAdmin.js
node registerUser.js
mv files/connection-org1.json files/connection-org1-for-localhost.json
mv files/connection-org2.json files/connection-org2-for-localhost.json
mv files/connection-org1-for-docker.json files/connection-org1.json
mv files/connection-org2-for-docker.json files/connection-org2.json
docker-compose up -d --build
popd
pushd ../test-network
#echo Creating admin and user wallet
#popd
#node enrollAdmin.js
#node registerUser.js
#pushd ../test-network
export PATH=${PWD}/../bin:${PWD}:$PATH export PATH=${PWD}/../bin:${PWD}:$PATH
export FABRIC_CFG_PATH=${PWD}/../config export FABRIC_CFG_PATH=${PWD}/../config

View file

@ -0,0 +1 @@
{"credentials":{"certificate":"-----BEGIN CERTIFICATE-----\nMIIB8jCCAZmgAwIBAgIUD5BT6A6tbOI1DV6+o5n8e12I8Q0wCgYIKoZIzj0EAwIw\ncDELMAkGA1UEBhMCVVMxFzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMQ8wDQYDVQQH\nEwZEdXJoYW0xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2Nh\nLm9yZzEuZXhhbXBsZS5jb20wHhcNMjAwOTAyMTI0MzAwWhcNMjEwOTAyMTI0ODAw\nWjAhMQ8wDQYDVQQLEwZjbGllbnQxDjAMBgNVBAMTBWFkbWluMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAE3Q1CrssZsPsi2kBpAA1ET9zc3lLpPyyGSQkm81UfUSL9\n7HldsNSAGhR4RAsnGWPQTtlIOMCN2vMnIxGVLIXQlaNgMF4wDgYDVR0PAQH/BAQD\nAgeAMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFGKRYFnAJqVfRKGfpL8cL+pJt2bG\nMB8GA1UdIwQYMBaAFPCOmFwkR3fG8Aj86llcMJ39qgzEMAoGCCqGSM49BAMCA0cA\nMEQCIAJE27zMnqeInlRS6+RBQiDKxLu9vc3zkLhe8jaQSvCBAiAL3hNPpvLS99yG\nZUTFtmtBE2cqnPlrQzQyIjEWDyDwAQ==\n-----END CERTIFICATE-----\n","privateKey":"-----BEGIN PRIVATE KEY-----\r\nMIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgs2sdp3R/tqHt8KrG\r\nO5Bf6mVQBqw+SuBZ3x6oVIQLJ6ahRANCAATdDUKuyxmw+yLaQGkADURP3NzeUuk/\r\nLIZJCSbzVR9RIv3seV2w1IAaFHhECycZY9BO2Ug4wI3a8ycjEZUshdCV\r\n-----END PRIVATE KEY-----\r\n"},"mspId":"Org1MSP","type":"X.509","version":1}

View file

@ -0,0 +1 @@
{"credentials":{"certificate":"-----BEGIN CERTIFICATE-----\nMIIChDCCAiqgAwIBAgIUD75+CCeBRhGk9EcXWlBXWUw0du0wCgYIKoZIzj0EAwIw\ncDELMAkGA1UEBhMCVVMxFzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMQ8wDQYDVQQH\nEwZEdXJoYW0xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2Nh\nLm9yZzEuZXhhbXBsZS5jb20wHhcNMjAwOTAyMTI0MzAwWhcNMjEwOTAyMTI0ODAw\nWjBEMTAwDQYDVQQLEwZjbGllbnQwCwYDVQQLEwRvcmcxMBIGA1UECxMLZGVwYXJ0\nbWVudDExEDAOBgNVBAMTB2FwcFVzZXIwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC\nAATQC3qTQuhSTQPX9qypSot6gDzt8KdNstH8ZbH9TVQswdkgTMqMhO822X0iWTo2\nPsK7wCFWpDaTq0rm3KlYYvyho4HNMIHKMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMB\nAf8EAjAAMB0GA1UdDgQWBBRCSGtwMHSB9NN1Pv1mCNqTqnxCcjAfBgNVHSMEGDAW\ngBTwjphcJEd3xvAI/OpZXDCd/aoMxDBqBggqAwQFBgcIAQReeyJhdHRycyI6eyJo\nZi5BZmZpbGlhdGlvbiI6Im9yZzEuZGVwYXJ0bWVudDEiLCJoZi5FbnJvbGxtZW50\nSUQiOiJhcHBVc2VyIiwiaGYuVHlwZSI6ImNsaWVudCJ9fTAKBggqhkjOPQQDAgNI\nADBFAiEAr+l/dAPgMtXPz+5CMDWUDesa9spsksjwr0u8vRtWxv8CIC+QrZNHeJId\n9N1Ubdav4bMzgntBtLCamhMm5TnE4AaP\n-----END CERTIFICATE-----\n","privateKey":"-----BEGIN PRIVATE KEY-----\r\nMIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgaLfWkqiyUsKH0ZZm\r\nKIAQ+XgEoWIGs1ZDfiFDigtrbKKhRANCAATQC3qTQuhSTQPX9qypSot6gDzt8KdN\r\nstH8ZbH9TVQswdkgTMqMhO822X0iWTo2PsK7wCFWpDaTq0rm3KlYYvyh\r\n-----END PRIVATE KEY-----\r\n"},"mspId":"Org1MSP","type":"X.509","version":1}

View file

@ -15,6 +15,17 @@ function json_ccp {
organizations/ccp-template.json organizations/ccp-template.json
} }
function json_ccp_for_docker {
local PP=$(one_line_pem $4)
local CP=$(one_line_pem $5)
sed -e "s/\${ORG}/$1/" \
-e "s/\${P0PORT}/$2/" \
-e "s/\${CAPORT}/$3/" \
-e "s#\${PEERPEM}#$PP#" \
-e "s#\${CAPEM}#$CP#" \
organizations/ccp-template-for-docker.json
}
function yaml_ccp { function yaml_ccp {
local PP=$(one_line_pem $4) local PP=$(one_line_pem $4)
local CP=$(one_line_pem $5) local CP=$(one_line_pem $5)
@ -33,6 +44,7 @@ PEERPEM=organizations/peerOrganizations/org1.example.com/tlsca/tlsca.org1.exampl
CAPEM=organizations/peerOrganizations/org1.example.com/ca/ca.org1.example.com-cert.pem CAPEM=organizations/peerOrganizations/org1.example.com/ca/ca.org1.example.com-cert.pem
echo "$(json_ccp $ORG $P0PORT $CAPORT $PEERPEM $CAPEM)" > organizations/peerOrganizations/org1.example.com/connection-org1.json echo "$(json_ccp $ORG $P0PORT $CAPORT $PEERPEM $CAPEM)" > organizations/peerOrganizations/org1.example.com/connection-org1.json
echo "$(json_ccp_for_docker $ORG $P0PORT $CAPORT $PEERPEM $CAPEM)" > organizations/peerOrganizations/org1.example.com/connection-org1-for-docker.json
echo "$(yaml_ccp $ORG $P0PORT $CAPORT $PEERPEM $CAPEM)" > organizations/peerOrganizations/org1.example.com/connection-org1.yaml echo "$(yaml_ccp $ORG $P0PORT $CAPORT $PEERPEM $CAPEM)" > organizations/peerOrganizations/org1.example.com/connection-org1.yaml
ORG=2 ORG=2
@ -42,4 +54,5 @@ PEERPEM=organizations/peerOrganizations/org2.example.com/tlsca/tlsca.org2.exampl
CAPEM=organizations/peerOrganizations/org2.example.com/ca/ca.org2.example.com-cert.pem CAPEM=organizations/peerOrganizations/org2.example.com/ca/ca.org2.example.com-cert.pem
echo "$(json_ccp $ORG $P0PORT $CAPORT $PEERPEM $CAPEM)" > organizations/peerOrganizations/org2.example.com/connection-org2.json echo "$(json_ccp $ORG $P0PORT $CAPORT $PEERPEM $CAPEM)" > organizations/peerOrganizations/org2.example.com/connection-org2.json
echo "$(json_ccp_for_docker $ORG $P0PORT $CAPORT $PEERPEM $CAPEM)" > organizations/peerOrganizations/org2.example.com/connection-org2-for-docker.json
echo "$(yaml_ccp $ORG $P0PORT $CAPORT $PEERPEM $CAPEM)" > organizations/peerOrganizations/org2.example.com/connection-org2.yaml echo "$(yaml_ccp $ORG $P0PORT $CAPORT $PEERPEM $CAPEM)" > organizations/peerOrganizations/org2.example.com/connection-org2.yaml

View file

@ -0,0 +1,45 @@
#!/bin/bash
function one_line_pem {
echo "`awk 'NF {sub(/\\n/, ""); printf "%s\\\\\\\n",$0;}' $1`"
}
function json_ccp {
local PP=$(one_line_pem $4)
local CP=$(one_line_pem $5)
sed -e "s/\${ORG}/$1/" \
-e "s/\${P0PORT}/$2/" \
-e "s/\${CAPORT}/$3/" \
-e "s#\${PEERPEM}#$PP#" \
-e "s#\${CAPEM}#$CP#" \
organizations/ccp-template.json
}
function yaml_ccp {
local PP=$(one_line_pem $4)
local CP=$(one_line_pem $5)
sed -e "s/\${ORG}/$1/" \
-e "s/\${P0PORT}/$2/" \
-e "s/\${CAPORT}/$3/" \
-e "s#\${PEERPEM}#$PP#" \
-e "s#\${CAPEM}#$CP#" \
organizations/ccp-template.yaml | sed -e $'s/\\\\n/\\\n /g'
}
ORG=1
P0PORT=7051
CAPORT=7054
PEERPEM=organizations/peerOrganizations/org1.example.com/tlsca/tlsca.org1.example.com-cert.pem
CAPEM=organizations/peerOrganizations/org1.example.com/ca/ca.org1.example.com-cert.pem
echo "$(json_ccp $ORG $P0PORT $CAPORT $PEERPEM $CAPEM)" > organizations/peerOrganizations/org1.example.com/connection-org1.json
echo "$(yaml_ccp $ORG $P0PORT $CAPORT $PEERPEM $CAPEM)" > organizations/peerOrganizations/org1.example.com/connection-org1.yaml
ORG=2
P0PORT=9051
CAPORT=8054
PEERPEM=organizations/peerOrganizations/org2.example.com/tlsca/tlsca.org2.example.com-cert.pem
CAPEM=organizations/peerOrganizations/org2.example.com/ca/ca.org2.example.com-cert.pem
echo "$(json_ccp $ORG $P0PORT $CAPORT $PEERPEM $CAPEM)" > organizations/peerOrganizations/org2.example.com/connection-org2.json
echo "$(yaml_ccp $ORG $P0PORT $CAPORT $PEERPEM $CAPEM)" > organizations/peerOrganizations/org2.example.com/connection-org2.yaml

View file

@ -0,0 +1,49 @@
{
"name": "test-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"
],
"certificateAuthorities": [
"ca.org${ORG}.example.com"
]
}
},
"peers": {
"peer0.org${ORG}.example.com": {
"url": "grpcs://peer0.org${ORG}.example.com:${P0PORT}",
"tlsCACerts": {
"pem": "${PEERPEM}"
},
"grpcOptions": {
"ssl-target-name-override": "peer0.org${ORG}.example.com",
"hostnameOverride": "peer0.org${ORG}.example.com"
}
}
},
"certificateAuthorities": {
"ca.org${ORG}.example.com": {
"url": "https://ca_org{ORG}:${CAPORT}",
"caName": "ca-org${ORG}",
"tlsCACerts": {
"pem": ["${CAPEM}"]
},
"httpOptions": {
"verify": false
}
}
}
}