Reputation: 1587
I am using Hyperledger fabric 1.4.1 and the latest versions of fabric-contract-api for the smart contracts, fabric-client
for the low level APIs to manage channel creation and chaincodes, and fabric-network
for interaction with the peers. I have referred to this sample for setting up my network.
I have written a basic chaincode package in nodejs
and setup a simple 1 org, 1 peer, 1 orderer network. The first step is to connect to the peer node and use the fabric-ca-client
to create the admin identity. As per examples the enrollment id and secret used is admin
, adminpw
. This is dependent on the configuration used here.
The code I use to create and join a channel, followed by installing and instantiating a chaincode is
const CAClient = require('fabric-ca-client');
const client = require('fabric-client');
const User = client.User;
const fs = require('fs');
const path = require('path');
const basePath = path.resolve(__dirname, '../certs');
const readCryptoFile = filename => fs.readFileSync(path.resolve(basePath, filename)).toString();
const ccPath = path.resolve(__dirname, '../chaincode/src/ax-chaincode');
const url = require('url');
const http = require('http');
let myClient = new client();
const ordererConfig = {
hostname: 'orderer0',
url: 'grpc://localhost:7050',
pem: readCryptoFile('ordererOrg.pem')
};
const orderer = myClient.newOrderer(ordererConfig.url, {
pem: ordererConfig.pem,
'ssl-target-name-override': ordererConfig.hostname
});
let peerConfig = {
hostname: 'ax-peer',
url: 'grpc://localhost:7051', // change to grpcs://ax-peer:7051 in some condition (no idea?)
eventHubUrl: 'grpc://localhost:7053',
pem: readCryptoFile('axOrg.pem')
};
const defaultPeer = myClient.newPeer(peerConfig.url, {
pem: peerConfig.pem,
'ssl-target-name-override': peerConfig.hostname
});
// console.log(defaultPeer);
myClient.setStateStore(await client.newDefaultKeyValueStore({
path: './ax-peer'
}))
let url = 'http://localhost:7054'
const ca = new CAClient(url, {
verify: false
});
let enrollmentID = 'admin';
let enrollmentSecret = 'adminpw';
const enrollment = await ca.enroll({
enrollmentID: 'admin',
enrollmentSecret: 'adminpw'
});
user = new User(enrollmentID, myClient);
// console.log(enrollment);
await user.setEnrollment(enrollment.key, enrollment.certificate, 'AxOrgMSP');
The above will check if admin
user is available in the state store. Some queries regarding the above process
cryptogen
for each peer is used (code below)attrs
are passed along in ca.enroll()
, so naturally when querying the identity roles
field returns null. The ca-server
link shared clearly assigns roles of client, user, peer, validator, auditor
to it. Shouldn't that reflect here since it uses admin
and adminpw
for enrolling id and secret?Continuing the code
// crypto material got from cryptogen and shifted to new folder
let adminUser = await myClient.createUser({
username: `Admin@ax-peer`,
mspid: 'AxOrgMSP',
cryptoContent: {
privateKeyPEM: readCryptoFile('[email protected]'),
signedCertPEM: readCryptoFile('[email protected]')
}
});
let txId = myClient.newTransactionID();
let envelope_bytes = fs.readFileSync('./channel.tx');
let channelConfig = myClient.extractChannelConfig(envelope_bytes);
let signature = myClient.signChannelConfig(channelConfig);
const request = {
name: 'default',
orderer: orderer,
config: channelConfig,
signatures: [signature],
txId: txId
};
const response = await myClient.createChannel(request); // should be 200
// rest of code joins channel, installs and instantiates chaincode
// docker logs show init function being called in new cc container
The stateStore
has two files in it (as expected), called admin
and Admin@ax-peer
. These look like
"name": "Admin@ax-peer",
"mspid": "AxOrgMSP",
"roles": null,
"affiliation": "",
"enrollmentSecret": "",
enrollment: {
"signingIdentity": "554a5f5cfc5a59231a04b7b051bcbcb4f79c4226ff336a4aa48b551de4a8428f",
"certificate": "-----BEGIN CERTIFICATE----- xyz -----END CERTIFICATE-----"
}
When this user is used from the state store by await myClient.getUserContext('admin', true);
, how does the client sign the transactions? I am unable to locate the private key/ cert for any user created using the fabric-client
SDK.
Now If I use fabric-network
API, a FileSystemWallet()
function is implemented that stores the private and public cert for each user made by it.
const enrollment = await ca.enroll({ enrollmentID: `admin`, enrollmentSecret: `adminpw` });
const identity = X509WalletMixin.createIdentity('AxOrgMSP', enrollment.certificate, enrollment.key.toBytes());
wallet.import('admin', identity);
This function serves the same purpose as the ca.enroll()
but stores the private cert in a visible manner. If I want to use the users created by fabric-client
in the fabric-network
SDK, I would need to shift the certificates, how do I achieve this?
TLDR - Register user using fabric-client
and then use Gateway()
class from fabric-network
to submit transactions with the same user.
Any advice, guidance is much appreciated. Thanks!
Upvotes: 2
Views: 2102
Reputation: 5868
There are too many questions in this stack overflow, so all I will give is some insight into what you have posted.
My recommendation is to start everything with a fabric-network gateway if you can. Then if you need to drop to the lower level api's because the fabric-network doesn't do what you need then you can call
gateway.getClient()
or
network.getChannel()
to get a client/channel that has been pre-configured with the gateway configuration and identity.
To get access to a Certificate Authority you can use
gateway.getClient().getCertificateAuthority()
All of this allows you to use the wallet implementation for identity management (and the wallet implementation provides different persistence mechanisms such as in memory, file system, couchdb or you can write your own)
Upvotes: 4