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

Hyperledger Fabric 1.0 从零开始(十)——智能合约(参阅:Hyperledger Fabric Chaincode for Operators——实操智能合约

Hyperledger Fabric 1.0 从零开始(十一)——CouchDB(参阅:Hyperledger Fabric CouchDB as the State Database——使用CouchDB

 

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

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

年前实在太忙。

 

JAVA-SDK

9.1基本介绍

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

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

 

9.2架构

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

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

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

 

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

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

具体对应关系如下:

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

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

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

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

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

FabricOrg - 联盟组织对象

FabricUser - 联盟用户对象

FabricStore - 联盟存储配置对象

 

9.3具体实现

直接通过代码来看实现

 9.3.1Chaincode代码

 

 1 package cn.aberic.fabric.bean;
 2 
 3 /**
 4  * Fabric创建的chaincode信息,涵盖所属channel等信息
 5  * 
 6  * @author aberic
 7  *
 8  * @date 2017年10月18日 - 下午2:07:42
 9  * @email abericyang@gmail.com
10  */
11 public class Chaincode {
12 
13     /** 当前将要访问的智能合约所属频道名称 */
14     private String channelName; // ffetest
15     /** 智能合约名称 */
16     private String chaincodeName; // ffetestcc
17     /** 智能合约安装路径 */
18     private String chaincodePath; // github.com/hyperledger/fabric/xxx/chaincode/go/example/test
19     /** 智能合约版本号 */
20     private String chaincodeVersion; // 1.0
21     /** 执行智能合约操作等待时间 */
22     private int invokeWatiTime = 100000;
23     /** 执行智能合约实例等待时间 */
24     private int deployWatiTime = 120000;
25 
26     public String getChannelName() {
27         return channelName;
28     }
29 
30     public void setChannelName(String channelName) {
31         this.channelName = channelName;
32     }
33 
34     public String getChaincodeName() {
35         return chaincodeName;
36     }
37 
38     public void setChaincodeName(String chaincodeName) {
39         this.chaincodeName = chaincodeName;
40     }
41 
42     public String getChaincodePath() {
43         return chaincodePath;
44     }
45 
46     public void setChaincodePath(String chaincodePath) {
47         this.chaincodePath = chaincodePath;
48     }
49 
50     public String getChaincodeVersion() {
51         return chaincodeVersion;
52     }
53 
54     public void setChaincodeVersion(String chaincodeVersion) {
55         this.chaincodeVersion = chaincodeVersion;
56     }
57 
58     public int getInvokeWatiTime() {
59         return invokeWatiTime;
60     }
61 
62     public void setInvokeWatiTime(int invokeWatiTime) {
63         this.invokeWatiTime = invokeWatiTime;
64     }
65 
66     public int getDeployWatiTime() {
67         return deployWatiTime;
68     }
69 
70     public void setDeployWatiTime(int deployWatiTime) {
71         this.deployWatiTime = deployWatiTime;
72     }
73 
74 }

 

 

 9.3.2、Orderers代码

 

 1 package cn.aberic.fabric.bean;
 2 
 3 import java.util.ArrayList;
 4 import java.util.List;
 5 
 6 /**
 7  * Fabric创建的orderer信息,涵盖单机和集群两种方案
 8  * 
 9  * @author aberic
10  *
11  * @date 2017年10月18日 - 下午1:56:48
12  * @email abericyang@gmail.com
13  */
14 public class Orderers {
15 
16     /** orderer 排序服务器所在根域名 */
17     private String ordererDomainName; // anti-moth.com
18     /** orderer 排序服务器集合 */
19     private List<Orderer> orderers;
20 
21     public Orderers() {
22         orderers = new ArrayList<>();
23     }
24 
25     public String getOrdererDomainName() {
26         return ordererDomainName;
27     }
28 
29     public void setOrdererDomainName(String ordererDomainName) {
30         this.ordererDomainName = ordererDomainName;
31     }
32 
33     /** 新增排序服务器 */
34     public void addOrderer(String name, String location) {
35         orderers.add(new Orderer(name, location));
36     }
37 
38     /** 获取排序服务器集合 */
39     public List<Orderer> get() {
40         return orderers;
41     }
42 
43     /**
44      * 排序服务器对象
45      * 
46      * @author aberic
47      *
48      * @date 2017年10月18日 - 下午2:06:22
49      * @email abericyang@gmail.com
50      */
51     public class Orderer {
52 
53         /** orderer 排序服务器的域名 */
54         private String ordererName;
55         /** orderer 排序服务器的访问地址 */
56         private String ordererLocation;
57 
58         public Orderer(String ordererName, String ordererLocation) {
59             super();
60             this.ordererName = ordererName;
61             this.ordererLocation = ordererLocation;
62         }
63 
64         public String getOrdererName() {
65             return ordererName;
66         }
67 
68         public void setOrdererName(String ordererName) {
69             this.ordererName = ordererName;
70         }
71 
72         public String getOrdererLocation() {
73             return ordererLocation;
74         }
75 
76         public void setOrdererLocation(String ordererLocation) {
77             this.ordererLocation = ordererLocation;
78         }
79 
80     }
81 
82 }

 

 

 9.3.3、Peers代码

 

  1 package cn.aberic.fabric.bean;
  2 
  3 import java.util.ArrayList;
  4 import java.util.List;
  5 
  6 /**
  7  * Fabric创建的peer信息,包含有cli、org、ca、couchdb等节点服务器关联启动服务信息集合
  8  * 
  9  * @author aberic
 10  *
 11  * @date 2017年10月18日 - 下午1:49:03
 12  * @email abericyang@gmail.com
 13  */
 14 public class Peers {
 15 
 16     /** 当前指定的组织名称 */
 17     private String orgName; // Org1
 18     /** 当前指定的组织名称 */
 19     private String orgMSPID; // Org1MSP
 20     /** 当前指定的组织所在根域名 */
 21     private String orgDomainName; //org1.example.com
 22     /** orderer 排序服务器集合 */
 23     private List<Peer> peers;
 24 
 25     public Peers() {
 26         peers = new ArrayList<>();
 27     }
 28 
 29     public String getOrgName() {
 30         return orgName;
 31     }
 32 
 33     public void setOrgName(String orgName) {
 34         this.orgName = orgName;
 35     }
 36 
 37     public String getOrgMSPID() {
 38         return orgMSPID;
 39     }
 40 
 41     public void setOrgMSPID(String orgMSPID) {
 42         this.orgMSPID = orgMSPID;
 43     }
 44 
 45     public String getOrgDomainName() {
 46         return orgDomainName;
 47     }
 48 
 49     public void setOrgDomainName(String orgDomainName) {
 50         this.orgDomainName = orgDomainName;
 51     }
 52 
 53     /** 新增排序服务器 */
 54     public void addPeer(String peerName, String peerEventHubName, String peerLocation, String peerEventHubLocation, String caLocation) {
 55         peers.add(new Peer(peerName, peerEventHubName, peerLocation, peerEventHubLocation, caLocation));
 56     }
 57 
 58     /** 获取排序服务器集合 */
 59     public List<Peer> get() {
 60         return peers;
 61     }
 62 
 63     /**
 64      * 节点服务器对象
 65      * 
 66      * @author aberic
 67      *
 68      * @date 2017年11月11日 - 下午6:56:14
 69      * @email abericyang@gmail.com
 70      */
 71     public class Peer {
 72 
 73         /** 当前指定的组织节点域名 */
 74         private String peerName; // peer0.org1.example.com
 75         /** 当前指定的组织节点事件域名 */
 76         private String peerEventHubName; // peer0.org1.example.com
 77         /** 当前指定的组织节点访问地址 */
 78         private String peerLocation; // grpc://110.131.116.21:7051
 79         /** 当前指定的组织节点事件监听访问地址 */
 80         private String peerEventHubLocation; // grpc://110.131.116.21:7053
 81         /** 当前指定的组织节点ca访问地址 */
 82         private String caLocation; // http://110.131.116.21:7054
 83         /** 当前peer是否增加Event事件处理 */
 84         private boolean addEventHub = false;
 85 
 86         public Peer(String peerName, String peerEventHubName, String peerLocation, String peerEventHubLocation, String caLocation) {
 87             this.peerName = peerName;
 88             this.peerEventHubName = peerEventHubName;
 89             this.peerLocation = peerLocation;
 90             this.peerEventHubLocation = peerEventHubLocation;
 91             this.caLocation = caLocation;
 92         }
 93 
 94         public String getPeerName() {
 95             return peerName;
 96         }
 97 
 98         public void setPeerName(String peerName) {
 99             this.peerName = peerName;
100         }
101 
102         public String getPeerEventHubName() {
103             return peerEventHubName;
104         }
105 
106         public void setPeerEventHubName(String peerEventHubName) {
107             this.peerEventHubName = peerEventHubName;
108         }
109 
110         public String getPeerLocation() {
111             return peerLocation;
112         }
113 
114         public void setPeerLocation(String peerLocation) {
115             this.peerLocation = peerLocation;
116         }
117 
118         public String getPeerEventHubLocation() {
119             return peerEventHubLocation;
120         }
121 
122         public void setPeerEventHubLocation(String eventHubLocation) {
123             this.peerEventHubLocation = eventHubLocation;
124         }
125 
126         public String getCaLocation() {
127             return caLocation;
128         }
129 
130         public void setCaLocation(String caLocation) {
131             this.caLocation = caLocation;
132         }
133 
134         public boolean isAddEventHub() {
135             return addEventHub;
136         }
137 
138         public void addEventHub(boolean addEventHub) {
139             this.addEventHub = addEventHub;
140         }
141 
142     }
143 
144 }

 

 

 9.3.4、FabricUser代码

 

  1 package cn.aberic.fabric;
  2 
  3 import java.io.ByteArrayInputStream;
  4 import java.io.ByteArrayOutputStream;
  5 import java.io.IOException;
  6 import java.io.ObjectInputStream;
  7 import java.io.ObjectOutputStream;
  8 import java.io.Serializable;
  9 import java.util.Set;
 10 
 11 import org.bouncycastle.util.encoders.Hex;
 12 import org.hyperledger.fabric.sdk.Enrollment;
 13 import org.hyperledger.fabric.sdk.User;
 14 
 15 import io.netty.util.internal.StringUtil;
 16 
 17 /**
 18  * 联盟用户对象
 19  * 
 20  * @author aberic
 21  *
 22  * @date 2017年9月7日 - 下午4:36:53
 23  * @email abericyang@gmail.com
 24  */
 25 class FabricUser implements User, Serializable {
 26 
 27     private static final long serialVersionUID = 5695080465408336815L;
 28 
 29     /** 名称 */
 30     private String name;
 31     /** 规则 */
 32     private Set<String> roles;
 33     /** 账户 */
 34     private String account;
 35     /** 从属联盟 */
 36     private String affiliation;
 37     /** 组织 */
 38     private String organization;
 39     /** 注册操作的密�? */
 40     private String enrollmentSecret;
 41     /** 会员id */
 42     private String mspId;
 43     /** 注册登记操作 */
 44     Enrollment enrollment = null; // �?要在测试env中访�?
 45 
 46     /** 存储配置对象 */
 47     private transient FabricStore keyValStore;
 48     private String keyValStoreName;
 49 
 50     public FabricUser(String name, String org, FabricStore store) {
 51         this.name = name;
 52         this.keyValStore = store;
 53         this.organization = org;
 54         this.keyValStoreName = toKeyValStoreName(this.name, org);
 55 
 56         String memberStr = keyValStore.getValue(keyValStoreName);
 57         if (null != memberStr) {
 58             saveState();
 59         } else {
 60             restoreState();
 61         }
 62     }
 63 
 64     /**
 65      * 设置账户信息并将用户状�?�更新至存储配置对象
 66      * 
 67      * @param account
 68      *            账户
 69      */
 70     public void setAccount(String account) {
 71         this.account = account;
 72         saveState();
 73     }
 74 
 75     @Override
 76     public String getAccount() {
 77         return this.account;
 78     }
 79 
 80     /**
 81      * 设置从属联盟信息并将用户状�?�更新至存储配置对象
 82      * 
 83      * @param affiliation
 84      *            从属联盟
 85      */
 86     public void setAffiliation(String affiliation) {
 87         this.affiliation = affiliation;
 88         saveState();
 89     }
 90 
 91     @Override
 92     public String getAffiliation() {
 93         return this.affiliation;
 94     }
 95 
 96     @Override
 97     public Enrollment getEnrollment() {
 98         return this.enrollment;
 99     }
100 
101     /**
102      * 设置会员id信息并将用户状�?�更新至存储配置对象
103      * 
104      * @param mspID
105      *            会员id
106      */
107     public void setMspId(String mspID) {
108         this.mspId = mspID;
109         saveState();
110     }
111 
112     @Override
113     public String getMspId() {
114         return this.mspId;
115     }
116 
117     @Override
118     public String getName() {
119         return this.name;
120     }
121 
122     /**
123      * 设置规则信息并将用户状�?�更新至存储配置对象
124      * 
125      * @param roles
126      *            规则
127      */
128     public void setRoles(Set<String> roles) {
129         this.roles = roles;
130         saveState();
131     }
132 
133     @Override
134     public Set<String> getRoles() {
135         return this.roles;
136     }
137 
138     public String getEnrollmentSecret() {
139         return enrollmentSecret;
140     }
141 
142     /**
143      * 设置注册操作的密钥信息并将用户状态更新至存储配置对象
144      * 
145      * @param enrollmentSecret
146      *            注册操作的密�?
147      */
148     public void setEnrollmentSecret(String enrollmentSecret) {
149         this.enrollmentSecret = enrollmentSecret;
150         saveState();
151     }
152 
153     /**
154      * 设置注册登记操作信息并将用户状�?�更新至存储配置对象
155      * 
156      * @param enrollment
157      *            注册登记操作
158      */
159     public void setEnrollment(Enrollment enrollment) {
160         this.enrollment = enrollment;
161         saveState();
162     }
163 
164     /**
165      * 确定这个名称是否已注�?
166      * 
167      * @return 与否
168      */
169     public boolean isRegistered() {
170         return !StringUtil.isNullOrEmpty(enrollmentSecret);
171     }
172 
173     /**
174      * 确定这个名字是否已经注册
175      *
176      * @return 与否
177      */
178     public boolean isEnrolled() {
179         return this.enrollment != null;
180     }
181 
182     /** 将用户状态保存至存储配置对象 */
183     public void saveState() {
184         ByteArrayOutputStream bos = new ByteArrayOutputStream();
185         try {
186             ObjectOutputStream oos = new ObjectOutputStream(bos);
187             oos.writeObject(this);
188             oos.flush();
189             keyValStore.setValue(keyValStoreName, Hex.toHexString(bos.toByteArray()));
190             bos.close();
191         } catch (IOException e) {
192             e.printStackTrace();
193         }
194     }
195 
196     /**
197      * 从键值存储中恢复该用户的状�??(如果找到的话)。如果找不到,什么也不要做�??
198      * 
199      * @return 返回用户
200      */
201     private FabricUser restoreState() {
202         String memberStr = keyValStore.getValue(keyValStoreName);
203         if (null != memberStr) {
204             // 用户在键值存储中被找到,因此恢复状�?��??
205             byte[] serialized = Hex.decode(memberStr);
206             ByteArrayInputStream bis = new ByteArrayInputStream(serialized);
207             try {
208                 ObjectInputStream ois = new ObjectInputStream(bis);
209                 FabricUser state = (FabricUser) ois.readObject();
210                 if (state != null) {
211                     this.name = state.name;
212                     this.roles = state.roles;
213                     this.account = state.account;
214                     this.affiliation = state.affiliation;
215                     this.organization = state.organization;
216                     this.enrollmentSecret = state.enrollmentSecret;
217                     this.enrollment = state.enrollment;
218                     this.mspId = state.mspId;
219                     return this;
220                 }
221             } catch (Exception e) {
222                 throw new RuntimeException(String.format("Could not restore state of member %s", this.name), e);
223             }
224         }
225         return null;
226     }
227 
228     public static String toKeyValStoreName(String name, String org) {
229         System.out.println("toKeyValStoreName = " + "user." + name + org);
230         return "user." + name + org;
231     }
232 
233 }

 

 

 9.3.5、FabricOrg代码

 

  1 package cn.aberic.fabric;
  2 
  3 import java.io.File;
  4 import java.io.IOException;
  5 import java.nio.file.Paths;
  6 import java.security.NoSuchAlgorithmException;
  7 import java.security.NoSuchProviderException;
  8 import java.security.spec.InvalidKeySpecException;
  9 import java.util.Collection;
 10 import java.util.Collections;
 11 import java.util.HashMap;
 12 import java.util.HashSet;
 13 import java.util.Map;
 14 import java.util.Properties;
 15 import java.util.Set;
 16 
 17 import org.apache.log4j.Logger;
 18 import org.hyperledger.fabric.sdk.Peer;
 19 import org.hyperledger.fabric.sdk.User;
 20 import org.hyperledger.fabric_ca.sdk.HFCAClient;
 21 
 22 import cn.aberic.fabric.bean.Orderers;
 23 
 24 /**
 25  * 联盟组织对象
 26  * 
 27  * @author aberic
 28  *
 29  * @date 2017年9月7日 - 下午4:35:40
 30  * @email abericyang@gmail.com
 31  */
 32 class FabricOrg {
 33 
 34     private static Logger log = Logger.getLogger(FabricOrg.class);
 35 
 36     /** 名称 */
 37     private String name;
 38     /** 会员id */
 39     private String mspid;
 40     /** ca 客户端 */
 41     private HFCAClient caClient;
 42 
 43     /** 用户集合 */
 44     Map<String, User> userMap = new HashMap<>();
 45     /** 本地节点集合 */
 46     Map<String, String> peerLocations = new HashMap<>();
 47     /** 本地排序服务集合 */
 48     Map<String, String> ordererLocations = new HashMap<>();
 49     /** 本地事件集合 */
 50     Map<String, String> eventHubLocations = new HashMap<>();
 51     /** 节点集合 */
 52     Set<Peer> peers = new HashSet<>();
 53     /** 联盟管理员用户 */
 54     private FabricUser admin;
 55     /** 本地 ca */
 56     private String caLocation;
 57     /** ca 配置 */
 58     private Properties caProperties = null;
 59 
 60     /** 联盟单节点管理员用户 */
 61     private FabricUser peerAdmin;
 62 
 63     /** 域名名称 */
 64     private String domainName;
 65 
 66     public FabricOrg(cn.aberic.fabric.bean.Peers peers, Orderers orderers, FabricStore fabricStore, String cryptoConfigPath)
 67             throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException, IOException {
 68         this.name = peers.getOrgName();
 69         this.mspid = peers.getOrgMSPID();
 70         for (int i = 0; i < peers.get().size(); i++) {
 71             addPeerLocation(peers.get().get(i).getPeerName(), peers.get().get(i).getPeerLocation());
 72             addEventHubLocation(peers.get().get(i).getPeerEventHubName(), peers.get().get(i).getPeerEventHubLocation());
 73             setCALocation(peers.get().get(i).getCaLocation());
 74         }
 75         for (int i = 0; i < orderers.get().size(); i++) {
 76             addOrdererLocation(orderers.get().get(i).getOrdererName(), orderers.get().get(i).getOrdererLocation());
 77         }
 78         setDomainName(peers.getOrgDomainName()); // domainName=tk.anti-moth.com
 79 
 80         // Set up HFCA for Org1
 81         // setCAClient(HFCAClient.createNewInstance(peers.getCaLocation(), getCAProperties()));
 82 
 83         setAdmin(fabricStore.getMember("admin", peers.getOrgName())); // 设置该组织的管理员
 84 
 85         File skFile = Paths.get(cryptoConfigPath, "/peerOrganizations/", peers.getOrgDomainName(), String.format("/users/Admin@%s/msp/keystore", peers.getOrgDomainName())).toFile();
 86         File certificateFile = Paths.get(cryptoConfigPath, "/peerOrganizations/", peers.getOrgDomainName(),
 87                 String.format("/users/Admin@%s/msp/signcerts/Admin@%s-cert.pem", peers.getOrgDomainName(), peers.getOrgDomainName())).toFile();
 88         log.debug("skFile = " + skFile.getAbsolutePath());
 89         log.debug("certificateFile = " + certificateFile.getAbsolutePath());
 90         setPeerAdmin(fabricStore.getMember(peers.getOrgName() + "Admin", peers.getOrgName(), peers.getOrgMSPID(), findFileSk(skFile), certificateFile)); // 一个特殊的用户,可以创建通道,连接对等点,并安装链码
 91     }
 92 
 93     public String getName() {
 94         return name;
 95     }
 96 
 97     /**
 98      * 获取联盟管理员用户
 99      * 
100      * @return 联盟管理员用户
101      */
102     public FabricUser getAdmin() {
103         return admin;
104     }
105 
106     /**
107      * 设置联盟管理员用户
108      * 
109      * @param admin
110      *            联盟管理员用户
111      */
112     public void setAdmin(FabricUser admin) {
113         this.admin = admin;
114     }
115 
116     /**
117      * 获取会员id
118      * 
119      * @return 会员id
120      */
121     public String getMSPID() {
122         return mspid;
123     }
124 
125     /**
126      * 设置本地ca
127      * 
128      * @param caLocation
129      *            本地ca
130      */
131     public void setCALocation(String caLocation) {
132         this.caLocation = caLocation;
133     }
134 
135     /**
136      * 获取本地ca
137      * 
138      * @return 本地ca
139      */
140     public String getCALocation() {
141         return this.caLocation;
142     }
143 
144     /**
145      * 添加本地节点
146      * 
147      * @param name
148      *            节点key
149      * @param location
150      *            节点
151      */
152     public void addPeerLocation(String name, String location) {
153         peerLocations.put(name, location);
154     }
155 
156     /**
157      * 添加本地组织
158      * 
159      * @param name
160      *            组织key
161      * @param location
162      *            组织
163      */
164     public void addOrdererLocation(String name, String location) {
165         ordererLocations.put(name, location);
166     }
167 
168     /**
169      * 添加本地事件
170      * 
171      * @param name
172      *            事件key
173      * @param location
174      *            事件
175      */
176     public void addEventHubLocation(String name, String location) {
177         eventHubLocations.put(name, location);
178     }
179 
180     /**
181      * 获取本地节点
182      * 
183      * @param name
184      *            节点key
185      * @return 节点
186      */
187     public String getPeerLocation(String name) {
188         return peerLocations.get(name);
189     }
190 
191     /**
192      * 获取本地组织
193      * 
194      * @param name
195      *            组织key
196      * @return 组织
197      */
198     public String getOrdererLocation(String name) {
199         return ordererLocations.get(name);
200     }
201 
202     /**
203      * 获取本地事件
204      * 
205      * @param name
206      *            事件key
207      * @return 事件
208      */
209     public String getEventHubLocation(String name) {
210         return eventHubLocations.get(name);
211     }
212 
213     /**
214      * 获取一个不可修改的本地节点key集合
215      * 
216      * @return 节点key集合
217      */
218     public Set<String> getPeerNames() {
219         return Collections.unmodifiableSet(peerLocations.keySet());
220     }
221 
222     /**
223      * 获取一个不可修改的本地节点集合
224      * 
225      * @return 节点集合
226      */
227     public Set<Peer> getPeers() {
228         return Collections.unmodifiableSet(peers);
229     }
230 
231     /**
232      * 获取一个不可修改的本地组织key集合
233      * 
234      * @return 组织key集合
235      */
236     public Set<String> getOrdererNames() {
237         return Collections.unmodifiableSet(ordererLocations.keySet());
238     }
239 
240     /**
241      * 获取一个不可修改的本地组织集合
242      * 
243      * @return 组织集合
244      */
245     public Collection<String> getOrdererLocations() {
246         return Collections.unmodifiableCollection(ordererLocations.values());
247     }
248 
249     /**
250      * 获取一个不可修改的本地事件key集合
251      * 
252      * @return 事件key集合
253      */
254     public Set<String> getEventHubNames() {
255         return Collections.unmodifiableSet(eventHubLocations.keySet());
256     }
257 
258     /**
259      * 获取一个不可修改的本地事件集合
260      * 
261      * @return 事件集合
262      */
263     public Collection<String> getEventHubLocations() {
264         return Collections.unmodifiableCollection(eventHubLocations.values());
265     }
266 
267     /**
268      * 设置 ca 客户端
269      * 
270      * @param caClient
271      *            ca 客户端
272      */
273     public void setCAClient(HFCAClient caClient) {
274         this.caClient = caClient;
275     }
276 
277     /**
278      * 获取 ca 客户端
279      * 
280      * @return ca 客户端
281      */
282     public HFCAClient getCAClient() {
283         return caClient;
284     }
285 
286     /**
287      * 向用户集合中添加用户
288      * 
289      * @param user
290      *            用户
291      */
292     public void addUser(FabricUser user) {
293         userMap.put(user.getName(), user);
294     }
295 
296     /**
297      * 从用户集合根据名称获取用户
298      * 
299      * @param name
300      *            名称
301      * @return 用户
302      */
303     public User getUser(String name) {
304         return userMap.get(name);
305     }
306 
307     /**
308      * 向节点集合中添加节点
309      * 
310      * @param peer
311      *            节点
312      */
313     public void addPeer(Peer peer) {
314         peers.add(peer);
315     }
316 
317     /**
318      * 设置 ca 配置
319      * 
320      * @param caProperties
321      *            ca 配置
322      */
323     public void setCAProperties(Properties caProperties) {
324         this.caProperties = caProperties;
325     }
326 
327     /**
328      * 获取 ca 配置
329      * 
330      * @return ca 配置
331      */
332     public Properties getCAProperties() {
333         return caProperties;
334     }
335 
336     /**
337      * 设置联盟单节点管理员用户
338      * 
339      * @param peerAdmin
340      *            联盟单节点管理员用户
341      */
342     public void setPeerAdmin(FabricUser peerAdmin) {
343         this.peerAdmin = peerAdmin;
344     }
345 
346     /**
347      * 获取联盟单节点管理员用户
348      * 
349      * @return 联盟单节点管理员用户
350      */
351     public FabricUser getPeerAdmin() {
352         return peerAdmin;
353     }
354 
355     /**
356      * 设置域名名称
357      * 
358      * @param doainName
359      *            域名名称
360      */
361     public void setDomainName(String domainName) {
362         this.domainName = domainName;
363     }
364 
365     /**
366      * 获取域名名称
367      * 
368      * @return 域名名称
369      */
370     public String getDomainName() {
371         return domainName;
372     }
373 
374     /**
375      * 从指定路径中获取后缀为 _sk 的文件,且该路径下有且仅有该文件
376      * 
377      * @param directorys
378      *            指定路径
379      * @return File
380      */
381     private File findFileSk(File directory) {
382         File[] matches = directory.listFiles((dir, name) -> name.endsWith("_sk"));
383         if (null == matches) {
384             throw new RuntimeException(String.format("Matches returned null does %s directory exist?", directory.getAbsoluteFile().getName()));
385         }
386         if (matches.length != 1) {
387             throw new RuntimeException(String.format("Expected in %s only 1 sk file but found %d", directory.getAbsoluteFile().getName(), matches.length));
388         }
389         return matches[0];
390     }
391 
392 }

 

 

 9.3.6、FabricStore代码

 

  1 package cn.aberic.fabric;
  2 
  3 import java.io.File;
  4 import java.io.FileInputStream;
  5 import java.io.FileNotFoundException;
  6 import java.io.FileOutputStream;
  7 import java.io.IOException;
  8 import java.io.InputStream;
  9 import java.io.OutputStream;
 10 import java.io.Reader;
 11 import java.io.Serializable;
 12 import java.io.StringReader;
 13 import java.security.NoSuchAlgorithmException;
 14 import java.security.NoSuchProviderException;
 15 import java.security.PrivateKey;
 16 import java.security.Security;
 17 import java.security.spec.InvalidKeySpecException;
 18 import java.util.HashMap;
 19 import java.util.Map;
 20 import java.util.Properties;
 21 
 22 import org.apache.commons.io.IOUtils;
 23 import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
 24 import org.bouncycastle.jce.provider.BouncyCastleProvider;
 25 import org.bouncycastle.openssl.PEMParser;
 26 import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
 27 import org.hyperledger.fabric.sdk.Enrollment;
 28 
 29 /**
 30  * 联盟存储配置对象
 31  * 
 32  * @author aberic
 33  *
 34  * @date 2017年9月7日 - 下午4:36:19
 35  * @email abericyang@gmail.com
 36  */
 37 class FabricStore {
 38 
 39     private String file;
 40     /** 用户信息集合 */
 41     private final Map<String, FabricUser> members = new HashMap<>();
 42 
 43     public FabricStore(File file) {
 44         this.file = file.getAbsolutePath();
 45     }
 46 
 47     /**
 48      * 设置与名称相关的值
 49      *
 50      * @param name
 51      *            名称
 52      * @param value
 53      *            相关值
 54      */
 55     public void setValue(String name, String value) {
 56         Properties properties = loadProperties();
 57         try (OutputStream output = new FileOutputStream(file)) {
 58             properties.setProperty(name, value);
 59             properties.store(output, "");
 60             output.close();
 61         } catch (IOException e) {
 62             System.out.println(String.format("Could not save the keyvalue store, reason:%s", e.getMessage()));
 63         }
 64     }
 65 
 66     /**
 67      * 获取与名称相关的值
 68      *
 69      * @param 名称
 70      * @return 相关值
 71      */
 72     public String getValue(String name) {
 73         Properties properties = loadProperties();
 74         return properties.getProperty(name);
 75     }
 76 
 77     /**
 78      * 加载配置文件
 79      * 
 80      * @return 配置文件对象
 81      */
 82     private Properties loadProperties() {
 83         Properties properties = new Properties();
 84         try (InputStream input = new FileInputStream(file)) {
 85             properties.load(input);
 86             input.close();
 87         } catch (FileNotFoundException e) {
 88             System.out.println(String.format("Could not find the file \"%s\"", file));
 89         } catch (IOException e) {
 90             System.out.println(String.format("Could not load keyvalue store from file \"%s\", reason:%s", file, e.getMessage()));
 91         }
 92         return properties;
 93     }
 94 
 95     /**
 96      * 用给定的名称获取用户
 97      * 
 98      * @param 名称
 99      * @param 组织
100      * 
101      * @return 用户
102      */
103     public FabricUser getMember(String name, String org) {
104         // 尝试从缓存中获取User状�??
105         FabricUser fabricUser = members.get(FabricUser.toKeyValStoreName(name, org));
106         if (null != fabricUser) {
107             return fabricUser;
108         }
109         // 创建User,并尝试从键值存储中恢复它的状�??(如果找到的话)�?
110         fabricUser = new FabricUser(name, org, this);
111         return fabricUser;
112     }
113 
114     /**
115      * 用给定的名称获取用户
116      * 
117      * @param name
118      *            名称
119      * @param org
120      *            组织
121      * @param mspId
122      *            会员id
123      * @param privateKeyFile
124      * @param certificateFile
125      * 
126      * @return user 用户
127      * 
128      * @throws IOException
129      * @throws NoSuchAlgorithmException
130      * @throws NoSuchProviderException
131      * @throws InvalidKeySpecException
132      */
133     public FabricUser getMember(String name, String org, String mspId, File privateKeyFile, File certificateFile)
134             throws IOException, NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException {
135         try {
136             // 尝试从缓存中获取User状�??
137             FabricUser fabricUser = members.get(FabricUser.toKeyValStoreName(name, org));
138             if (null != fabricUser) {
139                 System.out.println("尝试从缓存中获取User状�?? User = " + fabricUser);
140                 return fabricUser;
141             }
142             // 创建User,并尝试从键值存储中恢复它的状�??(如果找到的话)�?
143             fabricUser = new FabricUser(name, org, this);
144             fabricUser.setMspId(mspId);
145             String certificate = new String(IOUtils.toByteArray(new FileInputStream(certificateFile)), "UTF-8");
146             PrivateKey privateKey = getPrivateKeyFromBytes(IOUtils.toByteArray(new FileInputStream(privateKeyFile)));
147             fabricUser.setEnrollment(new StoreEnrollement(privateKey, certificate));
148             return fabricUser;
149         } catch (IOException e) {
150             e.printStackTrace();
151             throw e;
152         } catch (NoSuchAlgorithmException e) {
153             e.printStackTrace();
154             throw e;
155         } catch (NoSuchProviderException e) {
156             e.printStackTrace();
157             throw e;
158         } catch (InvalidKeySpecException e) {
159             e.printStackTrace();
160             throw e;
161         } catch (ClassCastException e) {
162             e.printStackTrace();
163             throw e;
164         }
165     }
166 
167     /**
168      * 通过字节数组信息获取私钥
169      * 
170      * @param data
171      *            字节数组
172      * 
173      * @return 私钥
174      * 
175      * @throws IOException
176      * @throws NoSuchProviderException
177      * @throws NoSuchAlgorithmException
178      * @throws InvalidKeySpecException
179      */
180     private PrivateKey getPrivateKeyFromBytes(byte[] data) throws IOException, NoSuchProviderException, NoSuchAlgorithmException, InvalidKeySpecException {
181         final Reader pemReader = new StringReader(new String(data));
182         final PrivateKeyInfo pemPair;
183         try (PEMParser pemParser = new PEMParser(pemReader)) {
184             pemPair = (PrivateKeyInfo) pemParser.readObject();
185         }
186         PrivateKey privateKey = new JcaPEMKeyConverter().setProvider(BouncyCastleProvider.PROVIDER_NAME).getPrivateKey(pemPair);
187         return privateKey;
188     }
189 
190     static {
191         try {
192             Security.addProvider(new BouncyCastleProvider());
193         } catch (Exception e) {
194             e.printStackTrace();
195         }
196     }
197 
198     /**
199      * 自定义注册登记操作类
200      * 
201      * @author yangyi47
202      *
203      */
204     static final class StoreEnrollement implements Enrollment, Serializable {
205 
206         private static final long serialVersionUID = 6965341351799577442L;
207 
208         /** 私钥 */
209         private final PrivateKey privateKey;
210         /** 授权证书 */
211         private final String certificate;
212 
213         StoreEnrollement(PrivateKey privateKey, String certificate) {
214             this.certificate = certificate;
215             this.privateKey = privateKey;
216         }
217 
218         @Override
219         public PrivateKey getKey() {
220             return privateKey;
221         }
222 
223         @Override
224         public String getCert() {
225             return certificate;
226         }
227     }
228 
229 }

 

 

 9.3.7、FabricConfig代码

 

 1 package cn.aberic.fabric;
 2 
 3 import java.io.File;
 4 
 5 import org.apache.log4j.Logger;
 6 
 7 import cn.aberic.fabric.bean.Chaincode;
 8 import cn.aberic.fabric.bean.Orderers;
 9 import cn.aberic.fabric.bean.Peers;
10 
11 public class FabricConfig {
12 
13     private static Logger log = Logger.getLogger(FabricConfig.class);
14 
15     /** 节点服务器对象 */
16     private Peers peers;
17     /** 排序服务器对象 */
18     private Orderers orderers;
19     /** 智能合约对象 */
20     private Chaincode chaincode;
21     /** channel-artifacts所在路径:默认channel-artifacts所在路径/xxx/WEB-INF/classes/fabric/channel-artifacts/ */
22     private String channelArtifactsPath;
23     /** crypto-config所在路径:默认crypto-config所在路径/xxx/WEB-INF/classes/fabric/crypto-config/ */
24     private String cryptoConfigPath;
25     private boolean registerEvent = false;
26 
27     public FabricConfig() {
28         // 默认channel-artifacts所在路径 /xxx/WEB-INF/classes/fabric/channel-artifacts/
29         channelArtifactsPath = getChannlePath() + "/channel-artifacts/";
30         // 默认crypto-config所在路径 /xxx/WEB-INF/classes/fabric/crypto-config/
31         cryptoConfigPath = getChannlePath() + "/crypto-config/";
32     }
33 
34     /**
35      * 默认fabric配置路径
36      * 
37      * @return D:/installSoft/apache-tomcat-9.0.0.M21-02/webapps/xxx/WEB-INF/classes/fabric/channel-artifacts/
38      */
39     private String getChannlePath() {
40         String directorys = ChaincodeManager.class.getClassLoader().getResource("fabric").getFile();
41         log.debug("directorys = " + directorys);
42         File directory = new File(directorys);
43         log.debug("directory = " + directory.getPath());
44 
45         return directory.getPath();
46         // return "src/main/resources/fabric/channel-artifacts/";
47     }
48 
49     public Peers getPeers() {
50         return peers;
51     }
52 
53     public void setPeers(Peers peers) {
54         this.peers = peers;
55     }
56 
57     public Orderers getOrderers() {
58         return orderers;
59     }
60 
61     public void setOrderers(Orderers orderers) {
62         this.orderers = orderers;
63     }
64 
65     public Chaincode getChaincode() {
66         return chaincode;
67     }
68 
69     public void setChaincode(Chaincode chaincode) {
70         this.chaincode = chaincode;
71     }
72 
73     public String getChannelArtifactsPath() {
74         return channelArtifactsPath;
75     }
76 
77     public void setChannelArtifactsPath(String channelArtifactsPath) {
78         this.channelArtifactsPath = channelArtifactsPath;
79     }
80 
81     public String getCryptoConfigPath() {
82         return cryptoConfigPath;
83     }
84 
85     public void setCryptoConfigPath(String cryptoConfigPath) {
86         this.cryptoConfigPath = cryptoConfigPath;
87     }
88 
89     public boolean isRegisterEvent() {
90         return registerEvent;
91     }
92 
93     public void setRegisterEvent(boolean registerEvent) {
94         this.registerEvent = registerEvent;
95     }
96 
97 }

 

 

 9.3.8、ChaincodeManager代码

 

  1 package cn.aberic.fabric;
  2 
  3 import static java.nio.charset.StandardCharsets.UTF_8;
  4 
  5 import java.io.File;
  6 import java.io.IOException;
  7 import java.nio.file.Paths;
  8 import java.security.NoSuchAlgorithmException;
  9 import java.security.NoSuchProviderException;
 10 import java.security.spec.InvalidKeySpecException;
 11 import java.util.Collection;
 12 import java.util.HashMap;
 13 import java.util.LinkedList;
 14 import java.util.Map;
 15 import java.util.Properties;
 16 import java.util.Set;
 17 import java.util.concurrent.ExecutionException;
 18 import java.util.concurrent.TimeoutException;
 19 
 20 import org.apache.log4j.Logger;
 21 import org.hyperledger.fabric.sdk.BlockEvent;
 22 import org.hyperledger.fabric.sdk.BlockListener;
 23 import org.hyperledger.fabric.sdk.ChaincodeID;
 24 import org.hyperledger.fabric.sdk.Channel;
 25 import org.hyperledger.fabric.sdk.HFClient;
 26 import org.hyperledger.fabric.sdk.ProposalResponse;
 27 import org.hyperledger.fabric.sdk.QueryByChaincodeRequest;
 28 import org.hyperledger.fabric.sdk.SDKUtils;
 29 import org.hyperledger.fabric.sdk.TransactionProposalRequest;
 30 import org.hyperledger.fabric.sdk.exception.CryptoException;
 31 import org.hyperledger.fabric.sdk.exception.InvalidArgumentException;
 32 import org.hyperledger.fabric.sdk.exception.ProposalException;
 33 import org.hyperledger.fabric.sdk.exception.TransactionException;
 34 import org.hyperledger.fabric.sdk.security.CryptoSuite;
 35 
 36 import com.google.protobuf.ByteString;
 37 import com.google.protobuf.InvalidProtocolBufferException;
 38 
 39 import cn.aberic.fabric.bean.Chaincode;
 40 import cn.aberic.fabric.bean.Orderers;
 41 import cn.aberic.fabric.bean.Peers;
 42 
 43 public class ChaincodeManager {
 44 
 45     private static Logger log = Logger.getLogger(ChaincodeManager.class);
 46 
 47     private FabricConfig config;
 48     private Orderers orderers;
 49     private Peers peers;
 50     private Chaincode chaincode;
 51 
 52     private HFClient client;
 53     private FabricOrg fabricOrg;
 54     private Channel channel;
 55     private ChaincodeID chaincodeID;
 56 
 57     public ChaincodeManager(FabricConfig fabricConfig)
 58             throws CryptoException, InvalidArgumentException, NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException, IOException, TransactionException {
 59         this.config = fabricConfig;
 60 
 61         orderers = this.config.getOrderers();
 62         peers = this.config.getPeers();
 63         chaincode = this.config.getChaincode();
 64 
 65         client = HFClient.createNewInstance();
 66         log.debug("Create instance of HFClient");
 67         client.setCryptoSuite(CryptoSuite.Factory.getCryptoSuite());
 68         log.debug("Set Crypto Suite of HFClient");
 69 
 70         fabricOrg = getFabricOrg();
 71         channel = getChannel();
 72         chaincodeID = getChaincodeID();
 73 
 74         client.setUserContext(fabricOrg.getPeerAdmin()); // 也许是1.0.0测试版的bug,只有节点管理员可以调用链码
 75     }
 76 
 77     private FabricOrg getFabricOrg() throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException, IOException {
 78 
 79         // java.io.tmpdir : C:\Users\yangyi47\AppData\Local\Temp\
 80         File storeFile = new File(System.getProperty("java.io.tmpdir") + "/HFCSampletest.properties");
 81         FabricStore fabricStore = new FabricStore(storeFile);
 82 
 83         // Get Org1 from configuration
 84         FabricOrg fabricOrg = new FabricOrg(peers, orderers, fabricStore, config.getCryptoConfigPath());
 85         log.debug("Get FabricOrg");
 86         return fabricOrg;
 87     }
 88 
 89     private Channel getChannel()
 90             throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException, IOException, CryptoException, InvalidArgumentException, TransactionException {
 91         client.setUserContext(fabricOrg.getPeerAdmin());
 92         return getChannel(fabricOrg, client);
 93     }
 94 
 95     private Channel getChannel(FabricOrg fabricOrg, HFClient client)
 96             throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException, IOException, CryptoException, InvalidArgumentException, TransactionException {
 97         Channel channel = client.newChannel(chaincode.getChannelName());
 98         log.debug("Get Chain " + chaincode.getChannelName());
 99 
100 //        channel.setTransactionWaitTime(chaincode.getInvokeWatiTime());
101 //        channel.setDeployWaitTime(chaincode.getDeployWatiTime());
102 
103         for (int i = 0; i < peers.get().size(); i++) {
104             File peerCert = Paths.get(config.getCryptoConfigPath(), "/peerOrganizations", peers.getOrgDomainName(), "peers", peers.get().get(i).getPeerName(), "tls/server.crt")
105                     .toFile();
106             if (!peerCert.exists()) {
107                 throw new RuntimeException(
108                         String.format("Missing cert file for: %s. Could not find at location: %s", peers.get().get(i).getPeerName(), peerCert.getAbsolutePath()));
109             }
110             Properties peerProperties = new Properties();
111             peerProperties.setProperty("pemFile", peerCert.getAbsolutePath());
112             // ret.setProperty("trustServerCertificate", "true"); //testing
113             // environment only NOT FOR PRODUCTION!
114             peerProperties.setProperty("hostnameOverride", peers.getOrgDomainName());
115             peerProperties.setProperty("sslProvider", "openSSL");
116             peerProperties.setProperty("negotiationType", "TLS");
117             // 在grpc的NettyChannelBuilder上设置特定选项
118             peerProperties.put("grpc.ManagedChannelBuilderOption.maxInboundMessageSize", 9000000);
119             channel.addPeer(client.newPeer(peers.get().get(i).getPeerName(), fabricOrg.getPeerLocation(peers.get().get(i).getPeerName()), peerProperties));
120             if (peers.get().get(i).isAddEventHub()) {
121                 channel.addEventHub(
122                         client.newEventHub(peers.get().get(i).getPeerEventHubName(), fabricOrg.getEventHubLocation(peers.get().get(i).getPeerEventHubName()), peerProperties));
123             }
124         }
125 
126         for (int i = 0; i < orderers.get().size(); i++) {
127             File ordererCert = Paths.get(config.getCryptoConfigPath(), "/ordererOrganizations", orderers.getOrdererDomainName(), "orderers", orderers.get().get(i).getOrdererName(),
128                     "tls/server.crt").toFile();
129             if (!ordererCert.exists()) {
130                 throw new RuntimeException(
131                         String.format("Missing cert file for: %s. Could not find at location: %s", orderers.get().get(i).getOrdererName(), ordererCert.getAbsolutePath()));
132             }
133             Properties ordererProperties = new Properties();
134             ordererProperties.setProperty("pemFile", ordererCert.getAbsolutePath());
135             ordererProperties.setProperty("hostnameOverride", orderers.getOrdererDomainName());
136             ordererProperties.setProperty("sslProvider", "openSSL");
137             ordererProperties.setProperty("negotiationType", "TLS");
138             ordererProperties.put("grpc.ManagedChannelBuilderOption.maxInboundMessageSize", 9000000);
139             ordererProperties.setProperty("ordererWaitTimeMilliSecs", "300000");
140             channel.addOrderer(
141                     client.newOrderer(orderers.get().get(i).getOrdererName(), fabricOrg.getOrdererLocation(orderers.get().get(i).getOrdererName()), ordererProperties));
142         }
143 
144         log.debug("channel.isInitialized() = " + channel.isInitialized());
145         if (!channel.isInitialized()) {
146             channel.initialize();
147         }
148         if (config.isRegisterEvent()) {
149             channel.registerBlockListener(new BlockListener() {
150 
151                 @Override
152                 public void received(BlockEvent event) {
153                     // TODO
154                     log.debug("========================Event事件监听开始========================");
155                     try {
156                         log.debug("event.getChannelId() = " + event.getChannelId());
157                         log.debug("event.getEvent().getChaincodeEvent().getPayload().toStringUtf8() = " + event.getEvent().getChaincodeEvent().getPayload().toStringUtf8());
158                         log.debug("event.getBlock().getData().getDataList().size() = " + event.getBlock().getData().getDataList().size());
159                         ByteString byteString = event.getBlock().getData().getData(0);
160                         String result = byteString.toStringUtf8();
161                         log.debug("byteString.toStringUtf8() = " + result);
162 
163                         String r1[] = result.split("END CERTIFICATE");
164                         String rr = r1[2];
165                         log.debug("rr = " + rr);
166                     } catch (InvalidProtocolBufferException e) {
167                         // TODO
168                         e.printStackTrace();
169                     }
170                     log.debug("========================Event事件监听结束========================");
171                 }
172             });
173         }
174         return channel;
175     }
176 
177     private ChaincodeID getChaincodeID() {
178         return ChaincodeID.newBuilder().setName(chaincode.getChaincodeName()).setVersion(chaincode.getChaincodeVersion()).setPath(chaincode.getChaincodePath()).build();
179     }
180 
181     /**
182      * 执行智能合约
183      * 
184      * @param fcn
185      *            方法名
186      * @param args
187      *            参数数组
188      * @return
189      * @throws InvalidArgumentException
190      * @throws ProposalException
191      * @throws InterruptedException
192      * @throws ExecutionException
193      * @throws TimeoutException
194      * @throws IOException 
195      * @throws TransactionException 
196      * @throws CryptoException 
197      * @throws InvalidKeySpecException 
198      * @throws NoSuchProviderException 
199      * @throws NoSuchAlgorithmException 
200      */
201     public Map<String, String> invoke(String fcn, String[] args)
202             throws InvalidArgumentException, ProposalException, InterruptedException, ExecutionException, TimeoutException, NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException, CryptoException, TransactionException, IOException {
203         Map<String, String> resultMap = new HashMap<>();
204 
205         Collection<ProposalResponse> successful = new LinkedList<>();
206         Collection<ProposalResponse> failed = new LinkedList<>();
207 
208         /// Send transaction proposal to all peers
209         TransactionProposalRequest transactionProposalRequest = client.newTransactionProposalRequest();
210         transactionProposalRequest.setChaincodeID(chaincodeID);
211         transactionProposalRequest.setFcn(fcn);
212         transactionProposalRequest.setArgs(args);
213 
214         Map<String, byte[]> tm2 = new HashMap<>();
215         tm2.put("HyperLedgerFabric", "TransactionProposalRequest:JavaSDK".getBytes(UTF_8));
216         tm2.put("method", "TransactionProposalRequest".getBytes(UTF_8));
217         tm2.put("result", ":)".getBytes(UTF_8));
218         transactionProposalRequest.setTransientMap(tm2);
219 
220         Collection<ProposalResponse> transactionPropResp = channel.sendTransactionProposal(transactionProposalRequest, channel.getPeers());
221         for (ProposalResponse response : transactionPropResp) {
222             if (response.getStatus() == ProposalResponse.Status.SUCCESS) {
223                 successful.add(response);
224             } else {
225                 failed.add(response);
226             }
227         }
228 
229         Collection<Set<ProposalResponse>> proposalConsistencySets = SDKUtils.getProposalConsistencySets(transactionPropResp);
230         if (proposalConsistencySets.size() != 1) {
231             log.error("Expected only one set of consistent proposal responses but got " + proposalConsistencySets.size());
232         }
233 
234         if (failed.size() > 0) {
235             ProposalResponse firstTransactionProposalResponse = failed.iterator().next();
236             log.error("Not enough endorsers for inspect:" + failed.size() + " endorser error: " + firstTransactionProposalResponse.getMessage() + ". Was verified: "
237                     + firstTransactionProposalResponse.isVerified());
238             resultMap.put("code", "error");
239             resultMap.put("data", firstTransactionProposalResponse.getMessage());
240             return resultMap;
241         } else {
242             log.info("Successfully received transaction proposal responses.");
243             ProposalResponse resp = transactionPropResp.iterator().next();
244             byte[] x = resp.getChaincodeActionResponsePayload();
245             String resultAsString = null;
246             if (x != null) {
247                 resultAsString = new String(x, "UTF-8");
248             }
249             log.info("resultAsString = " + resultAsString);
250             channel.sendTransaction(successful);
251             resultMap.put("code", "success");
252             resultMap.put("data", resultAsString);
253             return resultMap;
254         }
255 
256 //        channel.sendTransaction(successful).thenApply(transactionEvent -> {
257 //            if (transactionEvent.isValid()) {
258 //                log.info("Successfully send transaction proposal to orderer. Transaction ID: " + transactionEvent.getTransactionID());
259 //            } else {
260 //                log.info("Failed to send transaction proposal to orderer");
261 //            }
262 //            // chain.shutdown(true);
263 //            return transactionEvent.getTransactionID();
264 //        }).get(chaincode.getInvokeWatiTime(), TimeUnit.SECONDS);
265     }
266 
267     /**
268      * 查询智能合约
269      * 
270      * @param fcn
271      *            方法名
272      * @param args
273      *            参数数组
274      * @return
275      * @throws InvalidArgumentException
276      * @throws ProposalException
277      * @throws IOException 
278      * @throws TransactionException 
279      * @throws CryptoException 
280      * @throws InvalidKeySpecException 
281      * @throws NoSuchProviderException 
282      * @throws NoSuchAlgorithmException 
283      */
284     public Map<String, String> query(String fcn, String[] args) throws InvalidArgumentException, ProposalException, NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException, CryptoException, TransactionException, IOException {
285         Map<String, String> resultMap = new HashMap<>();
286         String payload = "";
287         QueryByChaincodeRequest queryByChaincodeRequest = client.newQueryProposalRequest();
288         queryByChaincodeRequest.setArgs(args);
289         queryByChaincodeRequest.setFcn(fcn);
290         queryByChaincodeRequest.setChaincodeID(chaincodeID);
291 
292         Map<String, byte[]> tm2 = new HashMap<>();
293         tm2.put("HyperLedgerFabric", "QueryByChaincodeRequest:JavaSDK".getBytes(UTF_8));
294         tm2.put("method", "QueryByChaincodeRequest".getBytes(UTF_8));
295         queryByChaincodeRequest.setTransientMap(tm2);
296 
297         Collection<ProposalResponse> queryProposals = channel.queryByChaincode(queryByChaincodeRequest, channel.getPeers());
298         for (ProposalResponse proposalResponse : queryProposals) {
299             if (!proposalResponse.isVerified() || proposalResponse.getStatus() != ProposalResponse.Status.SUCCESS) {
300                 log.debug("Failed query proposal from peer " + proposalResponse.getPeer().getName() + " status: " + proposalResponse.getStatus() + ". Messages: "
301                         + proposalResponse.getMessage() + ". Was verified : " + proposalResponse.isVerified());
302                 resultMap.put("code", "error");
303                 resultMap.put("data", "Failed query proposal from peer " + proposalResponse.getPeer().getName() + " status: " + proposalResponse.getStatus() + ". Messages: "
304                         + proposalResponse.getMessage() + ". Was verified : " + proposalResponse.isVerified());
305             } else {
306                 payload = proposalResponse.getProposalResponse().getResponse().getPayload().toStringUtf8();
307                 log.debug("Query payload from peer: " + proposalResponse.getPeer().getName());
308                 log.debug("" + payload);
309                 resultMap.put("code", "success");
310                 resultMap.put("data", payload);
311             }
312         }
313         return resultMap;
314     }
315 
316 }

 

请注意,用法主要都依赖于ChaincodeManager这个智能合约管理器,建议以单例的形式生成该对象。

插入数据调用 manager.invoke(fcn, arguments)

查询数据调用 manager.query(fcn, arguments)

第一个参数是方法名,第二个参数是智能合约中的args字符串数组

切记不要用invoke来执行查询操作,一来没必要,二来该操作会生成数据集,且数据集也会发送给排序服务器,得不偿失。

上一篇:Hyperledger Fabric 1.0 从零开始(十三)——orderer分布式方案


下一篇:账户锁定策略