網(wǎng)站開發(fā)合同 下載襄陽(yáng)seo推廣
編寫一個(gè)應(yīng)用程序來(lái)連接到 fabrc 網(wǎng)絡(luò)中,通過(guò)調(diào)用智能合約來(lái)訪問(wèn)賬本.
fabric gateway
fabric gateway 有兩個(gè)項(xiàng)目,一個(gè)是 fabric-gateway-java , 一個(gè)是 fabric-gateway。
fabric-gateway-java
是比較早的項(xiàng)目,使用起來(lái)較為麻煩需要提供一個(gè) connection.json
配置文件,該配置文件中要詳細(xì)配置網(wǎng)絡(luò)中的各個(gè)節(jié)點(diǎn)的信息。
fabric-gateway
使用起來(lái)較為簡(jiǎn)單,不在需要 connection.json
配置文件,只需要指定網(wǎng)絡(luò)中的一個(gè)節(jié)點(diǎn)連接就可以了。
fabric 官方建議如果是 fabrc 2.4 或者之后的版本建議使用 fabric-gateway
。
本篇內(nèi)容基于
fabric-gateway
講解,fabric 版本 v2.4.1
使用 fabric-gateway
Fabric Gateway 是 Hyperledger Fabric 區(qū)塊鏈網(wǎng)絡(luò)的核心組件,代表客戶端應(yīng)用程序協(xié)調(diào)提交事務(wù)和查詢分類賬狀態(tài)所需的操作。通過(guò)使用 Gateway,客戶端應(yīng)用程序只需要連接到 Fabric 網(wǎng)絡(luò)中的單個(gè)端點(diǎn)。
官方示例: https://github.com/hyperledger/fabric-samples/tree/main/asset-transfer-events https://github.com/hyperledger/fabric-samples/tree/main/asset-transfer-basic
fabric-gateway 依賴
<dependency><groupId>org.hyperledger.fabric</groupId><artifactId>fabric-gateway</artifactId><version>1.0.1</version>
</dependency>
連接 fabric 網(wǎng)絡(luò)
application.properties
配置文件:
# 應(yīng)用名稱
spring.application.name=hyperledger-fabric-app-java-demo
# 應(yīng)用服務(wù) WEB 訪問(wèn)端口
server.port=8080fabric.networkConnectionConfigPath=src/main/resources/org1ProdNetworkConnection.json
fabric.mspId=Org1MSP
fabric.certificatePath=src/main/resources/crypto-config/prod-network/peerOrganizations/org1.example.com/users/User1@org1.example.com/msp/signcerts/User1@org1.example.com-cert.pem
fabric.privateKeyPath=src/main/resources/crypto-config/prod-network/peerOrganizations/org1.example.com/users/User1@org1.example.com/msp/keystore/priv_sk
fabric.tlsCertPath=src/main/resources/crypto-config/prod-network/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
fabric.channel=businesschannellogging.level.org.hyperledger=trace
src/main/resources/crypto-config/prod-network 路徑下存放的是身份信息文件.
初始化 Gateway , Network , Contract 對(duì)象
import io.grpc.ManagedChannel;
import io.grpc.netty.shaded.io.grpc.netty.GrpcSslContexts;
import io.grpc.netty.shaded.io.grpc.netty.NettyChannelBuilder;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.hyperledger.fabric.client.CallOption;
import org.hyperledger.fabric.client.Contract;
import org.hyperledger.fabric.client.Gateway;
import org.hyperledger.fabric.client.Network;
import org.hyperledger.fabric.client.identity.Identities;
import org.hyperledger.fabric.client.identity.Signers;
import org.hyperledger.fabric.client.identity.X509Identity;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.PrivateKey;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.concurrent.TimeUnit;/*** author he peng* date 2022/1/22 21:21*/@Configuration
@AllArgsConstructor
@Slf4j
public class HyperLedgerFabricGatewayConfig {final HyperLedgerFabricProperties hyperLedgerFabricProperties;@Beanpublic Gateway gateway() throws Exception {BufferedReader certificateReader = Files.newBufferedReader(Paths.get(hyperLedgerFabricProperties.getCertificatePath()), StandardCharsets.UTF_8);X509Certificate certificate = Identities.readX509Certificate(certificateReader);BufferedReader privateKeyReader = Files.newBufferedReader(Paths.get(hyperLedgerFabricProperties.getPrivateKeyPath()), StandardCharsets.UTF_8);PrivateKey privateKey = Identities.readPrivateKey(privateKeyReader);Gateway gateway = Gateway.newInstance().identity(new X509Identity(hyperLedgerFabricProperties.getMspId() , certificate)).signer(Signers.newPrivateKeySigner(privateKey)).connection(newGrpcConnection()).evaluateOptions(CallOption.deadlineAfter(5, TimeUnit.SECONDS)).endorseOptions(CallOption.deadlineAfter(15, TimeUnit.SECONDS)).submitOptions(CallOption.deadlineAfter(5, TimeUnit.SECONDS)).commitStatusOptions(CallOption.deadlineAfter(1, TimeUnit.MINUTES)).connect();log.info("=========================================== connected fabric gateway {} " , gateway);return gateway;}private ManagedChannel newGrpcConnection() throws IOException, CertificateException {Reader tlsCertReader = Files.newBufferedReader(Paths.get(hyperLedgerFabricProperties.getTlsCertPath()));X509Certificate tlsCert = Identities.readX509Certificate(tlsCertReader);return NettyChannelBuilder.forTarget("peer0.org1.example.com:7051").sslContext(GrpcSslContexts.forClient().trustManager(tlsCert).build()).overrideAuthority("peer0.org1.example.com").build();}@Beanpublic Network network(Gateway gateway) {return gateway.getNetwork(hyperLedgerFabricProperties.getChannel());}@Beanpublic Contract catContract(Network network) {return network.getContract("hyperledger-fabric-contract-java-demo" , "CatContract");}@Beanpublic ChaincodeEventListener chaincodeEventListener(Network network) {return new ChaincodeEventListener(network);}
}
鏈碼事件監(jiān)聽
用來(lái)監(jiān)聽交易完成之后通知的事件,事件中可以攜帶數(shù)據(jù)。
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.hyperledger.fabric.client.ChaincodeEvent;
import org.hyperledger.fabric.client.CloseableIterator;
import org.hyperledger.fabric.client.Network;import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;/*** @author he peng* @date 2022/3/4*/@Slf4j
public class ChaincodeEventListener implements Runnable {final Network network;public ChaincodeEventListener(Network network) {this.network = network;ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1, new ThreadFactory() {@Overridepublic Thread newThread(Runnable r) {Thread thread = new Thread(r);thread.setDaemon(true);thread.setName(this.getClass() + "chaincode_event_listener");return thread;}});executor.execute(this);}@Overridepublic void run() {CloseableIterator<ChaincodeEvent> events = network.getChaincodeEvents("hyperledger-fabric-contract-java-demo");log.info("chaincodeEvents {} " , events);while (events.hasNext()) {ChaincodeEvent event = events.next();log.info("receive chaincode event {} , block number {} , payload {} ", event.getEventName() , event.getBlockNumber() , JSONArray.toJSONString(Base64.decodeBase64(event.getPayload())));}}
}
異步調(diào)用合約
@PutMapping("/async")public Map<String, Object> createCatAsync(@RequestBody CatDTO cat) throws Exception {Map<String, Object> result = Maps.newConcurrentMap();contract.newProposal("createCat").addArguments(cat.getKey(), cat.getName(), String.valueOf(cat.getAge()), cat.getColor(), cat.getBreed()).build().endorse().submitAsync();result.put("status", "ok");return result;}
完整示例代碼項(xiàng)目:DevX/hyperledger-fabric-app-java-demo