首页 > 其他分享 >区块链合约的编写

区块链合约的编写

时间:2024-03-01 14:00:23浏览次数:19  
标签:function string public returns entry 编写 区块 合约 id

区块链合约的编写是基于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类型存储,如果在链上查询数据,拿到数据后需要对时间和金钱这样的数据进行处理还原。

 

标签:function,string,public,returns,entry,编写,区块,合约,id
From: https://www.cnblogs.com/braveym/p/18046486

相关文章

  • 【C++】Mat和Pat希望邀请他们的朋友来参加派对。他们要编写一个程序完成下面的任务。
    Mat和Pat希望邀请他们的朋友来参加派对。他们要编写一个程序完成下面的任务。让Mat输入他朋友的姓名列表。姓名存储在一个容器中,然后按排列后的顺序显示出来。让Pat输入她朋友的姓名列表。姓名存储在另一个容器中,然后按排列后的顺序显示出来。创建第三个容器,将两个列表合并,删除重......
  • 如何创建自己的Spring Boot Starter并为其编写单元测试
    当我们想要封装一些自定义功能给别人使用的时候,创建SpringBootStarter的形式是最好的实现方式。如果您还不会构建自己的SpringBootStarter的话,本文将带你一起创建一个自己的SpringBootStarter。快速入门创建一个新的Maven项目。第三方封装的命名格式是xxx-spring-boo......
  • Qt 编写的qml程序全屏时,挡住系统虚拟键盘的解决办法
    官方有提到该问题。尤其是使用qml时,一定会出现这个遮挡问题。https://doc.qt.io/qt-5/windows-issues.html 默认的qml工程的解决代码如下:1...2#include<QWindow>3#include<QtPlatformHeaders/QWindowsWindowFunctions>4...56intmain(intargc,char*arg......
  • 禅道编写测试用例规范
    1、标题规范格式2、用例标题需要概述出期望结果3、用例步骤不能超出10个步骤4、预期结果检查点不超过3个检查点5、描述需简洁扼要6、前置条件完整不冗余        ......
  • 记录 re:Invent 大会,使用 PartyRock 编写我们第一个 AI 应用以及心得
    如果说2023年什么应用技术最火,那么说是OpenAI为代表的ChatGPT在AI方面的突破和发展,是完全没有任何的争议的。随后,各大云厂商以及应用集成商甚至垂直领域的服务提供商都有了对应的AI模型。我们开玩笑的说,这个好比多年前的百团大战一样,各种的AI相关的应用奔涌出现、百......
  • CMakeLists的编写注意
    `add_executable(${CMAKE_PROJECT_NAME})`的位置对于`link_directories`命令的影响可能与项目的目录结构和依赖项的设置有关。一般来说,`link_directories`命令应该在`add_executable`命令之前调用,以确保在链接时能够正确找到所需的库文件。如果在`add_executable`之后调用`link_d......
  • 在mapper.xml中编写sql规则和常见函数写法
    在mapper.xml中编写规则和常见函数写法目录在mapper.xml中编写规则和常见函数写法service传到mapper.xml常见查询语句的写法group_concatcasewhenelseendCOALESCEDUAL模糊查询写法关于where1=1xml中不能存在的特殊字符——特殊转义或<![CDATA[]]>sql编写的一些......
  • html四边形的的框怎么编写,html知识点之利用css四边形切角并且加上边框
    前言这几个月做了很多前端工作,其中一个需求还是蛮头疼,UI给的图上面的四边形是一个带斜边的,直接用背景图可以实现,但是会出现各种布局的问题,比如内容太大了,边框不会跟着扩大,废话不多说,这里写一些如何利用css话四边形带有斜边,并且给斜边加边框,在这之前,先简单说一下需要用到的函数li......
  • Css中的display属性linline-block(行内区块元素)的详解和应用
    原文链接:https://www.cnblogs.com/lijinwen/p/5679864.html说inline-block(行内区块元素)之前,先说下他另外的2个兄弟display:inline;内联元素,简单来说就是在同一行显示。他没有高度,给内联元素设置width和height是没效果的。display:block;块级元素,简单来说就是就是有换行,会换......
  • 【C++】编写一个具有老式风格接口的函数,其原型如下:int reduce(long arr[], int n)。实
    #include<iostream>#include<string>usingnamespacestd;intreduce(longarr[],intn){sort(arr,arr+n);autostr=unique(arr,arr+n);returnstr-arr;}intmain(){longarr[10]={15,8,5,6,11,11,6,6,198,50};......