Hyperledger Fabric 1.0 从零开始——fabric-sdk-java应用(1)

Hyperledger Fabric 1.0 从零开始(十)——智能合约

Hyperledger Fabric 1.0 从零开始(十一)——CouchDB

上述两章,最近网上各路大神文章云集,方案多多,因为最近工作太忙太忙,我暂时就先不赘述了,可以优先参考深蓝大大的文章HyperLedger Fabric ChainCode开发——shim.ChaincodeStubInterface用法。

这章先捡大家都比较在意的java sdk应用方案贴出来,很多朋友都找我要过,我主要是把注释都写进去了,用法简单了说了下,一般情况下会java开发的都能看懂。

年前实在太忙。

JAVA-SDK9.1、基本介绍

官方在Fabric1.0之后就推荐使用SDK来实现交互的操作,原本在0.6上的restapi已经被废弃。JAVA-SDK可以参考github。官方给的SDK的DEMO很难入手,注释稀少内容还很杂,所幸感谢github上有位朋友(具体地址实在是找不到了,以后会补上)稍加整理了一下,直接重写了官方的DEMO,让像我这样的新人更容易入手。

本次在官方SDK和大神重新的DEMO的基础上做了一次整理,能够更加清晰简单的入门并使用JAVA-SDK来进行交互。

9.2、架构

相信看到这里的朋友应该都对Fabric已经有了足够的了解,至少是应用层上已经可以实现分布式账本的各项功能,sdk也是在这样的基础进行讲述。

首先看下针对JAVA-SDK所写的辅助工程目录

关于Fabric,我们知道一个channel中可以创建多个chaincode,而一个chaincode需要指定对应orderer和peer。

所以,在此建立了一个bean目录来存放自定义的chaincode、orderer和peer对象。这几个对象都包含各自最基本的访问属性。

具体对应关系如下:

bean.Chaincode - Fabric创建的chaincode信息,涵盖所属channel等信息

bean.Orderers - Fabric创建的orderer信息,涵盖单机和集群两种方案

bean.Peers - Fabric创建的peer信息,包含有cli、org、ca、couchdb等节点服务器关联启动服务信息集合

ChaincodeManager -智能合约操作总控制器

FabricConfig -智能合约操作总参数配置器

FabricOrg -联盟组织对象

FabricUser -联盟用户对象

FabricStore -联盟存储配置对象

9.3、具体实现

直接通过代码来看实现

9.3.1、Chaincode代码

1packagecn.aberic.fabric.bean;23/**4* Fabric创建的chaincode信息,涵盖所属channel等信息5*6*@authoraberic7*8* @date 2017年10月18日 - 下午2:07:429* @email abericyang@gmail.com10*/11publicclassChaincode {1213/**当前将要访问的智能合约所属频道名称*/14privateString channelName;//ffetest15/**智能合约名称*/16privateString chaincodeName;//ffetestcc17/**智能合约安装路径*/18privateString chaincodePath;//github.com/hyperledger/fabric/xxx/chaincode/go/example/test19/**智能合约版本号*/20privateString chaincodeVersion;//1.021/**执行智能合约操作等待时间*/22privateintinvokeWatiTime = 100000;23/**执行智能合约实例等待时间*/24privateintdeployWatiTime = 120000;2526publicString getChannelName() {27returnchannelName;28}2930publicvoidsetChannelName(String channelName) {31this.channelName =channelName;32}3334publicString getChaincodeName() {35returnchaincodeName;36}3738publicvoidsetChaincodeName(String chaincodeName) {39this.chaincodeName =chaincodeName;40}4142publicString getChaincodePath() {43returnchaincodePath;44}4546publicvoidsetChaincodePath(String chaincodePath) {47this.chaincodePath =chaincodePath;48}4950publicString getChaincodeVersion() {51returnchaincodeVersion;52}5354publicvoidsetChaincodeVersion(String chaincodeVersion) {55this.chaincodeVersion =chaincodeVersion;56}5758publicintgetInvokeWatiTime() {59returninvokeWatiTime;60}6162publicvoidsetInvokeWatiTime(intinvokeWatiTime) {63this.invokeWatiTime =invokeWatiTime;64}6566publicintgetDeployWatiTime() {67returndeployWatiTime;68}6970publicvoidsetDeployWatiTime(intdeployWatiTime) {71this.deployWatiTime =deployWatiTime;72}7374}

9.3.2、Orderers代码

1packagecn.aberic.fabric.bean;23importjava.util.ArrayList;4importjava.util.List;56/**7* Fabric创建的orderer信息,涵盖单机和集群两种方案8*9*@authoraberic10*11* @date 2017年10月18日 - 下午1:56:4812* @email abericyang@gmail.com13*/14publicclassOrderers {1516/**orderer 排序服务器所在根域名*/17privateString ordererDomainName;//anti-moth.com18/**orderer 排序服务器集合*/19privateListorderers;2021publicOrderers() {22orderers =newArrayList();23}2425publicString getOrdererDomainName() {26returnordererDomainName;27}2829publicvoidsetOrdererDomainName(String ordererDomainName) {30this.ordererDomainName =ordererDomainName;31}3233/**新增排序服务器*/34publicvoidaddOrderer(String name, String location) {35orderers.add(newOrderer(name, location));36}3738/**获取排序服务器集合*/39publicListget() {40returnorderers;41}4243/**44* 排序服务器对象45*46*@authoraberic47*48* @date 2017年10月18日 - 下午2:06:2249* @email abericyang@gmail.com50*/51publicclassOrderer {5253/**orderer 排序服务器的域名*/54privateString ordererName;55/**orderer 排序服务器的访问地址*/56privateString ordererLocation;5758publicOrderer(String ordererName, String ordererLocation) {59super();60this.ordererName =ordererName;61this.ordererLocation =ordererLocation;62}6364publicString getOrdererName() {65returnordererName;66}6768publicvoidsetOrdererName(String ordererName) {69this.ordererName =ordererName;70}7172publicString getOrdererLocation() {73returnordererLocation;74}7576publicvoidsetOrdererLocation(String ordererLocation) {77this.ordererLocation =ordererLocation;78}7980}8182}

9.3.3、Peers代码

1packagecn.aberic.fabric.bean;23importjava.util.ArrayList;4importjava.util.List;56/**7* Fabric创建的peer信息,包含有cli、org、ca、couchdb等节点服务器关联启动服务信息集合8*9*@authoraberic10*11* @date 2017年10月18日 - 下午1:49:0312* @email abericyang@gmail.com13*/14publicclassPeers {1516/**当前指定的组织名称*/17privateString orgName;//Org118/**当前指定的组织名称*/19privateString orgMSPID;//Org1MSP20/**当前指定的组织所在根域名*/21privateString orgDomainName;//org1.example.com22/**orderer 排序服务器集合*/23privateList

peers;2425publicPeers() {26peers =newArrayList();27}2829publicString getOrgName() {30returnorgName;31}3233publicvoidsetOrgName(String orgName) {34this.orgName =orgName;35}3637publicString getOrgMSPID() {38returnorgMSPID;39}4041publicvoidsetOrgMSPID(String orgMSPID) {42this.orgMSPID =orgMSPID;43}4445publicString getOrgDomainName() {46returnorgDomainName;47}4849publicvoidsetOrgDomainName(String orgDomainName) {50this.orgDomainName =orgDomainName;51}5253/**新增排序服务器*/54publicvoidaddPeer(String peerName, String peerEventHubName, String peerLocation, String peerEventHubLocation, String caLocation) {55peers.add(newPeer(peerName, peerEventHubName, peerLocation, peerEventHubLocation, caLocation));56}5758/**获取排序服务器集合*/59publicList

get() {60returnpeers;61}6263/**64* 节点服务器对象65*66*@authoraberic67*68* @date 2017年11月11日 - 下午6:56:1469* @email abericyang@gmail.com70*/71publicclassPeer {7273/**当前指定的组织节点域名*/74privateString peerName;//peer0.org1.example.com75/**当前指定的组织节点事件域名*/76privateString peerEventHubName;//peer0.org1.example.com77/**当前指定的组织节点访问地址*/78privateString peerLocation;//grpc://110.131.116.21:705179/**当前指定的组织节点事件监听访问地址*/80privateString peerEventHubLocation;//grpc://110.131.116.21:705381/**当前指定的组织节点ca访问地址*/82privateString caLocation;//http://110.131.116.21:705483/**当前peer是否增加Event事件处理*/84privatebooleanaddEventHub =false;8586publicPeer(String peerName, String peerEventHubName, String peerLocation, String peerEventHubLocation, String caLocation) {87this.peerName =peerName;88this.peerEventHubName =peerEventHubName;89this.peerLocation =peerLocation;90this.peerEventHubLocation =peerEventHubLocation;91this.caLocation =caLocation;92}9394publicString getPeerName() {95returnpeerName;96}9798publicvoidsetPeerName(String peerName) {99this.peerName =peerName;100}101102publicString getPeerEventHubName() {103returnpeerEventHubName;104}105106publicvoidsetPeerEventHubName(String peerEventHubName) {107this.peerEventHubName =peerEventHubName;108}109110publicString getPeerLocation() {111returnpeerLocation;112}113114publicvoidsetPeerLocation(String peerLocation) {115this.peerLocation =peerLocation;116}117118publicString getPeerEventHubLocation() {119returnpeerEventHubLocation;120}121122publicvoidsetPeerEventHubLocation(String eventHubLocation) {123this.peerEventHubLocation =eventHubLocation;124}125126publicString getCaLocation() {127returncaLocation;128}129130publicvoidsetCaLocation(String caLocation) {131this.caLocation =caLocation;132}133134publicbooleanisAddEventHub() {135returnaddEventHub;136}137138publicvoidaddEventHub(booleanaddEventHub) {139this.addEventHub =addEventHub;140}141142}143144}

9.3.4、FabricUser代码

1packagecn.aberic.fabric;23importjava.io.ByteArrayInputStream;4importjava.io.ByteArrayOutputStream;5importjava.io.IOException;6importjava.io.ObjectInputStream;7importjava.io.ObjectOutputStream;8importjava.io.Serializable;9importjava.util.Set;1011importorg.bouncycastle.util.encoders.Hex;12importorg.hyperledger.fabric.sdk.Enrollment;13importorg.hyperledger.fabric.sdk.User;1415importio.netty.util.internal.StringUtil;1617/**18* 联盟用户对象19*20*@authoraberic21*22* @date 2017年9月7日 - 下午4:36:5323* @email abericyang@gmail.com24*/25classFabricUserimplementsUser, Serializable {2627privatestaticfinallongserialVersionUID = 5695080465408336815L;2829/**名称*/30privateString name;31/**规则*/32privateSetroles;33/**账户*/34privateString account;35/**从属联盟*/36privateString affiliation;37/**组织*/38privateString organization;39/**注册操作的密�?*/40privateString enrollmentSecret;41/**会员id*/42privateString mspId;43/**注册登记操作*/44Enrollment enrollment =null;//�?要在测试env中访�?4546/**存储配置对象*/47privatetransientFabricStore keyValStore;48privateString keyValStoreName;4950publicFabricUser(String name, String org, FabricStore store) {51this.name =name;52this.keyValStore =store;53this.organization =org;54this.keyValStoreName = toKeyValStoreName(this.name, org);5556String memberStr =keyValStore.getValue(keyValStoreName);57if(null!=memberStr) {58saveState();59}else{60restoreState();61}62}6364/**65* 设置账户信息并将用户状�?�更新至存储配置对象66*67*@paramaccount68* 账户69*/70publicvoidsetAccount(String account) {71this.account =account;72saveState();73}7475@Override76publicString getAccount() {77returnthis.account;78}7980/**81* 设置从属联盟信息并将用户状�?�更新至存储配置对象82*83*@paramaffiliation84* 从属联盟85*/86publicvoidsetAffiliation(String affiliation) {87this.affiliation =affiliation;88saveState();89}9091@Override92publicString getAffiliation() {93returnthis.affiliation;94}9596@Override97publicEnrollment getEnrollment() {98returnthis.enrollment;99}100101/**102* 设置会员id信息并将用户状�?�更新至存储配置对象103*104*@parammspID105* 会员id106*/107publicvoidsetMspId(String mspID) {108this.mspId =mspID;109saveState();110}111112@Override113publicString getMspId() {114returnthis.mspId;115}116117@Override118publicString getName() {119returnthis.name;120}121122/**123* 设置规则信息并将用户状�?�更新至存储配置对象124*125*@paramroles126* 规则127*/128publicvoidsetRoles(Setroles) {129this.roles =roles;130saveState();131}132133@Override134publicSetgetRoles() {135returnthis.roles;136}137138publicString getEnrollmentSecret() {139returnenrollmentSecret;140}141142/**143* 设置注册操作的密钥信息并将用户状态更新至存储配置对象144*145*@paramenrollmentSecret146* 注册操作的密�?147*/148publicvoidsetEnrollmentSecret(String enrollmentSecret) {149this.enrollmentSecret =enrollmentSecret;150saveState();151}152153/**154* 设置注册登记操作信息并将用户状�?�更新至存储配置对象155*156*@paramenrollment157* 注册登记操作158*/159publicvoidsetEnrollment(Enrollment enrollment) {160this.enrollment =enrollment;161saveState();162}163164/**165* 确定这个名称是否已注�?166*167*@return与否168*/169publicbooleanisRegistered() {170return!StringUtil.isNullOrEmpty(enrollmentSecret);171}172173/**174* 确定这个名字是否已经注册175*176*@return与否177*/178publicbooleanisEnrolled() {179returnthis.enrollment !=null;180}181182/**将用户状态保存至存储配置对象*/183publicvoidsaveState() {184ByteArrayOutputStream bos =newByteArrayOutputStream();185try{186ObjectOutputStream oos =newObjectOutputStream(bos);187oos.writeObject(this);188oos.flush();189keyValStore.setValue(keyValStoreName, Hex.toHexString(bos.toByteArray()));190bos.close();191}catch(IOException e) {192e.printStackTrace();193}194}195196/**197* 从键值存储中恢复该用户的状�??(如果找到的话)。如果找不到,什么也不要做�??198*199*@return返回用户200*/201privateFabricUser restoreState() {202String memberStr =keyValStore.getValue(keyValStoreName);203if(null!=memberStr) {204//用户在键值存储中被找到,因此恢复状�?��??205byte[] serialized =Hex.decode(memberStr);206ByteArrayInputStream bis =newByteArrayInputStream(serialized);207try{208ObjectInputStream ois =newObjectInputStream(bis);209FabricUser state =(FabricUser) ois.readObject();210if(state !=null) {211this.name =state.name;212this.roles =state.roles;213this.account =state.account;214this.affiliation =state.affiliation;215this.organization =state.organization;216this.enrollmentSecret =state.enrollmentSecret;217this.enrollment =state.enrollment;218this.mspId =state.mspId;219returnthis;220}221}catch(Exception e) {222thrownewRuntimeException(String.format("Could not restore state of member %s",this.name), e);223}224}225returnnull;226}227228publicstaticString toKeyValStoreName(String name, String org) {229System.out.println("toKeyValStoreName = " + "user." + name +org);230return"user." + name +org;231}232233}

关于本号

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180212G05DZ800?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券