fabric2.2.0中使用fabric-sdk-java 2.2.0 创建channel,添加peer.
在进行fabric-sdk-java 2.2.0的学习中,在进行创建channel和添加peer的过程,网上能查到的资料很少并且还不全面,在这边我根据官方给的测试案例和自己的研究,成功的完成了这个过程,下面进行一些总结和代码的展示,参考案例地址:https://github.com/hyperledger/fabric-sdk-java/blob/release-2.2/src/test/java
文章共2,274字 · 阅读需要大约8分钟
一键AI生成摘要,助你高效阅读
问答
·
在进行fabric-sdk-java 2.2.0的学习中,在进行创建channel和添加peer的过程,网上能查到的资料很少并且还不全面,在这边我根据官方给的测试案例和自己的研究,成功的完成了这个过程,下面进行一些总结和代码的展示,
基于 fabric2.2.0 的测试案例进行测试 test-network
项目目录
src
-- main
-- java
--com
--ictnj
-- java
-- service -- 里面存放的是核心代码
-- sources
-- crypto-config
-- peerOrganizations
-- OrdererOrganizations
-- channel1.tx
-- application.yaml
POM文件 (在这里我使用的是springboot框架,使用的是nacos和dubbo进行的服务注册和服务发现,如果不使用的话,可以将相关依赖删除,也不影响项目的正常操作)
<properties>
<java.version>1.8</java.version>
<dubbo.version>2.7.8</dubbo.version>
<mybatis-plus>3.4.2</mybatis-plus>
<mysql>8.0.17</mysql>
<fabric.version>2.0.0</fabric.version>
<cloud-nacos>2.2.1.RELEASE</cloud-nacos>
</properties>
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>application_apis</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.hyperledger.fabric</groupId>
<artifactId>fabric-gateway-java</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-registry-nacos</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hyperledger.fabric-chaincode-java/fabric-chaincode-shim -->
<dependency>
<groupId>org.hyperledger.fabric-chaincode-java</groupId>
<artifactId>fabric-chaincode-shim</artifactId>
<version>2.2.0</version>
<exclusions>
<exclusion>
<groupId>com.github.everit-org.json-schema</groupId>
<artifactId>org.everit.json.schema</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- https://mvnrepository.com/artifact/com.owlike/genson -->
<dependency>
<groupId>com.owlike</groupId>
<artifactId>genson</artifactId>
<version>1.4</version>
</dependency>
</dependencies>
在source下的crypto-config 下面的文件为启动fabric生成的文件,可以直接进行替换
我们还需要一个 .tx文件,用来生成通道,
获取文件步骤:
1.在test-network的目录下,进行工具脚本路径的添加 (默认已经启动了fabric服务)
export PATH=${PWD}/../bin:$PATH
export FABRIC_CFG_PATH=${PWD}/configtx
2.创建创世块
configtxgen -profile TwoOrgsOrdererGenesis -channelID system-channel -outputBlock ./system-genesis-block/genesis.block
3.生成.tx文件
configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel1.tx -channelID channel1
这里的名称可以自己进行定义,我这里定义的是 channel1.tx
// 创建用户注册类,在这里 必须实现 User接口,
public class UserContextImp implements User, Serializable {
private static final long serialVersionUID = 11384281131231L;
protected String name;
protected Set<String> roles;
protected String account;
protected String affiliation;
protected Enrollment enrollment;
protected String mspId;
public void setName(String name) {
this.name = name;
}
public void setRoles(Set<String> roles) {
this.roles = roles;
}
public void setAccount(String account) {
this.account = account;
}
public void setAffiliation(String affiliation) {
this.affiliation = affiliation;
}
public void setEnrollment(Enrollment enrollment) {
this.enrollment = enrollment;
}
public void setMspId(String mspId) {
this.mspId = mspId;
}
@Override
public String getName() {
return name;
}
@Override
public Set<String> getRoles() {
return roles;
}
@Override
public String getAccount() {
return account;
}
@Override
public String getAffiliation() {
return affiliation;
}
@Override
public Enrollment getEnrollment() {
return enrollment;
}
@Override
public String getMspId() {
return mspId;
}
}
然后进行HFClient对象的生成
public class FabricClient {
private HFClient instance;
/**
* Return an instance of HFClient.
*
* @return
*/
public HFClient getInstance() {
return instance;
}
/**
* Constructor
*
* @param context
* @throws CryptoException
* @throws InvalidArgumentException
* @throws InvocationTargetException
* @throws NoSuchMethodException
* @throws ClassNotFoundException
* @throws InstantiationException
* @throws IllegalAccessException
*/
public FabricClient(User context) throws CryptoException, InvalidArgumentException, IllegalAccessException, InstantiationException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException {
CryptoSuite cryptoSuite = CryptoSuite.Factory.getCryptoSuite();
// setup the client
instance = HFClient.createNewInstance();
instance.setCryptoSuite(cryptoSuite);
instance.setUserContext(context);
}
一些基本配置类
package com.ictnj.java.admin.config;
public class TestConfig {
// 因为我这边用的是微服务,所有,路径必须要包括我的模块名称
// orderer
public static final String ORDERER_PEMFILE="application_java_admin/src/main/resources/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt";
public static final String ORDERER_CERT="application_java_admin/src/main/resources/crypto-config/ordererOrganizations/example.com/users/Admin@example.com/tls/client.crt";
public static final String ORDERER_KEY="application_java_admin/src/main/resources/crypto-config/ordererOrganizations/example.com/users/Admin@example.com/tls/client.key";
public static final String ORDER_NAME="orderer.example.com";
// peer0.org1
public static final String PEER1_PEMFILE="application_java_admin/src/main/resources/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.crt";
public static final String PEER1_CERT="application_java_admin/src/main/resources/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/tls/client.crt";
public static final String PEER1_KEY="application_java_admin/src/main/resources/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/tls/client.key";
public static final String PEER1_NAME="peer0.org1.example.com";
// peer0.org2
public static final String PEER2_PEMFILE="application_java_admin/src/main/resources/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/server.crt";
public static final String PEER2_CERT="application_java_admin/src/main/resources/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/tls/client.crt";
public static final String PEER2_KEY="application_java_admin/src/main/resources/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/tls/client.key";
public static final String PEER2_NAME="peer0.org2.example.com";
}
然后下面进行基本业务的处理过程
public class CreateChannel {
public void createChannel() {
try {
// 创建org1的用户管理员对象的创建
UserContextImp org1Admin = new UserContextImp();
// 秘钥地址
String pkPath = "application_java_admin/src/main/resources/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/keystore";
File pkFile1 = new File(pkPath);
File[] pkFiles1 = pkFile1.listFiles();
// 证书地址
String certPath = "application_java_admin/src/main/resources/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/signcerts";
File certFile1 = new File(certPath);
File[] certFiles1 = certFile1.listFiles();
// 进行证书和秘钥的登记
Enrollment enrollment = getEnrollment(pkPath, pkFiles1[0].getName(), certPath, certFiles1[0].getName());
org1Admin.setEnrollment(enrollment);
org1Admin.setName("admin");
org1Admin.setMspId("Org1MSP");
org1Admin.setAffiliation("org1");
// org2的用户管理对象的创建
UserContextImp org2Admin = new UserContextImp();
String pkPath2 = "application_java_admin/src/main/resources/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp/keystore";
File pkFile2 = new File(pkPath2);
File[] pkFiles2 = pkFile2.listFiles();
String certPath2 = "application_java_admin/src/main/resources/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp/signcerts";
File certFile2 = new File(certPath2);
File[] certFiles2 = certFile2.listFiles();
Enrollment enrollment1 = getEnrollment(pkPath2, pkFiles2[0].getName(), certPath2, certFiles2[0].getName());
org2Admin.setEnrollment(enrollment1);
org2Admin.setName("user2");
org2Admin.setMspId("Org2MSP");
org2Admin.setAffiliation("org2");
FabricClient fabricClient = new FabricClient(org1Admin);
// Properties orderPro = new Properties();
// properties配置的信息导入
Properties orderPro = loadTLSFile(TestConfig.ORDERER_PEMFILE, TestConfig.ORDERER_CERT, TestConfig.ORDERER_KEY, TestConfig.ORDER_NAME, "OrdererMSP");
// 通过HFClient对象新建一个orderer对象,
Orderer orderer = fabricClient.getInstance().newOrderer("orderer.example.com", "grpcs://orderer.example.com:7050", orderPro);
// 创建通道配置对象,参数为创建的.tx通道文件
ChannelConfiguration channelConfiguration = new ChannelConfiguration(new File("application_java_admin/src/main/resources/channel1.tx"));
byte[] channelConfigurationSignatures = fabricClient.getInstance().getChannelConfigurationSignature(channelConfiguration, org1Admin);
// 新建一个channel
Channel channel1 = fabricClient.getInstance().newChannel("channel1", orderer, channelConfiguration, channelConfigurationSignatures);
// Channel channel1 = fabricClient.getInstance().newChannel("mychannel");
for (Peer peer : channel1.getPeers()) {
System.out.println(peer.getName());
}
// 加载配置
Properties peer1Pro = loadTLSFile(TestConfig.PEER1_PEMFILE, TestConfig.PEER1_CERT, TestConfig.PEER1_KEY, TestConfig.PEER1_NAME, "Org1MSP");
//新建peer1
Peer peer0_Org1 = fabricClient.getInstance().newPeer(TestConfig.PEER1_NAME, "grpcs://192.168.127.130:7051", peer1Pro);
// 新建peer2
Properties peer2Pro = loadTLSFile(TestConfig.PEER2_PEMFILE, TestConfig.PEER2_CERT, TestConfig.PEER2_KEY, TestConfig.PEER2_NAME, "Org2MSP");
Peer peer0_Org2 = fabricClient.getInstance().newPeer(TestConfig.PEER2_NAME, "grpcs://192.168.127.130:9051", peer2Pro);
// 将peer加入到channel中
channel1.joinPeer(peer0_Org1, Channel.PeerOptions.createPeerOptions().setPeerRoles(EnumSet.of(PeerRole.ENDORSING_PEER, PeerRole.LEDGER_QUERY, PeerRole.CHAINCODE_QUERY, PeerRole.EVENT_SOURCE)));
channel1.addOrderer(orderer);
// 进行判断,是否加入成功
assertFalse(channel1.getPeers(EnumSet.of(Peer.PeerRole.EVENT_SOURCE)).isEmpty());
assertFalse(channel1.getPeers(PeerRole.NO_EVENT_SOURCE).isEmpty());
// 进行初始化通道
channel1.initialize();
Logger.getLogger(CreateChannel.class.getName()).log(Level.INFO, "Channel created " + channel1.getName());
// 切换为org2的用户进行上述操作,添加peer
fabricClient.getInstance().setUserContext(org2Admin);
channel1 = fabricClient.getInstance().getChannel("channel1");
channel1.joinPeer(peer0_Org2, Channel.PeerOptions.createPeerOptions().setPeerRoles(EnumSet.of(Peer.PeerRole.ENDORSING_PEER, Peer.PeerRole.LEDGER_QUERY, Peer.PeerRole.CHAINCODE_QUERY, Peer.PeerRole.EVENT_SOURCE)));
Iterator<Peer> iterator = channel1.getPeers().iterator();
assertFalse(channel1.getPeers(EnumSet.of(Peer.PeerRole.EVENT_SOURCE)).isEmpty());
assertFalse(channel1.getPeers(PeerRole.NO_EVENT_SOURCE).isEmpty());
channel1.initialize();
} catch (Exception e) {
e.printStackTrace();
}
}
// 将配置项导入到配置pro中
private static Properties loadTLSFile(String servicePath, String certPath, String keyPath, String hostName, String Msp) throws IOException {
Properties properties = new Properties();
// # 其实只需要一个TLS根证书就可以了,比如TLS相关的秘钥等都是可选的
properties.put("pemBytes", Files.readAllBytes(Paths.get(servicePath)));
properties.setProperty("clientCertFile", certPath);
properties.setProperty("clientKeyFile", keyPath);
properties.setProperty("sslProvider", "openSSL");
properties.setProperty("negotiationType", "TLS");
properties.setProperty("trustServerCertificate", "true");
properties.setProperty("hostnameOverride", hostName);
properties.setProperty("ssl-target-name-override", hostName);
if (hostName.contains("peer")) {
properties.put("grpc.NettyChannelBuilderOption.maxInboundMessageSize", 9000000);
// properties.setProperty("org.hyperledger.fabric.sdk.peer.organization_mspid", Msp);
}
if (hostName.contains("orderer")) {
properties.put("grpc.NettyChannelBuilderOption.keepAliveTime", new Object[]{5L, TimeUnit.MINUTES});
properties.put("grpc.NettyChannelBuilderOption.keepAliveTimeout", new Object[]{8L, TimeUnit.SECONDS});
properties.put("grpc.NettyChannelBuilderOption.keepAliveWithoutCalls", new Object[]{true});
// properties.setProperty("org.hyperledger.fabric.sdk.orderer.organization_mspid", Msp);
//
}
return properties;
}
// 证书和秘钥的登记过程
public static CAEnrollment getEnrollment(String keyFolderPath, String keyFileName, String certFolderPath, String certFileName)
throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, CryptoException {
PrivateKey key = null;
String certificate = null;
InputStream isKey = null;
BufferedReader brKey = null;
try {
isKey = new FileInputStream(keyFolderPath + File.separator + keyFileName);
brKey = new BufferedReader(new InputStreamReader(isKey));
StringBuilder keyBuilder = new StringBuilder();
for (String line = brKey.readLine(); line != null; line = brKey.readLine()) {
if (line.indexOf("PRIVATE") == -1) {
keyBuilder.append(line);
}
}
certificate = new String(Files.readAllBytes(Paths.get(certFolderPath, certFileName)));
byte[] encoded = DatatypeConverter.parseBase64Binary(keyBuilder.toString());
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);
KeyFactory kf = KeyFactory.getInstance("EC");
key = kf.generatePrivate(keySpec);
} finally {
isKey.close();
brKey.close();
}
CAEnrollment enrollment = new CAEnrollment(key, certificate);
return enrollment;
}
更多推荐
已为社区贡献1条内容
所有评论(0)