前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Hyperledger Fabric 2.x Java区块链应用

Hyperledger Fabric 2.x Java区块链应用

作者头像
陶陶技术笔记
发布2022-02-25 09:55:58
9940
发布2022-02-25 09:55:58
举报
文章被收录于专栏:陶陶技术笔记

一、说明

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

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

网络拓扑图:

应用程序将各自的网络交互委托给其网关,每个网关都了解网络信道拓扑,包括组织的多个Peer节点和排序节点,使应用程序专注于业务逻辑;Peer节点可以使用gossip协议在组织内部和组织之间相互通信。

二、Mavn依赖

添加网关sdk的依赖:

代码语言:javascript
复制
<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 内容如下:

代码语言:javascript
复制
{
    "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 中添加以下内容,用于访问网关的相关配置:

代码语言:javascript
复制
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对象,代码如下:

代码语言:javascript
复制
/**
 * 连接网关
 */
@Bean
public 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();
}

/**
 * 获取通道
 */
@Bean
public Network network(Gateway gateway) {
  return gateway.getNetwork(this.channelName);
}

/**
 * 获取合约
 */
@Bean
public Contract contract(Network network) {
  return network.getContract(this.contractName);
}

五、合约调用

创建controller类,注入Contract对象调用合约方法:

代码语言:javascript
复制
@Resource
private Contract contract;

@Resource
private 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

代码语言:javascript
复制
http://127.0.0.1:9001/getUser?userId=1

返回:

代码语言:javascript
复制
{
  "money": 300,
  "name": "zlt",
  "userId": "1"
}

调用接口 addUser

代码语言:javascript
复制
http://127.0.0.1:9001/addUser?userId=6&userName=test6&money=600

返回:

代码语言:javascript
复制
2ae291bb6a366b5ba01ad49e4237da8def9e9828cc2c982e8c49d4b763af0157

七、代码下载

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

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

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-02-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 陶陶技术笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、说明
  • 二、Mavn依赖
  • 三、准备配置文件
    • 3.1. 准备网络证书
      • 3.2. 创建网络配置
        • 3.3. SpringBoot配置
        • 四、连接合约
        • 五、合约调用
        • 六、测试接口
        • 七、代码下载
        相关产品与服务
        区块链
        云链聚未来,协同无边界。腾讯云区块链作为中国领先的区块链服务平台和技术提供商,致力于构建技术、数据、价值、产业互联互通的区块链基础设施,引领区块链底层技术及行业应用创新,助力传统产业转型升级,推动实体经济与数字经济深度融合。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档