Web3SDK

    2.0版本主要特性包括:

    • 提供调用FISCO BCOS JSON-RPC的Java API
    • 支持预编译(Precompiled)合约管理区块链
    • 支持为联盟链提供安全高效的消息信道
    • 支持使用国密算法发送交易

    重要

    • java版本
    • FISCO BCOS区块链环境搭建
    • 网络连通性

    通过gradle或maven引入SDK到java应用

    gradle:

    maven:

    1. <dependency>
    2. <groupId>org.fisco-bcos</groupId>
    3. <artifactId>web3sdk</artifactId>
    4. <version>2.0.3</version>
    5. </dependency>

    由于引入了以太坊的solidity编译器相关jar包,需要在Java应用的gradle配置文件build.gradle中添加以太坊的远程仓库。

    1. repositories {
    2. mavenCentral()
    3. maven { url "https://dl.bintray.com/ethereum/maven/" }
    4. }

    注: 如果下载Web3SDK的依赖速度过慢,可以参考这里进行下载。

    FISCO BCOS作为联盟链,其SDK连接区块链节点需要通过证书(ca.crt、node.crt)和私钥(node.key)进行双向认证。因此需要将节点所在目录nodes/${ip}/sdk下的ca.crtnode.crtnode.key文件拷贝到项目的资源目录,供SDK与节点建立连接时使用。

    配置文件设置

    Java应用的配置文件需要做相关配置。值得关注的是,FISCO BCOS 2.0版本支持,SDK需要配置群组的节点信息。将以Spring项目和Spring Boot项目为例,提供配置指引。

    Spring项目配置

    提供Spring项目中关于的配置下所示。

    1. <?xml version="1.0" encoding="UTF-8" ?>
    2.  
    3. <beans xmlns="http://www.springframework.org/schema/beans"
    4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    5. xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
    6. xmlns:context="http://www.springframework.org/schema/context"
    7. xsi:schemaLocation="http://www.springframework.org/schema/beans
    8. http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    9. http://www.springframework.org/schema/tx
    10. http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
    11. http://www.springframework.org/schema/aop
    12. http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
    13.  
    14. <bean id="encryptType" class="org.fisco.bcos.web3j.crypto.EncryptType">
    15. <constructor-arg value="0"/> <!-- 0:standard 1:guomi -->
    16. </bean>
    17.  
    18. <bean id="groupChannelConnectionsConfig" class="org.fisco.bcos.channel.handler.GroupChannelConnectionsConfig">
    19. <property name="allChannelConnections">
    20. <list> <!-- 每个群组需要配置一个bean,每个群组可以配置多个节点 -->
    21. <bean id="group1" class="org.fisco.bcos.channel.handler.ChannelConnections">
    22. <property name="groupId" value="1" /> <!-- 群组的groupID -->
    23. <property name="connectionsStr">
    24. <list>
    25. <value>127.0.0.1:20200</value> <!-- IP:channel_port -->
    26. <value>127.0.0.1:20201</value>
    27. </list>
    28. </property>
    29. </bean>
    30. <bean id="group2" class="org.fisco.bcos.channel.handler.ChannelConnections">
    31. <property name="groupId" value="2" /> <!-- 群组的groupID -->
    32. <property name="connectionsStr">
    33. <list>
    34. <value>127.0.0.1:20203</value>
    35. </list>
    36. </property>
    37. </bean>
    38. </list>
    39. </property>
    40. </bean>
    41.  
    42. <bean id="channelService" class="org.fisco.bcos.channel.client.Service" depends-on="groupChannelConnectionsConfig">
    43. <property name="groupId" value="1" /> <!-- 配置连接群组1 -->
    44. <property name="agencyName" value="fisco" /> <!-- 配置机构名 -->
    45. <property name="allChannelConnections" ref="groupChannelConnectionsConfig"></property>
    46. </bean>
    47.  
    48. </beans>
    • encryptType: 国密算法开关(默认为0)
      • 0: 不使用国密算法发交易
      • 1: 使用国密算法发交易(开启国密功能,需要连接的区块链节点是国密节点,搭建国密版FISCO BCOS区块链参考这里)
    • groupChannelConnectionsConfig:
      • 配置待连接的群组,可以配置一个或多个群组,每个群组需要配置群组ID
      • 每个群组可以配置一个或多个节点,设置群组节点的配置文件config.ini[rpc]部分的listen_ipchannel_listen_port
    • channelService: 通过指定群组ID配置SDK实际连接的群组,指定的群组ID是groupChannelConnectionsConfig配置中的群组ID。SDK会与群组中配置的节点均建立连接,然后随机选择一个节点发送请求。

    提供Spring Boot项目中关于的配置如下所示。

    1. encrypt-type: 0 # 0:standard, 1:guomi
    2. group-channel-connections-config:
    3. all-channel-connections:
    4. - group-id: 1 #group ID
    5. connections-str:
    6. - 127.0.0.1:20200 # node listen_ip:channel_listen_port
    7. - 127.0.0.1:20201
    8. - group-id: 2
    9. connections-str:
    10. - 127.0.0.1:20202 # node listen_ip:channel_listen_port
    11. - 127.0.0.1:20203
    12.  
    13. channel-service:
    14. group-id: 1 # The specified group to which the SDK connects
    15. agency-name: fisco # agency name

    application.yml配置项与applicationContext.xml配置项相对应,详细介绍参考applicationContext.xml配置说明。

    Spring项目开发指引

    调用SDK的API(参考Web3SDK API列表设置或查询相关的区块链数据。

    调用SDK Web3j的API

    加载配置文件,SDK与区块链节点建立连接,获取web3j对象,根据Web3j对象调用相关API。示例代码如下:

    注: SDK处理交易超时时间默认为60秒,即60秒内没有收到交易响应,判断为超时。该值可以通过ChannelEthereumService进行设置,示例如下:

    1. // 设置交易超时时间为100000毫秒,即100秒
    2. channelEthereumService.setTimeout(100000);
    调用SDK Precompiled的API

    加载配置文件,SDK与区块链节点建立连接。获取SDK Precompiled Service对象,调用相关的API。示例代码如下:

    1. //读取配置文件,SDK与区块链节点建立连接,获取Web3j对象
    2. ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
    3. Service service = context.getBean(Service.class);
    4. service.run();
    5. ChannelEthereumService channelEthereumService = new ChannelEthereumService();
    6. channelEthereumService.setChannelService(service);
    7. Web3j web3j = Web3j.build(channelEthereumService, service.getGroupId());
    8. String privateKey = "b83261efa42895c38c6c2364ca878f43e77f3cddbc922bf57d0d48070f79feb6";
    9. //指定外部账户私钥,用于交易签名
    10. Credentials credentials = GenCredential.create(privateKey);
    11. //获取SystemConfigService对象
    12. SystemConfigService systemConfigService = new SystemConfigService(web3j, credentials);
    13. //通过SystemConfigService对象调用API接口setValueByKey
    14. String result = systemConfigService.setValueByKey("tx_count_limit", "2000");
    15. //通过Web3j对象调用API接口getSystemConfigByKey
    16. String value = web3j.getSystemConfigByKey("tx_count_limit").send().getSystemConfigByKey();
    17. System.out.println(value);
    创建并使用指定外部账户

    sdk发送交易需要一个外部账户,下面是随机创建一个外部账户的方法。

    1. //创建普通外部账户
    2. EncryptType.encryptType = 0;
    3. //创建国密外部账户,向国密区块链节点发送交易需要使用国密外部账户
    4. // EncryptType.encryptType = 1;
    5. Credentials credentials = GenCredential.create();
    6. //账户地址
    7. String address = credentials.getAddress();
    8. //账户私钥
    9. String privateKey = credentials.getEcKeyPair().getPrivateKey().toString(16);
    10. //账户公钥
    11. String publicKey = credentials.getEcKeyPair().getPublicKey().toString(16);

    使用指定的外部账户

    1. //通过指定外部账户私钥使用指定的外部账户
    2. Credentials credentials = GenCredential.create(privateKey);
    加载账户私钥文件

    如果通过账户生成脚本生成了PEM或PKCS12格式的账户私钥文件(账户生成脚本的用法参考),则可以通过加载PEM或PKCS12账户私钥文件使用账户。加载私钥有两个类:P12Manager和PEMManager,其中,P12Manager用于加载PKCS12格式的私钥文件,PEMManager用于加载PEM格式的私钥文件。

    • P12Manager用法举例:在applicationContext.xml中配置PKCS12账户的私钥文件路径和密码

    开发代码

    1. //加载Bean
    2. ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
    3. P12Manager p12 = context.getBean(P12Manager.class);
    4. //提供密码获取ECKeyPair,密码在生产p12账户文件时指定
    5. ECKeyPair p12KeyPair = p12.getECKeyPair(p12.getPassword());
    6.  
    7. System.out.println("p12 privateKey: " + p12KeyPair.getPrivateKey().toString(16));
    8. System.out.println("p12 publicKey: " + p12KeyPair.getPublicKey().toString(16));
    9.  
    10. //生成web3sdk使用的Credentials
    11. Credentials credentials = Credentials.create(p12KeyPair);
    12. System.out.println("p12 Address: " + credentials.getAddress());
    • PEMManager使用举例在applicationContext.xml中配置PEM账户的私钥文件路径
    1. <bean id="pem" class="org.fisco.bcos.channel.client.PEMManager" init-method="load" >
    2. <property name="pemFile" value="classpath:0x0fc3c4bb89bd90299db4c62be0174c4966286c00.pem" />
    3. </bean>

    使用代码加载

    1. //加载Bean
    2. ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext-keystore-sample.xml");
    3. PEMManager pem = context.getBean(PEMManager.class);
    4. ECKeyPair pemKeyPair = pem.getECKeyPair();
    5.  
    6. //以十六进制串输出私钥和公钥
    7. System.out.println("PEM privateKey: " + pemKeyPair.getPrivateKey().toString(16));
    8. System.out.println("PEM publicKey: " + pemKeyPair.getPublicKey().toString(16));
    9.  
    10. //生成web3sdk使用的Credentials
    11. Credentials credentialsPEM = Credentials.create(pemKeyPair);
    12. System.out.println("PEM Address: " + credentialsPEM.getAddress());

    通过SDK部署并调用合约

    准备Java合约文件
    部署并调用合约

    SDK的核心功能是部署/加载合约,然后调用合约相关接口,实现相关业务功能。部署合约调用Java合约类的deploy方法,获取合约对象。通过合约对象可以调用getContractAddress方法获取部署合约的地址以及调用该合约的其他方法实现业务功能。如果合约已部署,则通过部署的合约地址可以调用load方法加载合约对象,然后调用该合约的相关方法。

    1. //读取配置文件,sdk与区块链节点建立连接,获取web3j对象
    2. ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
    3. Service service = context.getBean(Service.class);
    4. service.run();
    5. ChannelEthereumService channelEthereumService = new ChannelEthereumService();
    6. channelEthereumService.setChannelService(service);
    7. channelEthereumService.setTimeout(10000);
    8. Web3j web3j = Web3j.build(channelEthereumService, service.getGroupId());
    9. //准备部署和调用合约的参数
    10. BigInteger gasPrice = new BigInteger("300000000");
    11. BigInteger gasLimit = new BigInteger("300000000");
    12. String privateKey = "b83261efa42895c38c6c2364ca878f43e77f3cddbc922bf57d0d48070f79feb6";
    13. //指定外部账户私钥,用于交易签名
    14. Credentials credentials = GenCredential.create(privateKey);
    15. //部署合约
    16. YourSmartContract contract = YourSmartContract.deploy(web3j, credentials, new StaticGasProvider(gasPrice, gasLimit)).send();
    17. //根据合约地址加载合约
    18. //YourSmartContract contract = YourSmartContract.load(address, web3j, credentials, new StaticGasProvider(gasPrice, gasLimit));
    19. //调用合约方法发送交易
    20. TransactionReceipt transactionReceipt = contract.someMethod(<param1>, ...).send();
    21. //查询合约方法查询该合约的数据状态
    22. Type result = contract.someMethod(<param1>, ...).send();

    Spring Boot项目开发指引

    提供spring-boot-starter示例项目供参考。Spring Boot项目开发与Spring项目开发类似,其主要区别在于配置文件方式的差异。该示例项目提供相关的测试案例,具体描述参考示例项目的README文档。

    • 前置条件:FISCO BCOS区块链采用国密算法,搭建国密版的FISCO BCOS区块链请参考。
    • 启用国密功能:application.xml/application.yml配置文件中将encryptType属性设置为1。国密版SDK调用API的方式与普通版SDK调用API的方式相同,其差异在于国密版SDK需要生成国密版的Java合约文件。国密版的编译器jar包下载请参考这里,用于将Solidity合约文件转为国密版的Java合约文件。可以在项目src目录下新建一个lib目录,将下载的国密版jar包放置在lib目录下。然后修改项目的build.gradle文件,移除普通版编译器jar包,引入国密编译器jar包。

    Solidity合约文件转换为国密版Java合约文件的步骤、部署和调用国密版合约的方法均与普通版SDK相同。

    Web3SDK API主要分为Web3j API和Precompiled Service API。其中Web3j API可以查询区块链相关的状态,发送和查询交易信息;Precompiled Service API可以管理区块链相关配置以及实现特定功能。

    Web3j API

    Web3j API是由web3j对象调用的FISCO BCOS的RPC API,其API名称与RPC API相同,参考。

    Precompiled Service API

    预编译合约是FISCO BCOS底层通过C++实现的一种高效智能合约。SDK已提供预编译合约对应的Java接口,控制台通过调用这些Java接口实现了相关的操作命令,体验控制台,参考控制台手册。SDK提供Precompiled对应的Service类,分别是分布式控制权限相关的PermissionService,相关的CnsService,系统属性配置相关的SystemConfigService和节点类型配置相关ConsensusService。相关错误码请参考:Precompiled Service API 错误码

    PermissionService

    SDK提供对的支持,PermissionService可以配置权限信息,其API如下:

    • public String grantUserTableManager(String tableName, String address): 根据用户表名和外部账户地址设置权限信息。
    • public String revokeUserTableManager(String tableName, String address): 根据用户表名和外部账户地址去除权限信息。
    • public List listUserTableManager(String tableName): 根据用户表名查询设置的权限记录列表(每条记录包含外部账户地址和生效块高)。
    • public String grantDeployAndCreateManager(String address): 增加外部账户地址的部署合约和创建用户表权限。
    • public String revokeDeployAndCreateManager(String address): 移除外部账户地址的部署合约和创建用户表权限。
    • public List listDeployAndCreateManager(): 查询拥有部署合约和创建用户表权限的权限记录列表。
    • public String grantPermissionManager(String address): 增加外部账户地址的管理权限的权限。
    • public String revokePermissionManager(String address): 移除外部账户地址的管理权限的权限。
    • public List listPermissionManager(): 查询拥有管理权限的权限记录列表。
    • public String grantNodeManager(String address): 增加外部账户地址的节点管理权限。
    • public String revokeNodeManager(String address): 移除外部账户地址的节点管理权限。
    • public List listNodeManager(): 查询拥有节点管理的权限记录列表。
    • public String grantCNSManager(String address): 增加外部账户地址的使用CNS权限。
    • public String revokeCNSManager(String address): 移除外部账户地址的使用CNS权限。
    • public List listCNSManager(): 查询拥有使用CNS的权限记录列表。
    • public String grantSysConfigManager(String address): 增加外部账户地址的系统参数管理权限。
    • public String revokeSysConfigManager(String address): 移除外部账户地址的系统参数管理权限。
    • public List listSysConfigManager(): 查询拥有系统参数管理的权限记录列表。

    CnsService

    SDK提供对CNS的支持。CnsService可以配置CNS信息,其API如下:

    • String registerCns(String name, String version, String address, String abi): 根据合约名、合约版本号、合约地址和合约abi注册CNS信息。
    • String getAddressByContractNameAndVersion(String contractNameAndVersion): 根据合约名和合约版本号(合约名和合约版本号用英文冒号连接)查询合约地址。若缺失合约版本号,默认使用合约最新版本。
    • List queryCnsByName(String name): 根据合约名查询CNS信息。
    • List queryCnsByNameAndVersion(String name, String version): 根据合约名和合约版本号查询CNS信息。

    SystemConfigService

    SDK提供对系统配置的支持。SystemConfigService可以配置系统属性值(目前支持tx_count_limit和tx_gas_limit属性的设置),其API如下:

    • String setValueByKey(String key, String value): 根据键设置对应的值(查询键对应的值,参考Web3j API中的getSystemConfigByKey接口)。

    ConsensusService

    SDK提供对配置的支持。ConsensusService可以设置节点类型,其API如下:

    • String addSealer(String nodeId): 根据节点NodeID设置对应节点为共识节点。
    • String addObserver(String nodeId): 根据节点NodeID设置对应节点为观察节点。
    • String removeNode(String nodeId): 根据节点NodeID设置对应节点为游离节点。

    CRUDService

    • int createTable(Table table): 创建表,提供表对象。表对象需要设置其表名,主键字段名和其他字段名。其中,其他字段名是以英文逗号分隔拼接的字符串。返回创建表的状态值,返回为0则代表创建成功。
    • int insert(Table table, Entry entry): 插入记录,提供表对象和Entry对象。表对象需要设置表名和主键字段名;Entry是map对象,提供插入的字段名和字段值,注意必须设置主键字段。返回插入的记录数。
    • int update(Table table, Entry entry, Condition condition): 更新记录,提供表对象,Entry对象和Condtion对象。表对象需要设置表名和主键字段名;Entry是map对象,提供更新的字段名和字段值;Condition对象是条件对象,可以设置更新的匹配条件。返回更新的记录数。
    • List> select(Table table, Condition condition): 查询记录,提供表对象和Condtion对象。表对象需要设置表名和主键字段名;Condition对象是条件对象,可以设置查询的匹配条件。返回查询的记录。
    • Table desc(String tableName): 根据表名查询表的信息,主要包含表的主键和其他属性字段。返回表类型,主要包含表的主键字段名和其他属性字段名。