Fisco Bcos学习 - Solidity合约开发_solidy 合约
文章目录
一、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
:用于创建和打开KVTableEntry
:表示一条记录,提供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函数:删除符合条件的记录
四、合约开发注意事项
-
表名唯一性:为实现AMDB创建的表可被多个合约共享访问,其表名是群组内全局可见且唯一的,无法在同一条链上的同一个群组中创建多个表名相同的表。
-
字段长度限制:
- Table合约的insert、remove、update和select函数中key的类型为string,长度最大支持255字符。
- Entry的get/set接口的key的类型为string,长度最大支持255字符,value支持的类型有int256(int)、address和string,其中string不能超过16MB。
-
客户端调用:客户端需要调用转换为Java文件的合约代码,需要将Solidity合约和Table.sol放入控制台的contracts/solidity目录下,通过控制台的编译脚本sol2java.sh生成对应的Java文件。
-
存储引擎选择:
- 使用Table合约的CRUD接口时,推荐使用关系型数据库MySQL作为后端数据库,因为其支持批量操作和范围查询。
- 使用KVTable合约的get/set接口时,推荐使用RocksDB作为后端数据库,因为RocksDB是Key-Value存储的非关系型数据库,单key操作效率更高。
更多详细内容请访问:https://www.bookstack.cn/read/fisco-bcos-2.4-zh/d29922a72208071e.md