百里登风

导航

区块链合约的编写

区块链合约的编写是基于solidity语言编写的,编写环境是基于webase平台

webase平台的部署可以参考:https://www.cnblogs.com/braveym/p/17974554

 

一、合约的创建

进入webase平台

 

 

创建合约文件和文件夹目录

 

二、通用Table工具类的创建

 

Table合约
这是一个关于Table的 Solidity 智能合约。该智能合约定义了一些重要的实体和方法,可以用于创建、操作和管理表格数据。

首先是 TableFactory 合约,用于创建和打开表格。其中包含:

   openTable(string) 方法用于打开一个已经存在的表格并返回该表格实例 Table
   createTable(string, string, string) 方法用于创建一个新的表格,并需要传入三个参数:表格名、主键名、存储引擎类型
接下来是一个 Condition 合约,用于设置查询条件。其中包含:

等于(Equal)
不等于(Not Equal)
大于(Greater Than)
大于等于(Greater or Equal)
小于(Less Than)
小于等于(Less or Equal)
限制返回记录数(limit)
然后是一个 Entry 合约,代表表格中的一行数据记录。它提供了获取和设置各种类型的数据值的方法,如整数、无符号整数、地址、字符串等。

最后是一个 Table 合约,包括以下方法:

select(string, Condition) 方法用于根据查询条件选择表格中的数据记录
insert(string, Entry) 方法用于往表格中插入一条新的数据记录
update(string, Entry, Condition) 方法用于根据给定的查询条件更新表格中的数据记录
remove(string, Condition) 方法用于根据给定的查询条件删除表格中的数据记录
newEntry() 方法用于创建一个新的数据记录实例
newCondition() 方法用于创建一个新的查询条件实例

pragma solidity ^0.4.0;

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 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 getFixed(string) public constant returns(fixed);
    function getUint(string) public constant returns(uint);
    
    function set(string, int) public;
    function set(string, string) public;
    function set(string, address) public;
    function set(string, fixed) public;
    function set(string, uint) public;
}

// 数据记录集
contract Entries {
    function get(int) public constant returns(Entry);
    function size() public constant returns(int);

}

// Table主类
contract Table {
    // 查询接口
    function select(string, Condition) public constant returns(Entries);
    // 插入接口
    function insert(string, Entry) public returns(bool);
    // 更新接口
    function update(string, Entry, Condition) public returns(int);
    // 删除接口
    function remove(string, Condition) public returns(bool);

    function newEntry() public constant returns(Entry);
    function newCondition() public constant returns(Condition);
}

 

 

三、合约的编写

 这边编写四个合约,要求实现数据上链和链上查询功能

分别是:

1、数据资产表

创建合约文件

 这里注意,合约文件名称和合约的名称要一致。

合约代码: 

pragma solidity ^0.4.5;
pragma experimental ABIEncoderV2;
import "./common/Table.sol";

contract SDD_DATA_ASSET{
   address public platform;
   TableFactory tf = TableFactory(0x1001);  // TableFactory的地址固定为0x1001

   //约束条件--平台方
    modifier onlyPlatform{
        require(msg.sender==platform);
        _;
    }

    constructor() public {
        platform =msg.sender;
        create();
    }

    // 创建表
    function create() returns(int){
        int count = tf.createTable("SDD_DATA_ASSET", "id", "data_type,hash,owner_id,owner_name,creation_time,platform_id,upload_time,introduction,detail");
        return count;
    }

    //数据上链
    function insert(
        string id, 
        int dataType,
        string hash,
        string ownerId,
        string ownerName,
        int creationTime,
        string platformId,
        int uploadTime,
        string introduction,
        string detail) onlyPlatform public returns(bool){
           
         //字段校验
        require(checkRepeat(id),"数字资产id已经存在");
        //检查重复上链
       // require((checkRepeat(id,dataType,hash,ownerId,ownerName,creationTime,platformId,uploadTime,introduction,detail))==true,"请勿重复上链");
        Table table = tf.openTable("SDD_DATA_ASSET");
        
        Entry entry = table.newEntry();
        entry.set("id", id);
        entry.set("data_type", dataType);
        entry.set("hash",hash);
        entry.set("owner_id",ownerId);
        entry.set("owner_name", ownerName);
        entry.set("creation_time", creationTime);
        entry.set("platform_id", platformId);
        entry.set("upload_time", uploadTime);
        entry.set("introduction", introduction);
        entry.set("detail", detail);
        table.insert(id, entry);
        return true;
        }

    //查询操作
      function select(string id) public view returns(string,int,string,string,string,int,string,int,string,string){
 
        Table table = tf.openTable("SDD_DATA_ASSET");
        Condition condition = table.newCondition();
        condition.EQ("id", id); 
 
        Entries entries = table.select(id, condition);
        if(entries.size() == 0){
            return (id,0,"","","",0,"",0,"","");
        }
        else{
            return (id,entries.get(0).getInt("data_type"),entries.get(0).getString("hash"),entries.get(0).getString("owner_id"),entries.get(0).getString("owner_name"),
            entries.get(0).getInt("creation_time"),entries.get(0).getString("platform_id"),entries.get(0).getInt("upload_time"),
            entries.get(0).getString("introduction"),entries.get(0).getString("detail"));
        }
    }
    
       //检查记录重复
    function checkRepeat(
        string id
    )  private view returns(bool){

        Table table = tf.openTable("SDD_DATA_ASSET");
        Entry entry = table.newEntry();
        Condition condition = table.newCondition();

        condition.EQ("id", id);

        Entries record = table.select(id,condition);
        if (0 == record.size()) {
            return true;
        }else{
            return false;
        }

    }
}

 

代码解释:

function create() 用于在链上创建表
function insert( string id,
int dataType, string hash, string ownerId, string ownerName, int creationTime, string platformId, int uploadTime, string introduction, string detail) onlyPlatform public returns(bool) 构建一个数据插入的函数,并定义插入数据的不同字段和相应的类型,返回布尔类型 function select(string id) public view returns(string,int,string,string,string,int,string,int,string,string) 链上数据的查询操作,通过主键id进行查询,并声明返回结果的字段类型 function checkRepeat( string id ) private view returns(bool) 检查数据上链是否有重复数据,通过主键id进行检查

 

 

2、资产交易表

创建合约文件 

 

合约代码: 

pragma solidity ^0.4.25;
pragma experimental ABIEncoderV2;
import "./common/Table.sol";

contract SDD_ASSET_EXCHANGE{
   address public platform;
   TableFactory tf = TableFactory(0x1001);  // TableFactory的地址固定为0x1001
   //约束条件--平台方
    modifier onlyPlatform{
        require(msg.sender==platform);
        _;
    }

    constructor() public {
        platform =msg.sender;
        create();
    }

      // 创建表
    function create() returns(int){
 int count = tf.createTable("SDD_ASSET_EXCHANGE", "id", "hash,introduction,owner_id,trade_time,trade_no,tradePlatform_id,source_platform_i,source_platform_income_ratio,price,buyer_id");                   
        return count;
    }

     //数据上链
    function insert(
        string id, 
        string hash,
        string introduction,
        string ownerId,
        int tradeTime,
        string tradeNo,
        string tradePlatformId,
        string sourcePlatformId,
        string sourcePlatformIncomeRatio,
        uint price,
        string buyerId) onlyPlatform public returns(bool){
           
         //字段校验
        require(checkRepeat(id),"上链数据交易id已经存在");
    
        Table table = tf.openTable("SDD_ASSET_EXCHANGE");
        
        Entry entry = table.newEntry();
        entry.set("id", id);
        entry.set("hash",hash);
        entry.set("introduction", introduction);
        entry.set("owner_id",ownerId);
        entry.set("trade_time", tradeTime);
        entry.set("trade_no", tradeNo);
        entry.set("tradePlatform_id", tradePlatformId);
        entry.set("source_platform_id", sourcePlatformId);
        entry.set("source_platform_income_ratio", sourcePlatformIncomeRatio);
        entry.set("price", price);
        entry.set("buyer_id", buyerId);
        table.insert(id, entry);
        return true;
        }

         //查询操作
      function select(string id) public view returns(Entry){
        Table table = tf.openTable("SDD_ASSET_EXCHANGE");
        Condition condition = table.newCondition();
        condition.EQ("id",id);
        Entries entries = table.select(id, condition);
        require(entries.size() == 1, "DATA_NOT_EXIST");
        return entries.get(0);
    }
    
    function selectById(string id) public view returns(string,string,string,string,string,string,string,string,string,string,string){
        Entry entry = select(id);
          return (strConcat("id:",id),strConcat("hash:",entry.getString("hash")),strConcat("introduction:",entry.getString("introduction")),strConcat("owner_id:",entry.getString("owner_id")),strConcat("trade_time:",entry.getString("trade_time")),strConcat("trade_no:",entry.getString("trade_no")),strConcat("tradePlatform_id:",entry.getString("tradePlatform_id")),strConcat("source_platform_id:",entry.getString("source_platform_id")),
                strConcat("source_platform_income_ratio:",entry.getString("source_platform_income_ratio")),strConcat("price:",entry.getString("price")),strConcat("buyer_id:",entry.getString("buyer_id")));
      
    }

            //检查记录重复
    function checkRepeat(
        string id
    )  private view returns(bool){

        Table table = tf.openTable("SDD_ASSET_EXCHANGE");
        Entry entry = table.newEntry();
        Condition condition = table.newCondition();

        condition.EQ("id", id);

        Entries record = table.select(id,condition);
        if (0 == record.size()) {
            return true;
        }else{
            return false;
        }
    }
     
     //字符串拼接
      function strConcat(string _a, string _b) internal returns (string){
        bytes memory _ba = bytes(_a);
        bytes memory _bb = bytes(_b);
        string memory ret = new string(_ba.length + _bb.length);
        bytes memory bret = bytes(ret);
        uint k = 0;
        for (uint i = 0; i < _ba.length; i++)bret[k++] = _ba[i];
        for (i = 0; i < _bb.length; i++) bret[k++] = _bb[i];
        return string(ret);
   } 
  
}

 

代码解释:

function create() returns(int)  //创建表,返回int类型

 function insert(
        string id, 
        string hash,
        string introduction,
        string ownerId,
        int tradeTime,
        string tradeNo,
        string tradePlatformId,
        string sourcePlatformId,
        string sourcePlatformIncomeRatio,
        uint price,
        string buyerId) onlyPlatform public returns(bool)
//数据插入,定义插入数据的字段已经相应的类型,返回布尔类型

 function select(string id) public view returns(Entry)
function selectById(string id) public view returns(string,string,string,string,string,string,string,string,string,string,string)
//数据查询用了两个函数,为什么不直接用一个函数写好呢,原因是因为solidity对单个函数的变量个数有限制,变量个数包括传入和传出个数,这也是solidity的局限性

function strConcat(string _a, string _b) internal returns (string)
//这函数用于字符串的拼接

 

 

3、资产挂单表

 创建合约文件:

 合约代码:

pragma solidity ^0.4.25;
pragma experimental ABIEncoderV2;
import "./common/Table.sol";

contract SDD_ASSET_POST{
   address public platform;
   TableFactory tf = TableFactory(0x1001);  // TableFactory的地址固定为0x1001
   //约束条件--平台方
    modifier onlyPlatform{
        require(msg.sender==platform);
        _;
    }

    constructor() public {
        platform =msg.sender;
        create();
    }

      // 创建表
    function create() returns(int){
    int count = tf.createTable("SDD_ASSET_POST", "id", "name,introduction,price,image,status,time,detail,trade_platform_id,source_platform_id,asset_id");                   
        return count;
    }

      //数据上链
    function insert(
        string id, 
        string name,
        string introduction,
        uint price,
        string image,
        int status,
        uint time,
        string detail,
        string tradePlatformId,
        string sourcePlatformId,
        int assetId) onlyPlatform public returns(bool){
           
         //字段校验
        require(checkRepeat(id),"上链数据交易id已经存在");
        Table table = tf.openTable("SDD_ASSET_POST");
        Entry entry = table.newEntry();
        entry.set("id", id);
        entry.set("name",name);
        entry.set("introduction", introduction);
        entry.set("price",int(price));
        entry.set("image",image);
        entry.set("status", status);
        entry.set("time", int(time));
        entry.set("detail", detail);
        entry.set("trade_platform_id", tradePlatformId);
        entry.set("source_platform_id", sourcePlatformId);
        entry.set("asset_id", assetId);
        table.insert(id, entry);
        return true;
        }


     //查询操作
      function select(string id) public view returns(Entry){
        Table table = tf.openTable("SDD_ASSET_POST");
        Condition condition = table.newCondition();
        condition.EQ("id",id);
        Entries entries = table.select(id, condition);
        require(entries.size() == 1, "DATA_NOT_EXIST");
        return entries.get(0);
    }
    
    function selectById(string id) public view returns(string,string,string,string,string,string,string,string,string,string,string){
        Entry entry = select(id);
          return (strConcat("id:",id),strConcat("name:",entry.getString("name")),strConcat("introduction:",entry.getString("introduction")),strConcat("price:",entry.getString("price")),strConcat("image:",entry.getString("image")),strConcat("status:",entry.getString("status")),strConcat("time:",entry.getString("time")),strConcat("detail:",entry.getString("detail")),strConcat("trade_platform_id:",entry.getString("trade_platform_id")),
                strConcat("source_platform_id:",entry.getString("source_platform_id")),strConcat("asset_id:",entry.getString("asset_id")));
      
    }

                //检查记录重复
    function checkRepeat(
        string id
    )  private view returns(bool){

        Table table = tf.openTable("SDD_ASSET_POST");
        Entry entry = table.newEntry();
        Condition condition = table.newCondition();

        condition.EQ("id", id);

        Entries record = table.select(id,condition);
        if (0 == record.size()) {
            return true;
        }else{
            return false;
        }
    }
     
     //字符串拼接
      function strConcat(string _a, string _b) internal returns (string){
        bytes memory _ba = bytes(_a);
        bytes memory _bb = bytes(_b);
        string memory ret = new string(_ba.length + _bb.length);
        bytes memory bret = bytes(ret);
        uint k = 0;
        for (uint i = 0; i < _ba.length; i++)bret[k++] = _ba[i];
        for (i = 0; i < _bb.length; i++) bret[k++] = _bb[i];
        return string(ret);
   }

}

 

   该代码的函数使用方法跟前一个合约一致,这里不多赘述了。

 

4、平台资金流转表

创建合约文件:

 

合约代码:

pragma solidity ^0.4.25;
pragma experimental ABIEncoderV2;
import "./common/Table.sol";

contract SDD_PLATFORM_FUND_EXCHANGE{
   address public platform;
   TableFactory tf = TableFactory(0x1001);  // TableFactory的地址固定为0x1001
   //约束条件--平台方
    modifier onlyPlatform{
        require(msg.sender==platform);
        _;
    }

    constructor() public {
        platform =msg.sender;
        create();
    }

     // 创建表
    function create() returns(int){
    int count = tf.createTable("SDD_PLATFORM_FUND_EXCHANGE", "id", "transfer_out_platform_id,transfer_in_platform_id,proof,sum,transfer_time");                   
        return count;
    }

          //数据上链
    function insert(
        string id, 
        string transferOutPlatformId,
        string transferInPlatformId,
        string proof,
        int sum,
        uint transferTime) onlyPlatform public returns(bool){
           
         //字段校验
        require(checkRepeat(id),"上链数据交易id已经存在");
        Table table = tf.openTable("SDD_PLATFORM_FUND_EXCHANGE");
        Entry entry = table.newEntry();
        entry.set("id", id);
        entry.set("transfer_out_platform_id",transferOutPlatformId);
        entry.set("transfer_in_platform_id", transferInPlatformId);
        entry.set("proof",proof);
        entry.set("sum", sum);
        entry.set("transfer_time", int(transferTime));
        table.insert(id, entry);
        return true;
        }


     //查询操作
      function select(string id) public view returns(Entry){
        Table table = tf.openTable("SDD_PLATFORM_FUND_EXCHANGE");
        Condition condition = table.newCondition();
        condition.EQ("id",id);
        Entries entries = table.select(id, condition);
        require(entries.size() == 1, "DATA_NOT_EXIST");
        return entries.get(0);
    }
    
    function selectById(string id) public view returns(string,string,string,string,string,string){
        Entry entry = select(id);
        return (strConcat("id:",id),strConcat("transfer_out_platform_id:",entry.getString("transfer_out_platform_id")),strConcat("transfer_in_platform_id:",entry.getString("transfer_in_platform_id")),strConcat("proof:",entry.getString("proof")),strConcat("sum:",entry.getString("sum")),strConcat("transfer_time:",entry.getString("transfer_time")));
    }

     //检查记录重复
    function checkRepeat(
        string id
    )  private view returns(bool){

        Table table = tf.openTable("SDD_PLATFORM_FUND_EXCHANGE");
        Entry entry = table.newEntry();
        Condition condition = table.newCondition();

        condition.EQ("id", id);

        Entries record = table.select(id,condition);
        if (0 == record.size()) {
            return true;
        }else{
            return false;
        }
    }
     
     //字符串拼接
      function strConcat(string _a, string _b) internal returns (string){
        bytes memory _ba = bytes(_a);
        bytes memory _bb = bytes(_b);
        string memory ret = new string(_ba.length + _bb.length);
        bytes memory bret = bytes(ret);
        uint k = 0;
        for (uint i = 0; i < _ba.length; i++)bret[k++] = _ba[i];
        for (i = 0; i < _bb.length; i++) bret[k++] = _bb[i];
        return string(ret);
   }
}

 

 

四、合约使用

分别点击保存、编译、部署、发交易

 如果在编译合约的时候报错,说是找不到Table.sol文件,但是Table工具类确实存在,这个时候就点击Table工具类点击保存、编辑就能解决了。

 

在第一次部署的时候,由于没有创建用户,所以不能选择用户,这个时候就先手动创建用户,可以在这里创建。

 

最后就是发交易,我们在方法拦里面就能选择我们在合约里面编写的函数了,先是创建表,然后我们插入数据,最后通过主键id进行数据查询

 创建表

 

数据上链

 

通过主键Id查询

 

五、注意点

solidity不能存放float类型和Date类型的数据,也就是说solidity不支持这两种数据类型,一般像价格、金额这样的数据,我们在存储前先乘100,以分作为单位,转成int类型存储,

对于Date类型的数据,我们存储的是时间戳,也是通过int类型存储,如果在链上查询数据,拿到数据后需要对时间和金钱这样的数据进行处理还原。

 

posted on 2024-03-01 13:57  百里登峰  阅读(117)  评论(0编辑  收藏  举报