区块链接入开发(Stub)¶
本章节首先介绍WeCross Stub
的设计原理,在此基础上给出区块链接入WeCross
的开发流程,用户可以根据教程实现一个区块链的WeCross Stub
插件,通过插件接入WeCross
。
注解
- Java编程语言
WeCross使用Java实现,区块链需要支持Java版本的SDK,要求开发人员具备Java开发能力。
- Gradle构建工具
WeCross Java组件使用Gradle构建,假定用户能够使用Gradle。
Stub设计¶
Stub开发¶
Stub
开发分为两个部分:
- 系统合约
- Java插件
系统合约¶
系统合约包括代理合约(WeCrossProxy)和桥接合约(WeCrossHub),代理合约是WeCross调用该链其它合约的统一入口,桥接合约用于记录跨链调用请求,以配合跨链路由实现合约跨链调用。
代理合约¶
功能点:
- 合约调用入口
- 事务管理
示例:
Solidity版:
Golang版:
以Solidity合约为例,接口列表:
/** 读接口,调用业务合约(不需要脏读,即无事务ID,读事务中资源)
*
* @param _XATransactionID 事务ID
* @param _path 目标资源路径
* @param _func 调用方法
* @param _args 调用参数
* @return 调用结果
*/
function constantCall(
string memory _XATransactionID,
string memory _path,
string memory _func,
bytes memory _args
) public returns(bytes memory)
/** 写接口,调用业务合约
*
* @param _uid 交易ID,用于去重
* @param _XATransactionID 事务ID
* @param _XATransactionSeq 事务序列号
* @param _path 目标资源路径
* @param _func 调用方法
* @param _args 调用参数
* @return 调用结果
*/
function sendTransaction(
string memory _uid,
string memory _XATransactionID,
uint256 _XATransactionSeq,
string memory _path,
string memory _func,
bytes memory _args
) public returns(bytes memory)
/** 开启事务
*
* @param _XATransactionID 事务ID
* @param _selfPaths 参与事务的己链资源列表
* @param _otherPaths 参与事务的它链资源列表
* @return 执行结果
*/
function startXATransaction(
string memory _xaTransactionID,
string[] memory _selfPaths,
string[] memory _otherPaths
) public returns(string memory)
/** 提交事务
*
* @param _XATransactionID 事务ID
* @return 执行结果
*/
function commitXATransaction(
string memory _xaTransactionID
) public returns(string memory)
/** 回滚事务
*
* @param _XATransactionID 事务ID
* @return 执行结果
*/
function rollbackXATransaction(
string memory _xaTransactionID
) public returns(string memory)
/** 获取事务列表
*
* @param _index 下标
* @param _size 数量
* @return 事务列表详情,JSON格式
*/
function listXATransactions(
string memory _index,
uint256 _size
) public view returns (string memory)
/** 获取事务详情
*
* @param _xaTransactionID 事务ID
* @return 事务详情,JSON格式
*/
function getXATransaction(
string memory _xaTransactionID
) public view returns(string memory)
桥接合约¶
功能点:
- 注册跨链调用请求
- 查询跨链调用回调结果
示例:
Solidity版:
Golang版:
以Solidity合约为例,接口列表:
/** 供业务合约调用,注册跨链调用请求
*
* @param _path 目标链合约的路径
* @param _method 调用方法名
* @param _args 调用参数列表
* @param _callbackPath 回调的合约路径
* @param _callbackMethod 回调方法名
* @return 跨链请求的唯一ID
*/
function interchainInvoke(
string memory _path,
string memory _method,
string[] memory _args,
string memory _callbackPath,
string memory _callbackMethod
) public returns(string memory uid)
/** 供跨链路由调用,获取跨链调用请求
*
* @param _num 获取数量
* @return 请求列表,JSON格式
*/
funct
function getInterchainRequests(
uint256 _num
) public view returns(string memory)
/** 供跨链路由调用,更新跨链任务处理进度
*
* @param _index 新下标
*/
function updateCurrentRequestIndex(uint256 _index) public
/** 供跨链路由调用,注册回调结果
*
* @param _uid 跨链请求的唯一ID
* @param _tid 事务ID
* @param _seq 事务序列号
* @param _errorCode 回调错误码
* @param _errorMsg 回调错误详情
* @param _result 回调结果
*/
function registerCallbackResult(
string memory _uid,
string memory _tid,
string memory _seq,
string memory _errorCode,
string memory _errorMsg,
string[] memory _result
) public
/** 供用户调用,查询回调的调用结果
*
* @param _uid 跨链请求的唯一ID
* @return 字符串数组: [事务ID, 事务Seq, 错误码, 错误消息, 回调调用结果的JSON序列化]
*/
function selectCallbackResult(
string memory _uid
) public view returns(string[] memory)
Java插件¶
Java核心组件¶
- StubFactory
- 组件实例化工厂类
- Account
- 区块链账户,用于交易签名
- Connection
- 调用区块链SDK接口,与区块链交互
- Driver
- 交易、交易回执、区块等与区块链相关数据的编解码
- 实现
Stub
的基础接口 - 调用
Connection
对象的发送入口与区块链交互
StubFactory¶
- 功能描述:
- 添加
@Stub
注解,定义插件类型 - 提供
Account
、Connection
、Driver
实例化入口
- 添加
重要
@Stub定义了插件类型,添加@Stub注解的插件才能被Wecross Router识别加载!
- 接口定义
public interface StubFactory {
public Driver newDriver();
public Connection newConnection(String path);
public Account newAccount(Map<String, Object> properties);
}
- 接口列表
- newDriver
- 实例化
Driver
对象
- 实例化
- newConnection
- 实例化
Connection
对象path
:配置文件路径,配置文件名称默认stub.toml
- 实例化
- newAccount
- 实例化
Account
对象properties
:Account
对象实例化的参数
- 实例化
- newDriver
FISCO-BCOS StubFactory
示例
/** @Stub注解,插件类型: BCOS2.0 */
@Stub("BCOS2.0")
public class BCOSStubFactory implements StubFactory {
@Override
public Driver newDriver() {
Driver driver = new BCOSDriver();
/** 其他逻辑 */
return driver;
}
@Override
public Connection newConnection(String path) {
Connection connection = new BCOSConnection();
/** 解析配置文件,初始化 BCOSConnection */
return connection;
}
@Override
public Account newAccount(Map<String, Object> properties) {
Account account = new BCOSAccount();
/** 根据properties参数,初始化 BCOSAccount */
return account;
}
}
Account¶
- 功能描述
- 交易签名
- 链账户签名、验签
- 接口定义
public interface Account {
String getName();
String getType();
String getIdentity();
int getKeyID();
boolean isDefault();
}
- 接口列表
- getName
- 链账户名称,自定义
- getType
- 链账户类型,与Stub类型保持一致
- getIdentify
- 链账户标记符,通常为链账户公钥
- isDefault
- 当前账户是否为默认链账户
- getKeyID
- 链账户KeyID
- getName
Connection¶
- 功能描述
- 解析配置文件,初始化区块链
JavaSDK
,参考下面配置文件
小节 - 为
Driver
提供统一的发送接口,与区块链进行交互 - 获取链上的资源列表
- 解析配置文件,初始化区块链
- 接口定义
public interface Connection {
Response send(Request request);
List<ResourceInfo> getResources();
}
接口列表
getResources
获取区块链上的资源列表
/** 资源对象 */ public class ResourceInfo { /** 资源名称 */ private String name; /** 资源类型,用户自定义 */ private String stubType; /** 资源属性 */ private Map<Object, Object> properties = new HashMap<Object, Object>(); }
send
发送接口
Request request
: 请求对象,包括请求类型、请求内容public class Request { // 请求类型,自定义类型 private int type; // 请求内容,序列化的请求参数 private byte[] data; }
Response response
: 返回对象,包括返回状态、描述信息、返回内容public class Response { // 返回状态码 private int errorCode; // 描述信息 private String errorMessage; // 返回内容,序列化的返回参数 private byte[] data; }
FISCO-BCOS BCOSConnection
示例:
// Request type定义,自定义
public class BCOSRequestType {
// 查询操作
public static final int CALL = 1000;
// 发送交易
public static final int SEND_TRANSACTION = 1001;
// 获取块高
public static final int GET_BLOCK_NUMBER = 1002;
// 获取区块
public static final int GET_BLOCK_BY_NUMBER = 1003;
// 获取交易证明
public static final int GET_TRANSACTION_PROOF = 1004;
}
// Connection定义各个类型消息的处理方式
public class BCOSConnection implements Connection {
/** 发送入口,区分消息类型,调用区块链RPC接口 */
@Override
public Response send(Request request) {
switch (request.getType()) {
/** 查询 */
case BCOSRequestType.CALL:
/** call请求 */
break;
/** 发送交易 */
case BCOSRequestType.SEND_TRANSACTION:
/** sendTransaction请求 */
break;
/** 获取区块头 */
case BCOSRequestType.GET_BLOCK_NUMBER:
/** 获取区块高度请求 */
break;
/** 获取块高 */
case BCOSRequestType.GET_BLOCK_BY_NUMBER:
/** 获取区块 */
break;
/** 获取交易证明 */
case BCOSRequestType.GET_TRANSACTION_PROOF:
/** 获取交易证明 */
break;
}
}
}
配置文件 配置文件主要包括区块链
JavaSDK
初始化需要的参数,也可以包含其他的一些附加信息,由用户自定义。配置默认位于chains/
目录,可以配置多个stub,每个stub位于单独的子目录,配置文件名称stub.toml
。# 目录结构, conf/chains/stub名称/ conf/chains/ └── bcos # stub名称: bcos └── stub.toml # stub.toml配置文件 # 其他文件列表,比如:证书文件
stub.toml
解析流程可以参考FISCO-BCOS Stub stub.toml解析
FISCO-BCOS stub.toml示例
[common] # 通用配置
name = 'bcos' # 名称,必须项
type = 'BCOS2.0' # 必须项,插件类型,与插件@Stub注解定义的类型保持一致
[chain] # FISCO-BCOS 属性
groupId = 1 # default 1
chainId = 1 # default 1
[channelService] # FISCO-BCOS JavaSDK配置
caCert = 'ca.crt'
sslCert = 'sdk.crt'
sslKey = 'sdk.key'
timeout = 300000 # 超时时间
connectionsStr = ['127.0.0.1:20200', '127.0.0.1:20201', '127.0.0.1:20202'] # 连接列表
Driver¶
- 功能描述
- 发送交易
- 状态查询
- 查询块高
- 查询区块
- 获取交易证明
- 交易、区块编解码
- 验证交易
- 查询资源列表
- 接口定义
public interface Driver {
interface Callback {
void onTransactionResponse(
TransactionException transactionException, TransactionResponse transactionResponse);
}
ImmutablePair<Boolean, TransactionRequest> decodeTransactionRequest(Request request);
List<ResourceInfo> getResources(Connection connection);
void asyncCall(
TransactionContext context,
TransactionRequest request,
boolean byProxy,
Connection connection,
Driver.Callback callback);
void asyncSendTransaction(
TransactionContext context,
TransactionRequest request,
boolean byProxy,
Connection connection,
Driver.Callback callback);
interface GetBlockNumberCallback {
void onResponse(Exception e, long blockNumber);
}
void asyncGetBlockNumber(Connection connection, GetBlockNumberCallback callback);
interface GetBlockCallback {
void onResponse(Exception e, Block block);
}
void asyncGetBlock(
long blockNumber, boolean onlyHeader, Connection connection, GetBlockCallback callback);
interface GetTransactionCallback {
void onResponse(Exception e, Transaction transaction);
}
void asyncGetTransaction(
String transactionHash,
long blockNumber,
BlockManager blockManager,
boolean isVerified,
Connection connection,
GetTransactionCallback callback);
interface CustomCommandCallback {
void onResponse(Exception error, Object response);
}
void asyncCustomCommand(
String command,
Path path,
Object[] args,
Account account,
BlockManager blockManager,
Connection connection,
CustomCommandCallback callback);
byte[] accountSign(Account account, byte[] message);
boolean accountVerify(String identity, byte[] signBytes, byte[] message);
}
- 接口列表:
- asyncCall
- asyncSendTransaction
状态查询/发送交易
- TransactionContext context
- 请求上下文,交易的上下文,包含交易的附属信息
- TransactionRequest request
- boolean byProxy
- 是否通过代理合约查询状态/发送交易
- Connection connection
- 发送请求
- Driver.Callback callback
- 回调返回
- TransactionContext context
- asyncGetBlockNumber
获取区块高度
- Connection connection
- 发送请求
- GetBlockNumberCallback callback
- 回调返回
- Connection connection
- asyncGetBlock
获取区块
- long blockNumber
- 区块高度
- boolean onlyHeader
- 是否只获取区块头
- Connection connection
- 发送请求
- GetBlockCallback callback
- 回调返回
- long blockNumber
- asyncGetTransaction
获取交易,并且对交易进行合法性验证
- String transactionHash
- 交易hash
- long blockNumber
- 区块高度
- BlockManager blockManager
- 区块管理对象,用于获取区块信息,可以使用区块头部的状态信息校验交易是否合法
- boolean isVerified
- 是否校验交易
- Connection connection
- 发送请求
- GetTransactionCallback callback
- 回调返回
- String transactionHash
- asyncCustomCommand
用户自定义其他接口
- String command
- 命令
- Path path
- 资源
- Object[] args
- 参数列表
- Account account
- 账户
- BlockManager blockManager
- 区块管理对象
- Connection connection
- 发送请求
- CustomCommandCallback callback
- 回调返回
- String command
- accountSign
链账户
Account
对消息进行签名,返回序列化之后的签名对象- Account account
- 签名账户
- byte[] message
- 代签名的消息
- Account account
- accountVerify
链账户验签
- String identity
- byte[] signBytes
- 签名对象,
accountSign
的返回值
- 签名对象,
- byte[] message
- 签名的原始消息
开发模板¶
WeCross提供一个Java
模板工程,加快用户开发WeCross Stub的速度,用户仅需要进行少量的修改。
获取:
git clone https://github.com/WeBankBlockchain/WeCross-Stub-Dev-Template.git
目录结构:
WeCross-Stub-Dev-Template
├── README.md
├── build.gradle
└── src
├── main
│ ├── java
│ │ └── wecross
│ │ └── stub
│ │ └── demo ## Java核心组件,参考上文各个组件的介绍
│ │ ├── DemoAccount.java # Account
│ │ ├── DemoConnection.java # Connection
│ │ ├── DemoDriver.java # Driver
│ │ └── DemoStubFactory.java # StubFactory
│ └── resources
└── test
├── java
│ └── wecross
│ └── stub
│ └── demo
│ └── DemoStubTest.java
└── resources
编译:
cd WeCross-Stub-Dev-Template
bash gradlew build
$ tree -L 1 dist/apps
dist/apps
└── WeCross-Stub-Dev-Template-1.0.0-SNAPSHOT.jar