区块链接入开发(Stub)
优质
小牛编辑
117浏览
2023-12-01
本章节首先介绍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