• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

fabric-gateway-java 调用虚拟机上的fabric链码,以fabcar为例

武飞扬头像
zxingyu
帮助1

作为学习的记录。我是在虚拟机上搭建了fabric网络和通道,并部署了官方示例fabcar链码,现在想在windows上通过fabric-gateway-java 实现对fabric上链码的调用。


fabric的版本是2.4.0,编译器是IDEA,代码基于springboot框架。

fanric环境的搭建、test-network及通道的创建、链码的部署这里不再赘述。


首先导入如下依赖:

  1.  
    <dependency>
  2.  
    <groupId>org.hyperledger.fabric-sdk-java</groupId>
  3.  
    <artifactId>fabric-sdk-java</artifactId>
  4.  
    <version>1.4.7</version>
  5.  
    </dependency>
  6.  
     
  7.  
    <dependency>
  8.  
    <groupId>org.hyperledger.fabric</groupId>
  9.  
    <artifactId>fabric-gateway-java</artifactId>
  10.  
    <version>2.2.0</version>
  11.  
    </dependency>

代码的结构,我的结构是这样的:

学新通

 首先,我们需要将test-network建立好之后,文件夹test-neteork/organizations下的orderorganizations和peerorganizations文件从虚拟机中复制到代码中,我是放在了resources/crypto-config目录下。

随后写的是链接建立文件,connection.json。

  1.  
    {
  2.  
    "name": "basic-network",
  3.  
    "version": "1.0.0",
  4.  
    "dependencies": {
  5.  
    },
  6.  
    "client": {
  7.  
    "organization": "Org1",
  8.  
    "connection": {
  9.  
    "timeout": {
  10.  
    "peer": {
  11.  
    "endorser": "300"
  12.  
    },
  13.  
    "orderer": "300"
  14.  
    }
  15.  
    }
  16.  
    },
  17.  
    "channels": {
  18.  
    "mychannel": {
  19.  
    "orderers": [
  20.  
    "orderer.example.com"
  21.  
    ],
  22.  
    "peers": {
  23.  
    "peer0.org1.example.com": {
  24.  
    "endorsingPeer": true,
  25.  
    "chaincodeQuery": true,
  26.  
    "ledgerQuery": true,
  27.  
    "eventSource": true
  28.  
    },
  29.  
    "peer0.org2.example.com": {
  30.  
    "endorsingPeer": true,
  31.  
    "chaincodeQuery": true,
  32.  
    "ledgerQuery": true,
  33.  
    "eventSource": true
  34.  
    }
  35.  
    }
  36.  
    }
  37.  
    },
  38.  
    "organizations": {
  39.  
    "Org1": {
  40.  
    "mspid": "Org1MSP",
  41.  
    "peers": [
  42.  
    "peer0.org1.example.com"
  43.  
    ],
  44.  
    "certificateAuthorities": [
  45.  
    "ca-org1"
  46.  
    ],
  47.  
    "adminPrivateKeyPEM": {
  48.  
    "path": "src/main/resources/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/keystore/priv_sk"
  49.  
    },
  50.  
    "signedCertPEM": {
  51.  
    "path": "src/main/resources/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/signcerts/Admin@org1.example.com-cert.pem"
  52.  
    }
  53.  
    },
  54.  
    "Org2": {
  55.  
    "mspid": "Org2MSP",
  56.  
    "peers": [
  57.  
    "peer0.org2.example.com"
  58.  
    ],
  59.  
    "certificateAuthorities": [
  60.  
    "ca-org2"
  61.  
    ],
  62.  
    "adminPrivateKeyPEM": {
  63.  
    "path": "src/main/resources/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp/keystore/priv_sk"
  64.  
    },
  65.  
    "signedCertPEM": {
  66.  
    "path": "src/main/resources/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp/signcerts/Admin@org2.example.com-cert.pem"
  67.  
    }
  68.  
    }
  69.  
    },
  70.  
    "orderers": {
  71.  
    "orderer.example.com": {
  72.  
    "url": "grpcs://192.168.16.129:7050",
  73.  
    "mspid": "OrdererMSP",
  74.  
    "grpcOptions": {
  75.  
    "ssl-target-name-override": "orderer.example.com",
  76.  
    "hostnameOverride": "orderer.example.com"
  77.  
    },
  78.  
    "tlsCACerts": {
  79.  
    "path": "src/main/resources/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/ca.crt"
  80.  
    },
  81.  
    "adminPrivateKeyPEM": {
  82.  
    "path": "src/main/resources/crypto-config/ordererOrganizations/example.com/users/Admin@example.com/msp/keystore/priv_sk"
  83.  
    },
  84.  
    "signedCertPEM": {
  85.  
    "path": "src/main/resources/crypto-config/ordererOrganizations/example.com/users/Admin@example.com/msp/signcerts/Admin@example.com-cert.pem"
  86.  
    }
  87.  
    }
  88.  
    },
  89.  
    "peers": {
  90.  
    "peer0.org1.example.com": {
  91.  
    "url": "grpcs://192.168.16.129:7051",
  92.  
    "grpcOptions": {
  93.  
    "ssl-target-name-override": "peer0.org1.example.com",
  94.  
    "hostnameOverride": "peer0.org1.example.com",
  95.  
    "request-timeout": 120001
  96.  
    },
  97.  
    "tlsCACerts": {
  98.  
    "path": "src/main/resources/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt"
  99.  
    }
  100.  
    },
  101.  
    "peer0.org2.example.com": {
  102.  
    "url": "grpcs://192.168.16.129:9051",
  103.  
    "grpcOptions": {
  104.  
    "ssl-target-name-override": "peer0.org2.example.com",
  105.  
    "hostnameOverride": "peer0.org2.example.com",
  106.  
    "request-timeout": 120001
  107.  
    },
  108.  
    "tlsCACerts": {
  109.  
    "path": "src/main/resources/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt"
  110.  
    }
  111.  
    }
  112.  
    },
  113.  
    "certificateAuthorities": {
  114.  
    "ca-org1": {
  115.  
    "url": "https://192.168.16.129:7054",
  116.  
    "grpcOptions": {
  117.  
    "verify": true
  118.  
    },
  119.  
    "tlsCACerts": {
  120.  
    "path": "src/main/resources/crypto-config/peerOrganizations/org1.example.com/ca/ca.org1.example.com-cert.pem"
  121.  
    },
  122.  
    "registrar": [
  123.  
    {
  124.  
    "enrollId": "admin",
  125.  
    "enrollSecret": "adminpw"
  126.  
    }
  127.  
    ]
  128.  
    },
  129.  
    "ca-org2": {
  130.  
    "url": "https://192.168.16.129:8054",
  131.  
    "grpcOptions": {
  132.  
    "verify": true
  133.  
    },
  134.  
    "tlsCACerts": {
  135.  
    "path": "src/main/resources/crypto-config/peerOrganizations/org2.example.com/ca/ca.org2.example.com-cert.pem"
  136.  
    },
  137.  
    "registrar": [
  138.  
    {
  139.  
    "enrollId": "admin",
  140.  
    "enrollSecret": "adminpw"
  141.  
    }
  142.  
    ]
  143.  
    }
  144.  
    }
  145.  
    }
  146.  
     
学新通

其中的ip换成自己虚拟机的ip,文件路径根据自己存放的orderorganizations和peerorganizations的目录进行调整。

之后配置properties文件:

  1.  
    fabric.networkConnectionConfigPath = src/main/resources/connection.json
  2.  
     
  3.  
    fabric.certificatePath = src/main/resources/crypto-config/peerOrganizations/org1.example.com/users/User1@org1.example.com/msp/signcerts/User1@org1.example.com-cert.pem
  4.  
     
  5.  
    fabric.privateKeyPath = src/main/resources/crypto-config/peerOrganizations/org1.example.com/users/User1@org1.example.com/msp/keystore/priv_sk

指定了,connection,json文件的位置,和后续链接用到的私钥和证书目录。

之后就可以开始写代码了hh。

首先是配置类的代码,主要功能是从properties文件中读取需要的参数值

  1.  
    import lombok.Data;
  2.  
    import org.springframework.boot.context.properties.ConfigurationProperties;
  3.  
    import org.springframework.context.annotation.Configuration;
  4.  
     
  5.  
    @Configuration
  6.  
    @ConfigurationProperties(prefix = "fabric")
  7.  
    @Data
  8.  
     
  9.  
    public class HyperLedgerFabricProperties {
  10.  
     
  11.  
     
  12.  
    String networkConnectionConfigPath;
  13.  
    String certificatePath;
  14.  
    String privateKeyPath;
  15.  
     
  16.  
     
  17.  
    }
学新通

之后还是一个配置类,用来获取gateway.

  1.  
    import lombok.AllArgsConstructor;
  2.  
    import lombok.extern.slf4j.Slf4j;
  3.  
    import org.hyperledger.fabric.gateway.Gateway;
  4.  
    import org.hyperledger.fabric.gateway.Identities;
  5.  
    import org.hyperledger.fabric.gateway.Wallet;
  6.  
    import org.hyperledger.fabric.gateway.Wallets;
  7.  
    import org.springframework.context.annotation.Bean;
  8.  
    import org.springframework.context.annotation.Configuration;
  9.  
     
  10.  
    import java.io.BufferedReader;
  11.  
    import java.nio.charset.StandardCharsets;
  12.  
    import java.nio.file.Files;
  13.  
    import java.nio.file.Paths;
  14.  
    import java.security.PrivateKey;
  15.  
    import java.security.cert.X509Certificate;
  16.  
    import java.util.concurrent.TimeUnit;
  17.  
     
  18.  
    @Configuration
  19.  
    @AllArgsConstructor
  20.  
    @Slf4j
  21.  
    public class HyperLedgerConfig {
  22.  
     
  23.  
    final HyperLedgerFabricProperties hyperLedgerFabricProperties;
  24.  
     
  25.  
    @Bean
  26.  
    public Gateway gateway() throws Exception {
  27.  
     
  28.  
     
  29.  
    BufferedReader certificateReader = Files.newBufferedReader(Paths.get(hyperLedgerFabricProperties.getCertificatePath()), StandardCharsets.UTF_8);
  30.  
     
  31.  
    X509Certificate certificate = Identities.readX509Certificate(certificateReader);
  32.  
     
  33.  
    BufferedReader privateKeyReader = Files.newBufferedReader(Paths.get(hyperLedgerFabricProperties.getPrivateKeyPath()), StandardCharsets.UTF_8);
  34.  
     
  35.  
    PrivateKey privateKey = Identities.readPrivateKey(privateKeyReader);
  36.  
     
  37.  
    Wallet wallet = Wallets.newInMemoryWallet();
  38.  
    wallet.put("user1" , Identities.newX509Identity("Org1MSP", certificate , privateKey));
  39.  
     
  40.  
     
  41.  
    Gateway.Builder builder = Gateway.createBuilder()
  42.  
    .identity(wallet , "user1")
  43.  
    .networkConfig(Paths.get("src/main/resources/connection.json"));
  44.  
     
  45.  
    Gateway gateway = builder.connect();
  46.  
     
  47.  
     
  48.  
    log.info("=========================================== connected fabric gateway {} " , gateway);
  49.  
     
  50.  
    return gateway;
  51.  
    }
  52.  
    }
学新通

没有问题以后,就是controller的代码,这里就以queryAllCars命令为例。

  1.  
    import com.谷歌.common.collect.Maps;
  2.  
    import lombok.AllArgsConstructor;
  3.  
    import lombok.extern.slf4j.Slf4j;
  4.  
    import org.apache.commons.codec.binary.StringUtils;
  5.  
    import org.hyperledger.fabric.gateway.*;
  6.  
    import org.springframework.context.annotation.Bean;
  7.  
    import org.springframework.context.annotation.Configuration;
  8.  
    import org.springframework.web.bind.annotation.GetMapping;
  9.  
    import org.springframework.web.bind.annotation.PathVariable;
  10.  
    import org.springframework.web.bind.annotation.RequestMapping;
  11.  
    import org.springframework.web.bind.annotation.RestController;
  12.  
     
  13.  
    import javax.servlet.http.HttpServletRequest;
  14.  
    import java.io.BufferedReader;
  15.  
    import java.nio.charset.StandardCharsets;
  16.  
    import java.nio.file.Files;
  17.  
    import java.nio.file.Paths;
  18.  
    import java.security.PrivateKey;
  19.  
    import java.security.cert.X509Certificate;
  20.  
    import java.util.Map;
  21.  
    import java.util.concurrent.TimeoutException;
  22.  
     
  23.  
     
  24.  
    @RestController
  25.  
    @RequestMapping("/car")
  26.  
    @Slf4j
  27.  
    @AllArgsConstructor
  28.  
    public class Fabriccontroller {
  29.  
    final Gateway gateway;
  30.  
     
  31.  
     
  32.  
     
  33.  
    @GetMapping("/queryall")
  34.  
    public Map<String, Object> queryall() throws ContractException {
  35.  
     
  36.  
    Map<String, Object> result = Maps.newConcurrentMap();
  37.  
    Contract contract = getContract();
  38.  
    byte[] car = contract.evaluateTransaction("queryAllCars");
  39.  
     
  40.  
    result.put("result", StringUtils.newStringUtf8(car));
  41.  
     
  42.  
     
  43.  
    return result;
  44.  
    }
  45.  
     
  46.  
    private Network getNetwork(){
  47.  
    return gateway.getNetwork("mychannel");
  48.  
    }
  49.  
     
  50.  
    private Contract getContract(){
  51.  
    return getNetwork().getContract("fabcar");
  52.  
    }
  53.  
     
  54.  
     
  55.  
    }
学新通

最后getnetwork()和getcontract()的参数分别是通道的名称和链码的名称,根据自己的情况做调整。

最后,运行主启动类。

  1.  
    import org.springframework.boot.SpringApplication;
  2.  
    import org.springframework.boot.autoconfigure.SpringBootApplication;
  3.  
    import org.springframework.boot.context.properties.EnableConfigurationProperties;
  4.  
     
  5.  
    @SpringBootApplication
  6.  
    @EnableConfigurationProperties
  7.  
    public class FabricJdkApplication {
  8.  
     
  9.  
    public static void main(String[] args) {
  10.  
    SpringApplication.run(FabricJdkApplication.class, args);
  11.  
    }
  12.  
     
  13.  
    }

注意:一定要在linux中先运行起来测试网络并安装好链码后才能够连接成功。

浏览器测试一下,返回查询数据

学新通

还有一点注意的是,当我们这一次工作结束,关闭了区块链网络。下一次在重启网络,要更新代码中的 orderorganizations和peerorganizations,替换成新网络的属性文件,否则自然是链接不上的。

学习中参考了B站“老哥没有饿意”的视频。作为初学者,如有问题和错误,欢迎大家的讨论和指正。

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhfjajai
系列文章
更多 icon
同类精品
更多 icon
继续加载