hyperchain开放入门


hpc.properties配置

基于Hyperchain的应用程序需要运行在至少4个节点上,hpc.properties主要用于配置节点信息。
hpc.properties主要内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#Hyperchain Nodes IP Ports
#node = {"nodes":["ino2","ino2","ino2","ino2"]}
#node = {"nodes":["123.206.232.138:8081","123.206.232.138:8082","123.206.232.138:8083","123.206.232.138:8084"]}
#node = {"nodes":["122.152.218.100:8081","111.231.106.89:8081","111.231.118.14:8081","111.231.106.41:8081"]}
node = {"nodes":["192.168.130.141","192.168.130.142","192.168.130.143","192.168.130.65"]}

# JsonRpc connect port
#jsonRpcPort = [9041, 9042, 9043, 9044]
jsonRpcPort = [8047, 8047, 8047, 8047]

# webSocket connect port
webSocketPort = [10001, 10001, 10001, 10001]

#Namespace
namespace = global

#重发次数
resendTime = 10
#第一次轮训时间间隔 unit /ms
firstPollingInterval = 100
#发送一次,第一次轮训的次数
firstPollingTimes = 10
#第二次轮训时间间隔 unit /ms
secondPollingInterval = 1000
#发送一次,第二次轮训的次数
secondPollingTimes = 10

#Send Tcert during the request or not
SendTcert = false
#if sendTcert is true , you should add follow path.
#ecertPath = certs/sdkcert.cert
#ecertPriPath = certs/sdkcert.priv
#uniquePrivPath = certs/unique.priv
#uniquePubPath = certs/unique.pub

#发送重新连接请求间隔(/ms)
reConnectTime = 10000

}

其中,主要注意node, jsonRpcPort, webSocketProt的配置,分别对应各个节点的IP和开放的端口。

日志的配置log4j.properties

hyperchain采用log4j作为日志输出,配置文件如下:

1
2
3
4
5
6
7
8
### 设置###
## 如果设置为DEBUG将输出调用信息
log4j.rootLogger=INFO,stdout
### 输出信息到控制抬 ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n

合约编译

hyperchain平台支持solidity和java两种语言的合约,由于solidity是Ehtereum推出的语言,相关支撑的工具更多。
Solidity合约可以在remix中编辑、编译、调试,并能获取对应的abi,bin。可以在hyperchain应用代码中编译合约,但是更推荐通过别的工具编译好以后在代码中直接用。

合约代码

一个简单的合约:

1
2
3
4
5
6
7
8
pragma solidity ^0.4.24;

contract Echo {
function echo(uint32 a) public pure returns(uint32 _a) {
return a;
}

}

应用程序代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package com.qqq.test;

import cn.hyperchain.sdk.rpc.HyperchainAPI;
import cn.hyperchain.sdk.rpc.Transaction.Transaction;
import cn.hyperchain.sdk.rpc.account.Account;
import cn.hyperchain.sdk.rpc.base.VMType;
import cn.hyperchain.sdk.rpc.function.FuncParamReal;
import cn.hyperchain.sdk.rpc.function.FunctionDecode;
import cn.hyperchain.sdk.rpc.function.FunctionEncode;
import cn.hyperchain.sdk.rpc.returns.ReceiptReturn;
import cn.hyperchain.sdk.rpc.utils.Utils;

import java.math.BigInteger;

public class Main {
private static String hpcPath = "D:\\mycode\\java\\echo\\src\\resources\\hpc.properties";
private static String accountJsonPath = "D:\\mycode\\java\\echo\\info\\accountJson.txt";
private static String contractAddressPath = "D:\\mycode\\java\\echo\\info\\contractAddress.txt";
private static String contractBinPath = "D:\\mycode\\java\\echo\\src\\contract\\echo.bin";
private static String contractAbiPath = "D:\\mycode\\java\\echo\\src\\contract\\echo.abi";

public static void main(String[] args) throws Exception{
System.out.println("qqq");

//deployContract();
echo();
}

public static void deployContract() throws Exception{
HyperchainAPI hyperchain = new HyperchainAPI(hpcPath);

String accountJson = hyperchain.newAccountSM2("123456");
Utils.writeFile(accountJsonPath,accountJson);
Account account = new Account(accountJson);

/**
* 在线编译合约
*/
//String contractPath = "D:\\mycode\\java\\echo\\src\\contract\\echo.sol";
//String contract = Utils.readFile(contractPath);
//CompileReturn compileReturn = hyperchain.compileContract(contract);
//List<String> contractAbi = compileReturn.getAbi();
//List<String> contractBin = compileReturn.getBin();
//System.out.println("=== Abi Bin");
//System.out.println(contractBin.get(0));
//System.out.println(contractAbi.get(0));
//System.out.println("===");

String bin = Utils.readFile(contractBinPath);

Transaction transaction = new Transaction(account.getAddress(), bin, true, VMType.EVM);
transaction.signWithSM2(accountJson,"123456");
ReceiptReturn receiptReturn = hyperchain.deployContract(transaction);

String txHash = receiptReturn.getTxHash();
int code = receiptReturn.getCode();
String contractAddress = receiptReturn.getContractAddress();
Utils.writeFile(contractAddressPath,contractAddress);
System.out.println(txHash);
System.out.println(code);
System.out.println(contractAddress);
}

public static void echo() throws Exception {
String accountJson = Utils.readFile(accountJsonPath);
Account account = new Account(accountJson);

HyperchainAPI hyperchain = new HyperchainAPI(hpcPath);

FuncParamReal param1 = new FuncParamReal("uint32",new BigInteger("11111"));

String contractAddress = Utils.readFile(contractAddressPath);
String payload = FunctionEncode.encodeFunction("insert",param1);
Transaction transaction = new Transaction(account.getAddress(),contractAddress,
payload,false, VMType.EVM);

transaction.signWithSM2(accountJson,"123456");
ReceiptReturn receipt = hyperchain.invokeContract(transaction);

if(!receipt.isSuccess()) {
System.out.println("echo error!");
}

String abi = Utils.readFile(contractAbiPath);
int code = receipt.getCode();
String rawReturn = receipt.getRet();
String decodeRet = FunctionDecode.resultDecode("echo",abi,rawReturn);
System.out.println(code);
System.out.println(decodeRet);
}

}

合约部署

参照程序代码,部署合约分成3步:

  • 通过hpc.properties生成HyperchainAPI对象。这是调用hyperchain平台的主要类。
  • 生成账户,可以将accountJson保存成文本,今后再使用同一账户时,可以直接read改文本,再生成Account。
  • 编译合约。可以在线编译,更推荐将编译好的合约直接使用。直接read合约的bin文件。。
  • 生成交易。部署合约对于区块链也是一笔交易。交易都需要使用账户信息进行签名。
  • 解析交易的返回信息。

触发合约

参照程序代码,分成3步:

  • 读取accountJson,生成Account。
  • 生成HyperchainAPI.
  • 规范化调用参数,由于solidity与java直接有一个数据类型映射关系。
  • 获取合约地址。
  • 生成交易信息。
  • 生成交易。
  • 对交易进行签名,触发。
  • 解析交易回执。