我是靠谱客的博主 狂野小土豆,最近开发中收集的这篇文章主要介绍链乔教育在线|智能合约入门——以太坊智能合约学习笔记(一)以太坊智能合约学习笔记(一),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

以太坊智能合约学习笔记(一)

58672f50188dab6cf222782f0966a3f3.jpeg

前言

以太坊的目标是打造一个用于运行智能合约的去中心化平台,根据程序代码的设置来运行应用,目的是保障程序运行时不存在审查、欺诈、停机、以及第三方人为干预的可能。开发者可以使用官方提供的工具在其上开发、部署并运行智能合约。

一些名词解释

1.图灵完备

图灵完备来自计算机的概念,指程序代码语言加上能在图灵机上运行的运算规则,符合这种要去的逻辑系统、装置、或者编程语言就可以被认为是图灵完备的。图灵完备的语言有循环执行语句、判断分支语句等,理论上能解决任何算法。那么它的一个显著特点就是支持程序循环不断地运行下去。缺点就是其有可能进入死循环而导致程序崩溃。

2.智能合约

img-hmKDeMta-1617168900726

智能合约概念于1995年由Nick Szabo首次提出,是一种旨在以信息化方式传播、验证或执行合同的计算机协议。智能合约允许在没有第三方的情况下进行可信交易,这些交易可追踪且不可逆转。智能合约的目的是为了提供一种优于传统合约条款执行的安全方法,减少合约相关的交易成本

智能合约以数字形式执行,意味着合约必须以计算机可读的代码形式来呈现,只要参与方达成协议,智能合约简历的权利和义务会由一台计算机或者是一个计算机网络来执行。

合约的作用

(1)维护存储的数据。

(2)为具有复杂访问规则的EOA账户服务

(3)管理执行中的合约

(4)给其它合约提供函数。

3.智能合约与DApp的关系与区别

DApp(Decentralized App),即去中心化的应用程序,是一种基于智能合约的应用,其目的是让智能合约有一个友好的界面,并扩展一些额外的功能,如分布式存储等。与传统的网站不同,DApp不能在普通的服务器上运行,而是运行在一台以太坊交互节点或一台与以太坊节点交互的中心化服务器上,需要将交易提交到区块链并且从区块链中读取重要的数据。用户在区块链网络上被表示成一个“钱包”地址,其它用户数据则保存在本地,这点与传统的用户登录系统不同。

655c9094a426b0ffbc5a2fff36c8a229.jpeg

一个完整的DApp流程如下:

1)用Solidity(或其他语言)编写智能合约(后缀为.sol)。

2)用sole编译器将.sol合约编译成EVM字节码。

3)编译好的字节码回送给DApp前端。

4)前端将编译好的智能合约部署到区块链中。

5)区块链返回智能合约地址+ABI(即合约接口)。

6)前端通过Address+ABI+nonce,调用智能合约。

7)智能合约开始处理。

4.智能合约开发语言solidity

img-msYqHW4Y-1617168900732

​ Solidity 语言是一种专门用于编写和执行智能合约的语言,是在以太坊虚拟机基础上运行的、面向合约的高级语言,最初是在 2014 年 8 月由以太坊的前任 CTO和联合创始人 Gavin Wood 提出来的,后来由以太坊开发人员组建了一支专门的团队,对 Solidity 语言进行不断改进,目前仍在开发和优化之中,在 GitHub 上的开发存储区域是htps:/github.com/thereum/solidity,在这里我们可以了解到最全面的关于 Solidity 语言开发和迭代的过程详情、相关文档。
在语言的风格上,Solidity 语言受到 C++、Python 和 JavaScript 3 种语言的深刻影响,它是一种静态类型的编程语言,以字节码(Bytecode)的模式进行编译,因此可以在以太坊虚拟机上运行。Gavin Wood 在开发 Solidity 语言时借鉴了 JavaScript 的 ECMAScript 脚本语言的语法规则,使它与现有的网页开发语言有些类似,但其实有较大不同,如 Solidity 语言拥有静态类型、可变返回函数等。最重要的一点是,Solidity 语言可以编写具有自执行的业务逻辑、嵌入智能合约中的合约,因此它不但是以太坊的基础编程语言之一,而且是其他绝大部分基于以太坊的、具有智能合约的各种区块链产品(Blockchain 2.0)的基础编程语言,被广泛应用于目前绝大多数区块链产品,如超级账本(Hyperledger)项目就是用 Soliditv 语言开发而成的。

简单的智能合约代码

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 <0.8.0;

contract SimpleStorage {
    uint storedData;

    function set(uint x) public {
        storedData = x;
    }

    function get() public view returns (uint) {
        return storedData;
    }
}

第一行是一个注释,用于说明源代码的使用许可证书版本为:GPL3.0。在发布源代码时,在代码中加入机器可读许可证是很有必要的。

第二行用于指定源代码的版本,即solidity的版本范围为:0.4.16(含)以上,0.8.0(不含)以下,此行代码设置用以避免编译器在编译代码时出现版本异常。pragma的含义是告知编译器如何处理源代码指令。

接下来,contract关键字声明了一个合约结构,合约名为SimpleSotrage。合约就是一组代码和数据的组合,被保存在以太坊区块链的一个特定地址上。

uint storedData ,声明了一个名为 storedData的 uint(256位无符号)整数,用于存储一个特定的整数数据。无符号的意思表示该数字最小值是0,不能存储负数。数据将会被存储在以太坊中一个特定的位置。

声明storedData之后有一个函数(function):名为set, 并指定了一个参数,uint x,即一个无符号整数 x,访问权限为public,即公开的,任何人都可以访问和使用,作用是将参数x中保存的数据转存到storedData代表的数据地址中。

另外一个函数get的作用与set相反,作用是将storedData中保存的数据读取出来。

对于以太坊来说,上述的合约就是拥有合约(owning contract)。

要访问一个状态变量,并不需要像 this. 这样的前缀,虽然这是其他语言常见的做法。

该合约非常简单,只能做两件事:1.它能允许任何人在合约中存储一个单独的数字 ;2.这个数字可以被世界上任何人访问,且没有可行的办法阻止你发布这个数字。当然,任何人都可以再次调用 set ,传入不同的值,覆盖之前的数字,但是这个数字仍会被存储在区块链的历史记录中。

货币合约(Subcurrency)示例

下面的合约实现了一个最简单的加密货币。这里,币确实可以无中生有地产生,但是只有创建合约的人才能做到(实现一个不同的发行计划也不难)。而且,任何人都可以给其他人转币,不需要注册用户名和密码 —— 所需要的只是以太坊密钥对。

// SPDX-License-Identifier: GPL-3.0
pragma solidity  >=0.7.0 <0.9.0;

contract Coin {
    // 关键字“public”让这些变量可以从外部读取
    address public minter;
    mapping (address => uint) public balances;

    // 轻客户端可以通过事件针对变化作出高效的反应
    event Sent(address from, address to, uint amount);

    // 这是构造函数,只有当合约创建时运行
    constructor() {
        minter = msg.sender;
    }

    function mint(address receiver, uint amount) public {
        require(msg.sender == minter);
        require(amount < 1e60);
        balances[receiver] += amount;
    }

    function send(address receiver, uint amount) public {
        require(amount <= balances[msg.sender], "Insufficient balance.");
        balances[msg.sender] -= amount;
        balances[receiver] += amount;
        emit Sent(msg.sender, receiver, amount);
    }
}

这个合约比上一个稍微复杂一点,我们来解释一下:

第一行依然是代码许可证,第二行是编译版本。

接下来是合约的名字,这次我们起的名字是Coin。

第6行address public minter;这行声明了一个可被访问的名为minter的变量,用于存储地址(address)。 address 类型是一个有160位长度的整数但不允许任何计算操作。这种类型适合存储合约地址或外部人员的密钥对。关键字 public的意思是允许外部访问,在编译时,编译器会自动生成一个函数,允许从合约外部访问这个状态变量的当前值。由编译器生成的函数的代码大致如下所示(external view即外部访问):

function minter() external view returns (address) { return minter; }

要注意,此函数已经由编译器自动帮助我们生成出来了,我们没有必要再写一遍了:)。

第7行, mapping (address => uint) public balances; 这里创建了一个新的变量balances,只是它的类型是mapping(映射),这是一个比较复杂的数据类型,可以看到它的括号里的映射说明,用于将address地址与一个uint数值建立对应关系,即通过这个地址可以从此映射表中获取到一个uint数值。在程序运行时,mapping会有一次初始化的过程,最初的uint数值均为0。同样的,public关键字也会创建一个访问函数,只是这次返回的将是地址映射的uint数值,它大致如下所示:

function balances(address _account) external view returns (uint) {
    return balances[_account];
}

正如你所看到的,你可以通过该函数轻松地查询到账户的余额。

第10行,event Sent(address from, address to, uint amount); 这行声明了一个“事件(event)”,它会在 send 函数的最后一行(第27行代码)被发出 ,使用emit关键字触发一个事件。用户界面(当然也包括服务器应用程序)可以监听区块链上正在发送的事件,而不会花费太多成本。一旦它被发出,监听该事件的listener都将收到通知。而所有的事件都包含了 fromtoamount 三个参数,可方便追踪交易。 为了监听这个事件,你可以使用如下JavaScript代码(假设 Coin 是已经通过 web3.js 创建好的合约对象:

Coin.Sent().watch({}, '', function(error, result) {
    if (!error) {
        console.log("Coin transfer: " + result.args.amount +
            " coins were sent from " + result.args.from +
            " to " + result.args.to + ".");
        console.log("Balances now:n" +
            "Sender: " + Coin.balances.call(result.args.from) +
            "Receiver: " + Coin.balances.call(result.args.to));
    }
})

这里请注意观察自动生成的 balances 函数是如何从用户界面调用的(监听事件代码第8、9行)。

合约代码第13行, constructor 是仅在创建合约期间运行的构造函数,不能在事后调用。 它永久存储创建合约的人的地址: msg (以及 txblock ) 是一个特殊的全局变量,其中包含一些允许访问区块链的属性。 msg.sender 始终是当前(外部)函数调用的来源地址。

最后,真正被用户或其他合约所调用的,以完成本合约功能的方法是 mintsend。 如果 mint 被合约创建者外的其他人调用则什么也不会发生(由require函数控制验证条件)。 另一方面, send 函数可被任何人用于向他人发送币 (当然,前提是发送者拥有这些币)。记住,如果你使用合约发送币给一个地址,当你在区块链浏览器上查看该地址时是看不到任何相关信息的。因为,实际上你发送币和更改余额的信息仅仅存储在特定合约的数据存储器中。通过使用事件,你可以非常简单地为你的新币创建一个“区块链浏览器”来追踪交易和余额。

注:代码仅可用于学习。

最后

以上就是狂野小土豆为你收集整理的链乔教育在线|智能合约入门——以太坊智能合约学习笔记(一)以太坊智能合约学习笔记(一)的全部内容,希望文章能够帮你解决链乔教育在线|智能合约入门——以太坊智能合约学习笔记(一)以太坊智能合约学习笔记(一)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(58)

评论列表共有 0 条评论

立即
投稿
返回
顶部