[FAB-5363] fabric-samples update balance

Update balance transfer sample to use the
connection profile and node 8.

Change-Id: I17c74c6cb23ebe55a8f2bba735d41525ae9e5ab1
Signed-off-by: Bret Harrison <beharrison@nc.rr.com>
Signed-off-by: ratnakar <asara.ratnakar@gmail.com>
This commit is contained in:
Bret Harrison 2017-10-19 20:17:31 -04:00
parent 6b2799e620
commit bb3ac84e6e
21 changed files with 3864 additions and 1047 deletions

View file

@ -7,7 +7,7 @@ A sample Node.js app to demonstrate **__fabric-client__** & **__fabric-ca-client
* [Docker](https://www.docker.com/products/overview) - v1.12 or higher
* [Docker Compose](https://docs.docker.com/compose/overview/) - v1.8 or higher
* [Git client](https://git-scm.com/downloads) - needed for clone commands
* **Node.js** v6.9.0 - 6.10.0 ( __Node v7+ is not supported__ )
* **Node.js** v8.4.0 or higher
* [Download Docker images](http://hyperledger-fabric.readthedocs.io/en/latest/samples.html#binaries)
```
@ -99,7 +99,7 @@ cd fabric-samples/balance-transfer
* Register and enroll new users in Organization - **Org1**:
`curl -s -X POST http://localhost:4000/users -H "content-type: application/x-www-form-urlencoded" -d 'username=Jim&orgName=org1'`
`curl -s -X POST http://localhost:4000/users -H "content-type: application/x-www-form-urlencoded" -d 'username=Jim&orgName=Org1'`
**OUTPUT:**
@ -137,7 +137,7 @@ curl -s -X POST \
-H "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTQ4NjU1OTEsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Im9yZzEiLCJpYXQiOjE0OTQ4NjE5OTF9.yWaJhFDuTvMQRaZIqg20Is5t-JJ_1BP58yrNLOKxtNI" \
-H "content-type: application/json" \
-d '{
"peers": ["peer1","peer2"]
"peers": ["peer0.org1.example.com","peer1.org1.example.com"]
}'
```
### Install chaincode
@ -148,7 +148,7 @@ curl -s -X POST \
-H "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTQ4NjU1OTEsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Im9yZzEiLCJpYXQiOjE0OTQ4NjE5OTF9.yWaJhFDuTvMQRaZIqg20Is5t-JJ_1BP58yrNLOKxtNI" \
-H "content-type: application/json" \
-d '{
"peers": ["peer1","peer2"],
"peers": ["peer0.org1.example.com","peer1.org1.example.com"],
"chaincodeName":"mycc",
"chaincodePath":"github.com/example_cc",
"chaincodeType": "golang",
@ -163,7 +163,7 @@ curl -s -X POST \
-H "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTQ4NjU1OTEsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Im9yZzEiLCJpYXQiOjE0OTQ4NjE5OTF9.yWaJhFDuTvMQRaZIqg20Is5t-JJ_1BP58yrNLOKxtNI" \
-H "content-type: application/json" \
-d "{
\"peers\": [\"peer1\",\"peer2\"],
\"peers\": [\"peer0.org1.example.com\",\"peer1.org1.example.com\"],
\"chaincodeName\":\"mycc\",
\"chaincodePath\":\"$PWD/artifacts/src/github.com/example_cc/node\",
\"chaincodeType\": \"node\",
@ -205,7 +205,7 @@ curl -s -X POST \
```
curl -s -X GET \
"http://localhost:4000/channels/mychannel/chaincodes/mycc?peer=peer1&fcn=query&args=%5B%22a%22%5D" \
"http://localhost:4000/channels/mychannel/chaincodes/mycc?peer=peer0.org1.example.com&fcn=query&args=%5B%22a%22%5D" \
-H "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTQ4NjU1OTEsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Im9yZzEiLCJpYXQiOjE0OTQ4NjE5OTF9.yWaJhFDuTvMQRaZIqg20Is5t-JJ_1BP58yrNLOKxtNI" \
-H "content-type: application/json"
```
@ -214,7 +214,7 @@ curl -s -X GET \
```
curl -s -X GET \
"http://localhost:4000/channels/mychannel/blocks/1?peer=peer1" \
"http://localhost:4000/channels/mychannel/blocks/1?peer=peer0.org1.example.com" \
-H "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTQ4NjU1OTEsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Im9yZzEiLCJpYXQiOjE0OTQ4NjE5OTF9.yWaJhFDuTvMQRaZIqg20Is5t-JJ_1BP58yrNLOKxtNI" \
-H "content-type: application/json"
```
@ -222,18 +222,18 @@ curl -s -X GET \
### Query Transaction by TransactionID
```
curl -s -X GET http://localhost:4000/channels/mychannel/transactions/TRX_ID?peer=peer1 \
curl -s -X GET http://localhost:4000/channels/mychannel/transactions/TRX_ID?peer=peer0.org1.example.com \
-H "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTQ4NjU1OTEsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Im9yZzEiLCJpYXQiOjE0OTQ4NjE5OTF9.yWaJhFDuTvMQRaZIqg20Is5t-JJ_1BP58yrNLOKxtNI" \
-H "content-type: application/json"
```
**NOTE**: Here the TRX_ID can be from any previous invoke transaction
**NOTE**: Here the TRX_ID can be from any previous invoke transaction, see results of the invoke request, will look something like `8a95b1794cb17e7772164c3f1292f8410fcfdc1943955a35c9764a21fcd1d1b3`.
### Query ChainInfo
```
curl -s -X GET \
"http://localhost:4000/channels/mychannel?peer=peer1" \
"http://localhost:4000/channels/mychannel?peer=peer0.org1.example.com" \
-H "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTQ4NjU1OTEsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Im9yZzEiLCJpYXQiOjE0OTQ4NjE5OTF9.yWaJhFDuTvMQRaZIqg20Is5t-JJ_1BP58yrNLOKxtNI" \
-H "content-type: application/json"
```
@ -242,7 +242,7 @@ curl -s -X GET \
```
curl -s -X GET \
"http://localhost:4000/chaincodes?peer=peer1&type=installed" \
"http://localhost:4000/chaincodes?peer=peer0.org1.example.com&type=installed" \
-H "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTQ4NjU1OTEsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Im9yZzEiLCJpYXQiOjE0OTQ4NjE5OTF9.yWaJhFDuTvMQRaZIqg20Is5t-JJ_1BP58yrNLOKxtNI" \
-H "content-type: application/json"
```
@ -251,7 +251,7 @@ curl -s -X GET \
```
curl -s -X GET \
"http://localhost:4000/chaincodes?peer=peer1&type=instantiated" \
"http://localhost:4000/chaincodes?peer=peer0.org1.example.com&type=instantiated" \
-H "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTQ4NjU1OTEsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Im9yZzEiLCJpYXQiOjE0OTQ4NjE5OTF9.yWaJhFDuTvMQRaZIqg20Is5t-JJ_1BP58yrNLOKxtNI" \
-H "content-type: application/json"
```
@ -260,50 +260,23 @@ curl -s -X GET \
```
curl -s -X GET \
"http://localhost:4000/channels?peer=peer1" \
"http://localhost:4000/channels?peer=peer0.org1.example.com" \
-H "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTQ4NjU1OTEsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Im9yZzEiLCJpYXQiOjE0OTQ4NjE5OTF9.yWaJhFDuTvMQRaZIqg20Is5t-JJ_1BP58yrNLOKxtNI" \
-H "content-type: application/json"
```
### Network configuration considerations
You have the ability to change configuration parameters by either directly editing the network-config.json file or provide an additional file for an alternative target network. The app uses an optional environment variable "TARGET_NETWORK" to control the configuration files to use. For example, if you deployed the target network on Amazon Web Services EC2, you can add a file "network-config-aws.json", and set the "TARGET_NETWORK" environment to 'aws'. The app will pick up the settings inside the "network-config-aws.json" file.
You have the ability to change configuration parameters by either directly editing the network-config.yaml file or provide an additional file for an alternative target network. The app uses an optional environment variable "TARGET_NETWORK" to control the configuration files to use. For example, if you deployed the target network on Amazon Web Services EC2, you can add a file "network-config-aws.yaml", and set the "TARGET_NETWORK" environment to 'aws'. The app will pick up the settings inside the "network-config-aws.yaml" file.
#### IP Address** and PORT information
If you choose to customize your docker-compose yaml file by hardcoding IP Addresses and PORT information for your peers and orderer, then you MUST also add the identical values into the network-config.json file. The paths shown below will need to be adjusted to match your docker-compose yaml file.
If you choose to customize your docker-compose yaml file by hardcoding IP Addresses and PORT information for your peers and orderer, then you MUST also add the identical values into the network-config.yaml file. The url and eventUrl settings will need to be adjusted to match your docker-compose yaml file.
```
"orderer": {
"url": "grpcs://x.x.x.x:7050",
"server-hostname": "orderer0",
"tls_cacerts": "../artifacts/tls/orderer/ca-cert.pem"
},
"org1": {
"ca": "http://x.x.x.x:7054",
"peer1": {
"requests": "grpcs://x.x.x.x:7051",
"events": "grpcs://x.x.x.x:7053",
...
},
"peer2": {
"requests": "grpcs://x.x.x.x:7056",
"events": "grpcs://x.x.x.x:7058",
...
}
},
"org2": {
"ca": "http://x.x.x.x:8054",
"peer1": {
"requests": "grpcs://x.x.x.x:8051",
"events": "grpcs://x.x.x.x:8053",
... },
"peer2": {
"requests": "grpcs://x.x.x.x:8056",
"events": "grpcs://x.x.x.x:8058",
...
}
}
peer1.org1.example.com:
url: grpcs://x.x.x.x:7056
eventUrl: grpcs://x.x.x.x:7058
```

View file

@ -32,7 +32,7 @@ require('./config.js');
var hfc = require('fabric-client');
var helper = require('./app/helper.js');
var channels = require('./app/create-channel.js');
var createChannel = require('./app/create-channel.js');
var join = require('./app/join-channel.js');
var install = require('./app/install-chaincode.js');
var instantiate = require('./app/instantiate-chaincode.js');
@ -60,6 +60,7 @@ app.use(expressJWT({
}));
app.use(bearerToken());
app.use(function(req, res, next) {
logger.debug(' ------>>>>>> new request for %s',req.originalUrl);
if (req.originalUrl.indexOf('/users') >= 0) {
return next();
}
@ -90,8 +91,7 @@ app.use(function(req, res, next) {
///////////////////////////////////////////////////////////////////////////////
var server = http.createServer(app).listen(port, function() {});
logger.info('****************** SERVER STARTED ************************');
logger.info('************** http://' + host + ':' + port +
' ******************');
logger.info('*************** http://%s:%s ******************',host,port);
server.timeout = 240000;
function getErrorMessage(field) {
@ -106,7 +106,7 @@ function getErrorMessage(field) {
///////////////////////// REST ENDPOINTS START HERE ///////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Register and enroll user
app.post('/users', function(req, res) {
app.post('/users', async function(req, res) {
var username = req.body.username;
var orgName = req.body.orgName;
logger.debug('End point : /users');
@ -125,20 +125,18 @@ app.post('/users', function(req, res) {
username: username,
orgName: orgName
}, app.get('secret'));
helper.getRegisteredUsers(username, orgName, true).then(function(response) {
if (response && typeof response !== 'string') {
response.token = token;
res.json(response);
} else {
res.json({
success: false,
message: response
});
}
});
let response = await helper.getRegisteredUser(username, orgName, true);
logger.debug('Successfully returned from registering the username %s for organization %s',username,orgName);
if (response && typeof response !== 'string') {
response.token = token;
res.json(response);
} else {
res.json({success: false, message: response});
}
});
// Create Channel
app.post('/channels', function(req, res) {
app.post('/channels', async function(req, res) {
logger.info('<<<<<<<<<<<<<<<<< C R E A T E C H A N N E L >>>>>>>>>>>>>>>>>');
logger.debug('End point : /channels');
var channelName = req.body.channelName;
@ -154,18 +152,19 @@ app.post('/channels', function(req, res) {
return;
}
channels.createChannel(channelName, channelConfigPath, req.username, req.orgname)
.then(function(message) {
res.send(message);
});
let message = await createChannel.createChannel(channelName, channelConfigPath, req.username, req.orgname);
res.send(message);
});
// Join Channel
app.post('/channels/:channelName/peers', function(req, res) {
app.post('/channels/:channelName/peers', async function(req, res) {
logger.info('<<<<<<<<<<<<<<<<< J O I N C H A N N E L >>>>>>>>>>>>>>>>>');
var channelName = req.params.channelName;
var peers = req.body.peers;
logger.debug('channelName : ' + channelName);
logger.debug('peers : ' + peers);
logger.debug('username :' + req.username);
logger.debug('orgname:' + req.orgname);
if (!channelName) {
res.json(getErrorMessage('\'channelName\''));
return;
@ -175,13 +174,11 @@ app.post('/channels/:channelName/peers', function(req, res) {
return;
}
join.joinChannel(channelName, peers, req.username, req.orgname)
.then(function(message) {
res.send(message);
});
let message = await join.joinChannel(channelName, peers, req.username, req.orgname);
res.send(message);
});
// Install chaincode on target peers
app.post('/chaincodes', function(req, res) {
app.post('/chaincodes', async function(req, res) {
logger.debug('==================== INSTALL CHAINCODE ==================');
var peers = req.body.peers;
var chaincodeName = req.body.chaincodeName;
@ -213,13 +210,10 @@ app.post('/chaincodes', function(req, res) {
res.json(getErrorMessage('\'chaincodeType\''));
return;
}
install.installChaincode(peers, chaincodeName, chaincodePath, chaincodeVersion, chaincodeType, req.username, req.orgname)
.then(function(message) {
res.send(message);
});
});
let message = await install.installChaincode(peers, chaincodeName, chaincodePath, chaincodeVersion, chaincodeType, req.username, req.orgname)
res.send(message);});
// Instantiate chaincode on target peers
app.post('/channels/:channelName/chaincodes', function(req, res) {
app.post('/channels/:channelName/chaincodes', async function(req, res) {
logger.debug('==================== INSTANTIATE CHAINCODE ==================');
var chaincodeName = req.body.chaincodeName;
var chaincodeVersion = req.body.chaincodeVersion;
@ -253,13 +247,12 @@ app.post('/channels/:channelName/chaincodes', function(req, res) {
res.json(getErrorMessage('\'args\''));
return;
}
instantiate.instantiateChaincode(channelName, chaincodeName, chaincodeVersion, chaincodeType, fcn, args, req.username, req.orgname)
.then(function(message) {
res.send(message);
});
let message = await instantiate.instantiateChaincode(channelName, chaincodeName, chaincodeVersion, chaincodeType, fcn, args, req.username, req.orgname);
res.send(message);
});
// Invoke transaction on chaincode on target peers
app.post('/channels/:channelName/chaincodes/:chaincodeName', function(req, res) {
app.post('/channels/:channelName/chaincodes/:chaincodeName', async function(req, res) {
logger.debug('==================== INVOKE ON CHAINCODE ==================');
var peers = req.body.peers;
var chaincodeName = req.params.chaincodeName;
@ -287,13 +280,11 @@ app.post('/channels/:channelName/chaincodes/:chaincodeName', function(req, res)
return;
}
invoke.invokeChaincode(peers, channelName, chaincodeName, fcn, args, req.username, req.orgname)
.then(function(message) {
res.send(message);
});
let message = await invoke.invokeChaincode(peers, channelName, chaincodeName, fcn, args, req.username, req.orgname);
res.send(message);
});
// Query on chaincode on target peers
app.get('/channels/:channelName/chaincodes/:chaincodeName', function(req, res) {
app.get('/channels/:channelName/chaincodes/:chaincodeName', async function(req, res) {
logger.debug('==================== QUERY BY CHAINCODE ==================');
var channelName = req.params.channelName;
var chaincodeName = req.params.chaincodeName;
@ -326,13 +317,11 @@ app.get('/channels/:channelName/chaincodes/:chaincodeName', function(req, res) {
args = JSON.parse(args);
logger.debug(args);
query.queryChaincode(peer, channelName, chaincodeName, args, fcn, req.username, req.orgname)
.then(function(message) {
res.send(message);
});
let message = await query.queryChaincode(peer, channelName, chaincodeName, args, fcn, req.username, req.orgname);
res.send(message);
});
// Query Get Block by BlockNumber
app.get('/channels/:channelName/blocks/:blockId', function(req, res) {
app.get('/channels/:channelName/blocks/:blockId', async function(req, res) {
logger.debug('==================== GET BLOCK BY NUMBER ==================');
let blockId = req.params.blockId;
let peer = req.query.peer;
@ -344,16 +333,12 @@ app.get('/channels/:channelName/blocks/:blockId', function(req, res) {
return;
}
query.getBlockByNumber(peer, blockId, req.username, req.orgname)
.then(function(message) {
res.send(message);
});
let message = await query.getBlockByNumber(peer, req.params.channelName, blockId, req.username, req.orgname);
res.send(message);
});
// Query Get Transaction by Transaction ID
app.get('/channels/:channelName/transactions/:trxnId', function(req, res) {
logger.debug(
'================ GET TRANSACTION BY TRANSACTION_ID ======================'
);
app.get('/channels/:channelName/transactions/:trxnId', async function(req, res) {
logger.debug('================ GET TRANSACTION BY TRANSACTION_ID ======================');
logger.debug('channelName : ' + req.params.channelName);
let trxnId = req.params.trxnId;
let peer = req.query.peer;
@ -362,13 +347,11 @@ app.get('/channels/:channelName/transactions/:trxnId', function(req, res) {
return;
}
query.getTransactionByID(peer, trxnId, req.username, req.orgname)
.then(function(message) {
res.send(message);
});
let message = await query.getTransactionByID(peer, req.params.channelName, trxnId, req.username, req.orgname);
res.send(message);
});
// Query Get Block by Hash
app.get('/channels/:channelName/blocks', function(req, res) {
app.get('/channels/:channelName/blocks', async function(req, res) {
logger.debug('================ GET BLOCK BY HASH ======================');
logger.debug('channelName : ' + req.params.channelName);
let hash = req.query.hash;
@ -378,43 +361,38 @@ app.get('/channels/:channelName/blocks', function(req, res) {
return;
}
query.getBlockByHash(peer, hash, req.username, req.orgname).then(
function(message) {
res.send(message);
});
let message = await query.getBlockByHash(peer, req.params.channelName, hash, req.username, req.orgname);
res.send(message);
});
//Query for Channel Information
app.get('/channels/:channelName', function(req, res) {
logger.debug(
'================ GET CHANNEL INFORMATION ======================');
app.get('/channels/:channelName', async function(req, res) {
logger.debug('================ GET CHANNEL INFORMATION ======================');
logger.debug('channelName : ' + req.params.channelName);
let peer = req.query.peer;
query.getChainInfo(peer, req.username, req.orgname).then(
function(message) {
res.send(message);
});
let message = await query.getChainInfo(peer, req.params.channelName, req.username, req.orgname);
res.send(message);
});
//Query for Channel instantiated chaincodes
app.get('/channels/:channelName/chaincodes', async function(req, res) {
logger.debug('================ GET INSTANTIATED CHAINCODES ======================');
logger.debug('channelName : ' + req.params.channelName);
let peer = req.query.peer;
let message = await query.getInstalledChaincodes(peer, req.params.channelName, 'instantiated', req.username, req.orgname);
res.send(message);
});
// Query to fetch all Installed/instantiated chaincodes
app.get('/chaincodes', function(req, res) {
app.get('/chaincodes', async function(req, res) {
var peer = req.query.peer;
var installType = req.query.type;
//TODO: add Constnats
if (installType === 'installed') {
logger.debug(
'================ GET INSTALLED CHAINCODES ======================');
} else {
logger.debug(
'================ GET INSTANTIATED CHAINCODES ======================');
}
logger.debug('================ GET INSTALLED CHAINCODES ======================');
query.getInstalledChaincodes(peer, installType, req.username, req.orgname)
.then(function(message) {
res.send(message);
});
let message = await query.getInstalledChaincodes(peer, null, 'installed', req.username, req.orgname)
res.send(message);
});
// Query to fetch channels
app.get('/channels', function(req, res) {
app.get('/channels', async function(req, res) {
logger.debug('================ GET CHANNELS ======================');
logger.debug('peer: ' + req.query.peer);
var peer = req.query.peer;
@ -423,9 +401,6 @@ app.get('/channels', function(req, res) {
return;
}
query.getChannels(peer, req.username, req.orgname)
.then(function(
message) {
res.send(message);
});
let message = await query.getChannels(peer, req.username, req.orgname);
res.send(message);
});

View file

@ -16,41 +16,37 @@
var util = require('util');
var fs = require('fs');
var path = require('path');
var config = require('../config.json');
var helper = require('./helper.js');
var logger = helper.getLogger('Create-Channel');
//Attempt to send a request to the orderer with the sendCreateChain method
var createChannel = function(channelName, channelConfigPath, username, orgName) {
//Attempt to send a request to the orderer with the sendTransaction method
var createChannel = async function(channelName, channelConfigPath, username, orgName) {
logger.debug('\n====== Creating Channel \'' + channelName + '\' ======\n');
var client = helper.getClientForOrg(orgName);
var channel = helper.getChannelForOrg(orgName);
try {
// first setup the client for this org
var client = await helper.getClientForOrg(orgName);
logger.debug('Successfully got the fabric client for the organization "%s"', orgName);
// read in the envelope for the channel config raw bytes
var envelope = fs.readFileSync(path.join(__dirname, channelConfigPath));
// extract the channel config bytes from the envelope to be signed
var channelConfig = client.extractChannelConfig(envelope);
// read in the envelope for the channel config raw bytes
var envelope = fs.readFileSync(path.join(__dirname, channelConfigPath));
// extract the channel config bytes from the envelope to be signed
var channelConfig = client.extractChannelConfig(envelope);
//Acting as a client in the given organization provided with "orgName" param
return helper.getOrgAdmin(orgName).then((admin) => {
logger.debug(util.format('Successfully acquired admin user for the organization "%s"', orgName));
//Acting as a client in the given organization provided with "orgName" param
// sign the channel config bytes as "endorsement", this is required by
// the orderer's channel creation policy
// this will use the admin identity assigned to the client when the connection profile was loaded
let signature = client.signChannelConfig(channelConfig);
let request = {
config: channelConfig,
signatures: [signature],
name: channelName,
orderer: channel.getOrderers()[0],
txId: client.newTransactionID()
txId: client.newTransactionID(true) // get an admin based transactionID
};
// send to orderer
return client.createChannel(request);
}, (err) => {
logger.error('Failed to enroll user \''+username+'\'. Error: ' + err);
throw new Error('Failed to enroll user \''+username+'\'' + err);
}).then((response) => {
var response = await client.createChannel(request)
logger.debug(' response ::%j', response);
if (response && response.status === 'SUCCESS') {
logger.debug('Successfully created the channel.');
@ -58,17 +54,16 @@ var createChannel = function(channelName, channelConfigPath, username, orgName)
success: true,
message: 'Channel \'' + channelName + '\' created Successfully'
};
return response;
return response;
} else {
logger.error('\n!!!!!!!!! Failed to create the channel \'' + channelName +
'\' !!!!!!!!!\n\n');
throw new Error('Failed to create the channel \'' + channelName + '\'');
}
}, (err) => {
logger.error('Failed to initialize the channel: ' + err.stack ? err.stack :
err);
throw new Error('Failed to initialize the channel: ' + err.stack ? err.stack : err);
});
} catch (err) {
logger.error('Failed to initialize the channel: ' + err.stack ? err.stack : err);
throw new Error('Failed to initialize the channel: ' + err.toString());
}
};
exports.createChannel = createChannel;

View file

@ -33,270 +33,89 @@ var clients = {};
var channels = {};
var caClients = {};
// set up the client and channel objects for each org
for (let key in ORGS) {
if (key.indexOf('org') === 0) {
let client = new hfc();
let cryptoSuite = hfc.newCryptoSuite();
cryptoSuite.setCryptoKeyStore(hfc.newCryptoKeyStore({path: getKeyStoreForOrg(ORGS[key].name)}));
client.setCryptoSuite(cryptoSuite);
let channel = client.newChannel(hfc.getConfigSetting('channelName'));
channel.addOrderer(newOrderer(client));
clients[key] = client;
channels[key] = channel;
setupPeers(channel, key, client);
let caUrl = ORGS[key].ca;
caClients[key] = new copService(caUrl, null /*defautl TLS opts*/, '' /* default CA */, cryptoSuite);
}
var sleep = async function (sleep_time_ms) {
return new Promise(resolve => setTimeout(resolve, sleep_time_ms));
}
function setupPeers(channel, org, client) {
for (let key in ORGS[org].peers) {
let data = fs.readFileSync(path.join(__dirname, ORGS[org].peers[key]['tls_cacerts']));
let peer = client.newPeer(
ORGS[org].peers[key].requests,
{
pem: Buffer.from(data).toString(),
'ssl-target-name-override': ORGS[org].peers[key]['server-hostname']
}
);
peer.setName(key);
async function getClientForOrg (userorg, username) {
logger.debug('getClientForOrg - ****** START %s %s', userorg, username)
// get a fabric client loaded with a connection profile for this org
let config = '-connection-profile-path';
channel.addPeer(peer);
}
}
// build a client context and load it with a connection profile
// lets only load the network settings and save the client for later
let client = hfc.loadFromConfig(hfc.getConfigSetting('network'+config));
function newOrderer(client) {
var caRootsPath = ORGS.orderer.tls_cacerts;
let data = fs.readFileSync(path.join(__dirname, caRootsPath));
let caroots = Buffer.from(data).toString();
return client.newOrderer(ORGS.orderer.url, {
'pem': caroots,
'ssl-target-name-override': ORGS.orderer['server-hostname']
});
}
// This will load a connection profile over the top of the current one one
// since the first one did not have a client section and the following one does
// nothing will actually be replaced.
// This will also set an admin identity because the organization defined in the
// client section has one defined
client.loadFromConfig(hfc.getConfigSetting(userorg+config));
function readAllFiles(dir) {
var files = fs.readdirSync(dir);
var certs = [];
files.forEach((file_name) => {
let file_path = path.join(dir,file_name);
let data = fs.readFileSync(file_path);
certs.push(data);
});
return certs;
}
// this will create both the state store and the crypto store based
// on the settings in the client section of the connection profile
await client.initCredentialStores();
function getOrgName(org) {
return ORGS[org].name;
}
function getKeyStoreForOrg(org) {
return hfc.getConfigSetting('keyValueStore') + '_' + org;
}
function newRemotes(names, forPeers, userOrg) {
let client = getClientForOrg(userOrg);
let targets = [];
// find the peer that match the names
for (let idx in names) {
let peerName = names[idx];
if (ORGS[userOrg].peers[peerName]) {
// found a peer matching the name
let data = fs.readFileSync(path.join(__dirname, ORGS[userOrg].peers[peerName]['tls_cacerts']));
let grpcOpts = {
pem: Buffer.from(data).toString(),
'ssl-target-name-override': ORGS[userOrg].peers[peerName]['server-hostname']
};
if (forPeers) {
targets.push(client.newPeer(ORGS[userOrg].peers[peerName].requests, grpcOpts));
} else {
let eh = client.newEventHub();
eh.setPeerAddr(ORGS[userOrg].peers[peerName].events, grpcOpts);
targets.push(eh);
}
// The getUserContext call tries to get the user from persistence.
// If the user has been saved to persistence then that means the user has
// been registered and enrolled. If the user is found in persistence
// the call will then assign the user to the client object.
if(username) {
let user = await client.getUserContext(username, true);
if(!user) {
throw new Error(util.format('User was not found :', username));
} else {
logger.debug('User %s was found to be registered and enrolled', username);
}
}
logger.debug('getClientForOrg - ****** END %s %s \n\n', userorg, username)
if (targets.length === 0) {
logger.error(util.format('Failed to find peers matching the names %s', names));
}
return targets;
return client;
}
//-------------------------------------//
// APIs
//-------------------------------------//
var getChannelForOrg = function(org) {
return channels[org];
};
var getClientForOrg = function(org) {
return clients[org];
};
var newPeers = function(names, org) {
return newRemotes(names, true, org);
};
var newEventHubs = function(names, org) {
return newRemotes(names, false, org);
};
var getMspID = function(org) {
logger.debug('Msp ID : ' + ORGS[org].mspid);
return ORGS[org].mspid;
};
var getAdminUser = function(userOrg) {
var users = hfc.getConfigSetting('admins');
var username = users[0].username;
var password = users[0].secret;
var member;
var client = getClientForOrg(userOrg);
return hfc.newDefaultKeyValueStore({
path: getKeyStoreForOrg(getOrgName(userOrg))
}).then((store) => {
client.setStateStore(store);
// clearing the user context before switching
client._userContext = null;
return client.getUserContext(username, true).then((user) => {
if (user && user.isEnrolled()) {
logger.info('Successfully loaded member from persistence');
return user;
} else {
let caClient = caClients[userOrg];
// need to enroll it with CA server
return caClient.enroll({
enrollmentID: username,
enrollmentSecret: password
}).then((enrollment) => {
logger.info('Successfully enrolled user \'' + username + '\'');
member = new User(username);
member.setCryptoSuite(client.getCryptoSuite());
return member.setEnrollment(enrollment.key, enrollment.certificate, getMspID(userOrg));
}).then(() => {
return client.setUserContext(member);
}).then(() => {
return member;
}).catch((err) => {
logger.error('Failed to enroll and persist user. Error: ' + err.stack ?
err.stack : err);
return null;
});
}
});
});
};
var getRegisteredUsers = function(username, userOrg, isJson) {
var member;
var client = getClientForOrg(userOrg);
var enrollmentSecret = null;
return hfc.newDefaultKeyValueStore({
path: getKeyStoreForOrg(getOrgName(userOrg))
}).then((store) => {
client.setStateStore(store);
// clearing the user context before switching
client._userContext = null;
return client.getUserContext(username, true).then((user) => {
if (user && user.isEnrolled()) {
logger.info('Successfully loaded member from persistence');
return user;
} else {
let caClient = caClients[userOrg];
return getAdminUser(userOrg).then(function(adminUserObj) {
member = adminUserObj;
return caClient.register({
enrollmentID: username,
affiliation: userOrg + '.department1'
}, member);
}).then((secret) => {
enrollmentSecret = secret;
logger.debug(username + ' registered successfully');
return caClient.enroll({
enrollmentID: username,
enrollmentSecret: secret
});
}, (err) => {
logger.debug(username + ' failed to register');
return '' + err;
//return 'Failed to register '+username+'. Error: ' + err.stack ? err.stack : err;
}).then((message) => {
if (message && typeof message === 'string' && message.includes(
'Error:')) {
logger.error(username + ' enrollment failed');
return message;
}
logger.debug(username + ' enrolled successfully');
member = new User(username);
member._enrollmentSecret = enrollmentSecret;
return member.setEnrollment(message.key, message.certificate, getMspID(userOrg));
}).then(() => {
client.setUserContext(member);
return member;
}, (err) => {
logger.error(util.format('%s enroll failed: %s', username, err.stack ? err.stack : err));
return '' + err;
});;
}
});
}).then((user) => {
if (isJson && isJson === true) {
var response = {
success: true,
secret: user._enrollmentSecret,
message: username + ' enrolled Successfully',
};
return response;
var getRegisteredUser = async function(username, userOrg, isJson) {
try {
var client = await getClientForOrg(userOrg);
logger.debug('Successfully initialized the credential stores');
// client can now act as an agent for organization Org1
// first check to see if the user is already enrolled
var user = await client.getUserContext(username, true);
if (user && user.isEnrolled()) {
logger.info('Successfully loaded member from persistence');
} else {
// user was not enrolled, so we will need an admin user object to register
var admins = hfc.getConfigSetting('admins');
let adminUserObj = await client.setUserContext({username: admins[0].username, password: admins[0].secret});
let caClient = client.getCertificateAuthority();
let secret = await caClient.register({
enrollmentID: username,
affiliation: userOrg.toLowerCase() + '.department1'
}, adminUserObj);
logger.debug('Successfully got the secret for user %s',username);
user = await client.setUserContext({username:username, password:secret});
logger.debug('Successfully enrolled username %s and setUserContext on the client object', username);
}
return user;
}, (err) => {
logger.error(util.format('Failed to get registered user: %s, error: %s', username, err.stack ? err.stack : err));
return '' + err;
});
};
var getOrgAdmin = function(userOrg) {
var admin = ORGS[userOrg].admin;
var keyPath = path.join(__dirname, admin.key);
var keyPEM = Buffer.from(readAllFiles(keyPath)[0]).toString();
var certPath = path.join(__dirname, admin.cert);
var certPEM = readAllFiles(certPath)[0].toString();
var client = getClientForOrg(userOrg);
var cryptoSuite = hfc.newCryptoSuite();
if (userOrg) {
cryptoSuite.setCryptoKeyStore(hfc.newCryptoKeyStore({path: getKeyStoreForOrg(getOrgName(userOrg))}));
client.setCryptoSuite(cryptoSuite);
if(user && user.isEnrolled) {
if (isJson && isJson === true) {
var response = {
success: true,
secret: user._enrollmentSecret,
message: username + ' enrolled Successfully',
};
return response;
}
} else {
throw new Error('User was not enrolled ');
}
} catch(error) {
logger.error('Failed to get registered user: %s with error: %s', username, error.toString());
return 'failed '+error.toString();
}
return hfc.newDefaultKeyValueStore({
path: getKeyStoreForOrg(getOrgName(userOrg))
}).then((store) => {
client.setStateStore(store);
return client.createUser({
username: 'peer'+userOrg+'Admin',
mspid: getMspID(userOrg),
cryptoContent: {
privateKeyPEM: keyPEM,
signedCertPEM: certPEM
}
});
});
};
var setupChaincodeDeploy = function() {
process.env.GOPATH = path.join(__dirname, hfc.getConfigSetting('CC_SRC_PATH'));
};
@ -307,13 +126,7 @@ var getLogger = function(moduleName) {
return logger;
};
exports.getChannelForOrg = getChannelForOrg;
exports.getClientForOrg = getClientForOrg;
exports.getLogger = getLogger;
exports.setupChaincodeDeploy = setupChaincodeDeploy;
exports.getMspID = getMspID;
exports.ORGS = ORGS;
exports.newPeers = newPeers;
exports.newEventHubs = newEventHubs;
exports.getRegisteredUsers = getRegisteredUsers;
exports.getOrgAdmin = getOrgAdmin;
exports.getRegisteredUser = getRegisteredUser;

View file

@ -22,29 +22,36 @@ var helper = require('./helper.js');
var logger = helper.getLogger('install-chaincode');
var tx_id = null;
var installChaincode = function(peers, chaincodeName, chaincodePath,
chaincodeVersion, chaincodeType, username, org) {
logger.debug(
'\n============ Install chaincode on organizations ============\n');
var installChaincode = async function(peers, chaincodeName, chaincodePath,
chaincodeVersion, chaincodeType, username, org_name) {
logger.debug('\n\n============ Install chaincode on organizations ============\n');
helper.setupChaincodeDeploy();
var channel = helper.getChannelForOrg(org);
var client = helper.getClientForOrg(org);
let error_message = null;
try {
logger.info('Calling peers in organization "%s" to join the channel', org_name);
return helper.getOrgAdmin(org).then((user) => {
// first setup the client for this org
var client = await helper.getClientForOrg(org_name, username);
logger.debug('Successfully got the fabric client for the organization "%s"', org_name);
tx_id = client.newTransactionID(true); //get an admin transactionID
var request = {
targets: helper.newPeers(peers, org),
targets: peers,
chaincodePath: chaincodePath,
chaincodeId: chaincodeName,
chaincodeVersion: chaincodeVersion,
chaincodeType: chaincodeType
};
return client.installChaincode(request);
}, (err) => {
logger.error('Failed to enroll user \'' + username + '\'. ' + err);
throw new Error('Failed to enroll user \'' + username + '\'. ' + err);
}).then((results) => {
let results = await client.installChaincode(request);
// the returned object has both the endorsement results
// and the actual proposal, the proposal will be needed
// later when we send a transaction to the orederer
var proposalResponses = results[0];
var proposal = results[1];
// lets have a look at the responses to see if they are
// all good, if good they will also include signatures
// required to be committed
var all_good = true;
for (var i in proposalResponses) {
let one_good = false;
@ -53,28 +60,34 @@ var installChaincode = function(peers, chaincodeName, chaincodePath,
one_good = true;
logger.info('install proposal was good');
} else {
logger.error('install proposal was bad');
logger.error('install proposal was bad %j',proposalResponses.toJSON());
}
all_good = all_good & one_good;
}
if (all_good) {
logger.info(util.format(
'Successfully sent install Proposal and received ProposalResponse: Status - %s',
proposalResponses[0].response.status));
logger.debug('\nSuccessfully Installed chaincode on organization ' + org +
'\n');
return 'Successfully Installed chaincode on organization ' + org;
logger.info('Successfully sent install Proposal and received ProposalResponse');
} else {
logger.error(
'Failed to send install Proposal or receive valid response. Response null or status is not 200. exiting...'
);
return 'Failed to send install Proposal or receive valid response. Response null or status is not 200. exiting...';
error_message = 'Failed to send install Proposal or receive valid response. Response null or status is not 200'
logger.error(error_message);
}
}, (err) => {
logger.error('Failed to send install proposal due to error: ' + err.stack ?
err.stack : err);
throw new Error('Failed to send install proposal due to error: ' + err.stack ?
err.stack : err);
});
} catch(error) {
logger.error('Failed to install due to error: ' + error.stack ? error.stack : error);
error_message = error.toString();
}
if (!error_message) {
let message = util.format('Successfully install chaincode');
logger.info(message);
// build a response to send back to the REST caller
let response = {
success: true,
message: message
};
return response;
} else {
let message = util.format('Failed to install due to:%s',error_message);
logger.error(message);
throw new Error(message);
}
};
exports.installChaincode = installChaincode;

View file

@ -18,32 +18,31 @@ var path = require('path');
var fs = require('fs');
var util = require('util');
var hfc = require('fabric-client');
var Peer = require('fabric-client/lib/Peer.js');
var EventHub = require('fabric-client/lib/EventHub.js');
var helper = require('./helper.js');
var logger = helper.getLogger('instantiate-chaincode');
var ORGS = hfc.getConfigSetting('network-config');
var tx_id = null;
var eh = null;
var instantiateChaincode = function(channelName, chaincodeName, chaincodeVersion, functionName, chaincodeType,
args, username, org) {
logger.debug('\n============ Instantiate chaincode on organization ' + org +
var instantiateChaincode = async function(channelName, chaincodeName, chaincodeVersion, functionName, chaincodeType, args, username, org_name) {
logger.debug('\n\n============ Instantiate chaincode on channel ' + channelName +
' ============\n');
var error_message = null;
var eventhubs_in_use = [];
try {
// first setup the client for this org
var client = await helper.getClientForOrg(org_name, username);
logger.debug('Successfully got the fabric client for the organization "%s"', org_name);
var channel = client.getChannel(channelName);
if(!channel) {
let message = util.format('Channel %s was not defined in the connection profile', channelName);
logger.error(message);
throw new Error(message);
}
var tx_id = client.newTransactionID(true); // Get an admin based transactionID
// An admin based transactionID will
// indicate that admin identity should
// be used to sign the proposal request.
// will need the transaction ID string for the event registration later
var deployId = tx_id.getTransactionID();
var channel = helper.getChannelForOrg(org);
var client = helper.getClientForOrg(org);
return helper.getOrgAdmin(org).then((user) => {
// read the config block from the orderer for the channel
// and initialize the verify MSPs based on the participating
// organizations
return channel.initialize();
}, (err) => {
logger.error('Failed to enroll user \'' + username + '\'. ' + err);
throw new Error('Failed to enroll user \'' + username + '\'. ' + err);
}).then((success) => {
tx_id = client.newTransactionID();
// send proposal to endorser
var request = {
chaincodeId: chaincodeName,
@ -56,13 +55,17 @@ var instantiateChaincode = function(channelName, chaincodeName, chaincodeVersion
if (functionName)
request.fcn = functionName;
return channel.sendInstantiateProposal(request);
}, (err) => {
logger.error('Failed to initialize the channel');
throw new Error('Failed to initialize the channel');
}).then((results) => {
let results = await channel.sendInstantiateProposal(request, 60000); //instantiate takes much longer
// the returned object has both the endorsement results
// and the actual proposal, the proposal will be needed
// later when we send a transaction to the orderer
var proposalResponses = results[0];
var proposal = results[1];
// lets have a look at the responses to see if they are
// all good, if good they will also include signatures
// required to be committed
var all_good = true;
for (var i in proposalResponses) {
let one_good = false;
@ -75,89 +78,118 @@ var instantiateChaincode = function(channelName, chaincodeName, chaincodeVersion
}
all_good = all_good & one_good;
}
if (all_good) {
logger.info(util.format(
'Successfully sent Proposal and received ProposalResponse: Status - %s, message - "%s", metadata - "%s", endorsement signature: %s',
proposalResponses[0].response.status, proposalResponses[0].response.message,
proposalResponses[0].response.payload, proposalResponses[0].endorsement
.signature));
var request = {
// tell each peer to join and wait for the event hub of each peer to tell us
// that the channel has been created on each peer
var promises = [];
let event_hubs = client.getEventHubsForOrg(org_name);
logger.debug('found %s eventhubs for this organization %s',event_hubs.length, org_name);
event_hubs.forEach((eh) => {
let instantiateEventPromise = new Promise((resolve, reject) => {
logger.debug('instantiateEventPromise - setting up event');
let event_timeout = setTimeout(() => {
let message = 'REQUEST_TIMEOUT:' + eh._ep._endpoint.addr;
logger.error(message);
eh.disconnect();
reject(new Error(message));
}, 60000);
eh.registerTxEvent(deployId, (tx, code) => {
logger.info('The chaincode instantiate transaction has been committed on peer %s',eh._ep._endpoint.addr);
clearTimeout(event_timeout);
eh.unregisterTxEvent(deployId);
if (code !== 'VALID') {
let message = until.format('The chaincode instantiate transaction was invalid, code:%s',code);
logger.error(message);
reject(new Error(message));
} else {
let message = 'The chaincode instantiate transaction was valid.';
logger.info(message);
resolve(message);
}
}, (err) => {
clearTimeout(event_timeout);
eh.unregisterTxEvent(deployId);
let message = 'Problem setting up the event hub :'+ err.toString();
logger.error(message);
reject(new Error(message));
});
});
promises.push(instantiateEventPromise);
eh.connect();
eventhubs_in_use.push(eh);
});
var orderer_request = {
txId: tx_id, //must includethe transaction id so that the outbound
// transaction to the orderer will be signed by the admin
// id as was the proposal above, notice that transactionID
// generated above was based on the admin id not userContext.
proposalResponses: proposalResponses,
proposal: proposal
};
// set the transaction listener and set a timeout of 30sec
// if the transaction did not get committed within the timeout period,
// fail the test
var deployId = tx_id.getTransactionID();
var sendPromise = channel.sendTransaction(orderer_request);
// put the send to the orderer last so that the events get registered and
// are ready for the orderering and committing
promises.push(sendPromise);
let results = await Promise.all(promises);
logger.debug(util.format('------->>> R E S P O N S E : %j', results));
let response = results.pop(); // orderer results are last in the results
if (response.status === 'SUCCESS') {
logger.info('Successfully sent transaction to the orderer.');
} else {
error_message = util.format('Failed to order the transaction. Error code: %s',response.status);
logger.debug(error_message);
}
eh = client.newEventHub();
let data = fs.readFileSync(path.join(__dirname, ORGS[org].peers['peer1'][
'tls_cacerts'
]));
eh.setPeerAddr(ORGS[org].peers['peer1']['events'], {
pem: Buffer.from(data).toString(),
'ssl-target-name-override': ORGS[org].peers['peer1']['server-hostname']
});
eh.connect();
let txPromise = new Promise((resolve, reject) => {
let handle = setTimeout(() => {
eh.disconnect();
reject();
}, 30000);
eh.registerTxEvent(deployId, (tx, code) => {
logger.info(
'The chaincode instantiate transaction has been committed on peer ' +
eh._ep._endpoint.addr);
clearTimeout(handle);
eh.unregisterTxEvent(deployId);
eh.disconnect();
if (code !== 'VALID') {
logger.error('The chaincode instantiate transaction was invalid, code = ' + code);
reject();
} else {
logger.info('The chaincode instantiate transaction was valid.');
resolve();
}
});
});
var sendPromise = channel.sendTransaction(request);
return Promise.all([sendPromise].concat([txPromise])).then((results) => {
logger.debug('Event promise all complete and testing complete');
return results[0]; // the first returned value is from the 'sendPromise' which is from the 'sendTransaction()' call
}).catch((err) => {
logger.error(
util.format('Failed to send instantiate transaction and get notifications within the timeout period. %s', err)
);
return 'Failed to send instantiate transaction and get notifications within the timeout period.';
});
// now see what each of the event hubs reported
for(let i in results) {
let event_hub_result = results[i];
let event_hub = event_hubs[i];
logger.debug('Event results for event hub :%s',event_hub._ep._endpoint.addr);
if(typeof event_hub_result === 'string') {
logger.debug(event_hub_result);
} else {
if(!error_message) error_message = event_hub_result.toString();
logger.debug(event_hub_result.toString());
}
}
} else {
logger.error(
'Failed to send instantiate Proposal or receive valid response. Response null or status is not 200. exiting...'
);
return 'Failed to send instantiate Proposal or receive valid response. Response null or status is not 200. exiting...';
error_message = util.format('Failed to send Proposal and receive all good ProposalResponse');
logger.debug(error_message);
}
}, (err) => {
logger.error('Failed to send instantiate proposal due to error: ' + err.stack ?
err.stack : err);
return 'Failed to send instantiate proposal due to error: ' + err.stack ?
err.stack : err;
}).then((response) => {
if (response.status === 'SUCCESS') {
logger.info('Successfully sent transaction to the orderer.');
return 'Chaincode Instantiation is SUCCESS';
} else {
logger.error('Failed to order the transaction. Error code: ' + response.status);
return 'Failed to order the transaction. Error code: ' + response.status;
}
}, (err) => {
logger.error('Failed to send instantiate due to error: ' + err.stack ? err
.stack : err);
return 'Failed to send instantiate due to error: ' + err.stack ? err.stack :
err;
} catch (error) {
logger.error('Failed to send instantiate due to error: ' + error.stack ? error.stack : error);
error_message = error.toString();
}
// need to shutdown open event streams
eventhubs_in_use.forEach((eh) => {
eh.disconnect();
});
if (!error_message) {
let message = util.format(
'Successfully instantiate chaingcode in organization %s to the channel \'%s\'',
org_name, channelName);
logger.info(message);
// build a response to send back to the REST caller
let response = {
success: true,
message: message
};
return response;
} else {
let message = util.format('Failed to instantiate. cause:%s',error_message);
logger.error(message);
throw new Error(message);
}
};
exports.instantiateChaincode = instantiateChaincode;

View file

@ -18,22 +18,28 @@ var path = require('path');
var fs = require('fs');
var util = require('util');
var hfc = require('fabric-client');
var Peer = require('fabric-client/lib/Peer.js');
var helper = require('./helper.js');
var logger = helper.getLogger('invoke-chaincode');
var EventHub = require('fabric-client/lib/EventHub.js');
var ORGS = hfc.getConfigSetting('network-config');
var invokeChaincode = function(peerNames, channelName, chaincodeName, fcn, args, username, org) {
logger.debug(util.format('\n============ invoke transaction on organization %s ============\n', org));
var client = helper.getClientForOrg(org);
var channel = helper.getChannelForOrg(org);
var targets = (peerNames) ? helper.newPeers(peerNames, org) : undefined;
var tx_id = null;
var invokeChaincode = async function(peerNames, channelName, chaincodeName, fcn, args, username, org_name) {
logger.debug(util.format('\n============ invoke transaction on channel %s ============\n', channelName));
var error_message = null;
var eventhubs_in_use = [];
var tx_id_string = null;
try {
// first setup the client for this org
var client = await helper.getClientForOrg(org_name, username);
logger.debug('Successfully got the fabric client for the organization "%s"', org_name);
var channel = client.getChannel(channelName);
if(!channel) {
let message = util.format('Channel %s was not defined in the connection profile', channelName);
logger.error(message);
throw new Error(message);
}
var tx_id = client.newTransactionID();
// will need the transaction ID string for the event registration later
tx_id_string = tx_id.getTransactionID();
return helper.getRegisteredUsers(username, org).then((user) => {
tx_id = client.newTransactionID();
logger.debug(util.format('Sending transaction "%j"', tx_id));
// send proposal to endorser
var request = {
chaincodeId: chaincodeName,
@ -43,115 +49,133 @@ var invokeChaincode = function(peerNames, channelName, chaincodeName, fcn, args,
txId: tx_id
};
if (targets)
request.targets = targets;
let results = await channel.sendTransactionProposal(request);
return channel.sendTransactionProposal(request);
}, (err) => {
logger.error('Failed to enroll user \'' + username + '\'. ' + err);
throw new Error('Failed to enroll user \'' + username + '\'. ' + err);
}).then((results) => {
// the returned object has both the endorsement results
// and the actual proposal, the proposal will be needed
// later when we send a transaction to the orderer
var proposalResponses = results[0];
var proposal = results[1];
// lets have a look at the responses to see if they are
// all good, if good they will also include signatures
// required to be committed
var all_good = true;
for (var i in proposalResponses) {
let one_good = false;
if (proposalResponses && proposalResponses[i].response &&
proposalResponses[i].response.status === 200) {
one_good = true;
logger.info('transaction proposal was good');
logger.info('invoke chaincode proposal was good');
} else {
logger.error('transaction proposal was bad');
logger.error('invoke chaincode proposal was bad');
}
all_good = all_good & one_good;
}
if (all_good) {
logger.debug(util.format(
logger.info(util.format(
'Successfully sent Proposal and received ProposalResponse: Status - %s, message - "%s", metadata - "%s", endorsement signature: %s',
proposalResponses[0].response.status, proposalResponses[0].response.message,
proposalResponses[0].response.payload, proposalResponses[0].endorsement
.signature));
var request = {
// tell each peer to join and wait for the event hub of each peer to tell us
// that the channel has been created on each peer
var promises = [];
let event_hubs = client.getEventHubsForOrg(org_name);
event_hubs.forEach((eh) => {
logger.debug('invokeEventPromise - setting up event');
let invokeEventPromise = new Promise((resolve, reject) => {
let event_timeout = setTimeout(() => {
let message = 'REQUEST_TIMEOUT:' + eh._ep._endpoint.addr;
logger.error(message);
eh.disconnect();
reject(new Error(message));
}, 3000);
eh.registerTxEvent(tx_id_string, (tx, code) => {
logger.info('The chaincode invoke chaincode transaction has been committed on peer %s',eh._ep._endpoint.addr);
clearTimeout(event_timeout);
eh.unregisterTxEvent(tx_id_string);
if (code !== 'VALID') {
let message = until.format('The invoke chaincode transaction was invalid, code:%s',code);
logger.error(message);
reject(new Error(message));
} else {
let message = 'The invoke chaincode transaction was valid.';
logger.info(message);
resolve(message);
}
}, (err) => {
clearTimeout(event_timeout);
eh.unregisterTxEvent(tx_id_string);
let message = 'Problem setting up the event hub :'+ err.toString();
logger.error(message);
reject(new Error(message));
});
});
promises.push(invokeEventPromise);
eh.connect();
eventhubs_in_use.push(eh);
});
var orderer_request = {
txId: tx_id,
proposalResponses: proposalResponses,
proposal: proposal
};
// set the transaction listener and set a timeout of 30sec
// if the transaction did not get committed within the timeout period,
// fail the test
var transactionID = tx_id.getTransactionID();
var eventPromises = [];
if (!peerNames) {
peerNames = channel.getPeers().map(function(peer) {
return peer.getName();
});
var sendPromise = channel.sendTransaction(orderer_request);
// put the send to the orderer last so that the events get registered and
// are ready for the orderering and committing
promises.push(sendPromise);
let results = await Promise.all(promises);
logger.debug(util.format('------->>> R E S P O N S E : %j', results));
let response = results.pop(); // orderer results are last in the results
if (response.status === 'SUCCESS') {
logger.info('Successfully sent transaction to the orderer.');
} else {
error_message = util.format('Failed to order the transaction. Error code: %s',response.status);
logger.debug(error_message);
}
var eventhubs = helper.newEventHubs(peerNames, org);
for (let key in eventhubs) {
let eh = eventhubs[key];
eh.connect();
let txPromise = new Promise((resolve, reject) => {
let handle = setTimeout(() => {
eh.disconnect();
reject();
}, 30000);
eh.registerTxEvent(transactionID, (tx, code) => {
clearTimeout(handle);
eh.unregisterTxEvent(transactionID);
eh.disconnect();
if (code !== 'VALID') {
logger.error(
'The balance transfer transaction was invalid, code = ' + code);
reject();
} else {
logger.info(
'The balance transfer transaction has been committed on peer ' +
eh._ep._endpoint.addr);
resolve();
}
});
});
eventPromises.push(txPromise);
};
var sendPromise = channel.sendTransaction(request);
return Promise.all([sendPromise].concat(eventPromises)).then((results) => {
logger.debug(' event promise all complete and testing complete');
return results[0]; // the first returned value is from the 'sendPromise' which is from the 'sendTransaction()' call
}).catch((err) => {
logger.error(
'Failed to send transaction and get notifications within the timeout period.'
);
return 'Failed to send transaction and get notifications within the timeout period.';
});
// now see what each of the event hubs reported
for(let i in results) {
let event_hub_result = results[i];
let event_hub = event_hubs[i];
logger.debug('Event results for event hub :%s',event_hub._ep._endpoint.addr);
if(typeof event_hub_result === 'string') {
logger.debug(event_hub_result);
} else {
if(!error_message) error_message = event_hub_result.toString();
logger.debug(event_hub_result.toString());
}
}
} else {
logger.error(
'Failed to send Proposal or receive valid response. Response null or status is not 200. exiting...'
);
return 'Failed to send Proposal or receive valid response. Response null or status is not 200. exiting...';
error_message = util.format('Failed to send Proposal and receive all good ProposalResponse');
logger.debug(error_message);
}
}, (err) => {
logger.error('Failed to send proposal due to error: ' + err.stack ? err.stack :
err);
return 'Failed to send proposal due to error: ' + err.stack ? err.stack :
err;
}).then((response) => {
if (response.status === 'SUCCESS') {
logger.info('Successfully sent transaction to the orderer.');
return tx_id.getTransactionID();
} else {
logger.error('Failed to order the transaction. Error code: ' + response.status);
return 'Failed to order the transaction. Error code: ' + response.status;
}
}, (err) => {
logger.error('Failed to send transaction due to error: ' + err.stack ? err
.stack : err);
return 'Failed to send transaction due to error: ' + err.stack ? err.stack :
err;
} catch (error) {
logger.error('Failed to invoke due to error: ' + error.stack ? error.stack : error);
error_message = error.toString();
}
// need to shutdown open event streams
eventhubs_in_use.forEach((eh) => {
eh.disconnect();
});
if (!error_message) {
let message = util.format(
'Successfully invoked the chaincode %s to the channel \'%s\'',
org_name, channelName);
logger.info(message);
return tx_id_string;
} else {
let message = util.format('Failed to invoke chaincode. cause:%s',error_message);
logger.error(message);
throw new Error(message);
}
};
exports.invokeChaincode = invokeChaincode;

View file

@ -17,123 +17,144 @@ var util = require('util');
var path = require('path');
var fs = require('fs');
var Peer = require('fabric-client/lib/Peer.js');
var EventHub = require('fabric-client/lib/EventHub.js');
var tx_id = null;
var nonce = null;
var config = require('../config.json');
var helper = require('./helper.js');
var logger = helper.getLogger('Join-Channel');
//helper.hfc.addConfigFile(path.join(__dirname, 'network-config.json'));
var ORGS = helper.ORGS;
var allEventhubs = [];
//
//Attempt to send a request to the orderer with the sendCreateChain method
//
var joinChannel = function(channelName, peers, username, org) {
// on process exit, always disconnect the event hub
var closeConnections = function(isSuccess) {
if (isSuccess) {
logger.debug('\n============ Join Channel is SUCCESS ============\n');
} else {
logger.debug('\n!!!!!!!! ERROR: Join Channel FAILED !!!!!!!!\n');
/*
* Have an organization join a channel
*/
var joinChannel = async function(channel_name, peers, username, org_name) {
logger.debug('\n\n============ Join Channel start ============\n')
var error_message = null;
var all_eventhubs = [];
try {
logger.info('Calling peers in organization "%s" to join the channel', org_name);
// first setup the client for this org
var client = await helper.getClientForOrg(org_name, username);
logger.debug('Successfully got the fabric client for the organization "%s"', org_name);
var channel = client.getChannel(channel_name);
if(!channel) {
let message = util.format('Channel %s was not defined in the connection profile', channel_name);
logger.error(message);
throw new Error(message);
}
logger.debug('');
for (var key in allEventhubs) {
var eventhub = allEventhubs[key];
if (eventhub && eventhub.isconnected()) {
//logger.debug('Disconnecting the event hub');
eventhub.disconnect();
}
}
};
//logger.debug('\n============ Join Channel ============\n')
logger.info(util.format(
'Calling peers in organization "%s" to join the channel', org));
var client = helper.getClientForOrg(org);
var channel = helper.getChannelForOrg(org);
var eventhubs = [];
return helper.getOrgAdmin(org).then((admin) => {
logger.info(util.format('received member object for admin of the organization "%s": ', org));
tx_id = client.newTransactionID();
// next step is to get the genesis_block from the orderer,
// the starting point for the channel that we want to join
let request = {
txId : tx_id
txId : client.newTransactionID(true) //get an admin based transactionID
};
let genesis_block = await channel.getGenesisBlock(request);
return channel.getGenesisBlock(request);
}).then((genesis_block) => {
tx_id = client.newTransactionID();
var request = {
targets: helper.newPeers(peers, org),
txId: tx_id,
block: genesis_block
};
eventhubs = helper.newEventHubs(peers, org);
for (let key in eventhubs) {
let eh = eventhubs[key];
eh.connect();
allEventhubs.push(eh);
}
var eventPromises = [];
eventhubs.forEach((eh) => {
let txPromise = new Promise((resolve, reject) => {
let handle = setTimeout(reject, parseInt(config.eventWaitTime));
eh.registerBlockEvent((block) => {
clearTimeout(handle);
// in real-world situations, a peer may have more than one channels so
// we must check that this block came from the channel we asked the peer to join
// tell each peer to join and wait for the event hub of each peer to tell us
// that the channel has been created on each peer
var promises = [];
var block_registration_numbers = [];
let event_hubs = client.getEventHubsForOrg(org_name);
event_hubs.forEach((eh) => {
let configBlockPromise = new Promise((resolve, reject) => {
let event_timeout = setTimeout(() => {
let message = 'REQUEST_TIMEOUT:' + eh._ep._endpoint.addr;
logger.error(message);
eh.disconnect();
reject(new Error(message));
}, 60000);
let block_registration_number = eh.registerBlockEvent((block) => {
clearTimeout(event_timeout);
// a peer may have more than one channel so
// we must check that this block came from the channel we
// asked the peer to join
if (block.data.data.length === 1) {
// Config block must only contain one transaction
var channel_header = block.data.data[0].payload.header.channel_header;
if (channel_header.channel_id === channelName) {
resolve();
}
else {
reject();
if (channel_header.channel_id === channel_name) {
let message = util.format('EventHub % has reported a block update for channel %s',eh._ep._endpoint.addr,channel_name);
logger.info(message)
resolve(message);
} else {
let message = util.format('Unknown channel block event received from %s',eh._ep._endpoint.addr);
logger.error(message);
reject(new Error(message));
}
}
}, (err) => {
clearTimeout(event_timeout);
let message = 'Problem setting up the event hub :'+ err.toString();
logger.error(message);
reject(new Error(message));
});
// save the registration handle so able to deregister
block_registration_numbers.push(block_registration_number);
all_eventhubs.push(eh); //save for later so that we can shut it down
});
eventPromises.push(txPromise);
promises.push(configBlockPromise);
eh.connect(); //this opens the event stream that must be shutdown at some point with a disconnect()
});
let sendPromise = channel.joinChannel(request);
return Promise.all([sendPromise].concat(eventPromises));
}, (err) => {
logger.error('Failed to enroll user \'' + username + '\' due to error: ' +
err.stack ? err.stack : err);
throw new Error('Failed to enroll user \'' + username +
'\' due to error: ' + err.stack ? err.stack : err);
}).then((results) => {
let join_request = {
targets: peers, //using the peer names which only is allowed when a connection profile is loaded
txId: client.newTransactionID(true), //get an admin based transactionID
block: genesis_block
};
let join_promise = channel.joinChannel(join_request);
promises.push(join_promise);
let results = await Promise.all(promises);
logger.debug(util.format('Join Channel R E S P O N S E : %j', results));
if (results[0] && results[0][0] && results[0][0].response && results[0][0]
.response.status == 200) {
logger.info(util.format(
'Successfully joined peers in organization %s to the channel \'%s\'',
org, channelName));
closeConnections(true);
let response = {
success: true,
message: util.format(
'Successfully joined peers in organization %s to the channel \'%s\'',
org, channelName)
};
return response;
} else {
logger.error(' Failed to join channel');
closeConnections();
throw new Error('Failed to join channel');
// lets check the results of sending to the peers which is
// last in the results array
let peers_results = results.pop();
// then each peer results
for(let i in peers_results) {
let peer_result = peers_results[i];
if(peer_result.response && peer_result.response.status == 200) {
logger.info('Successfully joined peer to the channel %s',channel_name);
} else {
let message = util.format('Failed to joined peer to the channel %s',channel_name);
error_message = message;
logger.error(message);
}
}
}, (err) => {
logger.error('Failed to join channel due to error: ' + err.stack ? err.stack :
err);
closeConnections();
throw new Error('Failed to join channel due to error: ' + err.stack ? err.stack :
err);
// now see what each of the event hubs reported
for(let i in results) {
let event_hub_result = results[i];
let event_hub = event_hubs[i];
let block_registration_number = block_registration_numbers[i];
logger.debug('Event results for event hub :%s',event_hub._ep._endpoint.addr);
if(typeof event_hub_result === 'string') {
logger.debug(event_hub_result);
} else {
if(!error_message) error_message = event_hub_result.toString();
logger.debug(event_hub_result.toString());
}
event_hub.unregisterBlockEvent(block_registration_number);
}
} catch(error) {
logger.error('Failed to join channel due to error: ' + error.stack ? error.stack : error);
error_message = error.toString();
}
// need to shutdown open event streams
all_eventhubs.forEach((eh) => {
eh.disconnect();
});
if (!error_message) {
let message = util.format(
'Successfully joined peers in organization %s to the channel:%s',
org_name, channel_name);
logger.info(message);
// build a response to send back to the REST caller
let response = {
success: true,
message: message
};
return response;
} else {
let message = util.format('Failed to join all peers to channel. cause:%s',error_message);
logger.error(message);
throw new Error(message);
}
};
exports.joinChannel = joinChannel;

View file

@ -1,55 +0,0 @@
{
"network-config": {
"orderer": {
"url": "grpc://ec2-13-59-99-140.us-east-2.compute.amazonaws.com:7050",
"server-hostname": "orderer.example.com",
"tls_cacerts": "../artifacts/channel/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/ca.crt"
},
"org1": {
"name": "peerOrg1",
"mspid": "Org1MSP",
"ca": "https://ec2-13-59-99-140.us-east-2.compute.amazonaws.com:7054",
"peers": {
"peer1": {
"requests": "grpc://ec2-13-59-99-140.us-east-2.compute.amazonaws.com:7051",
"events": "grpc://ec2-13-59-99-140.us-east-2.compute.amazonaws.com:7053",
"server-hostname": "peer0.org1.example.com",
"tls_cacerts": "../artifacts/channel/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt"
},
"peer2": {
"requests": "grpc://ec2-13-59-99-140.us-east-2.compute.amazonaws.com:7056",
"events": "grpc://ec2-13-59-99-140.us-east-2.compute.amazonaws.com:7058",
"server-hostname": "peer1.org1.example.com",
"tls_cacerts": "../artifacts/channel/crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/ca.crt"
}
},
"admin": {
"key": "../artifacts/channel/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/keystore",
"cert": "../artifacts/channel/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/signcerts"
}
},
"org2": {
"name": "peerOrg2",
"mspid": "Org2MSP",
"ca": "https://ec2-13-59-99-140.us-east-2.compute.amazonaws.com:8054",
"peers": {
"peer1": {
"requests": "grpc://ec2-13-59-99-140.us-east-2.compute.amazonaws.com:8051",
"events": "grpc://ec2-13-59-99-140.us-east-2.compute.amazonaws.com:8053",
"server-hostname": "peer0.org2.example.com",
"tls_cacerts": "../artifacts/channel/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt"
},
"peer2": {
"requests": "grpc://ec2-13-59-99-140.us-east-2.compute.amazonaws.com:8056",
"events": "grpc://ec2-13-59-99-140.us-east-2.compute.amazonaws.com:8058",
"server-hostname": "peer1.org2.example.com",
"tls_cacerts": "../artifacts/channel/crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/ca.crt"
}
},
"admin": {
"key": "../artifacts/channel/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp/keystore",
"cert": "../artifacts/channel/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp/signcerts"
}
}
}
}

View file

@ -1,55 +0,0 @@
{
"network-config": {
"orderer": {
"url": "grpcs://localhost:7050",
"server-hostname": "orderer.example.com",
"tls_cacerts": "../artifacts/channel/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/ca.crt"
},
"org1": {
"name": "peerOrg1",
"mspid": "Org1MSP",
"ca": "https://localhost:7054",
"peers": {
"peer1": {
"requests": "grpcs://localhost:7051",
"events": "grpcs://localhost:7053",
"server-hostname": "peer0.org1.example.com",
"tls_cacerts": "../artifacts/channel/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt"
},
"peer2": {
"requests": "grpcs://localhost:7056",
"events": "grpcs://localhost:7058",
"server-hostname": "peer1.org1.example.com",
"tls_cacerts": "../artifacts/channel/crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/ca.crt"
}
},
"admin": {
"key": "../artifacts/channel/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/keystore",
"cert": "../artifacts/channel/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/signcerts"
}
},
"org2": {
"name": "peerOrg2",
"mspid": "Org2MSP",
"ca": "https://localhost:8054",
"peers": {
"peer1": {
"requests": "grpcs://localhost:8051",
"events": "grpcs://localhost:8053",
"server-hostname": "peer0.org2.example.com",
"tls_cacerts": "../artifacts/channel/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt"
},
"peer2": {
"requests": "grpcs://localhost:8056",
"events": "grpcs://localhost:8058",
"server-hostname": "peer1.org2.example.com",
"tls_cacerts": "../artifacts/channel/crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/ca.crt"
}
},
"admin": {
"key": "../artifacts/channel/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp/keystore",
"cert": "../artifacts/channel/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp/signcerts"
}
}
}
}

View file

@ -17,31 +17,29 @@ var path = require('path');
var fs = require('fs');
var util = require('util');
var hfc = require('fabric-client');
var Peer = require('fabric-client/lib/Peer.js');
var EventHub = require('fabric-client/lib/EventHub.js');
var config = require('../config.json');
var helper = require('./helper.js');
var logger = helper.getLogger('Query');
var queryChaincode = function(peer, channelName, chaincodeName, args, fcn, username, org) {
var channel = helper.getChannelForOrg(org);
var client = helper.getClientForOrg(org);
var target = buildTarget(peer, org);
return helper.getRegisteredUsers(username, org).then((user) => {
tx_id = client.newTransactionID();
var queryChaincode = async function(peer, channelName, chaincodeName, args, fcn, username, org_name) {
try {
// first setup the client for this org
var client = await helper.getClientForOrg(org_name, username);
logger.debug('Successfully got the fabric client for the organization "%s"', org_name);
var channel = client.getChannel(channelName);
if(!channel) {
let message = util.format('Channel %s was not defined in the connection profile', channelName);
logger.error(message);
throw new Error(message);
}
// send query
var request = {
targets : [peer], //queryByChaincode allows for multiple targets
chaincodeId: chaincodeName,
txId: tx_id,
fcn: fcn,
args: args
};
return channel.queryByChaincode(request, target);
}, (err) => {
logger.info('Failed to get submitter \''+username+'\'');
return 'Failed to get submitter \''+username+'\'. Error: ' + err.stack ? err.stack :
err;
}).then((response_payloads) => {
let response_payloads = await channel.queryByChaincode(request);
if (response_payloads) {
for (let i = 0; i < response_payloads.length; i++) {
logger.info(args[0]+' now has ' + response_payloads[i].toString('utf8') +
@ -53,147 +51,130 @@ var queryChaincode = function(peer, channelName, chaincodeName, args, fcn, usern
logger.error('response_payloads is null');
return 'response_payloads is null';
}
}, (err) => {
logger.error('Failed to send query due to error: ' + err.stack ? err.stack :
err);
return 'Failed to send query due to error: ' + err.stack ? err.stack : err;
}).catch((err) => {
logger.error('Failed to end to end test with error:' + err.stack ? err.stack :
err);
return 'Failed to end to end test with error:' + err.stack ? err.stack :
err;
});
} catch(error) {
logger.error('Failed to query due to error: ' + error.stack ? error.stack : error);
return error.toString();
}
};
var getBlockByNumber = function(peer, blockNumber, username, org) {
var target = buildTarget(peer, org);
var channel = helper.getChannelForOrg(org);
return helper.getRegisteredUsers(username, org).then((member) => {
return channel.queryBlock(parseInt(blockNumber), target);
}, (err) => {
logger.info('Failed to get submitter "' + username + '"');
return 'Failed to get submitter "' + username + '". Error: ' + err.stack ?
err.stack : err;
}).then((response_payloads) => {
if (response_payloads) {
//logger.debug(response_payloads);
logger.debug(response_payloads);
return response_payloads; //response_payloads.data.data[0].buffer;
} else {
logger.error('response_payloads is null');
return 'response_payloads is null';
var getBlockByNumber = async function(peer, channelName, blockNumber, username, org_name) {
try {
// first setup the client for this org
var client = await helper.getClientForOrg(org_name, username);
logger.debug('Successfully got the fabric client for the organization "%s"', org_name);
var channel = client.getChannel(channelName);
if(!channel) {
let message = util.format('Channel %s was not defined in the connection profile', channelName);
logger.error(message);
throw new Error(message);
}
}, (err) => {
logger.error('Failed to send query due to error: ' + err.stack ? err.stack :
err);
return 'Failed to send query due to error: ' + err.stack ? err.stack : err;
}).catch((err) => {
logger.error('Failed to query with error:' + err.stack ? err.stack : err);
return 'Failed to query with error:' + err.stack ? err.stack : err;
});
let response_payload = await channel.queryBlock(parseInt(blockNumber, peer));
if (response_payload) {
logger.debug(response_payload);
return response_payload;
} else {
logger.error('response_payload is null');
return 'response_payload is null';
}
} catch(error) {
logger.error('Failed to query due to error: ' + error.stack ? error.stack : error);
return error.toString();
}
};
var getTransactionByID = function(peer, trxnID, username, org) {
var target = buildTarget(peer, org);
var channel = helper.getChannelForOrg(org);
return helper.getRegisteredUsers(username, org).then((member) => {
return channel.queryTransaction(trxnID, target);
}, (err) => {
logger.info('Failed to get submitter "' + username + '"');
return 'Failed to get submitter "' + username + '". Error: ' + err.stack ?
err.stack : err;
}).then((response_payloads) => {
if (response_payloads) {
logger.debug(response_payloads);
return response_payloads;
} else {
logger.error('response_payloads is null');
return 'response_payloads is null';
var getTransactionByID = async function(peer, channelName, trxnID, username, org_name) {
try {
// first setup the client for this org
var client = await helper.getClientForOrg(org_name, username);
logger.debug('Successfully got the fabric client for the organization "%s"', org_name);
var channel = client.getChannel(channelName);
if(!channel) {
let message = util.format('Channel %s was not defined in the connection profile', channelName);
logger.error(message);
throw new Error(message);
}
}, (err) => {
logger.error('Failed to send query due to error: ' + err.stack ? err.stack :
err);
return 'Failed to send query due to error: ' + err.stack ? err.stack : err;
}).catch((err) => {
logger.error('Failed to query with error:' + err.stack ? err.stack : err);
return 'Failed to query with error:' + err.stack ? err.stack : err;
});
let response_payload = await channel.queryTransaction(trxnID, peer);
if (response_payload) {
logger.debug(response_payload);
return response_payload;
} else {
logger.error('response_payload is null');
return 'response_payload is null';
}
} catch(error) {
logger.error('Failed to query due to error: ' + error.stack ? error.stack : error);
return error.toString();
}
};
var getBlockByHash = function(peer, hash, username, org) {
var target = buildTarget(peer, org);
var channel = helper.getChannelForOrg(org);
return helper.getRegisteredUsers(username, org).then((member) => {
return channel.queryBlockByHash(Buffer.from(hash), target);
}, (err) => {
logger.info('Failed to get submitter "' + username + '"');
return 'Failed to get submitter "' + username + '". Error: ' + err.stack ?
err.stack : err;
}).then((response_payloads) => {
if (response_payloads) {
logger.debug(response_payloads);
return response_payloads;
} else {
logger.error('response_payloads is null');
return 'response_payloads is null';
var getBlockByHash = async function(peer, channelName, hash, username, org_name) {
try {
// first setup the client for this org
var client = await helper.getClientForOrg(org_name, username);
logger.debug('Successfully got the fabric client for the organization "%s"', org_name);
var channel = client.getChannel(channelName);
if(!channel) {
let message = util.format('Channel %s was not defined in the connection profile', channelName);
logger.error(message);
throw new Error(message);
}
}, (err) => {
logger.error('Failed to send query due to error: ' + err.stack ? err.stack :
err);
return 'Failed to send query due to error: ' + err.stack ? err.stack : err;
}).catch((err) => {
logger.error('Failed to query with error:' + err.stack ? err.stack : err);
return 'Failed to query with error:' + err.stack ? err.stack : err;
});
let response_payload = await channel.queryBlockByHash(Buffer.from(hash), peer);
if (response_payload) {
logger.debug(response_payload);
return response_payload;
} else {
logger.error('response_payload is null');
return 'response_payload is null';
}
} catch(error) {
logger.error('Failed to query due to error: ' + error.stack ? error.stack : error);
return error.toString();
}
};
var getChainInfo = function(peer, username, org) {
var target = buildTarget(peer, org);
var channel = helper.getChannelForOrg(org);
return helper.getRegisteredUsers(username, org).then((member) => {
return channel.queryInfo(target);
}, (err) => {
logger.info('Failed to get submitter "' + username + '"');
return 'Failed to get submitter "' + username + '". Error: ' + err.stack ?
err.stack : err;
}).then((blockchainInfo) => {
if (blockchainInfo) {
// FIXME: Save this for testing 'getBlockByHash' ?
logger.debug('===========================================');
logger.debug(blockchainInfo.currentBlockHash);
logger.debug('===========================================');
//logger.debug(blockchainInfo);
return blockchainInfo;
} else {
logger.error('response_payloads is null');
return 'response_payloads is null';
var getChainInfo = async function(peer, channelName, username, org_name) {
try {
// first setup the client for this org
var client = await helper.getClientForOrg(org_name, username);
logger.debug('Successfully got the fabric client for the organization "%s"', org_name);
var channel = client.getChannel(channelName);
if(!channel) {
let message = util.format('Channel %s was not defined in the connection profile', channelName);
logger.error(message);
throw new Error(message);
}
}, (err) => {
logger.error('Failed to send query due to error: ' + err.stack ? err.stack :
err);
return 'Failed to send query due to error: ' + err.stack ? err.stack : err;
}).catch((err) => {
logger.error('Failed to query with error:' + err.stack ? err.stack : err);
return 'Failed to query with error:' + err.stack ? err.stack : err;
});
let response_payload = await channel.queryInfo(peer);
if (response_payload) {
logger.debug(response_payload);
return response_payload;
} else {
logger.error('response_payload is null');
return 'response_payload is null';
}
} catch(error) {
logger.error('Failed to query due to error: ' + error.stack ? error.stack : error);
return error.toString();
}
};
//getInstalledChaincodes
var getInstalledChaincodes = function(peer, type, username, org) {
var target = buildTarget(peer, org);
var channel = helper.getChannelForOrg(org);
var client = helper.getClientForOrg(org);
var getInstalledChaincodes = async function(peer, channelName, type, username, org_name) {
try {
// first setup the client for this org
var client = await helper.getClientForOrg(org_name, username);
logger.debug('Successfully got the fabric client for the organization "%s"', org_name);
return helper.getOrgAdmin(org).then((member) => {
let response = null
if (type === 'installed') {
return client.queryInstalledChaincodes(target);
response = await client.queryInstalledChaincodes(peer, true); //use the admin identity
} else {
return channel.queryInstantiatedChaincodes(target);
var channel = client.getChannel(channelName);
if(!channel) {
let message = util.format('Channel %s was not defined in the connection profile', channelName);
logger.error(message);
throw new Error(message);
}
response = await channel.queryInstantiatedChaincodes(peer, true); //use the admin identity
}
}, (err) => {
logger.info('Failed to get submitter "' + username + '"');
return 'Failed to get submitter "' + username + '". Error: ' + err.stack ?
err.stack : err;
}).then((response) => {
if (response) {
if (type === 'installed') {
logger.debug('<<< Installed Chaincodes >>>');
@ -214,28 +195,18 @@ var getInstalledChaincodes = function(peer, type, username, org) {
logger.error('response is null');
return 'response is null';
}
}, (err) => {
logger.error('Failed to send query due to error: ' + err.stack ? err.stack :
err);
return 'Failed to send query due to error: ' + err.stack ? err.stack : err;
}).catch((err) => {
logger.error('Failed to query with error:' + err.stack ? err.stack : err);
return 'Failed to query with error:' + err.stack ? err.stack : err;
});
} catch(error) {
logger.error('Failed to query due to error: ' + error.stack ? error.stack : error);
return error.toString();
}
};
var getChannels = function(peer, username, org) {
var target = buildTarget(peer, org);
var channel = helper.getChannelForOrg(org);
var client = helper.getClientForOrg(org);
var getChannels = async function(peer, username, org_name) {
try {
// first setup the client for this org
var client = await helper.getClientForOrg(org_name, username);
logger.debug('Successfully got the fabric client for the organization "%s"', org_name);
return helper.getRegisteredUsers(username, org).then((member) => {
//channel.setPrimaryPeer(targets[0]);
return client.queryChannels(target);
}, (err) => {
logger.info('Failed to get submitter "' + username + '"');
return 'Failed to get submitter "' + username + '". Error: ' + err.stack ?
err.stack : err;
}).then((response) => {
let response = await client.queryChannels(peer);
if (response) {
logger.debug('<<< channels >>>');
var channelNames = [];
@ -248,25 +219,11 @@ var getChannels = function(peer, username, org) {
logger.error('response_payloads is null');
return 'response_payloads is null';
}
}, (err) => {
logger.error('Failed to send query due to error: ' + err.stack ? err.stack :
err);
return 'Failed to send query due to error: ' + err.stack ? err.stack : err;
}).catch((err) => {
logger.error('Failed to query with error:' + err.stack ? err.stack : err);
return 'Failed to query with error:' + err.stack ? err.stack : err;
});
};
function buildTarget(peer, org) {
var target = null;
if (typeof peer !== 'undefined') {
let targets = helper.newPeers([peer], org);
if (targets && targets.length > 0) target = targets[0];
} catch(error) {
logger.error('Failed to query due to error: ' + error.stack ? error.stack : error);
return error.toString();
}
return target;
}
};
exports.queryChaincode = queryChaincode;
exports.getBlockByNumber = getBlockByNumber;

View file

@ -11,6 +11,7 @@ services:
image: hyperledger/fabric-ca
environment:
- FABRIC_CA_HOME=/etc/hyperledger/fabric-ca-server
- FABRIC_CA_SERVER_CA_NAME=ca-org1
- FABRIC_CA_SERVER_CA_CERTFILE=/etc/hyperledger/fabric-ca-server-config/ca.org1.example.com-cert.pem
- FABRIC_CA_SERVER_CA_KEYFILE=/etc/hyperledger/fabric-ca-server-config/0e729224e8b3f31784c8a93c5b8ef6f4c1c91d9e6e577c45c33163609fe40011_sk
- FABRIC_CA_SERVER_TLS_ENABLED=true
@ -27,6 +28,7 @@ services:
image: hyperledger/fabric-ca
environment:
- FABRIC_CA_HOME=/etc/hyperledger/fabric-ca-server
- FABRIC_CA_SERVER_CA_NAME=ca-org2
- FABRIC_CA_SERVER_CA_CERTFILE=/etc/hyperledger/fabric-ca-server-config/ca.org2.example.com-cert.pem
- FABRIC_CA_SERVER_CA_KEYFILE=/etc/hyperledger/fabric-ca-server-config/a7d47efa46a6ba07730c850fed2c1375df27360d7227f48cdc2f80e505678005_sk
- FABRIC_CA_SERVER_TLS_ENABLED=true

View file

@ -0,0 +1,236 @@
---
#
# The network connection profile provides client applications the information about the target
# blockchain network that are necessary for the applications to interact with it. These are all
# knowledge that must be acquired from out-of-band sources. This file provides such a source.
#
name: "balance-transfer"
#
# Any properties with an "x-" prefix will be treated as application-specific, exactly like how naming
# in HTTP headers or swagger properties work. The SDK will simply ignore these fields and leave
# them for the applications to process. This is a mechanism for different components of an application
# to exchange information that are not part of the standard schema described below. In particular,
# the "x-type" property with the "hlfv1" value example below is used by Hyperledger Composer to
# determine the type of Fabric networks (v0.6 vs. v1.0) it needs to work with.
#
x-type: "hlfv1"
#
# Describe what the target network is/does.
#
description: "Balance Transfer Network"
#
# Schema version of the content. Used by the SDK to apply the corresponding parsing rules.
#
version: "1.0"
#
# The client section will be added on a per org basis see org1.yaml and org2.yaml
#
#client:
#
# [Optional]. But most apps would have this section so that channel objects can be constructed
# based on the content below. If an app is creating channels, then it likely will not need this
# section.
#
channels:
# name of the channel
mychannel:
# Required. list of orderers designated by the application to use for transactions on this
# channel. This list can be a result of access control ("org1" can only access "ordererA"), or
# operational decisions to share loads from applications among the orderers. The values must
# be "names" of orgs defined under "organizations/peers"
orderers:
- orderer.example.com
# Required. list of peers from participating orgs
peers:
peer0.org1.example.com:
# [Optional]. will this peer be sent transaction proposals for endorsement? The peer must
# have the chaincode installed. The app can also use this property to decide which peers
# to send the chaincode install request. Default: true
endorsingPeer: true
# [Optional]. will this peer be sent query proposals? The peer must have the chaincode
# installed. The app can also use this property to decide which peers to send the
# chaincode install request. Default: true
chaincodeQuery: true
# [Optional]. will this peer be sent query proposals that do not require chaincodes, like
# queryBlock(), queryTransaction(), etc. Default: true
ledgerQuery: true
# [Optional]. will this peer be the target of the SDK's listener registration? All peers can
# produce events but the app typically only needs to connect to one to listen to events.
# Default: true
eventSource: true
peer1.org1.example.com:
endorsingPeer: false
chaincodeQuery: true
ledgerQuery: true
eventSource: false
peer0.org2.example.com:
endorsingPeer: true
chaincodeQuery: true
ledgerQuery: true
eventSource: true
peer1.org2.example.com:
endorsingPeer: false
chaincodeQuery: true
ledgerQuery: true
eventSource: false
# [Optional]. what chaincodes are expected to exist on this channel? The application can use
# this information to validate that the target peers are in the expected state by comparing
# this list with the query results of getInstalledChaincodes() and getInstantiatedChaincodes()
chaincodes:
# the format follows the "cannonical name" of chaincodes by fabric code
- mycc:v0
#
# list of participating organizations in this network
#
organizations:
Org1:
mspid: Org1MSP
peers:
- peer0.org1.example.com
- peer1.org1.example.com
# [Optional]. Certificate Authorities issue certificates for identification purposes in a Fabric based
# network. Typically certificates provisioning is done in a separate process outside of the
# runtime network. Fabric-CA is a special certificate authority that provides a REST APIs for
# dynamic certificate management (enroll, revoke, re-enroll). The following section is only for
# Fabric-CA servers.
certificateAuthorities:
- ca-org1
# [Optional]. If the application is going to make requests that are reserved to organization
# administrators, including creating/updating channels, installing/instantiating chaincodes, it
# must have access to the admin identity represented by the private key and signing certificate.
# Both properties can be the PEM string or local path to the PEM file. Note that this is mainly for
# convenience in development mode, production systems should not expose sensitive information
# this way. The SDK should allow applications to set the org admin identity via APIs, and only use
# this route as an alternative when it exists.
adminPrivateKey:
path: artifacts/channel/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/keystore/5890f0061619c06fb29dea8cb304edecc020fe63f41a6db109f1e227cc1cb2a8_sk
signedCert:
path: artifacts/channel/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/signcerts/Admin@org1.example.com-cert.pem
# the profile will contain public information about organizations other than the one it belongs to.
# These are necessary information to make transaction lifecycles work, including MSP IDs and
# peers with a public URL to send transaction proposals. The file will not contain private
# information reserved for members of the organization, such as admin key and certificate,
# fabric-ca registrar enroll ID and secret, etc.
Org2:
mspid: Org2MSP
peers:
- peer0.org2.example.com
- peer1.org2.example.com
certificateAuthorities:
- ca-org2
adminPrivateKey:
path: artifacts/channel/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp/keystore/1995b11d6573ed3be52fcd7a5fa477bc0f183e1f5f398c8281d0ce7c2c75a076_sk
signedCert:
path: artifacts/channel/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp/signcerts/Admin@org2.example.com-cert.pem
#
# List of orderers to send transaction and channel create/update requests to. For the time
# being only one orderer is needed. If more than one is defined, which one get used by the
# SDK is implementation specific. Consult each SDK's documentation for its handling of orderers.
#
orderers:
orderer.example.com:
url: grpcs://ec2-13-59-99-140.us-east-2.compute.amazonaws.com:7050
# these are standard properties defined by the gRPC library
# they will be passed in as-is to gRPC client constructor
grpcOptions:
ssl-target-name-override: orderer.example.com
grpc-max-send-message-length: 15
tlsCACerts:
path: artifacts/channel/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/ca.crt
#
# List of peers to send various requests to, including endorsement, query
# and event listener registration.
#
peers:
peer0.org1.example.com:
# this URL is used to send endorsement and query requests
url: grpcs://ec2-13-59-99-140.us-east-2.compute.amazonaws.com:7051
# this URL is used to connect the EventHub and registering event listeners
eventUrl: grpcs://ec2-13-59-99-140.us-east-2.compute.amazonaws.com:7053
grpcOptions:
ssl-target-name-override: peer0.org1.example.com
tlsCACerts:
path: artifacts/channel/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
peer1.org1.example.com:
url: grpcs://ec2-13-59-99-140.us-east-2.compute.amazonaws.com:7056
eventUrl: grpcs://ec2-13-59-99-140.us-east-2.compute.amazonaws.com:7058
grpcOptions:
ssl-target-name-override: peer1.org1.example.com
tlsCACerts:
path: artifacts/channel/crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/ca.crt
peer0.org2.example.com:
url: grpcs://ec2-13-59-99-140.us-east-2.compute.amazonaws.com:8051
eventUrl: grpcs://ec2-13-59-99-140.us-east-2.compute.amazonaws.com:8053
grpcOptions:
ssl-target-name-override: peer0.org2.example.com
tlsCACerts:
path: artifacts/channel/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
peer1.org2.example.com:
url: grpcs://ec2-13-59-99-140.us-east-2.compute.amazonaws.com:8056
eventUrl: grpcs://ec2-13-59-99-140.us-east-2.compute.amazonaws.com:8058
grpcOptions:
ssl-target-name-override: peer1.org2.example.com
tlsCACerts:
path: artifacts/channel/crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/ca.crt
#
# Fabric-CA is a special kind of Certificate Authority provided by Hyperledger Fabric which allows
# certificate management to be done via REST APIs. Application may choose to use a standard
# Certificate Authority instead of Fabric-CA, in which case this section would not be specified.
#
certificateAuthorities:
ca-org1:
url: https://ec2-13-59-99-140.us-east-2.compute.amazonaws.com:7054
# the properties specified under this object are passed to the 'http' client verbatim when
# making the request to the Fabric-CA server
httpOptions:
verify: false
tlsCACerts:
path: artifacts/channel/crypto-config/peerOrganizations/org1.example.com/ca/ca.org1.example.com-cert.pem
# Fabric-CA supports dynamic user enrollment via REST APIs. A "root" user, a.k.a registrar, is
# needed to enroll and invoke new users.
registrar:
- enrollId: admin
enrollSecret: adminpw
# [Optional] The optional name of the CA.
caName: ca-org1
ca-org2:
url: https://ec2-13-59-99-140.us-east-2.compute.amazonaws.com:8054
httpOptions:
verify: false
tlsCACerts:
path: artifacts/channel/crypto-config/peerOrganizations/org2.example.com/ca/ca.org2.example.com-cert.pem
registrar:
- enrollId: admin
enrollSecret: adminpw
# [Optional] The optional name of the CA.
caName: ca-org2

View file

@ -0,0 +1,236 @@
---
#
# The network connection profile provides client applications the information about the target
# blockchain network that are necessary for the applications to interact with it. These are all
# knowledge that must be acquired from out-of-band sources. This file provides such a source.
#
name: "balance-transfer"
#
# Any properties with an "x-" prefix will be treated as application-specific, exactly like how naming
# in HTTP headers or swagger properties work. The SDK will simply ignore these fields and leave
# them for the applications to process. This is a mechanism for different components of an application
# to exchange information that are not part of the standard schema described below. In particular,
# the "x-type" property with the "hlfv1" value example below is used by Hyperledger Composer to
# determine the type of Fabric networks (v0.6 vs. v1.0) it needs to work with.
#
x-type: "hlfv1"
#
# Describe what the target network is/does.
#
description: "Balance Transfer Network"
#
# Schema version of the content. Used by the SDK to apply the corresponding parsing rules.
#
version: "1.0"
#
# The client section will be added on a per org basis see org1.yaml and org2.yaml
#
#client:
#
# [Optional]. But most apps would have this section so that channel objects can be constructed
# based on the content below. If an app is creating channels, then it likely will not need this
# section.
#
channels:
# name of the channel
mychannel:
# Required. list of orderers designated by the application to use for transactions on this
# channel. This list can be a result of access control ("org1" can only access "ordererA"), or
# operational decisions to share loads from applications among the orderers. The values must
# be "names" of orgs defined under "organizations/peers"
orderers:
- orderer.example.com
# Required. list of peers from participating orgs
peers:
peer0.org1.example.com:
# [Optional]. will this peer be sent transaction proposals for endorsement? The peer must
# have the chaincode installed. The app can also use this property to decide which peers
# to send the chaincode install request. Default: true
endorsingPeer: true
# [Optional]. will this peer be sent query proposals? The peer must have the chaincode
# installed. The app can also use this property to decide which peers to send the
# chaincode install request. Default: true
chaincodeQuery: true
# [Optional]. will this peer be sent query proposals that do not require chaincodes, like
# queryBlock(), queryTransaction(), etc. Default: true
ledgerQuery: true
# [Optional]. will this peer be the target of the SDK's listener registration? All peers can
# produce events but the app typically only needs to connect to one to listen to events.
# Default: true
eventSource: true
peer1.org1.example.com:
endorsingPeer: false
chaincodeQuery: true
ledgerQuery: true
eventSource: false
peer0.org2.example.com:
endorsingPeer: true
chaincodeQuery: true
ledgerQuery: true
eventSource: true
peer1.org2.example.com:
endorsingPeer: false
chaincodeQuery: true
ledgerQuery: true
eventSource: false
# [Optional]. what chaincodes are expected to exist on this channel? The application can use
# this information to validate that the target peers are in the expected state by comparing
# this list with the query results of getInstalledChaincodes() and getInstantiatedChaincodes()
chaincodes:
# the format follows the "cannonical name" of chaincodes by fabric code
- mycc:v0
#
# list of participating organizations in this network
#
organizations:
Org1:
mspid: Org1MSP
peers:
- peer0.org1.example.com
- peer1.org1.example.com
# [Optional]. Certificate Authorities issue certificates for identification purposes in a Fabric based
# network. Typically certificates provisioning is done in a separate process outside of the
# runtime network. Fabric-CA is a special certificate authority that provides a REST APIs for
# dynamic certificate management (enroll, revoke, re-enroll). The following section is only for
# Fabric-CA servers.
certificateAuthorities:
- ca-org1
# [Optional]. If the application is going to make requests that are reserved to organization
# administrators, including creating/updating channels, installing/instantiating chaincodes, it
# must have access to the admin identity represented by the private key and signing certificate.
# Both properties can be the PEM string or local path to the PEM file. Note that this is mainly for
# convenience in development mode, production systems should not expose sensitive information
# this way. The SDK should allow applications to set the org admin identity via APIs, and only use
# this route as an alternative when it exists.
adminPrivateKey:
path: artifacts/channel/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/keystore/5890f0061619c06fb29dea8cb304edecc020fe63f41a6db109f1e227cc1cb2a8_sk
signedCert:
path: artifacts/channel/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/signcerts/Admin@org1.example.com-cert.pem
# the profile will contain public information about organizations other than the one it belongs to.
# These are necessary information to make transaction lifecycles work, including MSP IDs and
# peers with a public URL to send transaction proposals. The file will not contain private
# information reserved for members of the organization, such as admin key and certificate,
# fabric-ca registrar enroll ID and secret, etc.
Org2:
mspid: Org2MSP
peers:
- peer0.org2.example.com
- peer1.org2.example.com
certificateAuthorities:
- ca-org2
adminPrivateKey:
path: artifacts/channel/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp/keystore/1995b11d6573ed3be52fcd7a5fa477bc0f183e1f5f398c8281d0ce7c2c75a076_sk
signedCert:
path: artifacts/channel/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp/signcerts/Admin@org2.example.com-cert.pem
#
# List of orderers to send transaction and channel create/update requests to. For the time
# being only one orderer is needed. If more than one is defined, which one get used by the
# SDK is implementation specific. Consult each SDK's documentation for its handling of orderers.
#
orderers:
orderer.example.com:
url: grpcs://localhost:7050
# these are standard properties defined by the gRPC library
# they will be passed in as-is to gRPC client constructor
grpcOptions:
ssl-target-name-override: orderer.example.com
grpc-max-send-message-length: 15
tlsCACerts:
path: artifacts/channel/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/ca.crt
#
# List of peers to send various requests to, including endorsement, query
# and event listener registration.
#
peers:
peer0.org1.example.com:
# this URL is used to send endorsement and query requests
url: grpcs://localhost:7051
# this URL is used to connect the EventHub and registering event listeners
eventUrl: grpcs://localhost:7053
grpcOptions:
ssl-target-name-override: peer0.org1.example.com
tlsCACerts:
path: artifacts/channel/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
peer1.org1.example.com:
url: grpcs://localhost:7056
eventUrl: grpcs://localhost:7058
grpcOptions:
ssl-target-name-override: peer1.org1.example.com
tlsCACerts:
path: artifacts/channel/crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/ca.crt
peer0.org2.example.com:
url: grpcs://localhost:8051
eventUrl: grpcs://localhost:8053
grpcOptions:
ssl-target-name-override: peer0.org2.example.com
tlsCACerts:
path: artifacts/channel/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
peer1.org2.example.com:
url: grpcs://localhost:8056
eventUrl: grpcs://localhost:8058
grpcOptions:
ssl-target-name-override: peer1.org2.example.com
tlsCACerts:
path: artifacts/channel/crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/ca.crt
#
# Fabric-CA is a special kind of Certificate Authority provided by Hyperledger Fabric which allows
# certificate management to be done via REST APIs. Application may choose to use a standard
# Certificate Authority instead of Fabric-CA, in which case this section would not be specified.
#
certificateAuthorities:
ca-org1:
url: https://localhost:7054
# the properties specified under this object are passed to the 'http' client verbatim when
# making the request to the Fabric-CA server
httpOptions:
verify: false
tlsCACerts:
path: artifacts/channel/crypto-config/peerOrganizations/org1.example.com/ca/ca.org1.example.com-cert.pem
# Fabric-CA supports dynamic user enrollment via REST APIs. A "root" user, a.k.a registrar, is
# needed to enroll and invoke new users.
registrar:
- enrollId: admin
enrollSecret: adminpw
# [Optional] The optional name of the CA.
caName: ca-org1
ca-org2:
url: https://localhost:8054
httpOptions:
verify: false
tlsCACerts:
path: artifacts/channel/crypto-config/peerOrganizations/org2.example.com/ca/ca.org2.example.com-cert.pem
registrar:
- enrollId: admin
enrollSecret: adminpw
# [Optional] The optional name of the CA.
caName: ca-org2

View file

@ -0,0 +1,53 @@
---
#
# The network connection profile provides client applications the information about the target
# blockchain network that are necessary for the applications to interact with it. These are all
# knowledge that must be acquired from out-of-band sources. This file provides such a source.
#
name: "balance-transfer-org1"
#
# Any properties with an "x-" prefix will be treated as application-specific, exactly like how naming
# in HTTP headers or swagger properties work. The SDK will simply ignore these fields and leave
# them for the applications to process. This is a mechanism for different components of an application
# to exchange information that are not part of the standard schema described below. In particular,
# the "x-type" property with the "hlfv1" value example below is used by Hyperledger Composer to
# determine the type of Fabric networks (v0.6 vs. v1.0) it needs to work with.
#
x-type: "hlfv1"
#
# Describe what the target network is/does.
#
description: "Balance Transfer Network - client definition for Org1"
#
# Schema version of the content. Used by the SDK to apply the corresponding parsing rules.
#
version: "1.0"
#
# The client section is SDK-specific. The sample below is for the node.js SDK
#
client:
# Which organization does this application instance belong to? The value must be the name of an org
# defined under "organizations"
organization: Org1
# Some SDKs support pluggable KV stores, the properties under "credentialStore"
# are implementation specific
credentialStore:
# [Optional]. Specific to FileKeyValueStore.js or similar implementations in other SDKs. Can be others
# if using an alternative impl. For instance, CouchDBKeyValueStore.js would require an object
# here for properties like url, db name, etc.
path: "./fabric-client-kv-org1"
# [Optional]. Specific to the CryptoSuite implementation. Software-based implementations like
# CryptoSuite_ECDSA_AES.js in node SDK requires a key store. PKCS#11 based implementations does
# not.
cryptoStore:
# Specific to the underlying KeyValueStore that backs the crypto key store.
path: "/tmp/fabric-client-kv-org1"
# [Optional]. Specific to Composer environment
wallet: wallet-name

View file

@ -0,0 +1,53 @@
---
#
# The network connection profile provides client applications the information about the target
# blockchain network that are necessary for the applications to interact with it. These are all
# knowledge that must be acquired from out-of-band sources. This file provides such a source.
#
name: "balance-transfer-org2"
#
# Any properties with an "x-" prefix will be treated as application-specific, exactly like how naming
# in HTTP headers or swagger properties work. The SDK will simply ignore these fields and leave
# them for the applications to process. This is a mechanism for different components of an application
# to exchange information that are not part of the standard schema described below. In particular,
# the "x-type" property with the "hlfv1" value example below is used by Hyperledger Composer to
# determine the type of Fabric networks (v0.6 vs. v1.0) it needs to work with.
#
x-type: "hlfv1"
#
# Describe what the target network is/does.
#
description: "Balance Transfer Network - client definition for Org2"
#
# Schema version of the content. Used by the SDK to apply the corresponding parsing rules.
#
version: "1.0"
#
# The client section is SDK-specific. The sample below is for the node.js SDK
#
client:
# Which organization does this application instance belong to? The value must be the name of an org
# defined under "organizations"
organization: Org2
# Some SDKs support pluggable KV stores, the properties under "credentialStore"
# are implementation specific
credentialStore:
# [Optional]. Specific to FileKeyValueStore.js or similar implementations in other SDKs. Can be others
# if using an alternative impl. For instance, CouchDBKeyValueStore.js would require an object
# here for properties like url, db name, etc.
path: "./fabric-client-kv-org2"
# [Optional]. Specific to the CryptoSuite implementation. Software-based implementations like
# CryptoSuite_ECDSA_AES.js in node SDK requires a key store. PKCS#11 based implementations does
# not.
cryptoStore:
# Specific to the underlying KeyValueStore that backs the crypto key store.
path: "/tmp/fabric-client-kv-org2"
# [Optional]. Specific to Composer environment
wallet: wallet-name

View file

@ -2,13 +2,17 @@ var util = require('util');
var path = require('path');
var hfc = require('fabric-client');
var file = 'network-config%s.json';
var file = 'network-config%s.yaml';
var env = process.env.TARGET_NETWORK;
if (env)
file = util.format(file, '-' + env);
else
file = util.format(file, '');
hfc.addConfigFile(path.join(__dirname, 'app', file));
hfc.addConfigFile(path.join(__dirname, 'config.json'));
// indicate to the application where the setup file is located so it able
// to have the hfc load it to initalize the fabric client instance
hfc.setConfigSetting('network-connection-profile-path',path.join(__dirname, 'app', '../artifacts',file));
hfc.setConfigSetting('Org1-connection-profile-path',path.join(__dirname, 'app', '../artifacts','org1.yaml'));
hfc.setConfigSetting('Org2-connection-profile-path',path.join(__dirname, 'app', '../artifacts','org2.yaml'));
// some other settings the application might need to know
hfc.addConfigFile(path.join(__dirname, 'config.json'));

View file

@ -4,7 +4,6 @@
"jwt_expiretime": "36000",
"channelName":"mychannel",
"CC_SRC_PATH":"../artifacts",
"keyValueStore":"/tmp/fabric-client-kvs",
"eventWaitTime":"30000",
"admins":[
{

2541
balance-transfer/package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -36,8 +36,8 @@ function restartNetwork() {
dkcl
dkrm
#Cleanup the material
rm -rf /tmp/hfc-test-kvs_peerOrg* $HOME/.hfc-key-store/ /tmp/fabric-client-kvs_peerOrg*
#Cleanup the stores
rm -rf ./fabric-client-kv-org*
#Start the network
docker-compose up -d

View file

@ -57,7 +57,7 @@ echo
ORG1_TOKEN=$(curl -s -X POST \
http://localhost:4000/users \
-H "content-type: application/x-www-form-urlencoded" \
-d 'username=Jim&orgName=org1')
-d 'username=Jim&orgName=Org1')
echo $ORG1_TOKEN
ORG1_TOKEN=$(echo $ORG1_TOKEN | jq ".token" | sed "s/\"//g")
echo
@ -68,7 +68,7 @@ echo
ORG2_TOKEN=$(curl -s -X POST \
http://localhost:4000/users \
-H "content-type: application/x-www-form-urlencoded" \
-d 'username=Barry&orgName=org2')
-d 'username=Barry&orgName=Org2')
echo $ORG2_TOKEN
ORG2_TOKEN=$(echo $ORG2_TOKEN | jq ".token" | sed "s/\"//g")
echo
@ -95,7 +95,7 @@ curl -s -X POST \
-H "authorization: Bearer $ORG1_TOKEN" \
-H "content-type: application/json" \
-d '{
"peers": ["peer1","peer2"]
"peers": ["peer0.org1.example.com","peer1.org1.example.com"]
}'
echo
echo
@ -107,7 +107,7 @@ curl -s -X POST \
-H "authorization: Bearer $ORG2_TOKEN" \
-H "content-type: application/json" \
-d '{
"peers": ["peer1","peer2"]
"peers": ["peer0.org2.example.com","peer1.org2.example.com"]
}'
echo
echo
@ -119,7 +119,7 @@ curl -s -X POST \
-H "authorization: Bearer $ORG1_TOKEN" \
-H "content-type: application/json" \
-d "{
\"peers\": [\"peer1\", \"peer2\"],
\"peers\": [\"peer0.org1.example.com\",\"peer1.org1.example.com\"],
\"chaincodeName\":\"mycc\",
\"chaincodePath\":\"$CC_SRC_PATH\",
\"chaincodeType\": \"$LANGUAGE\",
@ -135,7 +135,7 @@ curl -s -X POST \
-H "authorization: Bearer $ORG2_TOKEN" \
-H "content-type: application/json" \
-d "{
\"peers\": [\"peer1\",\"peer2\"],
\"peers\": [\"peer0.org2.example.com\",\"peer1.org2.example.com\"],
\"chaincodeName\":\"mycc\",
\"chaincodePath\":\"$CC_SRC_PATH\",
\"chaincodeType\": \"$LANGUAGE\",
@ -176,7 +176,7 @@ echo
echo "GET query chaincode on peer1 of Org1"
echo
curl -s -X GET \
"http://localhost:4000/channels/mychannel/chaincodes/mycc?peer=peer1&fcn=query&args=%5B%22a%22%5D" \
"http://localhost:4000/channels/mychannel/chaincodes/mycc?peer=peer0.org1.example.com&fcn=query&args=%5B%22a%22%5D" \
-H "authorization: Bearer $ORG1_TOKEN" \
-H "content-type: application/json"
echo
@ -185,7 +185,7 @@ echo
echo "GET query Block by blockNumber"
echo
curl -s -X GET \
"http://localhost:4000/channels/mychannel/blocks/1?peer=peer1" \
"http://localhost:4000/channels/mychannel/blocks/1?peer=peer0.org1.example.com" \
-H "authorization: Bearer $ORG1_TOKEN" \
-H "content-type: application/json"
echo
@ -193,7 +193,7 @@ echo
echo "GET query Transaction by TransactionID"
echo
curl -s -X GET http://localhost:4000/channels/mychannel/transactions/$TRX_ID?peer=peer1 \
curl -s -X GET http://localhost:4000/channels/mychannel/transactions/$TRX_ID?peer=peer0.org1.example.com \
-H "authorization: Bearer $ORG1_TOKEN" \
-H "content-type: application/json"
echo
@ -217,7 +217,7 @@ echo
echo "GET query ChainInfo"
echo
curl -s -X GET \
"http://localhost:4000/channels/mychannel?peer=peer1" \
"http://localhost:4000/channels/mychannel?peer=peer0.org1.example.com" \
-H "authorization: Bearer $ORG1_TOKEN" \
-H "content-type: application/json"
echo
@ -226,7 +226,7 @@ echo
echo "GET query Installed chaincodes"
echo
curl -s -X GET \
"http://localhost:4000/chaincodes?peer=peer1&type=installed" \
"http://localhost:4000/chaincodes?peer=peer0.org1.example.com" \
-H "authorization: Bearer $ORG1_TOKEN" \
-H "content-type: application/json"
echo
@ -235,7 +235,7 @@ echo
echo "GET query Instantiated chaincodes"
echo
curl -s -X GET \
"http://localhost:4000/chaincodes?peer=peer1&type=instantiated" \
"http://localhost:4000/channels/mychannel/chaincodes?peer=peer0.org1.example.com" \
-H "authorization: Bearer $ORG1_TOKEN" \
-H "content-type: application/json"
echo
@ -244,7 +244,7 @@ echo
echo "GET query Channels"
echo
curl -s -X GET \
"http://localhost:4000/channels?peer=peer1" \
"http://localhost:4000/channels?peer=peer0.org1.example.com" \
-H "authorization: Bearer $ORG1_TOKEN" \
-H "content-type: application/json"
echo