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所写的辅助工程目录

 

关于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来执行查询操作,一来没必要,二来该操作会生成数据集,且数据集也会发送给排序服务器,得不偿失。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/391543.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

css跑道_如何不超出跑道:计划种子的简单方法

css跑道There’s lots of startup advice floating around. I’m going to give you a very practical one that’s often missed — how to plan your early growth. The seed round is usually devoted to finding your product-market fit, meaning you start with no or li…

熊猫数据集_为数据科学拆箱熊猫

熊猫数据集If you are already familiar with NumPy, Pandas is just a package build on top of it. Pandas provide more flexibility than NumPy to work with data. While in NumPy we can only store values of single data type(dtype) Pandas has the flexibility to st…

JAVA基础——时间Date类型转换

在java中有六大时间类&#xff0c;分别是&#xff1a; 1、java.util包下的Date类&#xff0c; 2、java.sql包下的Date类&#xff0c; 3、java.text包下的DateFormat类&#xff0c;&#xff08;抽象类&#xff09; 4、java.text包下的SimpleDateFormat类&#xff0c; 5、java.ut…

LeetCode第五天

leetcode 第五天 2018年1月6日 22.(566) Reshape the Matrix JAVA class Solution {public int[][] matrixReshape(int[][] nums, int r, int c) {int[][] newNums new int[r][c];int size nums.length*nums[0].length;if(r*c ! size)return nums;for(int i0;i<size;i){ne…

matplotlib可视化_使用Matplotlib改善可视化设计的5个魔术技巧

matplotlib可视化It is impossible to know everything, no matter how much our experience has increased over the years, there are many things that remain hidden from us. This is normal, and maybe an exciting motivation to search and learn more. And I am sure …

robot:循环遍历数据库查询结果是否满足要求

使用list类型变量{}接收查询结果&#xff0c;再for循环遍历每行数据&#xff0c;取出需要比较的数值 转载于:https://www.cnblogs.com/gcgc/p/11424114.html

rm命令

命令 ‘rm’ &#xff08;remove&#xff09;&#xff1a;删除一个目录中的一个或多个文件或目录&#xff0c;也可以将某个目录及其下属的所有文件及其子目录均删除掉 语法&#xff1a;rm&#xff08;选项&#xff09;&#xff08;参数&#xff09; 默认会提示‘是否’删除&am…

感知器 机器学习_机器学习感知器实现

感知器 机器学习In this post, we are going to have a look at a program written in Python3 using numpy. We will discuss the basics of what a perceptron is, what is the delta rule and how to use it to converge the learning of the perceptron.在本文中&#xff0…

Python之集合、解析式,生成器,函数

一 集合 1 集合定义&#xff1a; 1 如果花括号为空&#xff0c;则是字典类型2 定义一个空集合&#xff0c;使用set 加小括号使用B方式定义集合时&#xff0c;集合内部的数必须是可迭代对象&#xff0c;数值类型的不可以 其中的值必须是可迭代对象&#xff0c;其中的元素必须是可…

python:如何传递一个列表参数

转载于:https://www.cnblogs.com/gcgc/p/11426356.html

curl的安装与简单使用

2019独角兽企业重金招聘Python工程师标准>>> windows 篇&#xff1a; 安装篇&#xff1a; 我的电脑版本是windows7,64位&#xff0c;对应的curl下载地址如下&#xff1a; https://curl.haxx.se/download.html 直接找到下面的这个版本&#xff1a; curl-7.57.0.tar.g…

gcc 编译过程

gcc 编译过程从 hello.c 到 hello(或 a.out)文件&#xff0c; 必须历经 hello.i、 hello.s、 hello.o&#xff0c;最后才得到 hello(或a.out)文件&#xff0c;分别对应着预处理、编译、汇编和链接 4 个步骤&#xff0c;整个过程如图 10.5 所示。 这 4 步大致的工作内容如下&am…

虎牙直播电影一天收入_电影收入

虎牙直播电影一天收入“美国电影协会(MPAA)的首席执行官J. Valenti提到&#xff1a;“没有人能告诉您电影在市场上的表现。 直到电影在黑暗的剧院里放映并且银幕和观众之间都散发出火花。 (“The CEO of Motion Picture Association of America (MPAA) J. Valenti mentioned th…

Python操作Mysql实例代码教程在线版(查询手册)_python

实例1、取得MYSQL的版本在windows环境下安装mysql模块用于python开发MySQL-python Windows下EXE安装文件下载 复制代码 代码如下:# -*- coding: UTF-8 -*- #安装MYSQL DB for pythonimport MySQLdb as mdb con None try: #连接mysql的方法&#xff1a;connect(ip,user,pass…

批判性思维_为什么批判性思维技能对数据科学家至关重要

批判性思维As Alexander Pope said, to err is human. By that metric, who is more human than us data scientists? We devise wrong hypotheses constantly and then spend time working on them just to find out how wrong we were.正如亚历山大波普(Alexander Pope)所说…

Manjaro 17 搭建 redis 4.0.1 集群服务

安装Redis在Linux环境中 这里我们用的是manjaro一个小众一些的发行版 我选用的是manjaro 17 KDE 如果你已经安装好了manjaro 那么你需要准备一个redis.tar.gz包 这里我选用的是截至目前最新的redis 4.0.1版本 我们可以在官网进行下载 https://redis.io/download选择Stable &…

快速排序简便记_建立和测试股票交易策略的快速简便方法

快速排序简便记Note from Towards Data Science’s editors: While we allow independent authors to publish articles in accordance with our rules and guidelines, we do not endorse each author’s contribution. You should not rely on an author’s works without se…

robot:List变量的使用注意点

创建list类型变量&#xff0c;两种方式&#xff0c;建议使用Create List关键字 使用该列表变量时需要变为${}方式&#xff0c;切记切记&#xff01; 转载于:https://www.cnblogs.com/gcgc/p/11429482.html

python基础教程(十一)

迭代器 本节进行迭代器的讨论。只讨论一个特殊方法---- __iter__ &#xff0c;这个方法是迭代器规则的基础。 迭代器规则 迭代的意思是重复做一些事很多次---就像在循环中做的那样。__iter__ 方法返回一个迭代器&#xff0c;所谓迭代器就是具有next方法的对象&#xff0c;在调…

美剧迷失_迷失(机器)翻译

美剧迷失Machine translation doesn’t generate as much excitement as other emerging areas in NLP these days, in part because consumer-facing services like Google Translate have been around since April 2006.如今&#xff0c;机器翻译并没有像其他NLP新兴领域那样…