135.003 智能合约后端优化和产品化

@(135- Block Chain| 区块链)

Introduction

  • 如何通过数据结构优化降低合约执行成本
  • 合约的继承
  • 巧用modifier
  • 以太坊函数库的使用和基本介绍

如何减少gas 消耗?
(本质为节约计算资源,降低时间复杂度的问题)
数组越大,遍历所需资源越多
遍历数组 traverse array——> 映射 Mapping

1 Mapping in Solidity

类比map(c++),dict(python)
Hash table
Key - Value

  • types of Key in solidity
    (bool,int ,address,string)
  • types of Value in solidity
    (any type)
  • usage
    mapping (address=>Employee)employees
  • mapping只能作为合约的成员变量,而不能做本地局部变量

    2 Mapping底层实现

  • 不使用数组+链表,不需要扩容
  • hash函数为keccak256hash(keccak 即SHA- 3)
  • 在storage 上存储,理论上为无限大的hash表
    *** 无法naive地遍历整个mapping**
  • 赋值 employees[key] = value
  • 取值 value = employees[key]
  • value 是引用,在storage上存储,可以直接修改
  • 当key 不存在,value = type‘s default // 不会抛出异常

3 函数返回进阶

  • 命名参数返回
  • 命名返回参数直接赋值

1.命名参数返回

    function checkEmployee(address employeeId) returns(uint salary,uint lastPayday){ //quary the information of employees
    //name the returned parameter 命名参数返回
    

OUTPUT

"0": "uint256: salary 1000000000000000000",
"1": "uint256: lastPayday 1530411588"
}

2.命名返回参数直接赋值

等效代码

        // return (employee.salary,employee.lastPayday);
        salary = employee.salary;
        lastPayday = employee.lastPayday;

4 可视度

4.1 可视度

  • public :谁都可见
  • external:只有“外部调用”可见(特殊可视度)
  • internal:外部调用不可见,内部和子类可见(类比c++,protected)
  • private:只有当前合约可见

4.2 变量与可见度

  • 状态变量:public,internal,private

    • 默认:internal
    • public:自动定义取值函数
    • private:不代表别人无法看到,只代表别的区块链智能合约无法看到

合约的所有成员变量都是肉眼可见的!!!

  • 函数 :public,external,internal,private

    • 默认public

5 继承

5.1 继承-基本语法

private 对继承类不可见

5.2 继承-抽象合约

contract Parent{
    function someFunc() returns (uint);
}
contract Child is Parent{
    function someFunc() returns (uint){
        return 1;
    }
}

5.3 继承-interface

  • 类比 Java 相似
    只是一个告诉之后程序员的一个框架
pragma solidity ^0.4.0;
interface Parent{
//不可继承其他合约或Interface
//没有构造函数
//没有状态变量
//没有struct
//没有enum
//简单来说,只有function定义,啥都没有
    function someFunc() returns (uint);
}

contract Child is Parent{
    function someFunc() returns (uint){
        return 1;
    }
}

5.4 多继承

  • 重名函数的override 次序
    ```solidity
    contract Base1{
    function func1(){}
    }

contract Base2{
function func1(){}
}

contract Final is Base1,Base2 {
}

contract test{
Final f = new Final();
f.func1();//Base2 的function1被调用(从后往前,由于先继承base1,再继承base2)
}

```

  • Super:动态绑定上级函数
contract foundation{
    function func1{
    //do stuff
    }
}

contract Base1 is foundation{
    function func1(){
        super.func1();
    }
}

contract Base2 is foundation{
    function func1(){
    super.func1();
    }
}

contract Final is Base1,Base2{
    Final f = new Final();
    f.func1();
}

//调用顺序:Base2.func1,Base1.func1,foundation.func1

多继承 Method Resolution Order使用O3 Linearization

  • 与python 相同
  • 不能成环路

6 Modifier

pragma solidity ^0.4.0
contract Parent {
    uint public a=2;
    modifier someModifier(){
        _;
        a = 1;
    }
    function parentFunc2(uint value) someModifer public returns(uint){
    a = value;
    //下划线等效加入一句 modify a=1;
    return a;
    }
}

7 Safe Math 和 Library

7.1 加减乘除在solidity中很危险

contract Test {
    uint8 public a = 0;
    function set(){
        a -= 100;
    }
}

OUTPUT:整型溢出
a: uint8: 156

手动解决方法_silly

contract Test {
    uint8 public a = 0;
    function set(){
        uint c = a - 100;
        assert(c<a);
        a = c;
    }
}

库函数 Zppelin-solidity

  • 工程师——学习代码重用
  • 不要重复造轮子
    ```
    solidity ^0.4.0;

import ‘./SafeMath.sol‘; //local file,download from github

contract Test {
using SafeMath for uint8;
uint8 public a = 0;
function set(){
a = a.sub(100);
//a = SafeMath.sub(a,100);
}
}

```

8 Code in Remix (Solidity IDE)

pragma solidity ^0.4.14;

import './SafeMath.sol';
import './Ownable.sol'; //Github - Zppelin-solidity

contract Payroll{
    using SafeMath for uint;

    struct Employee{
        address id;
        uint salary;
        uint lastPayday;
    }

  // uint constant payDuration = 30 days;
   uint constant payDuration = 10 seconds;//for test:10 seconds

   uint totalSalary;
   address owner;
   mapping(address => Employee)public employees;

    // function Payroll(){//construction function
    // owner = msg.sender; // in ownable.sol
    // }

    // modifier onlyOwner{ //in Ownable.sol
    //     require(msg.sender == owner);
    //     _; //represent the function been modified, 除了return之外的语句
    // }
    modifier employeeExist(address employeeId){
        var employee = employees[employeeId];
        assert(employee.id != 0x0);//confirm that exist
        _;
    }
    function _partialPaid(Employee employee) private{
            uint payment = employee.salary * (now - employee.lastPayday) /payDuration;//if exist , calculate payment注意整除
            employee.id.transfer(payment);
    }

    function addEmployee(address employeeId,uint salary)onlyOwner{
       // require(msg.sender == owner);//whether is onwner
        var employee = employees[employeeId];//var - any type
        assert(employee.id == 0x0);//confirm that exist
        totalSalary += salary *1 ether;
        employees[employeeId] = Employee(employeeId,salary* 1 ether,now);
    }

    function removeEmployee(address employeeId)onlyOwner employeeExist(employeeId){
        // require(msg.sender == owner);//whether is onwner
        //  var (employee,index) = _findEmloyee(employeeId);
        var employee = employees[employeeId];
        _partialPaid(employee);
        totalSalary -=employees[employeeId].salary;
        delete employees[employeeId];//left with a blank in the array,wasteful
}

    function updateEmployee(address employeeId,uint salary)onlyOwner employeeExist(employeeId){
        //require(msg.sender == owner);
        //Equivalently 等效
        // if (msg.sender != owner){//avoid employee cheating
        //     revert();
        // }
         var employee = employees[employeeId];
        _partialPaid(employee);
        totalSalary -= employees[employeeId].salary;
        employees[employeeId].salary = salary *1 ether;
        totalSalary += employees[employeeId].salary;
        employees[employeeId].lastPayday = now;     

    }

    function addFund() payable returns(uint){
        return this.balance;//address.balance
    }

    function calculateRunway()returns(uint)
    { //how many times left to pay
        return this.balance / totalSalary;
    }
    function hasEnoughFund() returns(bool){
        // return this.balance >=salary;
        //return this.calculateRunway() > 0; //this方法 使用的gas 较多,不推荐
        return calculateRunway() > 0; //vm jump 操作,使用gas较少,推荐
    }

    function checkEmployee(address employeeId) returns(uint salary,uint lastPayday){ //quary the information of employees
    //name the returned parameter 命名参数返回 

        var employee = employees[employeeId];
        // return (employee.salary,employee.lastPayday);
        salary = employee.salary;
        lastPayday = employee.lastPayday;
    }

    function getPaid() employeeExist(msg.sender){

         var employee = employees[msg.sender];
         //assert(employee.id != 0x0);//confirm that exist
        uint nextPayday = employee.lastPayday + payDuration;
         //每一次运算都是真金白银~
         //原则:不重复运算!——省gas
        assert(nextPayday < now);
        // if( nextPayday > now){
        //     revert();
              //throw or revert
            //throw: 所有的gas 均会被消耗殆尽
            //revert:回滚,return没有消耗的gas

        // }

            employees[msg.sender].lastPayday = nextPayday;//原则:先修改内部变量,再给钱——》之后会讲,安全问题
            employee.id.transfer(employee.salary);

    }
}

参考阅读:老董-以太坊智能合约全栈开发

原文地址:https://www.cnblogs.com/Neo007/p/9249843.html

时间: 2024-10-07 22:12:51

135.003 智能合约后端优化和产品化的相关文章

135.001 智能合约设计-——单员工薪酬系统

@(135- Block Chain| 区块链) Introduction 参考阅读:老董-以太坊智能合约全栈开发 课程导读 1. 最终产品Demo 员工系统--人员管理+工资发放 大公司如何发工资?雇主跑路,讨薪难. 雇佣员工时,先把半年工资打到员工??? 去中心化信任 雇主,雇员 传统的员工系统 人力资源公司的成本太高 小公司--信任问题,拖欠工资,讨薪难? 目标 高效低成本 防止黑心老板违约拖欠工资? 2.项目特点 1)前端交互很简单,后端运行在智能合约???? 2)智能合约--不存在所谓

郑重告之:智能合约开发实训营第4期学员招募正式启动!

各位同学,抱歉久等了- 这是终于到来的<以太坊智能合约全栈开发>实战特训营第四期的正式招募通知. <以太坊智能合约全栈开发>实战特训营是由硅谷密探和 celer network 共同打造的全球第一档·智能合约全栈开发实战课程,也是目前唯一一个实现来自中.美.澳.英.日.韩等多国学员在线互动学习的区块链技术实战特训课程. 为了保证教学质量,如今已调整为每期仅招募100人,参与有门槛,需经过层层审核,录取通过率一度不到10%,并非所有人都适合参与. 拉至文末可直接进行报名. 请点击此处

使用Go语言与Ethereum智能合约进行交互

尽管最近出现了麻烦,但Ethereum仍然是区块链空间中实现智能合约最重要的系统,而且这种情况似乎不太可能很快改变. 在我看来,技术本身具有很大的潜力,从学术的角度来看是非常有趣的,但正如前面提到的问题,之前展示出来了很多问题,区块链技术,智能合约,特别是带有Solidity的Ethereum生态系统是非常不成熟的,而且也没有准备好的黄金时段/生产用例. 然而,这是学习和了解这种技术的一个很好的机会,能够在应用程序奔溃前提前做准备. 在我之前的一篇文章中,我创建了一个小型应用程序,其中包含一个简

智能合约从入门到精通:Solidity语法之内存变量的布局和状态变量的存储模型

简介:在前面我们已经讲过Solidity语言的一些语法内容,在矩阵元JUICE开放平台的JIDE开发时,一定要注意Layout in Memory和Layout of State Variables in Storage,即内存变量的布局和状态变量的存储模型.内存变量的布局(Layout in Memory) Solidity预留了3个32字节大小的槽位: 0-64:哈希方法的暂存空间(scratch space) 64-96:当前已分配内存大小(也称空闲内存指针(free memory poi

智能合约从入门到精通:Solidity汇编语言

简介:上一节,我们讲过在JUICE平台开发智能合约的开发规范,本节我们将继续就Solidity定义的汇编语言进行更加深入的讨论.Solidity定义的汇编语言可以达到下述的目标:1.使用它编写的代码要可读,即使代码是从Solidity编译得到的.2.从汇编语言转为字节码应该尽可能的少坑.3.控制流应该容易检测来帮助进行形式验证与优化.为了达到第一条和最后一条的目标,Solidity汇编语言提供了高层级的组件比如,for循环,switch语句和函数调用.这样的话,可以不直接使用SWAP,DUP,J

nodejs部署智能合约的方法-web3 0.20版本

参考:https://www.jianshu.com/p/7e541cd67be2 部署智能合约的方法有很多,比如使用truffle框架,使用remix-ide等,在这里的部署方法是使用nodejs一步步编译部署实现的: const Web3 = require('web3'); const web3 = new Web3();//使用web3来进行区块链接口的调用 //通过rpc连接区块链,这里连接的是本地私有链 web3.setProvider(new Web3.providers.Http

fabric 智能合约开发

1.智能合约状态图 2.实现功能,通过背书,签收机制实现任务在各部门流转 3.相关sdk Chaincode接口 {Init,Invoke}方法 ChaincodeStubInterface接口 1.GetTxTimestamp 2.CreateCompositeKey       3.GetQueryResult 4.GetHistoryForKey 5.SetEvent 6.GetStateByPartialCompositeKey 7.GetFunctionAndParameters 8.

WoToken智能合约软件开发搬砖钱包系统定制开发那家公司好

WoToken区块链模式APP开发,WoToken智能合约软件开发搬砖钱包系统定制开发那家公司好,专业请找[孙女士 微/电 ①⑧⑥①⑤⑥①④零⑥②],WoToken钱包智能系统定制开发,WoToken数字资产APP定制开发,WoToken智能合约软件定制开发,WoToken区块链模式APP定制开发;可开发类似软件,非平台方,玩家勿扰. wotoken利用AI人工智能实现高频交易,自动搬砖,首创期货交易,交易挖矿等多方面套利!!!wotoken拥有多智能合约技术,并结合自有的高性节点为数字资产提供

十分钟部署智能合约

eos环境搭建 1.git clone源代码 git clonehttps://github.com/EOSIO/eos --recursive 2.下载编译之后,里面有三个应用程序,这三个应用程序也都是命令行的: 1.Cleos: 2.Nodeos: 3.Keosd. 这三个应用程序之间有什么关系呢?我们现在使用的前端,怎么使用EOS呢? -Cleos,它是一个命令行程序.在前端使用EOS是通过Cleos输入命令,给EOS下达指令. -Nodeos,其实它就是挖矿客户端.在启动Nodeos之后