fabric node sdk 简单使用

一.架构设计

sdk在fabric中扮演的角色:

  • 通过节点的gRPC协议访问安装在peer节点上的链码
  • 将peer返回的背书,封装成交易,发送给orderer,作排序

    分为以下三大模块:
  • fabric-ca-client
  • fabric-client
  • fabric-network

fabric-ca-client

与fabric-ca 模块交互,主要负责证书管理,如向ca申请证书


fabric-client

负责与fabric网络交互,如发送提案,发送交易监听区块等,试用场景偏向与特殊业务定制


69ea5156.png

fabric-network

负责与fabric网络交互,如发送交易,监听区块等,是fabric-client的封装,适用场景偏向普通业务直接集成.


4afa9abe.png

二.怎么使用?

2. 1 环境搭建

  • 依赖环境 node 8.9-9.0
  • 包管理 yarn 1.6.0 or npm 5.5+
  • 部署fabric网络

2.2 fabric-ca-client的使用

  • admin登录
// 创建ca
let ca = new FabricCAServices('https://localhost:7054', tlsOptions , 'ca-org1', crypto_suite);
// 登录
let enrollment= await ca.enroll({enrollmentID: 'admin',enrollmentSecret: 'adminpw'})
  • 注册用户并登录
// 创建ca
let ca = new FabricCAServices('https://localhost:7054', tlsOptions , 'ca-org1', crypto_suite);
// 注册用户
let secret = awit fabric_ca_client.register({enrollmentID: 'user1', affiliation: 'org1.department1',role: 'client'}, admin_user);
// 用户登录
let enrollment = await fabric_ca_client.enroll({enrollmentID: 'user1', enrollmentSecret: secret});

2.3 fabric-client的简单使用(invoke交易)

  • 创建身份标识
let client = new Client
let keyPem = fs.readFileSync('.msp/keystore/user-key.pem','utf-8')
let certPem = fs.readFileSync('./msp/signcerts/user-cert.pem','utf-8')
let user = await client.createUser({        //创建User对象
  username: 'user',                         //用户名称
  mspid: 'Org1MSP',                       //所属MSP的ID
  cryptoContent: {
    privateKeyPEM: keyPem,                  //用户私钥
    signedCertPEM: certPem                  //用户证书
  },
  skipPersistence: true                     //不计入缓存
})
client.setUserContext(user,true)            //设置为client的当前身份
  • 创建通道对象,并添加peer与orderer
let channel = client.newChannel('mychannel')
channel.addPeer(client.newPeer('grpc://127.0.0.1:7051'))
channel.addOrderer(client.newOrderer('grpc://127.0.0.1:7050'))
  • 发送invoke交易
// 构建请求参数
let req = {
  chaincodeId: 'mycc',
  fcn: 'invoke',
  args: ['10'],
  txId: client.newTransactionID() // 创建交易id
}
// 获取背书
let prsp = await channel.sendTransactionProposal(req) 
// 提交交易
let rsp = await channel.sendTransaction({
  proposalResponses: prsp[0],
  proposal: prsp[1]
})

2.4 fabric-network 使用(invoke交易)

  • 创建wallet(存着身份标识)
const wallet = new FileSystemWallet(walletPath);
  • 创建 Gateway 并连接fabric网络
 const gateway = new Gateway();
// 启用了发现服务
await gateway.connect(ccpPath, { wallet, identity: 'user1', discovery: { enabled: true, asLocalhost: false } });
  • 获取智能合约部署的channel网络
const network = await gateway.getNetwork('mychannel');
  • 获取智能合约对象
const contract = network.getContract('fabcar');
  • 发送invoke交易
 await contract.submitTransaction('changeCarOwner', 'CAR10', 'Honda')
  • 发送privatedata交易
const result = await contract.createTransaction(transactionName)
.setTransient(privateData)
.submit(arg1, arg2);

2.5 具体详细案例

hyperledger/fabric-samples/fabcar

三.常用接口说明

fabric-ca-client模块

FabricCAServices

  • enroll(req) 登记用户
  • register(req, registrar) 注册用户

fabric-client模块

User

  • getName() 获取成员名称
  • getRolse() 获取角色
  • setRolse() 设置角色
  • getIdentity() 获取身份对象,身份对被用用于验签
  • getSigningIdentity() 获取SigningIdentity对象,SigningIdentity被用于生成签名
  • getCryptoSuite() 获取加密套件
  • setCryptoSuite(cryptoSuite) 设置加密套件
  • setEnrollment(privateKey, certificate, mspId, skipPersistence) 设置登记内容

输入参数:

参数名称 参数类型 描述
privateKey api.Key 私钥对象
certificate string 证书内容 PEM-encoded
mspId string 成员服务,提供的身份id
skipPersistence boolean 是否缓存
  • isEnrolled() 是否已经登录了

TransactionID

  • getTransactionID 获取交易id(string类型)
  • getNonce 获取随机数
  • isAdmin 是否被admin生成

Peer

  • sendProposal(proposal, timeout) 发送提案

输入参数:

参数名称 参数类型 描述
proposal Proposal 提案
timeout Number 超时时间
  • sendDiscovery(request,timeout) 发送服务发现请求

输入参数:

参数名称 参数类型 描述
request SignedRequest 请求
timeout Number 超时时间

Orderer

  • sendBroadcast(envelope, timeout) 向oderder服务发送广播消息

输入参数:

参数名称 参数类型 描述
envelope byte[] 数据(common.Envelope protobuf数据)
timeout Number 超时时间
  • sendDeliver(envelope) 向oderder服务发送传递消息

Channel

  • initialize(request) 初始化
  • close() 关闭所有连接
  • getName() 获取通道名称
  • getDiscoveryResults() 获取发现服务结果
  • getEndorsementPlan() 获取背书计划
  • getOrganizations() 从通道中获取组织id
  • addPeer(peer, mspid, roles, replace) 添加peer节点

输入参数:

参数名称 参数类型 描述
peer Peer peer节点对象
mspid string 组织id
roles ChannelPeerRoles 角色
replace Boolean 如果存在相同名称的peer,替换
  • removePeer(peer) 移除peer节点对象
  • getPeer(name) 获取peer节点对象
  • addOrderer(orderer,replace) 添加orderer节点对象

输入参数:

参数名称 参数类型 描述
orderer Orderer peer节点对象
replace Boolean 如果存在相同名称的orderer,替换
  • removeOrderer(orderer) 移除orderer 对象
  • getOrderer(name) 获取oderder对象
  • newChannelEventHub(peer) 创建ChannelEventHub对象
  • getGenesisBlock(request) 获取创世快
  • joinChannel(request, timeout) 加入channel
  • queryBlockByTxID(tx_id, target, useAdmin, skipDecode) 查询区块
  • queryBlockByHash(blockHash, target, useAdmin, skipDecode) 查询区块
  • queryTransaction() 查询交易
  • queryInstantiatedChaincodes(target, useAdmin) 查询这个通道实例化的链码
  • sendInstantiateProposal(request, timeout) 发送实例化chaincode的提案
  • sendUpgradeProposal(request, timeout) 发送升级chaincode提案
  • sendTransactionProposal(request, timeout) 发送交易提案
  • sendTransaction(request, timeout) 发送交易
  • generateUnsignedProposal(request, mspId, certificate, admin) 生成没有签名的proposal

输入参数:

参数名称 参数类型 描述
request ProposalRequest 交易请求
mspId string 成员身份
certificate string 证书
admin boolean 是否使用admin
  • sendSignedProposal(request, timeout) 发送签名的提案
  • generateUnsignedTransaction(request) 生成没有签名交易
  • sendSignedTransaction(request, timeout) 发送签名的交易
  • queryByChaincode(request, useAdmin) 查询

输入参数:

参数名称 参数类型 描述
request ChaincodeQueryRequest 交易请求
admin boolean 是否使用admin

eg:

const responsePayloads = await channel.queryByChaincode(request);
for (let i = 0; i < responsePayloads.length; i++) {
  console.log(util.format('Query result from peer [%s]: %s', i, responsePayloads[i].toString('utf8')));

Client

  • createChannel(request) 创建channel对象
  • createUser(opts) 创建user对象
  • getClientCertHash(create) 获取客户端证书hash
  • getMspid() 获取成员id
  • newTransactionID(admin) 创建TransactionID对象
  • createChannel(request) 发送创建channel交易
  • installChaincode(request, timeout) 发送安装chaincode交易
  • newChannel(name) 新建channel对象
  • newOrderer(url, opts) 创建oderer对象
  • newPeer(url, opts) 创建peer对象
  • queryChannels(peer, useAdmin) 查询peer节点上的所有通道
  • queryInstalledChaincodes(peer, useAdmin) 查询peer上安装的所有链码
  • setUserContext(user, skipPersistence) 设置当前所有user
  • updateChannel(request) 更新通道交易

fabric-network模块

Gateway

  • connect(config, options) 使用连接配置文件或预构建的客户端实例连接到Gateway

输入参数:

参数名称 参数类型 描述
config string,object,Client 配置
options GatewayOptions 选项

eg:

const gateway = new Gateway();
const wallet = new FileSystemWallet('./WALLETS/wallet');
const ccpFile = fs.readFileSync('./network.json');
const ccp = JSON.parse(ccpFile.toString());
await gateway.connect(ccp, {
  identity: 'admin',
   wallet: wallet
});
  • disconnect() 清理并关闭连接
  • getCurrentIdentity() 获取当前身份
  • getClient() 获取Client
  • getNetwork(networkName) 获取network对象

输入参数:

参数名称 参数类型 描述
networkName string channel名称

Network

  • getChannel() 获取network的底层通道对象
  • getContract(chaincodeId, name = '') 获取合约对象

输入参数:

参数名称 参数类型 描述
chaincodeId string 链码的标识
name string 合约的名称
  • getEventHubManager() 获取eventhub管理器
  • getEventHubSelectionStrategy() 获取eventhub选择策略
  • addBlockListener(listenerName, callback, options)创建一个区块监听者

输入参数:

参数名称 参数类型 描述
name string 名称
callback function 回调函数 (error,block)
options object 选项
  • addCommitListener(transactionId, callback, options, eventHub) 创建一个交易提交事件监听

输入参数:

参数名称 参数类型 描述
transactionId string 交易id
callback function 回调函数 (parameters)
options RegistrationOptions 选项 ,可选
eventHub ChannelEventHub 事件,可以选

Contract

  • createTransactionID 创建交易id对象
  • getChaincodeId() 获取链码id
  • submitTransaction(name, ...args) 提交交易

输入参数:

参数名称 参数类型 描述
name string 函数名称
args ...string 函数的参数

eg:

contract.submitTransaction('changeCarOwner', 'CAR10', 'Honda')
  • evaluateTransaction(name, ...args) 查询交易
  • createTransaction(name) 创建Transaction对象

Transaction

  • getName() 获取交易名称
  • getTransactionID() 获取交易id(fabric-client.TransactionID)对象
  • setTransient(transientMap) 设置将传递交易函的,数据但不会记在分类帐上。
  • submit(...args) 提交交易
  • evaluate(...args) 查询交易
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,752评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,100评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,244评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,099评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,210评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,307评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,346评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,133评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,546评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,849评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,019评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,702评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,331评论 3 319
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,030评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,260评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,871评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,898评论 2 351

推荐阅读更多精彩内容