本文共 51436 字,大约阅读时间需要 171 分钟。
Hyperledger Fabric 1.0 从零开始(十)——智能合约(参阅:)
Hyperledger Fabric 1.0 从零开始(十一)——CouchDB(参阅:)
上述两章,最近网上各路大神文章云集,方案多多,因为最近工作太忙太忙,我暂时就先不赘述了,可以优先参考深蓝大大的文章。
这章先捡大家都比较在意的java sdk应用方案贴出来,很多朋友都找我要过,我主要是把注释都写进去了,用法简单了说了下,一般情况下会java开发的都能看懂。
年前实在太忙。
官方在Fabric1.0之后就推荐使用SDK来实现交互的操作,原本在0.6上的restapi已经被废弃。JAVA-SDK可以参考。官方给的SDK的DEMO很难入手,注释稀少内容还很杂,所幸感谢github上有位朋友(具体地址实在是找不到了,以后会补上)稍加整理了一下,直接重写了官方的DEMO,让像我这样的新人更容易入手。
本次在官方SDK和大神重新的DEMO的基础上做了一次整理,能够更加清晰简单的入门并使用JAVA-SDK来进行交互。
相信看到这里的朋友应该都对Fabric已经有了足够的了解,至少是应用层上已经可以实现分布式账本的各项功能,sdk也是在这样的基础进行讲述。
首先看下针对JAVA-SDK所写的辅助工程目录
关于Fabric,我们知道一个channel中可以创建多个chaincode,而一个chaincode需要指定对应orderer和peer。
所以,在此建立了一个bean目录来存放自定义的chaincode、orderer和peer对象。这几个对象都包含各自最基本的访问属性。
具体对应关系如下:
bean.Chaincode - Fabric创建的chaincode信息,涵盖所属channel等信息
bean.Orderers - Fabric创建的orderer信息,涵盖单机和集群两种方案
bean.Peers - Fabric创建的peer信息,包含有cli、org、ca、couchdb等节点服务器关联启动服务信息集合
ChaincodeManager - 智能合约操作总控制器
FabricConfig - 智能合约操作总参数配置器
FabricOrg - 联盟组织对象
FabricUser - 联盟用户对象
FabricStore - 联盟存储配置对象
直接通过代码来看实现
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.com10 */11 public class Chaincode {12 13 /** 当前将要访问的智能合约所属频道名称 */14 private String channelName; // ffetest15 /** 智能合约名称 */16 private String chaincodeName; // ffetestcc17 /** 智能合约安装路径 */18 private String chaincodePath; // github.com/hyperledger/fabric/xxx/chaincode/go/example/test19 /** 智能合约版本号 */20 private String chaincodeVersion; // 1.021 /** 执行智能合约操作等待时间 */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 }
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 aberic10 *11 * @date 2017年10月18日 - 下午1:56:4812 * @email abericyang@gmail.com13 */14 public class Orderers {15 16 /** orderer 排序服务器所在根域名 */17 private String ordererDomainName; // anti-moth.com18 /** orderer 排序服务器集合 */19 private Listorderers;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 get() {40 return orderers;41 }42 43 /**44 * 排序服务器对象45 * 46 * @author aberic47 *48 * @date 2017年10月18日 - 下午2:06:2249 * @email abericyang@gmail.com50 */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 }
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 Listpeers; 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 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 }
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 Setroles; 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 mspID105 * 会员id106 */107 public void setMspId(String mspID) {108 this.mspId = mspID;109 saveState();110 }111 112 @Override113 public String getMspId() {114 return this.mspId;115 }116 117 @Override118 public String getName() {119 return this.name;120 }121 122 /**123 * 设置规则信息并将用户状�?�更新至存储配置对象124 * 125 * @param roles126 * 规则127 */128 public void setRoles(Set roles) {129 this.roles = roles;130 saveState();131 }132 133 @Override134 public Set getRoles() {135 return this.roles;136 }137 138 public String getEnrollmentSecret() {139 return enrollmentSecret;140 }141 142 /**143 * 设置注册操作的密钥信息并将用户状态更新至存储配置对象144 * 145 * @param enrollmentSecret146 * 注册操作的密�?147 */148 public void setEnrollmentSecret(String enrollmentSecret) {149 this.enrollmentSecret = enrollmentSecret;150 saveState();151 }152 153 /**154 * 设置注册登记操作信息并将用户状�?�更新至存储配置对象155 * 156 * @param enrollment157 * 注册登记操作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 }
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 MapuserMap = new HashMap<>(); 45 /** 本地节点集合 */ 46 Map peerLocations = new HashMap<>(); 47 /** 本地排序服务集合 */ 48 Map ordererLocations = new HashMap<>(); 49 /** 本地事件集合 */ 50 Map eventHubLocations = new HashMap<>(); 51 /** 节点集合 */ 52 Set 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 admin110 * 联盟管理员用户111 */112 public void setAdmin(FabricUser admin) {113 this.admin = admin;114 }115 116 /**117 * 获取会员id118 * 119 * @return 会员id120 */121 public String getMSPID() {122 return mspid;123 }124 125 /**126 * 设置本地ca127 * 128 * @param caLocation129 * 本地ca130 */131 public void setCALocation(String caLocation) {132 this.caLocation = caLocation;133 }134 135 /**136 * 获取本地ca137 * 138 * @return 本地ca139 */140 public String getCALocation() {141 return this.caLocation;142 }143 144 /**145 * 添加本地节点146 * 147 * @param name148 * 节点key149 * @param location150 * 节点151 */152 public void addPeerLocation(String name, String location) {153 peerLocations.put(name, location);154 }155 156 /**157 * 添加本地组织158 * 159 * @param name160 * 组织key161 * @param location162 * 组织163 */164 public void addOrdererLocation(String name, String location) {165 ordererLocations.put(name, location);166 }167 168 /**169 * 添加本地事件170 * 171 * @param name172 * 事件key173 * @param location174 * 事件175 */176 public void addEventHubLocation(String name, String location) {177 eventHubLocations.put(name, location);178 }179 180 /**181 * 获取本地节点182 * 183 * @param name184 * 节点key185 * @return 节点186 */187 public String getPeerLocation(String name) {188 return peerLocations.get(name);189 }190 191 /**192 * 获取本地组织193 * 194 * @param name195 * 组织key196 * @return 组织197 */198 public String getOrdererLocation(String name) {199 return ordererLocations.get(name);200 }201 202 /**203 * 获取本地事件204 * 205 * @param name206 * 事件key207 * @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 getPeerNames() {219 return Collections.unmodifiableSet(peerLocations.keySet());220 }221 222 /**223 * 获取一个不可修改的本地节点集合224 * 225 * @return 节点集合226 */227 public Set getPeers() {228 return Collections.unmodifiableSet(peers);229 }230 231 /**232 * 获取一个不可修改的本地组织key集合233 * 234 * @return 组织key集合235 */236 public Set getOrdererNames() {237 return Collections.unmodifiableSet(ordererLocations.keySet());238 }239 240 /**241 * 获取一个不可修改的本地组织集合242 * 243 * @return 组织集合244 */245 public Collection getOrdererLocations() {246 return Collections.unmodifiableCollection(ordererLocations.values());247 }248 249 /**250 * 获取一个不可修改的本地事件key集合251 * 252 * @return 事件key集合253 */254 public Set getEventHubNames() {255 return Collections.unmodifiableSet(eventHubLocations.keySet());256 }257 258 /**259 * 获取一个不可修改的本地事件集合260 * 261 * @return 事件集合262 */263 public Collection getEventHubLocations() {264 return Collections.unmodifiableCollection(eventHubLocations.values());265 }266 267 /**268 * 设置 ca 客户端269 * 270 * @param caClient271 * 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 user290 * 用户291 */292 public void addUser(FabricUser user) {293 userMap.put(user.getName(), user);294 }295 296 /**297 * 从用户集合根据名称获取用户298 * 299 * @param name300 * 名称301 * @return 用户302 */303 public User getUser(String name) {304 return userMap.get(name);305 }306 307 /**308 * 向节点集合中添加节点309 * 310 * @param peer311 * 节点312 */313 public void addPeer(Peer peer) {314 peers.add(peer);315 }316 317 /**318 * 设置 ca 配置319 * 320 * @param caProperties321 * 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 peerAdmin340 * 联盟单节点管理员用户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 doainName359 * 域名名称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 directorys378 * 指定路径379 * @return File380 */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 }
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 Mapmembers = 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 name118 * 名称119 * @param org120 * 组织121 * @param mspId122 * 会员id123 * @param privateKeyFile124 * @param certificateFile125 * 126 * @return user 用户127 * 128 * @throws IOException129 * @throws NoSuchAlgorithmException130 * @throws NoSuchProviderException131 * @throws InvalidKeySpecException132 */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 data171 * 字节数组172 * 173 * @return 私钥174 * 175 * @throws IOException176 * @throws NoSuchProviderException177 * @throws NoSuchAlgorithmException178 * @throws InvalidKeySpecException179 */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 yangyi47202 *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 @Override219 public PrivateKey getKey() {220 return privateKey;221 }222 223 @Override224 public String getCert() {225 return certificate;226 }227 }228 229 }
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 }
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"); //testing113 // 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 @Override152 public void received(BlockEvent event) {153 // TODO154 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 // TODO168 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 fcn185 * 方法名186 * @param args187 * 参数数组188 * @return189 * @throws InvalidArgumentException190 * @throws ProposalException191 * @throws InterruptedException192 * @throws ExecutionException193 * @throws TimeoutException194 * @throws IOException 195 * @throws TransactionException 196 * @throws CryptoException 197 * @throws InvalidKeySpecException 198 * @throws NoSuchProviderException 199 * @throws NoSuchAlgorithmException 200 */201 public Mapinvoke(String fcn, String[] args)202 throws InvalidArgumentException, ProposalException, InterruptedException, ExecutionException, TimeoutException, NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException, CryptoException, TransactionException, IOException {203 Map resultMap = new HashMap<>();204 205 Collection successful = new LinkedList<>();206 Collection failed = new LinkedList<>();207 208 /// Send transaction proposal to all peers209 TransactionProposalRequest transactionProposalRequest = client.newTransactionProposalRequest();210 transactionProposalRequest.setChaincodeID(chaincodeID);211 transactionProposalRequest.setFcn(fcn);212 transactionProposalRequest.setArgs(args);213 214 Map 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 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 > 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 fcn271 * 方法名272 * @param args273 * 参数数组274 * @return275 * @throws InvalidArgumentException276 * @throws ProposalException277 * @throws IOException 278 * @throws TransactionException 279 * @throws CryptoException 280 * @throws InvalidKeySpecException 281 * @throws NoSuchProviderException 282 * @throws NoSuchAlgorithmException 283 */284 public Map query(String fcn, String[] args) throws InvalidArgumentException, ProposalException, NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException, CryptoException, TransactionException, IOException {285 Map 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 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 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://zpgia.baihongyu.com/