您好,登錄后才能下訂單哦!
這篇文章主要為大家展示了“Hyperledger Fabric中通過(guò)SDK和Hyperledger Fabric Blockchain交互的示例分析”,內(nèi)容簡(jiǎn)而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“Hyperledger Fabric中通過(guò)SDK和Hyperledger Fabric Blockchain交互的示例分析”這篇文章吧。
首先看 enroll (登錄) admin 過(guò)程。
'use strict'; /* * Copyright IBM Corp All Rights Reserved * * SPDX-License-Identifier: Apache-2.0 */ /* * Enroll the admin user */ var Fabric_Client = require('fabric-client'); var Fabric_CA_Client = require('fabric-ca-client'); var path = require('path'); var util = require('util'); var os = require('os'); // var fabric_client = new Fabric_Client(); var fabric_ca_client = null; var admin_user = null; var member_user = null; var store_path = path.join(__dirname, 'hfc-key-store'); console.log(' Store path:'+store_path); // create the key value store as defined in the fabric-client/config/default.json 'key-value-store' setting Fabric_Client.newDefaultKeyValueStore({ path: store_path }).then((state_store) => { // assign the store to the fabric client fabric_client.setStateStore(state_store); var crypto_suite = Fabric_Client.newCryptoSuite(); // use the same location for the state store (where the users' certificate are kept) // and the crypto store (where the users' keys are kept) var crypto_store = Fabric_Client.newCryptoKeyStore({path: store_path}); crypto_suite.setCryptoKeyStore(crypto_store); fabric_client.setCryptoSuite(crypto_suite); var tlsOptions = { trustedRoots: [], verify: false }; // be sure to change the http to https when the CA is running TLS enabled fabric_ca_client = new Fabric_CA_Client('http://localhost:7054', tlsOptions , 'ca.example.com', crypto_suite); // first check to see if the admin is already enrolled return fabric_client.getUserContext('admin', true); }).then((user_from_store) => { if (user_from_store && user_from_store.isEnrolled()) { console.log('Successfully loaded admin from persistence'); admin_user = user_from_store; return null; } else { // need to enroll it with CA server return fabric_ca_client.enroll({ enrollmentID: 'admin', enrollmentSecret: 'adminpw' }).then((enrollment) => { console.log('Successfully enrolled admin user "admin"'); return fabric_client.createUser( {username: 'admin', mspid: 'Org1MSP', cryptoContent: { privateKeyPEM: enrollment.key.toBytes(), signedCertPEM: enrollment.certificate } }); }).then((user) => { admin_user = user; return fabric_client.setUserContext(admin_user); }).catch((err) => { console.error('Failed to enroll and persist admin. Error: ' + err.stack ? err.stack : err); throw new Error('Failed to enroll admin'); }); } }).then(() => { console.log('Assigned the admin user to the fabric client ::' + admin_user.toString()); }).catch((err) => { console.error('Failed to enroll admin: ' + err); });
和其他所有程序一樣, 首先需要加載相應(yīng)的lib, 這里加載 fabric-client 和 fabric-ca-client.
var Fabric_Client = require("fabric-client"); var Fabric_CA_Client = require("fabric-ca-client");
然后初始化Fabric_Client 和 Fabric_CA_Client對(duì)象
var fabric_client = new Fabric_Client(); var fabric_ca_client = null; //fabric_ca_client = new Fabric_CA_Client("http://localhost:7054", tlsOption, "ca.example.com", crypto_suite)
同時(shí)需要?jiǎng)?chuàng)建一個(gè)admin_user對(duì)象, 一個(gè)member_user對(duì)象,和一個(gè)目錄對(duì)象用來(lái)存儲(chǔ)用戶持久化信息和證書(shū)信息。
var admin_user = null; var member_user = null; var store_path = path.join(__dirname, "hfc-key-store"); //指定當(dāng)前目錄下的hfc_key_store文件夾
接下來(lái)創(chuàng)建key-value store, 這里調(diào)用Fabric_Client的static方法, 并且根據(jù)fabric-client/config/default.json配置文件中的key-value-store決定實(shí)現(xiàn), 也就是前面說(shuō)的Node SDK的默認(rèn)實(shí)現(xiàn)。
我們看源碼:
Fabric_Client.newDefaultKeyValueStore({path: store_path}) .then((state_store) => { // })...
此方法調(diào)用的是BaseClient.js的接口, 該接口位于 fabric-client/lib/BaseClient.js。
var sdkUtils = require('./utils.js'); static newDefaultKeyValueStore(options) { return sdkUtils.newKeyValueStore(options); }
通過(guò)閱讀源碼發(fā)現(xiàn), 實(shí)際上調(diào)用的是sdkUtils的方法, 該方法實(shí)際上調(diào)用fabric-client/lib/utils.js的 newKeyValueStore方法。
// Provide a Promise-based keyValueStore for couchdb, etc. module.exports.newKeyValueStore = function(options) { // initialize the correct KeyValueStore var kvsEnv = this.getConfigSetting('key-value-store'); var store = require(kvsEnv); return Promise.resolve(new store(options)); };
此處, 程序首先從獲取key-value-store的配置, 然后動(dòng)態(tài)加載該模塊, 然后返回Promise。可以看出, SDK提供了不同的KeyvalueStore實(shí)現(xiàn), 默認(rèn)為FileKeyValueStore實(shí)現(xiàn), fabric-client/config/default.json中指定。
我們看default.json文件
{ ... "key-value-store": "fabric-client/lib/impl/FileKeyValueStore.js", "certificate-authority-client": "fabric-ca-client", "nonce-size" : 24, ... }
在fabric-client/lib/impl下可以看到, SDK提供了2種不同的實(shí)現(xiàn):
FileKeyValueStore , CouchDBKeyValueStore.
我們看FileKeyValueStore的實(shí)現(xiàn)。在FileKeyValueStore的構(gòu)造函數(shù)中, 有這么一段:
// Create the keyValStore instance super(); var self = this; this._dir = options.path; return new Promise(function (resolve, reject) { fs.mkdirs(self._dir, function (err) { if (err) { logger.error('constructor, error creating directory, code: %s' , err.code); return reject(err); } return resolve(self); }); });
這一步執(zhí)行后, 生成上面指定的hfc-key-store目錄。 在看 FileKeyValueStore, 實(shí)際上實(shí)現(xiàn)了 setKey(name, value) 和 getValue(name) 方法。
上面步驟執(zhí)行成功后, 拿到KeyValueStore對(duì)象,然后執(zhí)行一下操作:
// assign the store to the fabric client fabric_client.setStateStore(state_store); var crypto_suite = Fabric_Client.newCryptoSuite(); // use the same location for the state store (where the users' certificate are kept) // and the crypto store (where the users' keys are kept) var crypto_store = Fabric_Client.newCryptoKeyStore({path: store_path}); crypto_suite.setCryptoKeyStore(crypto_store); fabric_client.setCryptoSuite(crypto_suite); var tlsOptions = { trustedRoots: [], verify: false }; // be sure to change the http to https when the CA is running TLS enabled fabric_ca_client = new Fabric_CA_Client('http://localhost:7054', tlsOptions , 'ca.example.com', crypto_suite); // first check to see if the admin is already enrolled return fabric_client.getUserContext('admin', true);
1 生成CrytoKeyStore, 用來(lái)存儲(chǔ)用戶的密鑰和用戶的證書(shū)(狀態(tài))。
var crypto_store = Fabric_Client.newCryptoKeyStore({path: store_path});
這里調(diào)用的是BaseClient.js的方法:
static newCryptoKeyStore(KVSImplClass, opts) { return sdkUtils.newCryptoKeyStore(KVSImplClass, opts); }
這里調(diào)用util.js中的方法
module.exports.newCryptoKeyStore = function(KVSImplClass, opts) { // this function supports skipping any of the arguments such that it can be called in any of the following fashions: // - newCryptoKeyStore(CouchDBKeyValueStore, {name: 'member_db', url: 'http://localhost:5984'}) // - newCryptoKeyStore({path: '/tmp/app-state-store'}) // - newCryptoKeyStore() return new CryptoKeyStore(KVSImplClass, opts); };
2 生成CryptoSuite
var crypto_suite = Fabric_Client.newCryptoSuite(); crypto_suite.setCryptoKeyStore(crypto_store);
3 指定 fabric_client的StateStore 和 CryptoSuite
fabric_client.setStateStore(state_store); fabric_client.setCryptoSuite(crypto_suite);
4 連接到Fabric CA
var tlsOptions = { trustedRoots: [], verify: false }; // be sure to change the http to https when the CA is running TLS enabled fabric_ca_client = new Fabric_CA_Client('http://localhost:7054', tlsOptions , 'ca.example.com', crypto_suite);
5 檢查admin是否enroll
fabric_client.getUserContext('admin', true);
這一步返回一個(gè)User對(duì)象。true用于檢測(cè)是否持久化。
同樣看代碼:
if (user_from_store && user_from_store.isEnrolled()) { console.log('Successfully loaded admin from persistence'); admin_user = user_from_store; return null; } else { // need to enroll it with CA server return fabric_ca_client.enroll({ enrollmentID: 'admin', enrollmentSecret: 'adminpw' }).then((enrollment) => { console.log('Successfully enrolled admin user "admin"'); return fabric_client.createUser( {username: 'admin', mspid: 'Org1MSP', cryptoContent: { privateKeyPEM: enrollment.key.toBytes(), signedCertPEM: enrollment.certificate } }); }).then((user) => { admin_user = user; return fabric_client.setUserContext(admin_user); }).catch((err) => { console.error('Failed to enroll and persist admin. Error: ' + err.stack ? err.stack : err); throw new Error('Failed to enroll admin'); }); }
這里檢測(cè)User對(duì)象是否已經(jīng)reroll, 否則先reroll, 然后register用戶。
1 檢測(cè)用戶狀態(tài)
if (user_from_store && user_from_store.isEnrolled()) { console.log('Successfully loaded admin from persistence'); admin_user = user_from_store; return null; }
這里User的API文檔見(jiàn):Hyperledger Fabric SDK for node.js Class: User 。
如果檢測(cè)到用戶已經(jīng)reroll, 則說(shuō)明當(dāng)前用戶已經(jīng)reroll, 并且證書(shū)有效, 可以使用此證書(shū)進(jìn)行后續(xù)操作, 否則需要注冊(cè)用戶。
2 reroll
return fabric_ca_client.enroll({ enrollmentID: 'admin', enrollmentSecret: 'adminpw' }).then((enrollment) => { // });
此處的admin用戶為配置文件中的啟動(dòng)用戶,或者說(shuō)是引導(dǎo)用戶身份?;蛘邞?yīng)該是注冊(cè)的具有相關(guān)權(quán)限的用戶。
這一步執(zhí)行后, 在hfc-key-store目錄下產(chǎn)生af37da4c94057cd98f288a671703d346c7a79a79acd28ea8de7bf03cf04baf36-priv 文件, 內(nèi)容為:
ThinkPad-L430:/opt/fabric-samples/fabcar$ ls hfc-key-store/ af37da4c94057cd98f288a671703d346c7a79a79acd28ea8de7bf03cf04baf36-priv ThinkPad-L430:/opt/fabric-samples/fabcar$ cat hfc-key-store/af37da4c94057cd98f288a671703d346c7a79a79acd28ea8de7bf03cf04baf36-priv -----BEGIN PRIVATE KEY----- MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgBqYfrwZerZFT2MU4 Dl5uyQxX2KyPzFu0ZUN14NDlMBuhRANCAARgBxgXvWsvWIPoxA8R1G+2A2D6YGtE NmE2ZTAeNXHJ+fWzitjOLrwaHKwl42/9sXfAaQP3WWYcEdSKicNrXTH3 -----END PRIVATE KEY-----
并且返回的enrollment對(duì)象內(nèi)容為:
{ key: ECDSA_KEY { _key: { type: 'EC', isPrivate: true, isPublic: false, getBigRandom: [Function], setNamedCurve: [Function], setPrivateKeyHex: [Function], setPublicKeyHex: [Function], getPublicKeyXYHex: [Function], getShortNISTPCurveName: [Function], generateKeyPairHex: [Function], signWithMessageHash: [Function], signHex: [Function], sign: [Function], verifyWithMessageHash: [Function], verifyHex: [Function], verify: [Function], verifyRaw: [Function], serializeSig: [Function], parseSig: [Function], parseSigCompact: [Function], readPKCS5PrvKeyHex: [Function], readPKCS8PrvKeyHex: [Function], readPKCS8PubKeyHex: [Function], readCertPubKeyHex: [Function], curveName: 'secp256r1', ecparams: [Object], prvKeyHex: '06a61faf065ead9153d8c5380e5e6ec90c57d8ac8fcc5bb4654375e0d0e5301b', pubKeyHex: '0460071817bd6b2f5883e8c40f11d46fb60360fa606b4436613665301e3571c9f9f5b38ad8ce2ebc1a1cac25e36ffdb177c06903f759661c11d48a89c36b5d31f7' } }, certificate: '-----BEGIN CERTIFICATE-----\nMIIB6jCCAZGgAwIBAgIUbwp/ziKtelTXH+F+t+KUPUp2H6gwCgYIKoZIzj0EAwIw\naDELMAkGA1UEBhMCVVMxFzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMRQwEgYDVQQK\nEwtIeXBlcmxlZGdlcjEPMA0GA1UECxMGRmFicmljMRkwFwYDVQQDExBmYWJyaWMt\nY2Etc2VydmVyMB4XDTE4MDcxMzAyMTYwMFoXDTE5MDcxMzAyMjEwMFowITEPMA0G\nA1UECxMGY2xpZW50MQ4wDAYDVQQDEwVhZG1pbjBZMBMGByqGSM49AgEGCCqGSM49\nAwEHA0IABGAHGBe9ay9Yg+jEDxHUb7YDYPpga0Q2YTZlMB41ccn59bOK2M4uvBoc\nrCXjb/2xd8BpA/dZZhwR1IqJw2tdMfejYDBeMA4GA1UdDwEB/wQEAwIHgDAMBgNV\nHRMBAf8EAjAAMB0GA1UdDgQWBBSVRkLelRKZo4YdwGsdCouXu4KkzjAfBgNVHSME\nGDAWgBSh2y67zVpnp1sh4kHj2x4mD5Rx4zAKBggqhkjOPQQDAgNHADBEAiAU3UEg\nx4q+vkWJRKjzXgzvZWUhAaAbHihFfjHmBmqKUQIgXDZfiLVVHkfOTIBoAIvTp2Ek\n8KVd0T9j8mlU7Sj3T7k=\n-----END CERTIFICATE-----\n', rootCertificate: '-----BEGIN CERTIFICATE-----\nMIICFzCCAb2gAwIBAgIUdjYbUaxnBoP/JrvomKxCZuwVeDQwCgYIKoZIzj0EAwIw\naDELMAkGA1UEBhMCVVMxFzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMRQwEgYDVQQK\nEwtIeXBlcmxlZGdlcjEPMA0GA1UECxMGRmFicmljMRkwFwYDVQQDExBmYWJyaWMt\nY2Etc2VydmVyMB4XDTE4MDcxMDA2NTQwMFoXDTMzMDcwNjA2NTQwMFowaDELMAkG\nA1UEBhMCVVMxFzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMRQwEgYDVQQKEwtIeXBl\ncmxlZGdlcjEPMA0GA1UECxMGRmFicmljMRkwFwYDVQQDExBmYWJyaWMtY2Etc2Vy\ndmVyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAESzbX2rdDUJWHu+K0C91A1Ukh\np/AIhEUp6J5SrxqrLJIh8bEv8Kv722Yj05qvVwFNi/0iRoCCNBM7XNMrpwqkEKNF\nMEMwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwHQYDVR0OBBYE\nFKHXLrvNWmenWyHeQePbHiYPlHHjMAoGCCqGSM49BAMCA0gAMEUCIQCoCz/1dpIt\nGYozrxTcBrgsEfGCkkN9JsSr5BtSGPoCMQIgbVBTgXyPGOBf4jk2Mo9DK4zZIrkF\n56GY03W/ZiZY6Zg=\n-----END CERTIFICATE-----\n' }
3 register
fabric_client.createUser( {username: 'admin', mspid: 'Org1MSP', cryptoContent: { privateKeyPEM: enrollment.key.toBytes(), signedCertPEM: enrollment.certificate } }); }).then((user) => { // });
執(zhí)行結(jié)果:
ThinkPad-L430:/opt/fabric-samples/fabcar$ ls hfc-key-store/ 2124ac635ac52a4c5d13c32812768ebe6837ae288bfa351c3712b9160f502214-priv admin 2124ac635ac52a4c5d13c32812768ebe6837ae288bfa351c3712b9160f502214-pub ThinkPad-L430:/opt/fabric-samples/fabcar$ cat hfc-key-store/2124ac635ac52a4c5d13c32812768ebe6837ae288bfa351c3712b9160f502214-pub -----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEnUNKr708UFaMWRHbdfcM8oTW130U H/u7X3tH+/88RQR5O8sA5EyKsMMi5OgrhwQkRbYZ8FUIiZuHRZUxL9as1w== -----END PUBLIC KEY----- ThinkPad-L430:/opt/fabric-samples/fabcar$ cat hfc-key-store/admin {"name":"admin","mspid":"Org1MSP","roles":null,"affiliation":"","enrollmentSecret":"","enrollment":{"signingIdentity":"2124ac635ac52a4c5d13c32812768ebe6837ae288bfa351c3712b9160f502214","identity":{"certificate":"-----BEGIN CERTIFICATE-----\nMIIB6zCCAZGgAwIBAgIUMR8qzOAWUEfAzYlvCzQ4yTL7AHAwCgYIKoZIzj0EAwIw\naDELMAkGA1UEBhMCVVMxFzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMRQwEgYDVQQK\nEwtIeXBlcmxlZGdlcjEPMA0GA1UECxMGRmFicmljMRkwFwYDVQQDExBmYWJyaWMt\nY2Etc2VydmVyMB4XDTE4MDcxMzAyMjUwMFoXDTE5MDcxMzAyMzAwMFowITEPMA0G\nA1UECxMGY2xpZW50MQ4wDAYDVQQDEwVhZG1pbjBZMBMGByqGSM49AgEGCCqGSM49\nAwEHA0IABJ1DSq+9PFBWjFkR23X3DPKE1td9FB/7u197R/v/PEUEeTvLAORMirDD\nIuToK4cEJEW2GfBVCImbh0WVMS/WrNejYDBeMA4GA1UdDwEB/wQEAwIHgDAMBgNV\nHRMBAf8EAjAAMB0GA1UdDgQWBBSvDlI5ax6zbDAGj3wq+4N9EF8iwDAfBgNVHSME\nGDAWgBSh2y67zVpnp1sh4kHj2x4mD5Rx4zAKBggqhkjOPQQDAgNIADBFAiEAgzdL\n6GWqvEtD03uushzYHzPUkTf+CdSISutr1hCQunkCIBY+LlllnXtW5iFnEcktP5RH\nnPmYhhiKe9DqeDw3H3ku\n-----END CERTIFICATE-----\n"}}}
這一步執(zhí)行成功后, 需要設(shè)置fabric_client中的當(dāng)前用戶。
fabric_client.setUserContext(admin_user);
此刻, reroll整個(gè)過(guò)程完成。
以上是“Hyperledger Fabric中通過(guò)SDK和Hyperledger Fabric Blockchain交互的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。