Java SDK¶
1 前言¶
此SDK文档面向BitXHub平台的应用开发者,提供BitXHub Java SDK的使用指南。
2 接口使用流程示例¶
2.1 基础流程示例¶
为了更好的理解接口的使用,本示例将从初始化Client,部署合约,调用合约和返回值解析这个大致流程作介绍,具体详细接口可参考第三章SDK文档。
2.1.1 初始化Client¶
使用默认的配置类初始化Grpc Client。
例如:
使用定制化的配置类初始化Grpc Client。
例如:
Config config = Config.builder()
            .host("localhost")
            .port(60011)
            .ecKey(new ECKeyP256())
            .build();
GrpcClient client = new GrpcClientImpl(config);
2.1.2 部署合约¶
开发者需提供已经编译的WebAssembly文件。
例如:
通过client部署合约,部署完成后可以获取合约地址contractAddress。
例如:
2.1.3 调用合约¶
调用合约需传入合约地址、合约方法名和对应的参数。
例如:
ReceiptOuterClass.Receipt receipt =
client.invokeXVMContract(contractAddress, "a", Types.i32(1), Types.i32(1)); \\方法名为a,传参1,传参2
2.1.4 返回值解析¶
得到返回值结果后,获得状态码可以判断是否调用成功,若调用成功,解析返回值可看到调用之后的结果。
例如:
if (receipt.getStatus() == ReceiptOuterClass.Receipt.Status.SUCCESS) {
    log.info(receipt.getRet().toStringUtf8());  
}
2.1.5 完整示例¶
//获取wasm字节数组
byte[] contractBytes = IOUtils.toByteArray(
new FileInputStream("./example.wasm"));
//部署合约,获取合约地址
String contractAddress = client.deployContract(contractBytes);
//调用合约,获取交易回执
ReceiptOuterClass.Receipt receipt = client.invokeXVMContract(contractAddress, "a", Types.i32(1), Types.i32(1));
//判断合约调用交易成功与否,打印合约调用数据
if (receipt.getStatus() == ReceiptOuterClass.Receipt.Status.SUCCESS) {
    log.info(receipt.getRet().toStringUtf8());
}
2.2 应用链管理流程示例¶
本示例展示应用链管理流程中的注册、审核以及注销操作。
2.2.1 应用链注册¶
调用BVM合约的Register方法,向BitXHub注册应用链。
例如:
ArgOuterClass.Arg[] args = Types.toArgArray(
    Types.string(""), //validators
    Types.i32(0), //consensus_type
    Types.string("hyperchain"), //chain_type
    Types.string("税务链"), //name
    Types.string("趣链税务链"), //desc
    Types.string("1.8")); //version
    Types.string("")); //public key
ReceiptOuterClass.Receipt receipt = client.invokeBVMContract(BVMAddr.APPCHAIN_MANAGER_CONTRACT_ADDR, "Register", args);
获取到成功的交易回执后,解析交易回执内容。
例如:
{
    "id": "0x5098cc26b0d485145fb8258d2e79c49886cd4662", \\应用链ID
    "name": "税务链",
    "validators": "", 
    "consensus_type": 0,
    "status": 0,
    "chain_type": "hyperchain",
    "desc": "趣链税务链",
    "version": "1.8",
    "public_key": ""
}
2.2.2 应用链审核¶
调用BVM合约的Audit方法,向BitXHub审核应用链。
例如:
ArgOuterClass.Arg[] adultArgs = Types.toArgArray(
    Types.string(appchainID), //应用链ID
    Types.i32(1), //审核通过
    Types.string("")); //描述信息
ReceiptOuterClass.Receipt adultReceipt = client.invokeBVMContract(BVMAddr.APPCHAIN_MANAGER_CONTRACT_ADDR, "Audit", adultArgs);
2.2.3 应用链注销¶
调用BVM合约的DeleteAppchain方法,向BitXHub注销应用链。
例如:
ArgOuterClass.Arg[] deleteArgs = Types.toArgArray(
    Types.string(appchainID); //应用链ID
ReceiptOuterClass.Receipt deleteReceipt = client.invokeBVMContract(BVMAddr.APPCHAIN_MANAGER_CONTRACT_ADDR, "DeleteAppchain", deleteArgs);
2.3 验证规则使用示例¶
本示例展示验证规则中的注册、审核操作,以及WebAssembly合约示例。
2.3.1 验证规则注册¶
调用BVM合约的RegisterRule方法,向应用链注册验证规则(WebAssembly合约),这里我们需要先注册应用链和部署验证规则合约,然后获取应用链ID和合约地址。
例如:
ArgOuterClass.Arg[] ruleArgs = Types.toArgArray(
    Types.string(appchainID),
    Types.string(contractAddress));
ReceiptOuterClass.Receipt ruleReceipt = client.invokeBVMContract(BVMAddr.RULE_MANAGER_CONTRACT_ADDR, "RegisterRule", ruleArgs);
2.3.2 验证规则审核¶
调用BVM合约的Audit方法,向BitXHub审核验证规则。
例如:
ArgOuterClass.Arg[] adultArgs = Types.toArgArray(
    Types.string(contractAddress), //验证规则的合约地址
    Types.i32(1), //审核通过
    Types.string("")); //描述信息
ReceiptOuterClass.Receipt adultReceipt = client.invokeBVMContract(BVMAddr.RULE_MANAGER_CONTRACT_ADDR, "Audit", adultArgs);
2.3.3 验证规则示例(WebAssembly合约, Fabric实例)¶
extern crate protobuf;
extern crate sha2;
use crate::crypto::ecdsa;
use crate::model::transaction;
use sha2::{Digest, Sha256};
pub fn verify(proof: &[u8], validator: &[u8]) -> bool {
  let cap =
    protobuf::parse_from_bytes::<transaction::ChaincodeActionPayload>(proof).expect("error");
  let cap_act = cap.action.unwrap();
  let endorsers = cap_act.endorsements;
  let mut digest = Sha256::new();
  let mut payload = cap_act.proposal_response_payload.to_owned();
  payload.extend(&endorsers[0].endorser);
  digest.input(&payload);
  let digest_byte = digest.result();
  return ecdsa::verify(
    &endorsers[0].signature,
    &digest_byte,
    &validator,
    ecdsa::EcdsaAlgorithmn::P256,
  );
}
3 SDK文档¶
3.1 初始化¶
3.1.1 初始化Client¶
用途:调用该接口获取与BitXHub交互的Client。
入参:Config 是BitXHub的网络地址, 端口以及密钥的配置。
返回值:与BitXHub交互的Client。
3.1.2 停止Client¶
用途:调用该接口将与BitXHub交互的Client关闭。
3.1.3 设置私钥¶
用途:调用该接口重新设置client私钥。
入参:key是ECDSA类型的私钥实例。
3.2 交易接口¶
3.2.1 发送交易¶
用途:调用该接口向中继链发送签名后的交易,交易类型包括普通交易、跨链交易和智能合约。若签名非法,仍会返回交易哈希,但是交易回执非法。
参数:
- transaction交易。
- opts跨链交易nonce。
用例:
public void sendTransaction() {
        Transaction.BxhTransaction unsignedTx = Transaction.BxhTransaction.newBuilder()
                .setFrom(ByteString.copyFrom(from))
                .setTo(ByteString.copyFrom(to))
                .setTimestamp(Utils.genTimestamp())
                .setPayload(Transaction.TransactionData.newBuilder().setAmount("100000").build().toByteString())
                .build();
        Transaction.BxhTransaction signedTx = SignUtils.sign(unsignedTx, config.getEcKey());
        String txHash = client.sendTransaction(signedTx, null);
    }
3.2.2 发送交易并返回回执¶
用途:调用该接口向中继链发送签名后的交易,并返回交易回执。
参数:
- transaction交易。
- opts跨链交易nonce。
public ReceiptOuterClass.Receipt sendTransactionWithReceipt(Transaction.BxhTransaction transaction, TransactOpts opts)
3.2.3 发送只读交易¶
用途:调用该接口向中继链发送只读交易并返回交易回执。
参数:
- transaction交易。
3.2.4 查询交易回执¶
用途:调用该接口向BitXHub查询交易回执,交易回执的状态标识了交易是否成功。
参数:
- hash交易哈希。
3.2.5 查询交易¶
用途:调用该接口向BitXHub查询交易。
参数:
- hash交易哈希。
3.3 合约接口¶
合约类型:
- 
BVM:BitXHub内置合约 
- 
XVM:WebAssembly合约 
3.3.1 部署合约¶
用途:调用该接口向BitXHub部署XVM合约。
参数:
- contract合约数据。
3.3.2 调用合约¶
用途:调用该接口向BitXHub调用BVM或者XVM合约并返回调用结果。
参数:
- vmType合约类型:BVM和XVM。
- contractAddress合约地址。
- method合约方法。
- args合约方法参数。
public ReceiptOuterClass.Receipt invokeContract(Transaction.TransactionData.VMType vmType, String contractAddress, String method, ArgOuterClass.Arg... args)
用例:
public void invokeBVMContract() {
        String result = "10";
        ReceiptOuterClass.Receipt receipt = client.invokeContract(Transaction.TransactionData.VMType.BVM
                , BVMAddr.STORE_CONTRACT_ADDR, "Set", Types.string("a"), Types.string(result));
        ReceiptOuterClass.Receipt receipt1 = client.sendView(client.generateContractTx(Transaction.TransactionData.VMType.BVM
                , BVMAddr.STORE_CONTRACT_ADDR, "Get", Types.string("a")));
    }
3.3.3 调用BVM合约¶
用途:调用该接口向BitXHub调用BVN合约并返回调用结果。
参数:
- contractAddress合约地址。
- method合约方法。
- args合约方法参数。
public ReceiptOuterClass.Receipt invokeBVMContract(String contractAddress, String method, ArgOuterClass.Arg... args)
3.3.4 调用XVM合约¶
用途:调用该接口向BitXHub调用XVN合约并返回调用结果。
参数:
- contractAddress合约地址。
- method合约方法。
- args合约方法参数。
public ReceiptOuterClass.Receipt invokeXVMContract(String contractAddress, String method, ArgOuterClass.Arg... args)
3.3.5 生成调用合约交易¶
用途:调用该接口生成合约调用交易。
参数:
- vmType合约类型:BVM和XVM。
- contractAddress合约地址。
- method合约方法。
- args合约方法参数。
public Transaction.BxhTransaction generateContractTx(Transaction.TransactionData.VMType vmType, String contractAddress, String method, ArgOuterClass.Arg... args)
3.4 区块接口¶
3.4.1 查询区块¶
用途:调用该接口向BitXHub查询区块,其中区块头包含区块基本信息,区块体包含所有打包的交易。
参数:
- value区块高度或者区块哈希。
- type查询类型。
3.4.2 批量查询区块¶
用途:批量查询区块,返回指定块高度范围(start到end)的区块信息。
参数:
- start指定范围的起始区块高度。
- end指定范围的结束区块高度。
3.4.3 批量查询HapplyBlock¶
用途:批量查询HappyBlock,返回指定块高度范围(start到end)的区块信息。HappyBlock中将BitXHub交易和以太坊交易分别存储。
参数:
- start指定范围的起始区块高度。
- end指定范围的结束区块高度。
3.4.4 查询区块Meta¶
用途:返回当前链的高度、区块哈希以及跨链交易数。
3.4.5 查询区块链状态¶
用途:返回当前区块链共识的状态(正常或者不正常)。
3.4.6 批量查询区块头¶
用途:调用该接口向BitXHub查询指定块高度范围内的区块头。
参数:
- begin指定范围的起始区块高度。
- end指定范围的结束区块高度
3.5 订阅接口¶
3.5.1 订阅事件¶
用途:调用该接口向BitXHub发起订阅事件。
参数:
- streamObserver事件通道。
- type事件类型。
用例:
public void subscribe(Broker.SubscriptionRequest.Type type, StreamObserver<Broker.Response> observer)
public void subscribe() throws InterruptedException {
    CountDownLatch asyncLatch = new CountDownLatch(1);
    StreamObserver<Broker.Response> observer = new StreamObserver<Broker.Response>() {
        @Override
        public void onNext(Broker.Response response) {
            ByteString data = response.getData();
            BlockOuterClass.Block block = null;
            try {
                block = BlockOuterClass.Block.parseFrom(data);
            } catch (InvalidProtocolBufferException e) {
                e.printStackTrace();
            }
        }
        @Override
        public void onError(Throwable throwable) {
            throwable.printStackTrace();
            asyncLatch.countDown();
        }
        @Override
        public void onCompleted() {
            asyncLatch.countDown();
        }
    };
    client.subscribe(Broker.SubscriptionRequest.Type.BLOCK, observer);
    asyncLatch.await();
}
3.5.2 订阅审计事件¶
用途:调用该接口向BitXHub订阅审计信息。
参数:
- type事件类型,AUDIT_NODE。
- blockHeight订阅事件开始块高度。
- observer事件通道。
public void subscribeAuditInfo(AuditInfo.AuditSubscriptionRequest.Type type, Long blockHeight, StreamObserver<Broker.Response> observer);
用例:
public void subscribeAudit() throws InterruptedException {
        CountDownLatch asyncLatch = new CountDownLatch(1);
        StreamObserver<Broker.Response> observer = new StreamObserver<Broker.Response>() {
            @Override
            public void onNext(Broker.Response response) {
                ByteString data = response.getData();
                AuditInfo.AuditTxInfo info = null;
                Transaction.TransactionData txData = null;
                Transaction.InvokePayload payload = null;
                try {
                    info = AuditInfo.AuditTxInfo.parseFrom(data);
                    if (!info.getTx().hasIBTP()){
                        txData = Transaction.TransactionData.parseFrom(info.getTx().getPayload());
                        payload = Transaction.InvokePayload.parseFrom(txData.getPayload());
                        System.out.printf("from: %s, to: %s\n",
                                Keys.toChecksumAddress(ByteUtil.toHexStringWithOx(info.getTx().getFrom().toByteArray())),
                                Keys.toChecksumAddress(ByteUtil.toHexStringWithOx(info.getTx().getTo().toByteArray()))
                        );
                        System.out.printf("method: %s\n", payload.getMethod());
                    }
                } catch (InvalidProtocolBufferException e) {
                    e.printStackTrace();
                }
                Assert.assertNotNull(info);
                asyncLatch.countDown();
            }
            @Override
            public void onError(Throwable throwable) {
                throwable.printStackTrace();
                asyncLatch.countDown();
            }
            @Override
            public void onCompleted() {
                asyncLatch.countDown();
            }
        };
        System.out.printf("adminAddr: %s\n", Keys.toChecksumAddress(ByteUtil.toHexStringWithOx(adminAddr1)));
        System.out.printf("appchainAddr: %s\n", Keys.toChecksumAddress(ByteUtil.toHexStringWithOx(appchainAdmin)));
        System.out.printf("nodeAccount: %s\n", Keys.toChecksumAddress(ByteUtil.toHexStringWithOx(nodeAccount)));
        try {
            registerAppchain("appchain1", "应用链1", Keys.toChecksumAddress(ByteUtil.toHexStringWithOx(appchainAdmin)));
            registerNode(Keys.toChecksumAddress(ByteUtil.toHexStringWithOx(nodeAccount)), "审计节点", "appchain1");
            Thread.sleep(5000);
        } catch (InterruptedException | StatusRuntimeException e) {
            e.printStackTrace();
        }
        try {
            Chain.ChainMeta chainMeta = nodeCli.getChainMeta();
        } catch (StatusRuntimeException e) {
            Assert.assertNotNull(e);
            e.printStackTrace();
        }
        try {
            Broker.GetBlocksResponse response = nodeCli.getBlocks(1L, 10L);
        } catch (StatusRuntimeException e) {
            e.printStackTrace();
        }
        try {
            nodeCli.subscribeAuditInfo(AuditInfo.AuditSubscriptionRequest.Type.AUDIT_NODE, 1L, observer);
        } catch (StatusRuntimeException e) {
            e.printStackTrace();
        }
        asyncLatch.await();
    }
3.5.3 订阅查询InterchainTxWrapper¶
用途:调用该接口向BitXHub获取指定块高度范围内的InterchainTxWrapper。通过InterchainTxWrapper可以获取区块中的跨链交易。
参数:
- pid应用链ID。
- begin指定范围的起始区块高度。
- end指定范围的结束区块高度。
- streamObserverInterchainTxWrapper通道。
public void getInterchainTxWrappers(String pid, Long begin, Long end, StreamObserver<Broker.InterchainTxWrappers> streamObserver)
用例:
public void getInterchainTxWrapper() throws InterruptedException {
        CountDownLatch asyncLatch = new CountDownLatch(1);
        StreamObserver<Broker.InterchainTxWrappers> observer = new StreamObserver<Broker.InterchainTxWrappers>() {
            @Override
            public void onNext(Broker.InterchainTxWrappers interchainTxWrapper) {
                asyncLatch.countDown();
            }
            @Override
            public void onError(Throwable throwable) {
                throwable.printStackTrace();
                asyncLatch.countDown();
            }
            @Override
            public void onCompleted() {
                asyncLatch.countDown();
            }
        };
        Chain.ChainMeta chainMeta = client.getChainMeta();
        client.getInterchainTxWrappers("node1", chainMeta.getHeight(), chainMeta.getHeight() + 100, observer);
        sendInterchaintx();
        asyncLatch.await();
    }
3.5.4 订阅查询区块头¶
用途:调用该接口向BitXHub获取指定块高度范围内的区块头。
参数:
- begin指定范围的起始区块高度。
- end指定范围的结束区块高度。
- streamObserver区块头通道。
public void getBlockHeaders(Long begin, Long end, StreamObserver<BlockOuterClass.BlockHeader> streamObserver)
用例:
public void getBlockHeaders() throws InterruptedException {
        CountDownLatch asyncLatch = new CountDownLatch(1);
        StreamObserver<BlockOuterClass.BlockHeader> observer = new StreamObserver<BlockOuterClass.BlockHeader>() {
            @Override
            public void onNext(BlockOuterClass.BlockHeader blockHeader) {
                asyncLatch.countDown();
            }
            @Override
            public void onError(Throwable throwable) {
                throwable.printStackTrace();
                asyncLatch.countDown();
            }
            @Override
            public void onCompleted() {
                asyncLatch.countDown();
            }
        };
        client.getBlockHeaders(1L, 2L, observer);
        sendTransaction();
        asyncLatch.await();
    }
3.6 其它接口¶
3.6.1 查询节点网络信息¶
用途:返回当前区块链网络的节点信息。
3.6.2 查询账户余额¶
参数:
- address地址。
3.6.3 查询账户nonce¶
用途:调用该接口获取账户地址下一笔跨链交易nonce。
参数:
- account账户地址。
3.6.4 查询中继链验证者¶
用途:返回中继链创世管理员地址。
3.6.5 查询TPS¶
用途:获取指定块高度范围内的TPS。
参数:
- begin指定范围的起始区块高度。
- end指定范围的结束区块高度。
3.6.6 查询BitXHub链ID¶
用途:获取中继链的链ID。
3.6.7 查询多签¶
用途:调用该接口向中继链获取指定多签结果。
参数:
- type指定类型,区块头、IBTP等。
- content查询内容。