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.pswp.cn/news/391543.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/391543.shtml
英文地址,請注明出處:http://en.pswp.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…

將json 填入表格_如何將Google表格用作JSON端點

將json 填入表格UPDATE: 5/13/2020 - New Share Dialog Box steps available below.更新&#xff1a;5/13/2020-下面提供了 新共享對話框步驟。 Thanks Erica H!謝謝埃里卡H&#xff01; Are you building a prototype dynamic web application and need to collaborate with …

leetcode 173. 二叉搜索樹迭代器

實現一個二叉搜索樹迭代器類BSTIterator &#xff0c;表示一個按中序遍歷二叉搜索樹&#xff08;BST&#xff09;的迭代器&#xff1a; BSTIterator(TreeNode root) 初始化 BSTIterator 類的一個對象。BST 的根節點 root 會作為構造函數的一部分給出。指針應初始化為一個不存在…

jyputer notebook 、jypyter、IPython basics

1 、修改jupyter默認工作目錄&#xff1a;打開cmd&#xff0c;在命令行下指定想要進的工作目錄&#xff0c;即鍵入“cd d/ G:\0工作面試\學習記錄”標紅部分是想要進入的工作目錄。 2、Tab補全 a、在命令行輸入表達式時&#xff0c;按下Tab鍵即可為任意變量&#xff08;對象、…

cookie和session(1)

cookie和session 1.cookie產生 識別用戶 HTTP是無狀態協議&#xff0c;這就回出現這種現象&#xff1a;當你登錄一個頁面&#xff0c;然后轉到登錄網站的另一個頁面&#xff0c;服務器無法認識到。或者說兩次的訪問&#xff0c;服務器不能認識到是同一個客戶端的訪問&#xff0…

熊貓數據集_為數據科學拆箱熊貓

熊貓數據集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…

2018年,你想從InfoQ獲取什么內容?丨Q言Q語

- Q 言 Q 語 第 三 期 - Q言Q語是 InfoQ 推出的最新板塊&#xff0c; 旨在給所有 InfoQer 一個展示觀點的平臺。 每期一個主題&#xff0c; 不扣帽子&#xff0c;不論對錯&#xff0c;不看輸贏&#xff0c; 只愿跟有趣的靈魂相遇。 本期話題&#xff1a; 2018年&#xff0c;你想…

特征阻抗輸入阻抗輸出阻抗_軟件阻抗說明

特征阻抗輸入阻抗輸出阻抗by Milan Mimica米蘭米米卡(Milan Mimica) 軟件阻抗說明 (Software impedance explained) 數據處理組件之間的阻抗不匹配 (The impedance mismatch between data processing components) It all starts with the simplest signal-processing diagram …

數學建模3

數學建模3 轉載于:https://www.cnblogs.com/Forever77/p/11423169.html

leetcode 190. 顛倒二進制位(位運算)

顛倒給定的 32 位無符號整數的二進制位。 提示&#xff1a; 請注意&#xff0c;在某些語言&#xff08;如 Java&#xff09;中&#xff0c;沒有無符號整數類型。在這種情況下&#xff0c;輸入和輸出都將被指定為有符號整數類型&#xff0c;并且不應影響您的實現&#xff0c;因…

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 …

adb 多點觸碰_無法觸及的神話

adb 多點觸碰On Twitter, in Slack, on Discord, in IRC, or wherever you hang out with other developers on the internet, you may have heard some formulation of the following statements:在Twitter上&#xff0c;在Slack中&#xff0c;在Discord中&#xff0c;在IRC…

robot:循環遍歷數據庫查詢結果是否滿足要求

使用list類型變量{}接收查詢結果&#xff0c;再for循環遍歷每行數據&#xff0c;取出需要比較的數值 轉載于:https://www.cnblogs.com/gcgc/p/11424114.html

leetcode 74. 搜索二維矩陣(二分)

編寫一個高效的算法來判斷 m x n 矩陣中&#xff0c;是否存在一個目標值。該矩陣具有如下特性&#xff1a; 每行中的整數從左到右按升序排列。 每行的第一個整數大于前一行的最后一個整數。 示例 1&#xff1a; 輸入&#xff1a;matrix [[1,3,5,7],[10,11,16,20],[23,30,34…

rm命令

命令 ‘rm’ &#xff08;remove&#xff09;&#xff1a;刪除一個目錄中的一個或多個文件或目錄&#xff0c;也可以將某個目錄及其下屬的所有文件及其子目錄均刪除掉 語法&#xff1a;rm&#xff08;選項&#xff09;&#xff08;參數&#xff09; 默認會提示‘是否’刪除&am…

javascript消除字符串兩邊空格的兩種方式,面向對象和函數式編程。python oop在調用時候的優點...

主要是javascript中消除字符串空格&#xff0c;比較兩種方式的不同 //面向對象&#xff0c;消除字符串兩邊空格 String.prototype.trim function() { return this.replace(/(^\s*)|(\s*$)/g, ""); };//去左右空格的函數; function trim(s){return s.replace(/(^\s*)…

如何使用Retrofit,OkHttp,Gson,Glide和Coroutines處理RESTful Web服務

Kriptofolio應用程序系列-第5部分 (Kriptofolio app series — Part 5) These days almost every Android app connects to internet to get/send data. You should definitely learn how to handle RESTful Web Services, as their correct implementation is the core knowle…

leetcode 90. 子集 II(回溯算法)

給你一個整數數組 nums &#xff0c;其中可能包含重復元素&#xff0c;請你返回該數組所有可能的子集&#xff08;冪集&#xff09;。 解集 不能 包含重復的子集。返回的解集中&#xff0c;子集可以按 任意順序 排列。 示例 1&#xff1a; 輸入&#xff1a;nums [1,2,2] 輸…