Hyperledger Fabric 2.x Java區塊鏈應用

語言: CN / TW / HK

file

一、説明

在上一篇文章中 《Hyperledger Fabric 2.x 自定義智能合約》 分享了智能合約的安裝並使用 cli 客户端進行合約的調用;本文將使用 Java 代碼基於 fabric-gateway-java 進行區塊鏈網絡的訪問與交易,並集成 SpringBoot 框架。

Fabric Gateway SDK 實現Fabric的編程模型,提供了一系列簡單的API給應用程序與Fabric區塊鏈網絡進行交互;

網絡拓撲圖:

file

應用程序將各自的網絡交互委託給其網關,每個網關都瞭解網絡信道拓撲,包括組織的多個Peer節點和排序節點,使應用程序專注於業務邏輯;Peer節點可以使用gossip協議在組織內部和組織之間相互通信。

 

二、Mavn依賴

添加網關sdk的依賴:

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

 

三、準備配置文件

工程的目錄結構如下圖所示:

file

 

3.1. 準備網絡證書

創建目錄 crypto-configordererpeer 節點的證書文件複製進來。

證書文件從 fabric-samplestest-network 目錄中複製 ordererOrganizationspeerOrganizations 文件夾:

file

 

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/[email protected]/msp/keystore/priv_sk"
            },
            "signedCertPEM": {
                "path": "src/main/resources/crypto-config/peerOrganizations/org1.example.com/users/[email protected]/msp/signcerts/[email protected]"
            }
        },
        "Org2": {
            "mspid": "Org2MSP",
            "peers": [
                "peer0.org2.example.com"
            ],
            "certificateAuthorities": [
                "ca-org2"
            ],
            "adminPrivateKeyPEM": {
                "path": "src/main/resources/crypto-config/peerOrganizations/org2.example.com/users/[email protected]/msp/keystore/priv_sk"
            },
            "signedCertPEM": {
                "path": "src/main/resources/crypto-config/peerOrganizations/org2.example.com/users/[email protected]/msp/signcerts/[email protected]"
            }
        }
    },
    "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/[email protected]/msp/keystore/priv_sk"
            },
            "signedCertPEM": {
                "path": "src/main/resources/crypto-config/ordererOrganizations/example.com/users/[email protected]/msp/signcerts/[email protected]"
            }
        }
    },
    "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": "http://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": "http://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/[email protected]/msp/signcerts/[email protected]
  # 用户私鑰路徑
  privateKeyPath: crypto-config/peerOrganizations/org1.example.com/users/[email protected]/msp/keystore/priv_sk
  # 訪問的組織名
  mspid: Org1MSP
  # 用户名
  username: user1
  # 通道名字
  channelName: mychannel
  # 鏈碼名字
  contractName: mycc

 

四、連接合約

分別構建網關、通道和合約的Bean對象,代碼如下:

/**
 * 連接網關
 */
@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對象調用合約方法:

@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

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:http://gitee.com/zlt2000/my-fabric-application-java

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

 

掃碼關注有驚喜!

file