本文通过示例阐述如何 运行应用,展示 示例执行流程,并指导如何 指定密码学套件。
运行应用
应用运行的过程主要分为 4 步:
准备环境
准备 SSL 连接文件和账户私钥文件。
要与 BaaS 平台建立 SSL 连接,您需准备三个证书文件:CA 机构的根证书(
trustCa
)、客户端的证书文件(client.crt
)以及客户端的私钥文件(client.key
)。此外,提交交易还需要账户的私钥文件(user.key
)。这四个文件的详细说明如下。文件名称
文件说明
文件来源
client.crt
客户端的证书文件
使用 BaaS 提供的 密钥生成工具生成证书请求文件
client.csr
,提交请求文件到 BaaS 平台申请证书,申请成功后可下载此 crt 文件。client.key
客户端的私钥文件
通过 BaaS 提供的 密钥生成工具生成。
trustCa
存储 CA 证书的 trustStore
通过 BaaS 平台下载,trustCa 文件密码为 mychain。
user.key
账户私钥文件
通过 BaaS 提供的 密钥生成工具手动生成,或自动生成下载。
准备 TEE 硬件隐私合约链文件。
如果使用 TEE 硬件隐私合约链,还需要使用一个
tee_rsa_public_key.pem
文件,此文件可从已存在的 TEE 硬件隐私合约链申请,如果使用的是标准的合约链,则不需要使用此文件。文件名称
文件说明
文件来源
tee_rsa_public_key.pem
TEE 硬件隐私合约链,节点对外公开的 RSA 公钥文件
通过 BaaS 平台下载。
看合约链节点信息。
要与合约链交互,您需要获取链节点的 IP 地址和端口号。在 BaaS 平台,通过查看目标合约链详情,在区块浏览器中查看节点详情,可获取链节点的 IP 地址和端口号。
编写应用
使用 IntelliJ IDEA 创建一个基于 Maven 构建的空项目(Demo)。创建完成后,项目目录结构应如下:
在上图中的
java
目录创建自定义包名,例如:com.example.demo,并将DemoSample.java
(点击下载 DemoSample.java文件)中的内容完整拷贝至创建的包中,并将 SDK 必须使用的client.crt
、client.key
、trustCa
及user.key
文件放入到resources
目录中,如下图所示:说明Demo 项目中需要使用合约源代码编译后的字节码。有关合约源代码,参见 Solidity 合约开发;Solidity 编译工具参见 Solidity 合约编译工具。
在
pom.xml
中添加依赖。将 SDK 与项目使用的依赖引入到pom.xml
,并在resources
中添加log4j
的配置文件。重要在本步骤中,SDK 依赖的版本号请使用最新版本。
完整 pom 依赖可参考:
<dependencies> <dependency> <groupId>com.alipay.mychainx</groupId> <artifactId>mychainx-sdk</artifactId> <!--请使用最新 SDK 版本 --> <version>0.10.2.12</version> </dependency> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcpkix-jdk15on</artifactId> <version>1.60</version> </dependency> <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1.29.Final</version> </dependency> <dependency> <groupId>io.netty</groupId> <artifactId>netty-tcnative-boringssl-static</artifactId> <version>2.0.17.Final</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.25</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.6</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.83</version> </dependency> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>20.0</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-collections4</artifactId> <version>4.2</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.5</version> </dependency> </dependencies> <build> <extensions> <extension> <groupId>kr.motd.maven</groupId> <artifactId>os-maven-plugin</artifactId> <version>1.6.1</version> </extension> </extensions> </build>
在某些情况下,可能会出现如下异常:
异常原因有可能是 Netty 加载失败,可以尝试修改 netty 依赖,如下所示:
<dependency> <groupId>com.alipay.mychainx</groupId> <artifactId>mychainx-sdk</artifactId> <!--请使用最新 SDK 版本 --> <version>0.10.2.12</version> <exclusions> <exclusion> <groupId>io.netty</groupId> <artifactId>netty-tcnative-openssl-static</artifactId> </exclusion> </exclusions> </dependency>
log4j.properties
文件内容如下:log4j.rootLogger=INFO, R # 日志输出位置为控制台 log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=[QC] %p [%t] %C.%M(%L) | %m%n # 日志输出位置为文件 log4j.appender.R=org.apache.log4j.DailyRollingFileAppender log4j.appender.R.File=./sdk.log log4j.appender.R.layout=org.apache.log4j.PatternLayout log4j.appender.R.layout.ConversionPattern=%d-[TS] %p %t %c - %m%n # mychain-sdk日志开关配置 log4j.logger.MychainClient=OFF
如果您使用的是logback的日志框架,则日志开关的配置方法如下:
<logger name="MychainClient" level="OFF"/>
编译应用
在项目根路径运行 mvn clean compile
执行项目编译。
执行应用
在 DemoSample.java
中,运行该项目。生成的日志文件位于 项目根路径 ./sdk.log
,若从日志中搜索到“Hand shake success”,则代表与区块链平台连接成功。
预期输出如下:
create testAccount1 success.
create testAccount2 success.
deploy contract success.
issue success.
transfer success.
check account balance success.
示例执行流程
初始化环境。
//step 1: init logger. initLogger(); //step 2:init mychain env. env = initMychainEnv(); //step 3: start sdk. MychainClient sdk = new MychainClient(); sdk.init(env);
创建账户交易。
//step 4: init account that will be created. initAccount(); //step 5: init private key list which will be used during transaction. initPrivateKeyList(); //step 6: execute create two accounts. createAccount();
部署智能合约。
//step 7 : deploy a contract using testAccount1. deployContract();
申购积分。
//step 8:issue 100 credits to testAccount2. issue();
进行账户间转账。
//step 9 : transfer 50 credits from testAccount2 to testAccount1 transfer();
查询账户余额。
//step 10 : query testAccount2 whose balance should be 50. BigInteger balance = query(test2PrivateKeyArrayList,testAccount2); //step 11 : compare to expect balance. expect(balance,BigInteger.valueOf(50));
关闭 SDK 连接。
//step 12 : sdk shut down sdk.shutDown();
指定密码学套件
合约链的链环境可能使用以下两种密码学套件中的一种:
classic:使用国际商用密码算法,包括 SHA256 摘要、ECC 公钥算法、AES 对称加密等,标准合约链默认为此套件配置;
china-sm:使用中国国家商用密码算法,包括 SM3 摘要、SM2 公钥算法、SM4 对称加密等,国密算法合约链默认为此套件配置。
如果不清楚 SDK 连接的目标合约链使用的是哪一种密码套件,可咨询该链的管理员。构建 ClientEnv
时,必须明确指定 SignerBase。示例如下:
Pkcs8KeyOperator pkcs8KeyOperator = new Pkcs8KeyOperator();
Keypair keyPair = pkcs8KeyOperator.load(privateKeyPath, keyPassword);
SignerBase signerBase = MyCrypto.getInstance().createSigner(keyPair);
SDK 与合约平台之间的 SSL 通信不受密码学套件影响,由颁发证书的 PKI 机构决定。