BIF-Core-SDK

各种语言的SDK

名称

开发语言

BIF-Core-SDK

JAVA

BIF-Core_SDK-JS

Nodejs

BIF-Core-SDK-Go

Go

简介

BIF-Core-SDK通过API调用的方式提供了星火链网-底层区块链平台公私钥对生成、星火链网-底层区块链平台私钥签名公钥验签、账号服务、区块服务、交易服务等接口,同时还提供了接口使用示例说明,开发者可以调用该SDK方便快捷的生成星火链网主链的快速接入。中国信通院秉持开源开放的理念,将星火“BID-Core-SDK”面向社区和公众完全开源,助力全行业伙伴提升数据价值流通的效率,实现数据价值转化。

image-20211012184224056
图1 BIF-Core-SDK 逻辑架构图

SDK 离线API

离线API主要是账户和密码学相关API, 不需要连接星火链网RPC接口也能工作。 主要接口如下:

账户生成

  1. 接口 KeyPairEntity.getBidAndKeyPair

  2. 用途:

    用来生成一个星火链bid地址和对应私钥。

  3. 示例

    import cn.bif.model.crypto.KeyPairEntity;
    
    KeyPairEntity keypair = KeyPairEntity.getBidAndKeyPair();
    String encAddress = keypair.getEncAddress();
    String encPublicKey = keypair.getEncPublicKey();
    String encPrivateKey = keypair.getEncPrivateKey();
    byte[] rawPublicKey = keypair.getRawPublicKey();
    byte[] rawPrivateKey = keypair.getRawPrivateKey();
    System.out.println(JsonUtils.toJSONString(keypair))
    

加密私钥生成keystore

  1. 接口 KeyStore.generateKeyStore

  2. 用途:

    用一个密码来加密保护私钥, 得到一个json表示的keystore, 对应密码不泄露的情况下, 可以公开保存。

  3. 示例

    package cn.bif.sdkSamples.encryption.example;
    
    import cn.bif.common.JsonUtils;
    import cn.bif.module.encryption.crypto.keystore.KeyStore;
    import cn.bif.module.encryption.crypto.keystore.entity.KeyStoreEty;
    
    import java.util.HashMap;
    import java.util.Map;
    
    public class TestCrypto {
        public static void main(String argv[]) {
            String encPrivateKey = "priSPKqru2zMzeb14XWxPNM1sassFeqyyUZotCAYcvCjhNof7t";
            String password = "bif8888";
            TestKeyStoreWithPrivateKey(encPrivateKey, password);
    
        }
    
        public static void TestKeyStoreWithPrivateKey(String encPrivateKey, String password) {
            try {
                int n = (int) Math.pow(2, 16);
                //生成keystore-1
                KeyStoreEty returEencPrivateKey = KeyStore.generateKeyStore(password,encPrivateKey, 2, 1, 1, n);
                System.out.println(JsonUtils.toJSONString(returEencPrivateKey));
    
                //生成keystore-2
                KeyStoreEty keyStore1 = KeyStore.generateKeyStore(password, encPrivateKey, n);
                System.out.println(JsonUtils.toJSONString(keyStore1));
    
                //从keystore反解出私钥
                String keyStoreStr="{\"address\":\"did:bid:efEScJgGPf54vfU8ciEjjugkJLB4xYzp\",\"aesctr_iv\":\"EEDDD37CEB6864030124142CEB081BCD\",\"cypher_text\":\"7274705F65388E30338A2D69AE2241DBABCF66550C0453BEE30CFA45F02E04D08FAC551B46171531CA067B6E85BC342F43C8\",\"scrypt_params\":{\"n\":16384,\"p\":1,\"r\":8,\"salt\":\"82D37133C13525EDE4EF19DCD692592FC1685B5EDAABA8C943EA2C1AD4596FB3\"},\"version\":2}";
                String privateKey = KeyStore.decipherKeyStore(password, JsonUtils.toJavaObject(keyStoreStr,KeyStoreEty.class));
                System.out.println(privateKey);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
    }
    

SDK 在线API

在线API主要用于向星火链上发出交易和查询合约, 需要初始化SDK连接后使用。

初始化SDK

  1. 示例

    import cn.bif.api.BIFSDK;
    
    BIFSDK sdk = BIFSDK.getInstance(SDK_INSTANCE_URL);   //SDK_INSTANCE_URL为星火链RPC地址
    

广播交易

image-20220929104105213

广播交易是指通过广播的方式发起交易。广播交易包括以下步骤:

  1. 获取账户nonce值

  2. 构建操作

  3. 序列化交易

  4. 签名交易

  5. 提交交易

  6. 查询交易

获取账户nonce值

开发者可自己维护各个账户nonce,在提交完一个交易后,自动为nonce值递增1,这样可以在短时间内发送多笔交易,否则,必须等上一个交易执行完成后,账户的nonce值才会加1。调用如下:

// 初始化请求参数
String senderAddress = "did:bid:efqhQu9YWEWpUKQYkAyGevPGtAdD1N6p";
BIFAccountGetNonceRequest request = new BIFAccountGetNonceRequest();
request.setAddress(senderAddress);
// 调用getNonce接口
Long nonce=0L;
BIFAccountGetNonceResponse response = sdk.getBIFAccountService().getNonce(request);
if (0 == response.getErrorCode()) {
    nonce=response.getResult().getNonce();
    System.out.println("Account nonce:" + response.getResult().getNonce());
}else {
    System.out.println(JsonUtils.toJSONString(response));
}

构建操作

这里的操作是指在交易中做的一些动作,便于序列化交易和评估费用。例如,构建创建账号操作(BIFAccountActivateOperation),接口调用如下:

Long initBalance = ToBaseUnit.ToUGas("0.01");
String destAddress = "did:bid:ef3LqNzb4ssNf2vqwNwBfqngrA3Sx8yD";

BIFAccountActivateOperation operation = new BIFAccountActivateOperation();
operation.setDestAddress(destAddress);
operation.setInitBalance(initBalance);

序列化交易

该接口用于序列化交易,并生成交易Blob串,便于网络传输。其中nonce和operation是上面接口得到的。调用如下:

// 初始化变量
String senderAddress = "did:bid:efqhQu9YWEWpUKQYkAyGevPGtAdD1N6p";
Long gasPrice = 1000L;
Long feeLimit = ToBaseUnit.ToUGas("0.01");

// 初始化请求参数
BIFTransactionSerializeRequest serializeRequest = new BIFTransactionSerializeRequest();
   serializeRequest.setSourceAddress(senderAddress);
   serializeRequest.setNonce(nonce + 1);
   serializeRequest.setFeeLimit(feeLimit);
   serializeRequest.setGasPrice(gasPrice);
   serializeRequest.setOperation(operation);
   
// 调用buildBlob接口
 BIFTransactionSerializeResponse serializeResponse = sdk.getBIFTransactionService().BIFSerializable(serializeRequest);
        if (!serializeResponse.getErrorCode().equals(Constant.SUCCESS)) {
            throw new SDKException(serializeResponse.getErrorCode(), serializeResponse.getErrorDesc());
  }
 String transactionBlob = serializeResponse.getResult().getTransactionBlob();

签名交易

该接口用于交易发起者使用其账户私钥对交易进行签名。其中transactionBlob是上面接口得到的。调用如下:

// 初始化请求参数
String senderPrivateKey = "priSPKqru2zMzeb14XWxPNM1sassFeqyyUZotCAYcvCjhNof7t";
byte[] signBytes = PrivateKeyManager.sign(HexFormat.hexToByte(transactionBlob), senderPrivateKey); 

提交交易

该接口用于向BIF-Core区块链发送交易请求,触发交易的执行。其中transactionBlob和signBytes是上面接口得到的。调用如下:

String publicKey = PrivateKeyManager.getEncPublicKey(senderPrivateKey);
BIFTransactionSubmitRequest submitRequest = new BIFTransactionSubmitRequest();
  submitRequest.setSerialization(transactionBlob);
  submitRequest.setPublicKey(publicKey);
  submitRequest.setSignData(HexFormat.byteToHex(signBytes));
     // 调用bifSubmit接口
 BIFTransactionSubmitResponse transactionSubmitResponse =         sdk.getBIFTransactionService().BIFSubmit(submitRequest);
//交易hash
String transactionHash=transactionSubmitResponse.getResult().getHash();

查询交易

该接口用于向BIF-Core区块链发送查询交易请求。交易打包时间为3~5秒,通过该接口判断交易是否完成,完成则可以进行下一笔交易。

        BIFTransactionGetInfoRequest request = new BIFTransactionGetInfoRequest();
        request.setHash("d098413c2882ae8cf95e384d778635909effaeb3616ce03d741726b5bc0af00a");

        BIFTransactionGetInfoResponse response = sdk.getBIFTransactionService().getTransactionInfo(request);
        if (response.getErrorCode() == 0) {
            System.out.println(JsonUtils.toJSONString(response.getResult()));
        } else {
            System.out.println(JsonUtils.toJSONString(response));
        }

查询交易池

该接口用于向BIF-Core区块链发送查询交易缓存池中交易内容。

        BIFTransactionCacheRequest cacheRequest=new BIFTransactionCacheRequest();
        cacheRequest.setHash("d098413c2882ae8cf95e384d778635909effaeb3616ce03d741726b5bc0af00a");

        BIFTransactionCacheResponse response = sdk.getBIFTransactionService().getTxCacheData(cacheRequest);
        if (response.getErrorCode() == 0) {
            System.out.println("txCacheData: "+JsonUtils.toJSONString(response.getResult().getTransactions()));
        } else {
            System.out.println(JsonUtils.toJSONString(response));
        }

账户处理接口

  1. 查询账户信息

    1. 接口 BIFAccountGetInfoRequest

    2. 用途:

      用来获取一个账户当前信息。

    3. 示例

      String accountAddress = "did:bid:efnVUgqQFfYeu97ABf6sGm3WFtVXHZB2";
      BIFAccountGetInfoRequest request = new BIFAccountGetInfoRequest();
      request.setAddress(accountAddress);
      // 调用getAccount接口
      BIFAccountGetInfoResponse response = sdk.getBIFAccountService().getAccount(request);
      
      if (response.getErrorCode() == 0) {
          System.out.println(JsonUtils.toJSONString(response.getResult()));
      } else {
          System.out.println(JsonUtils.toJSONString(response));
      }
      
  2. 获取账户nonce

    1. 接口 BIFAccountGetNonceRequest

    2. 用途:

      用来获取一个账户当前nonce值, 有关nonce含义, 请参照星火链开发基础节。

    3. 示例:

      String accountAddress = "did:bid:efnVUgqQFfYeu97ABf6sGm3WFtVXHZB2";
      BIFAccountGetNonceRequest request = new BIFAccountGetNonceRequest();
      request.setAddress(accountAddress);
      BIFAccountGetNonceResponse response = sdk.getBIFAccountService().getNonce(request);
      if (0 == response.getErrorCode()) {
          System.out.println("Account nonce:" + response.getResult().getNonce());
      }else {
          System.out.println(JsonUtils.toJSONString(response));
      }
      
  3. 获取账户余额

    1. 接口 BIFAccountGetBalanceRequest

    2. 用途:

      用来获取一个账户当前的XHT余额。

    3. 示例:

      String accountAddress = "did:bid:efzE8AcDgWUeNbgujA5hK3oUeuG9k19b";
      BIFAccountGetBalanceRequest request = new BIFAccountGetBalanceRequest();
      request.setAddress(accountAddress);
      
      BIFAccountGetBalanceResponse response = sdk.getBIFAccountService().getAccountBalance(request);
      if (0 == response.getErrorCode()) {
          System.out.println("Gas balance:" + ToBaseUnit.ToGas(response.getResult().getBalance().toString()) + "Gas");
      }else {
          System.out.println(JsonUtils.toJSONString(response));
      }
      

Block相关接口

  1. 获取当前块高度

    1. 接口 getBlockNumber

    2. 用途:

      获取当前链上最新的Block号。

    3. 示例:

      BIFBlockGetNumberResponse response = sdk.getBIFBlockService().getBlockNumber();
      System.out.println(JsonUtils.toJSONString(response));
      
  2. 获取指定块内的交易列表

    1. 接口 getTransactions(request)

    2. 用途:

      给定block号,获取该block内的交易列表信息。

    3. 示例:

      Long blockNumber = 1L;
      BIFBlockGetTransactionsRequest request = new BIFBlockGetTransactionsRequest();
      request.setBlockNumber(blockNumber);
      BIFBlockGetTransactionsResponse response = sdk.getBIFBlockService().getTransactions(request);
      if (0 == response.getErrorCode()) {
          System.out.println(JsonUtils.toJSONString(response.getResult()));
      } else {
          System.out.println(JsonUtils.toJSONString(response));
      }
      
  3. 获取指定块的统计信息

    1. 接口 getBlockInfo(request)

    2. 用途:

      给定block号, 查询指定block的信息。

    3. 示例:

       BIFBlockGetInfoRequest blockGetInfoRequest = new BIFBlockGetInfoRequest();
      blockGetInfoRequest.setBlockNumber(10L);
      BIFBlockGetInfoResponse lockGetInfoResponse = sdk.getBIFBlockService().getBlockInfo(blockGetInfoRequest);
      if (lockGetInfoResponse.getErrorCode() == 0) {
          BIFBlockGetInfoResult lockGetInfoResult = lockGetInfoResponse.getResult();
          System.out.println(JsonUtils.toJSONString(lockGetInfoResult));
      } else {
          System.out.println(JsonUtils.toJSONString(lockGetInfoResponse));
      }
      
  4. 查询最新块的信息

    1. 接口 getBlockLatestInfo

    2. 用途:

      获取当前最新块的信息。

    3. 示例:

      BIFBlockGetLatestInfoResponse lockGetLatestInfoResponse = sdk.getBIFBlockService().getBlockLatestInfo();
      if (lockGetLatestInfoResponse.getErrorCode() == 0) {
          BIFBlockGetLatestInfoResult lockGetLatestInfoResult = lockGetLatestInfoResponse.getResult();
          System.out.println(JsonUtils.toJSONString(lockGetLatestInfoResult));
      } else {
          System.out.println(JsonUtils.toJSONString(lockGetLatestInfoResponse));
      }
      

Transaction相关接口

  1. 获取指定交易相关信息

    1. 接口 getTransactionInfo

    2. 用途:

      获取指定交易的详细信息。

    3. 示例:

      BIFTransactionGetInfoRequest request = new BIFTransactionGetInfoRequest();
      request.setHash("8f3d53f0dfb5ae652d6ed93ca9512f57c2203fe0ffefdc7649908945ad96a730");
      BIFTransactionGetInfoResponse response = sdk.getBIFTransactionService().getTransactionInfo(request);
      if (response.getErrorCode() == 0) {
          System.out.println(JsonUtils.toJSONString(response.getResult()));
      } else {
          System.out.println(JsonUtils.toJSONString(response));
      }
      
  2. 提交交易

    1. 接口 BIFSubmit

    2. 用途:

      提交交易到星火链网。

    3. 示例:

      // 初始化参数
      String senderPrivateKey = "priSPKkWVk418PKAS66q4bsiE2c4dKuSSafZvNWyGGp2sJVtXL";
      //序列化交易
      String serialization ="";
      //签名
      byte[] signBytes = PrivateKeyManager.sign(HexFormat.hexToByte(serialization), senderPrivateKey);
      String publicKey = PrivateKeyManager.getEncPublicKey(senderPrivateKey);
      //提交交易
      BIFTransactionSubmitRequest submitRequest = new BIFTransactionSubmitRequest();
      submitRequest.setSerialization(serialization);
      submitRequest.setPublicKey(publicKey);
      submitRequest.setSignData(HexFormat.byteToHex(signBytes));
      // 调用bifSubmit接口
      BIFTransactionSubmitResponse response = sdk.getBIFTransactionService().BIFSubmit(submitRequest);
      if (response.getErrorCode() == 0) {
          System.out.println(JsonUtils.toJSONString(response.getResult()));
      } else {
          System.out.println("error: " + response.getErrorDesc());
      }
      

合约相关接口

  1. 部署合约

    1. 接口 contractCreate

    2. 用途:

      部署合约到星火链上。

    3. 示例:

      String senderAddress = "did:bid:ef21AHDJWnFfYQ3Qs3kMxo64jD2KATwBz";
      String senderPrivateKey = "priSPKkL8XpxHiRLuNoxph2ThSbexeRUGEETprvuVHkxy2yBDp";
      String payload = "\"use strict\";function init(bar){/*init whatever you want*/return;}function main(input){let para = JSON.parse(input);if (para.do_foo)\n            {\n              let x = {\n                \'hello\' : \'world\'\n              };\n            }\n          }\n          \n          function query(input)\n          { \n            return input;\n          }\n        ";
      Long initBalance = ToBaseUnit.ToUGas("1");
      
      BIFContractCreateRequest request = new BIFContractCreateRequest();
      request.setSenderAddress(senderAddress);
      request.setPrivateKey(senderPrivateKey);
      request.setInitBalance(initBalance);
      request.setPayload(payload);
      request.setRemarks("create contract");
      request.setType(1);
      request.setFeeLimit(10000000000L);
      
      // 调用bifContractCreate接口
      BIFContractCreateResponse response = sdk.getBIFContractService().contractCreate(request);
      if (response.getErrorCode() == 0) {
          System.out.println(JsonUtils.toJSONString(response.getResult()));
      } else {
          System.out.println(JsonUtils.toJSONString(response));
      }
      
  2. 从部署交易中获取合约地址

    1. 接口 getContractAddress

    2. 用途:

      提供部署合约的交易哈希, 返回合约地址。

    3. 示例

      // Init request
      String hash = "ff6a9d1a0c0011fbb9f51cfb99e4cd5e7c31380046fda3fd6e0daae44d1d4648";
      BIFContractGetAddressRequest request = new BIFContractGetAddressRequest();
      request.setHash(hash);
      
      // Call getAddress
      BIFContractGetAddressResponse response = sdk.getBIFContractService().getContractAddress(request);
      if (response.getErrorCode() == 0) {
          System.out.println(JsonUtils.toJSONString(response.getResult()));
      } else {
          System.out.println(JsonUtils.toJSONString(response));
      }
      
  3. 获取合约相关信息

    1. 接口 getContractInfo

    2. 用途:

      指定合约地址, 获取合约相关信息。

    3. 示例

      // Init request
      BIFContractGetInfoRequest request = new BIFContractGetInfoRequest();
      request.setContractAddress("did:bid:efiBacNvVSnr5QxgB282XGWkg4RXLLxL");
      
      // Call getContractInfo
      BIFContractGetInfoResponse response = sdk.getBIFContractService().getContractInfo(request);
      if (response.getErrorCode() == 0) {
          System.out.println(JsonUtils.toJSONString(response.getResult()));
      } else {
          System.out.println(JsonUtils.toJSONString(response));
      }
      
  4. 查询合约

    1. 接口 contractQuery

    2. 用途:

      调用合约Query接口, 查询合约数据。

    3. 示例:

      // Init variable
      // Contract address
      String contractAddress = "did:bid:ef2gAT82SGdnhj87wQWb9suPKLbnk9NP";
      
      // Init request
      BIFContractCallRequest request = new BIFContractCallRequest();
      request.setContractAddress(contractAddress);
      
      // Call contractQuery
      BIFContractCallResponse response = sdk.getBIFContractService().contractQuery(request);
      if (response.getErrorCode() == 0) {
          BIFContractCallResult result = response.getResult();
          System.out.println(JsonUtils.toJSONString(result));
      } else {
          System.out.println(JsonUtils.toJSONString(response));
      }  
      
  5. 调用合约

    1. 接口 contractInvoke

    2. 用途:

      在链上发出交易调用合约可写接口。

    3. 示例:

      String senderAddress = "did:bid:efVmotQW28QDtQyupnKTFvpjKQYs5bxf";
      String contractAddress = "did:bid:ef2gAT82SGdnhj87wQWb9suPKLbnk9NP";
      String senderPrivateKey = "priSPKnDue7AJ42gt7acy4AVaobGJtM871r1eukZ2M6eeW5LxG";
      Long amount = 0L;
      
      BIFContractInvokeRequest request = new BIFContractInvokeRequest();
      request.setSenderAddress(senderAddress);
      request.setPrivateKey(senderPrivateKey);
      request.setContractAddress(contractAddress);
      request.setBIFAmount(amount);
      request.setRemarks("contract invoke");
      
      // 调用 bifContractInvoke 接口
      BIFContractInvokeResponse response = sdk.getBIFContractService().contractInvoke(request);
      if (response.getErrorCode() == 0) {
          System.out.println(JsonUtils.toJSONString(response.getResult()));
      } else {
          System.out.println(JsonUtils.toJSONString(response));
      }