> 技术文档 > Fisco Bcos学习 - Solidity合约开发_solidy 合约

Fisco Bcos学习 - Solidity合约开发_solidy 合约


文章目录

    • 一、Solidity合约开发概述
    • 二、使用KVTable合约读写接口
      • 2.1 KVTable合约简介
      • 2.2 KVTable合约接口声明
      • 2.3 KVTable合约案例:KVTableTest.sol
      • 2.4 案例解析
    • 三、使用Table合约CRUD接口
      • 3.1 Table合约简介
      • 3.2 Table合约接口声明
      • 3.3 Table合约案例:TableTest.sol
      • 3.4 案例解析
    • 四、合约开发注意事项

一、Solidity合约开发概述

Solidity是一种面向对象的编程语言,专门为实现智能合约而设计,广泛应用于以太坊和FISCO BCOS等区块链平台。在FISCO BCOS中,Solidity合约与预编译(Precompiled)合约是两种主要的合约形式。其中,Solidity合约使用Solidity语法实现,最高支持0.5.2版本,具有灵活的开发模式,适合实现各种业务逻辑;而预编译合约使用C++开发,内置于平台,性能更优,适合逻辑固定但需要共识的场景。

本文将重点介绍FISCO BCOS中Solidity合约的开发,包括KVTable合约读写接口和Table合约CRUD接口的使用,帮助开发者快速掌握Solidity合约在区块链平台上的应用。

二、使用KVTable合约读写接口

2.1 KVTable合约简介

KVTable合约实现了键值型数据的读写方式,适合用于Key-Value存储场景。其核心接口包括:

  • KVTableFactory:用于创建和打开KVTable
  • Entry:表示一条记录,提供get和set方法
  • KVTable:每个键对应一条entry,提供get和set方法

2.2 KVTable合约接口声明

pragma solidity ^0.4.24;contract KVTableFactory { function openTable(string) public view returns (KVTable); function createTable(string, string, string) public returns (int256);}contract Entry { function getInt(string) public constant returns (int256); function getUInt(string) public constant returns (int256); function getAddress(string) public constant returns (address); function getBytes64(string) public constant returns (bytes1[64]); function getBytes32(string) public constant returns (bytes32); function getString(string) public constant returns (string); function set(string, int256) public; function set(string, uint256) public; function set(string, string) public; function set(string, address) public;}contract KVTable { function get(string) public view returns (bool, Entry); function set(string, Entry) public returns (int256); function newEntry() public view returns (Entry);}

2.3 KVTable合约案例:KVTableTest.sol

下面是一个完整的KVTable合约案例,实现了创建用户表t_kvtest并对其进行读写操作:

pragma solidity ^0.4.24;import \"./Table.sol\";contract KVTableTest { event SetResult(int256 count); KVTableFactory tableFactory; string constant TABLE_NAME = \"t_kvtest\"; constructor() public { tableFactory = KVTableFactory(0x1010); tableFactory.createTable(TABLE_NAME, \"id\", \"item_price,item_name\"); } function get(string id) public view returns (bool, int256, string) { KVTable table = tableFactory.openTable(TABLE_NAME); bool ok = false; Entry entry; (ok, entry) = table.get(id); int256 item_price; string memory item_name; if (ok) { item_price = entry.getInt(\"item_price\"); item_name = entry.getString(\"item_name\"); } return (ok, item_price, item_name); } function set(string id, int256 item_price, string item_name) public returns (int256) { KVTable table = tableFactory.openTable(TABLE_NAME); Entry entry = table.newEntry(); entry.set(\"id\", id); entry.set(\"item_price\", item_price); entry.set(\"item_name\", item_name); int256 count = table.set(id, entry); emit SetResult(count); return count; }}

2.4 案例解析

  • 构造函数:初始化KVTableFactory并创建表t_kvtest,指定主键为\"id\",字段为\"item_price\"和\"item_name\"
  • get函数:根据id查询记录,返回查询结果、物品价格和物品名称
  • set函数:插入或更新记录,返回操作结果

三、使用Table合约CRUD接口

3.1 Table合约简介

Table合约提供了类似关系型数据库的CRUD(增删改查)接口,适合用于需要批量操作数据的场景。其核心接口包括:

  • TableFactory:用于打开和创建表
  • Condition:用于定义查询条件
  • Entry:表示单条数据记录
  • Entries:表示数据记录集
  • Table:提供select、insert、update、remove等方法

3.2 Table合约接口声明

pragma solidity ^0.4.24;contract TableFactory { function openTable(string) public constant returns (Table); function createTable(string,string,string) public returns(int);}contract Condition { function EQ(string, int) public; function EQ(string, string) public; function NE(string, int) public; function NE(string, string) public; function GT(string, int) public; function GE(string, int) public; function LT(string, int) public; function LE(string, int) public; function limit(int) public; function limit(int, int) public;}contract Entry { function getInt(string) public constant returns(int); function getAddress(string) public constant returns(address); function getBytes64(string) public constant returns(byte[64]); function getBytes32(string) public constant returns(bytes32); function getString(string) public constant returns(string); function set(string, int) public; function set(string, string) public; function set(string, address) public;}contract Entries { function get(int) public constant returns(Entry); function size() public constant returns(int);}contract Table { function select(string, Condition) public constant returns(Entries); function insert(string, Entry) public returns(int); function update(string, Entry, Condition) public returns(int); function remove(string, Condition) public returns(int); function newEntry() public constant returns(Entry); function newCondition() public constant returns(Condition);}

3.3 Table合约案例:TableTest.sol

下面是一个完整的Table合约案例,实现了创建用户表t_test并对其进行增删改查操作:

pragma solidity ^0.4.24;import \"./Table.sol\";contract TableTest { event CreateResult(int count); event InsertResult(int count); event UpdateResult(int count); event RemoveResult(int count); function create() public returns(int){ TableFactory tf = TableFactory(0x1001); int count = tf.createTable(\"t_test\", \"name\", \"item_id,item_name\"); emit CreateResult(count); return count; } function select(string name) public constant returns(bytes32[], int[], bytes32[]){ TableFactory tf = TableFactory(0x1001); Table table = tf.openTable(\"t_test\"); Condition condition = table.newCondition(); Entries entries = table.select(name, condition); bytes32[] memory user_name_bytes_list = new bytes32[](uint256(entries.size())); int[] memory item_id_list = new int[](uint256(entries.size())); bytes32[] memory item_name_bytes_list = new bytes32[](uint256(entries.size())); for(int i=0; i<entries.size(); ++i) { Entry entry = entries.get(i); user_name_bytes_list[uint256(i)] = entry.getBytes32(\"name\"); item_id_list[uint256(i)] = entry.getInt(\"item_id\"); item_name_bytes_list[uint256(i)] = entry.getBytes32(\"item_name\"); } return (user_name_bytes_list, item_id_list, item_name_bytes_list); } function insert(string name, int item_id, string item_name) public returns(int) { TableFactory tf = TableFactory(0x1001); Table table = tf.openTable(\"t_test\"); Entry entry = table.newEntry(); entry.set(\"name\", name); entry.set(\"item_id\", item_id); entry.set(\"item_name\", item_name); int count = table.insert(name, entry); emit InsertResult(count); return count; } function update(string name, int item_id, string item_name) public returns(int) { TableFactory tf = TableFactory(0x1001); Table table = tf.openTable(\"t_test\"); Entry entry = table.newEntry(); entry.set(\"item_name\", item_name); Condition condition = table.newCondition(); condition.EQ(\"name\", name); condition.EQ(\"item_id\", item_id); int count = table.update(name, entry, condition); emit UpdateResult(count); return count; } function remove(string name, int item_id) public returns(int){ TableFactory tf = TableFactory(0x1001); Table table = tf.openTable(\"t_test\"); Condition condition = table.newCondition(); condition.EQ(\"name\", name); condition.EQ(\"item_id\", item_id); int count = table.remove(name, condition); emit RemoveResult(count); return count; }}

3.4 案例解析

  • create函数:创建表t_test,指定主键为\"name\",字段为\"item_id\"和\"item_name\"
  • select函数:根据name查询记录,返回查询结果集
  • insert函数:插入一条记录
  • update函数:更新符合条件的记录
  • remove函数:删除符合条件的记录

四、合约开发注意事项

  1. 表名唯一性:为实现AMDB创建的表可被多个合约共享访问,其表名是群组内全局可见且唯一的,无法在同一条链上的同一个群组中创建多个表名相同的表。

  2. 字段长度限制

    • Table合约的insert、remove、update和select函数中key的类型为string,长度最大支持255字符。
    • Entry的get/set接口的key的类型为string,长度最大支持255字符,value支持的类型有int256(int)、address和string,其中string不能超过16MB。
  3. 客户端调用:客户端需要调用转换为Java文件的合约代码,需要将Solidity合约和Table.sol放入控制台的contracts/solidity目录下,通过控制台的编译脚本sol2java.sh生成对应的Java文件。

  4. 存储引擎选择

    • 使用Table合约的CRUD接口时,推荐使用关系型数据库MySQL作为后端数据库,因为其支持批量操作和范围查询。
    • 使用KVTable合约的get/set接口时,推荐使用RocksDB作为后端数据库,因为RocksDB是Key-Value存储的非关系型数据库,单key操作效率更高。

更多详细内容请访问:https://www.bookstack.cn/read/fisco-bcos-2.4-zh/d29922a72208071e.md