zoukankan      html  css  js  c++  java
  • 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:Usersyangyi47AppDataLocalTemp
     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来执行查询操作,一来没必要,二来该操作会生成数据集,且数据集也会发送给排序服务器,得不偿失。

  • 相关阅读:
    嵌入式交叉编译环境的搭建
    linux驱动模块编写规范以及Makefiel文件的编写规范
    socket通信
    傀儡进程脱壳三步曲
    Thymeleaf 学习笔记-实例demo(中文教程)
    IntelliJ IDEA 快捷键
    github团队协作教程
    thymeleaf 学习笔记-基础篇(中文教程)
    二维码的生成
    .Net Core Web Api实践(四)填坑连接Redis时Timeout performing EVAL
  • 原文地址:https://www.cnblogs.com/aberic/p/8206551.html
Copyright © 2011-2022 走看看