一、阐明

在上一篇文章中 《Hyperledger Fabric 2.x 自定义智能合约》 分享了智能合约的装置并应用 cli 客户端进行合约的调用;本文将应用 Java 代码基于 fabric-gateway-java 进行区块链网络的拜访与交易,并集成 SpringBoot 框架。

Fabric Gateway SDK 实现Fabric的编程模型,提供了一系列简略的API给应用程序与Fabric区块链网络进行交互;

网络拓扑图:

应用程序将各自的网络交互委托给其网关,每个网关都理解网络信道拓扑,包含组织的多个Peer节点和排序节点,使应用程序专一于业务逻辑;Peer节点能够应用gossip协定在组织外部和组织之间互相通信。

 

二、Mavn依赖

增加网关sdk的依赖:

<dependency>        <groupId>org.hyperledger.fabric</groupId>        <artifactId>fabric-gateway-java</artifactId>        <version>2.2.3</version></dependency>

 

三、筹备配置文件

工程的目录构造如下图所示:

 

3.1. 筹备网络证书

创立目录 crypto-configordererpeer 节点的证书文件复制进来。

证书文件从 fabric-samplestest-network 目录中复制 ordererOrganizationspeerOrganizations 文件夹:

 

3.2. 创立网络配置

创立文件 connection.json 内容如下:

{    "name": "basic-network",    "version": "1.0.0",    "client": {        "organization": "Org1",        "connection": {            "timeout": {                "peer": {                    "endorser": "300"                },                "orderer": "300"            }        }    },    "channels": {        "mychannel": {            "orderers": [                "orderer.example.com"            ],            "peers": {                "peer0.org1.example.com": {                    "endorsingPeer": true,                    "chaincodeQuery": true,                    "ledgerQuery": true,                    "eventSource": true                },                "peer0.org2.example.com": {                    "endorsingPeer": true,                    "chaincodeQuery": true,                    "ledgerQuery": true,                    "eventSource": true                }            }        }    },    "organizations": {        "Org1": {            "mspid": "Org1MSP",            "peers": [                "peer0.org1.example.com"            ],            "certificateAuthorities": [                "ca-org1"            ],            "adminPrivateKeyPEM": {                "path": "src/main/resources/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/keystore/priv_sk"            },            "signedCertPEM": {                "path": "src/main/resources/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/signcerts/Admin@org1.example.com-cert.pem"            }        },        "Org2": {            "mspid": "Org2MSP",            "peers": [                "peer0.org2.example.com"            ],            "certificateAuthorities": [                "ca-org2"            ],            "adminPrivateKeyPEM": {                "path": "src/main/resources/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp/keystore/priv_sk"            },            "signedCertPEM": {                "path": "src/main/resources/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp/signcerts/Admin@org2.example.com-cert.pem"            }        }    },    "orderers": {        "orderer.example.com": {            "url": "grpcs://192.168.28.134:7050",            "mspid": "OrdererMSP",            "grpcOptions": {                "ssl-target-name-override": "orderer.example.com",                "hostnameOverride": "orderer.example.com"            },            "tlsCACerts": {                "path": "src/main/resources/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/ca.crt"            },            "adminPrivateKeyPEM": {                "path": "src/main/resources/crypto-config/ordererOrganizations/example.com/users/Admin@example.com/msp/keystore/priv_sk"            },            "signedCertPEM": {                "path": "src/main/resources/crypto-config/ordererOrganizations/example.com/users/Admin@example.com/msp/signcerts/Admin@example.com-cert.pem"            }        }    },    "peers": {        "peer0.org1.example.com": {            "url": "grpcs://192.168.28.134:7051",            "grpcOptions": {                "ssl-target-name-override": "peer0.org1.example.com",                "hostnameOverride": "peer0.org1.example.com",                "request-timeout": 120001            },            "tlsCACerts": {                "path": "src/main/resources/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt"            }        },        "peer0.org2.example.com": {            "url": "grpcs://192.168.28.134:9051",            "grpcOptions": {                "ssl-target-name-override": "peer0.org2.example.com",                "hostnameOverride": "peer0.org2.example.com",                "request-timeout": 120001            },            "tlsCACerts": {                "path": "src/main/resources/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt"            }        }    },    "certificateAuthorities": {        "ca-org1": {            "url": "https://192.168.28.134:7054",            "grpcOptions": {                "verify": true            },            "tlsCACerts": {                "path": "src/main/resources/crypto-config/peerOrganizations/org1.example.com/ca/ca.org1.example.com-cert.pem"            },            "registrar": [                {                    "enrollId": "admin",                    "enrollSecret": "adminpw"                }            ]        },        "ca-org2": {            "url": "https://192.168.28.134:8054",            "grpcOptions": {                "verify": true            },            "tlsCACerts": {                "path": "src/main/resources/crypto-config/peerOrganizations/org2.example.com/ca/ca.org2.example.com-cert.pem"            },            "registrar": [                {                    "enrollId": "admin",                    "enrollSecret": "adminpw"                }            ]        }    }}
需按理论状况批改url中的地址,内容中别离蕴含了 channelsorganizationsordererspeersca 的配置

 

3.3. SpringBoot配置

application.yml 中增加以下内容,用于拜访网关的相干配置:

fabric:  # wallet文件夹门路(主动创立)  walletDirectory: wallet  # 网络配置文件门路  networkConfigPath: connection.json  # 用户证书门路  certificatePath: crypto-config/peerOrganizations/org1.example.com/users/User1@org1.example.com/msp/signcerts/User1@org1.example.com-cert.pem  # 用户私钥门路  privateKeyPath: crypto-config/peerOrganizations/org1.example.com/users/User1@org1.example.com/msp/keystore/priv_sk  # 拜访的组织名  mspid: Org1MSP  # 用户名  username: user1  # 通道名字  channelName: mychannel  # 链码名字  contractName: mycc

 

四、连贯合约

别离构建网关、通道和合约的Bean对象,代码如下:

/** * 连贯网关 */@Beanpublic Gateway connectGateway() throws IOException, InvalidKeyException, CertificateException {        //应用org1中的user1初始化一个网关wallet账户用于连贯网络        Wallet wallet = Wallets.newFileSystemWallet(Paths.get(this.walletDirectory));        X509Certificate certificate = readX509Certificate(Paths.get(this.certificatePath));        PrivateKey privateKey = getPrivateKey(Paths.get(this.privateKeyPath));        wallet.put(username, Identities.newX509Identity(this.mspid, certificate, privateKey));        //依据connection.json 获取Fabric网络连接对象        Gateway.Builder builder = Gateway.createBuilder()                        .identity(wallet, username)                        .networkConfig(Paths.get(this.networkConfigPath));        //连贯网关        return builder.connect();}/** * 获取通道 */@Beanpublic Network network(Gateway gateway) {        return gateway.getNetwork(this.channelName);}/** * 获取合约 */@Beanpublic Contract contract(Network network) {        return network.getContract(this.contractName);}

 

五、合约调用

创立controller类,注入Contract对象调用合约办法:

@Resourceprivate Contract contract;@Resourceprivate Network network;@GetMapping("/getUser")public String getUser(String userId) throws ContractException {        byte[] queryAResultBefore = contract.evaluateTransaction("getUser",userId);        return new String(queryAResultBefore, StandardCharsets.UTF_8);}@GetMapping("/addUser")public String addUser(String userId, String userName, String money) throws ContractException, InterruptedException, TimeoutException {        byte[] invokeResult = contract.createTransaction("addUser")                        .setEndorsingPeers(network.getChannel().getPeers(EnumSet.of(Peer.PeerRole.ENDORSING_PEER)))                        .submit(userId, userName, money);        String txId = new String(invokeResult, StandardCharsets.UTF_8);        return txId;}

 

六、测试接口

调用接口 getUser

http://127.0.0.1:9001/getUser?userId=1

返回:

{  "money": 300,  "name": "zlt",  "userId": "1"}

 

调用接口 addUser

http://127.0.0.1:9001/addUser?userId=6&userName=test6&money=600

返回:

2ae291bb6a366b5ba01ad49e4237da8def9e9828cc2c982e8c49d4b763af0157

 

七、代码下载

gitee:https://gitee.com/zlt2000/my-fabric-application-java

github:https://github.com/zlt2000/my-fabric-application-java

 

扫码关注有惊喜!