以太坊智能合约开发-《精通以太坊智能合约开发》学习总结实践
发布日期:2021-06-29 22:26:11 浏览次数:3 分类:技术文章

本文共 13356 字,大约阅读时间需要 44 分钟。

文章目录

一、初探以太访智能合约

1. remix小demo

https://remix.ethereum.org

Remix,Remix是以太坊官方开源的Solidity在线集成开发环境,可以使用Solidity语言在网页内完成 以太坊智能合约的在线开发、在线编译、在线测试、在线部署、在线调试与在线交互, 非常适合Solidity智能合约的学习与原型快速开发。

目前尝试 Solidity 编程的最好方式是使用 Remixo Remix 是一个基于浏览器的 Solidity IDE , 它集成了 Solidity 编译器、运行环境 ,以及调试和发布工具。

使用浏览器打开网址 https://remix.ethereum.org

官方demo

// SPDX-License-Identifier: GPL-3.0pragma solidity >=0.7.0 <0.8.0;/** * @title Storage * @dev Store & retrieve value in a variable */contract Storage {    uint256 number;    /**     * @dev Store value in variable     * @param num value to store     */    function store(uint256 num) public {        number = num;    }    /**     * @dev Return value      * @return value of 'number'     */    function retrieve() public view returns (uint256){        return number;    }}

合约代码分析

  • pragma

    关键字 pragma 用来告诉编译器如何编译这段代码,〈表示这里需要 Solidity>=0.7.0 <0.8.0 版本)

  • contract Storage

    这行代码定义 了一个合约 , 合约 的名字为 Storage ( 这和在其他语言如 JavaScript 及 Python 中定义一个类很相似,只不过 class 关键字变成了 contract )。
    一个合约通常由一组代码(合约的函数)和数据(合约的状态)组成。一个合
    约被存储在 以太坊 区块链上 , 对应一个特殊地址 。

  • uint256 number;

    **这行代码声 明了 一个变量,在智能合约中称为“状态变量 ”。**这个状态变量名 为 number, 类型为 uint (一个 256 位的无符号整数) ,可以把它理解为数
    据库里面的一个存储单元 。

  • 修改变量 number 的值

    function store(uint256 num) public {        number = num;    }

    上面的代码定义了 一个函数 store() 。在 Solidity 中通过 function 关键字来定义

    函数,并且函数的可见性修饰符要写在函数名字及参数之后( 这和大部分常见
    语言不一样),这里 store()函数的作用是修改变量 number 的值。

  • 读取变量的值

    function retrieve() public view returns (uint256){        return number;    }

    上面的代码定义了 一个函数 retrieve(), 用来读取变量 number的值。这个函

    数通过 returns 来指定返回值 。 returns 返回值要放在所有函数修饰符之后 、 函数
    体之前 。

和大多数语言有点不一样,函数在访问状态变量时,不需要像其他语言那样添加前缀 this 。

所有的标识符如合约名称 、 函数名称 、 变量名称等都只能使用 ASCII 字符集里的字符,但是在字符串变量中可以存储 UTF-8 编码的数据。

2. 写智能合约用的编程语言

用Solidity就好。 要写智能合约有好几种语言可选:有点类似Javascript的Solidity, 文件扩展名是.sol. 和Python接近的Serpent, 文件名以.se结尾。还有类似Lisp的LLL。Serpent曾经流行过一段时间,但现在最流行而且最稳定的要算是Solidity了,因此用Solidity就好。

当Solidity合约编译好并且发送到网络上之后,你可以使用以太坊的web3.js JavaScript API来调用它,构建能与之交互的web应用。

二、以太坊核心概念

1. 交易/事务( Transaction )

注 : 英文 Transaction,大多数场合翻译为“交易”,当表示数据库特性时翻译为“事务”。

区块链是全球共享的事务性数据库 。 全球共享意味着参与这个网络的每一个人都可以读取其中的记录 。 如果想修改这个数据库中的内容,就必须创建一个得到其他所有人确认的事务, 事务意味着要做的修改(假如想同时修改两个值)只能被完全应用或者一点都没有应用 。

举个例子,想象一张表 , 里面列 出 了某个电子货币所有账户的余额。当从一个账户到另 一个账户的转账请求发生时,这个数据库的事务特性确保从一个账户中减掉的金额会被加到另 一个账户上。如果因为某种原因 , 往目标账户上增加金额的操作无法进行,那么原账户中 的金额也不会发生任何变化 。

2. 区块

一个区块就是若干交易 的集合,它会被标记上时间戳和前一个区块的 Hash标识 。区块在经过哈希运算后生成一份工作量证明 , 从而验证区块中的交易。有效的区块经过全网络的共识之后会被追加到区块链中。

这些块按时间形成了 一个线性序列,这正是区块链这个词的来源。区块 以一定的时 间间隔被添加到链上。对于 以太坊,这个间隔大约是 17 秒 。

作为“顺序选择机制”(也就是挖矿)的 一部分,可能有时会发生区块被回滚的情况,但通常仅在链的“末端”。 在末端增加的块越多,其发生回滚的概率越小 。因此交易被回滚甚至从区块链中抹除也是可能的,但交易发生后等待的时间越长, 这种情况发生的概率就越小 。

3. 共识协议:工作量证明( PoW)

在工作量证明系统中,创建区块的过程被称为“挖矿”。 矿工( Miner )是

网络中挖区块的节点。
任何人都可以成为网络中的矿工 。 每一个矿工都各自解决数学难题,其中第一个解决难题的矿工是胜利者 , 其得到的回报是 5 个以太 币和该区块中全部交易的交易费 。 如果某个矿工的处理器比网络中的其他节点更强大,则并不意味着这个矿工总会成功,但其成功的概率会比较大 。 实际上 以太坊的网络安全是由网络的全部算力衡量的 。

4. 权益证明( PoS)

以太坊最终会切换到使用权益证明,以解决工作量证明过于消耗资源的问

题 。 权益证明的主要思路是 : 作为验证节点 , 首先必须拥有一定数量的 以太币,
根据以太币的数量和时间会产生用于下注验证区块的权益。只有拥有权益的节点才能有效验证区块,当所验证的区块被打包进链后,将获得和权益成正比的区块奖励。如果是验证恶意或错误的区块,那么所下注的权益将被扣除。

5. 以太坊虚拟机( EVM)

以太坊虚拟机是一个被沙箱封装起来、 完全隔离的运行环境。**运行在 EVM内部的代码不能接触到网络、文件系统或其他进程,**即使是智能合约与其他智能合约也只能进行有限的交互 。

然而,以太坊虚拟机本身运行在以太坊节点上,当我们把合约部署到以太坊网络上之后,合约就可以在所有以太坊网络节点的以太坊虚拟机上运行了。

编译合约

在以太坊虚拟机上运行的是合约的宇节码形式,需要在部署之前先对合约
进行编译,可以选择使用 Remix 或 so le 编译器 。

6. 以太坊账户

参考URL: http://c.biancheng.net/view/1935.html

以太坊的两种账户:外部账户和合约账户

以太坊有两种账户,如下图所示:

  • 外部账户(externally owned accounts),由密钥控制。
  • 合约账户(contract accounts),由智能合约的代码控制。

在这里插入图片描述以太坊的账户包括四个字段:一个随机数、账户的余额、合约代码(如果有的话)、存储(通常为空)。

与比特币的区块中存储的是交易不同,以太坊的区块中以梅克尔帕特里夏树(Merkle Patricia Tree,MPT)形式存储的是相应的以太坊账户的状态。

以太坊的交易是所谓的状态转换函数,一个交易触发它的执行,它将相应的账户从一个状态转变成新状态,然后新状态被存储在区块链的数据区块中。

只有合约账户才有代码,其中存储的是 codeHash(这个账户的以太坊虚拟机代码的哈希值)。这个字段在生成后是不可修改的,这意味着智能合约代码是不可修改的。

外部账户可以触发交易,而合约账户不能主动发起交易,只能在被触发后按预先编写的智能合约代码执行。不像外部账户,合约账户不可以自己发起一笔交易 。 但合约账户可以在响应交易时触发另 一笔交易 。 因此,在以太坊上任何动作都是由外部账户触发的交易所发起的(即动作的发起者必须是外部账户〉 。

合约账户可以设置多重签名(multisign),比如一个简单示例是:现有一个合约账户,它要求一个转账由发起转账的人(Alice)和另一个人(Charles)签名均可。因此,当 Alice 通过这个合约向 Bob 转账 20 个 ETH 时,合约会通知 Charles 签名,在他签名后,Bob 才可以收到这 20 个 ETH(见图)。

在这里插入图片描述

7. 以太坊钱包

Geth 是以太坊官方提供的客户端(钱包〉,是开发智能合约常用的工具之一,它基于 Go 语言开发 。

Geth 提供了 一个交互式命令控制台,在控制台中可以通过接口命令来获取

节点信息井和智能合约交互 。

另一类常用的钱包是 MetaMask,它是一个浏览器插件,可以和 Remix 配合使用,用来部署和执行智能合约 。 相比 Geth , MetaMask 不用同步节点数据,使用 非常方便 。

8. 存储、内存和栈

每个账户都有一块持久化存储区域,被称为存储( storage ) 。其以 key-value对的形式存储, key 和 value 的长度均为 256 位 。 在合约中不能遍历账户的存储 。

存储的读写操作开销(消耗 gas 的 量)较大,修改操作开销更大 。一个合约只能对它自己的存储进行读写 。

第一个存储区被称为内存( memory ) 。 合约在执行每次消息调用时,都有

一块崭新的 、 被清除过的内存 。 内存是线性的,可以以宇节为粒度寻址。但读取的长度被限制为 32 个字节( 256 位),写的长度可以是 l 个字节或 32 个字节 。

当访问(无论是读还是写)之前从未访问过的内存字( word )时(无论偏移到该字内的任何位置〉,内存将按字(每个字是 32 个字节〉进行扩展 。 扩容也将消耗一定的 gas 。 随着内存使用 量的增长,其费用也会增高(以平方级别增加) 。

第二个存储区被称为栈( stack) , EVM 不是基于寄存器,而是基于栈的虚

拟机,因此所有的计算都在一个被称为栈的区域执行 。 栈最大有 1024 个元素,每个元素 256 位 。 每次只能访问栈顶的元素。限制是通过以下方式进行的 : 允许复制最顶端的 16 个元素中的一个元素到栈顶,或者交换栈顶元素和下面 16个元素中的一个 。 所有其他操作都只能取最顶端的元素( 一个或两个或更多元素 ,取决于具体的操作),运算后把结果压入栈顶。当然也可以把栈上的元素放到存储或内存中 。 但是无法只访问栈上指定深度的那个元素,除非先从栈顶移除其他元素 。

9. 自毁

合约代码从区块链上移除的唯一方式是合约在合约地址上的执行自毁操作 selfdestruct ;合约账户上剩余的以太币会发送给指定的目标,然后其存储和代码从状态中被移除

三、 Solidity 合约内容

官网参考: https://docs.soliditylang.org/en/latest/

合约就像一个类(class),其中包含状态变量(state variable)、函数(function)、函数修改器(function modifier)、事件(event)、结构(structure)和枚举(enum)。合约还支持继承,通过在编译时备份代码来实现。最后,合约还支持多态。

四、 Solidity 数据类型

强烈推荐官网参考: https://docs.soliditylang.org/en/latest/types.html

Solidi可 是 一种静态类型语言,常见的静态类型语言有 C 、 C++、 Java 等,静态类型意味着在编译时需要为每个变量(本地或状态变量)都指定类型(或至少可以推导出类型)。

Solidity 的类型非常在意所占空间的大小 。另外, Solidity 的一些基本类型可以组合成复杂类型 。Solidity 类型分为两类 : 值类型( Value Type )和引用类型( Reference Type )。

值类型(Value Types)

官网参考: https://docs.soliditylang.org/en/latest/types.html

值类型是指当传递这些类型时,传递的是类型的取值。值类型所占空间在 32 个字节以内,值类型变量在赋值或传参时总是进行值拷贝。

值类型包括 :

• 布尔类型( Boolean )
• 整型 Clnteger )
• 定长浮点型( Fixed Point Number )
• 定长字节数组( Fixed-size Byte Array)
• 有理数和整型常量( Rational and Integer Literal )
• 字符串常量( String Literal )
• 十六进制常量( Hexadecimal Literal )
• 枚举 CEnum )
• 函数类型( Function Type )
• 地址类型( Addres)
• 地址常量( Address Literal )

引用类型 (Reference Types)

官网参考: https://docs.soliditylang.org/en/latest/types.html#reference-types

引用类型主要包括 : 数组(Array ) 、 结构体( Struct )和映射( Mapping ) 。

函数类型( Function Type)

Solidity 中的函数也可以 是一种类型且属于值类型 。 可以将一个函数赋值给一个函数类型的变量,也可以将一个函数作为参数进行传递,还可以在函数调用中返回 一个函数。下面是一个把函数赋值给变量的例子 。

函数类型有两类:内 部( internal) 函数和外部( external )函数。

  • 内部函数只能在当前合约内被调用(在当前代码块内,包括内部库函数和继承的函数),它不会创建一个 EVM 消息调用,访问方式是直接使用函数名 页) 。
  • 外部函数通过 EVM 消息调用,它由地址和 函数方法签名两部分组成,访问方式是 this.f() 。 外部函数可作为外部函数调用的参数或返回值 。

internal 和 external 既表示调用方式也表明了其可见性,很多人在编写传统程序的时候,不是很关注可见性 。 但写智能合约时大家要特别注意,如果应该使用 internal ,却使用了 external ,则很容易引发安全问题,同时也增加了 gas的消耗 。

selector 成员属性

公有或外部( public /external )函数类型有一个特殊的成员属性 selector,它对应一个 ABI 函数选择器,这里只要知道它是一个函数签名即可) 。

如何区分合约地址及外部账号地址

判断一个地址是否为合约地址或是外部账户地址

参考URL: https://blog.csdn.net/qq_27500493/article/details/100303722

判断一个地址是否为合约地址或是外部账户地址

extcodesize

获取地址关联代码长度。 合约地址长度大于0, 外部账户地址为0

//pragma solidity ^0.4.18;//extcodesize获取地址关联代码长度 合约地址大于0 外部账户地址为0 contract IsCadd {    function isContract(address addr) returns (bool) {    uint size;    assembly { size := extcodesize(addr) }    return size > 0;  }}

五、 Solidity 中的单位

智能合约语言 Solidity 教程系列7 - 以太单位及时间单位

参考URL: https://www.cnblogs.com/tinyxiong/p/8407233.html

Solidity 中有两种单位 : 货币单位和时间单位。

1. 货币单位(Ether Units)

一个数字常量(字面量)后面跟随一个后缀wei, finney,szabo或ether,这个后缀就是货币单位。不同的单位可以转换。不含任何后缀的默认单位是wei。

不同的以太币单位转换关系如下:
1 ether == 10^3 finney == 1000 finney
1 ether == 10^6 szabo
1 ether == 10^18 wei

以太币单位其实是密码学家的名字,是以太坊创始人为了纪念他们在数字货币的领域的贡献。他们分别是:

  • wei: Wei Dai 戴伟 密码学家 ,发表 B-money
  • finney: Hal Finney 芬尼 密码学家、工作量证明机制(POW)提出
  • szabo: Nick Szabo 尼克萨博 密码学家、智能合约的提出者

2. 时间单位(Time Units)

时间单位: seconds, minutes, hours, days, weeks, years均可做为后缀,并进行相互转换,规则如下:

1 == 1 seconds (默认是seconds为单位)

1 minutes == 60 seconds
1 hours == 60 minutes
1 days == 24 hours
1 weeks = 7 days
1 years = 365 days

使用这些单位进行日期计算需要特别小心,因为不是每年都是365天,且并不是每天都有24小时,因为还有闰秒。由于无法预测闰秒,必须由外部的预言(oracle)来更新从而得到一个精确的日历库。

六、Solidity 全局变量及函数

在用 solidity 编写智能合约的时候,有些特殊变量和函数永远存在于全局中,整体来说分为一下几类。

  1. 区块和交易属性
  • block.blockhash(unit blockNumber) returns (bytes32). 给定区块的哈希值,只支持最近的256个区块。
  • block.coinbase(address) 当前区块旷工的地址
  • block.difficulty(unit) 当前的区块的难度值
  • block.gaslimit(unit) 当前区块的 gas 上限
  • block.number(unit) 当前区块的序号(高度)
  • block.timestamp(unit) 当前区块的时间戳
  • msg.data(bytes) 完整的调用数据里存储的函数以及其实参
  • msg.gas(unit) 当前剩余的 gas
  • msg.sender(address) 当前调用发起人的地址
  • msg.sig(bytes4) 调用数据的前4个字节
  • msg.value(unit) 这个消息所附带的货币量,单位为 wei
  • now(unit) 当前区块的时间戳,等同于 block.timestamp
  • tx.gasprice(unit) 交易的gas价格
  • tx.origin(address) 交易的发起人(完整的调用链)
  1. 地址相关
  • .balance(unit256) 地址余额,单位为 wei
  • .send(unit256 amount) returns(bool) 发送指定数量的 wei 到地址,失败时返回 false. __不过这里发送是低级对等的转账。 如果执行失败,当前合约将不会以异常方式停止
  1. 合约相关
  • this: 当前合约,可以显式的转换成地址
  • selfdestruct(address recipient) 销毁当前合约,把其中的资金发送到指定的地址。

需要掌握如何获取区块和交易 的属性、如何通过 ABI 编码函数获取编码数据 、 如何处理错误函数 ,以及有关数学和加密 的功能、 与地址及合约相关的函数。

七、Solidity 表达式及控制结构

略。查看原文或官方文档。

八、合约

1. 合约概述

Solidity 中合约和面向对象语言中的类差不多。合约包含状态变量( 状态变

量的数据保存在链上的区块中〉及函数 。 调用另一个合约实例的函数时,会执
行一个 EVM 函数调用 , 这个操作会切换执行时的上下 文 ,这时上一个合约
的状态变量就无法访 问了 。

2. 可见性

WF曲速未来:Solidity安全之默认可见性

参考URL: https://zhuanlan.zhihu.com/p/41756712

Solidity 有两种函数调用方式(在第 7 章 函数调用表达式中介绍过〉, 一种是内部调用,不会创建 EVM 调用(也叫作消息调用〉,另 一种是外部调用,会创建 EVM 调用(即会发起消息调用) 。 Solidity 对函数和状态变量提供了四种可见性,分别是 external 、 public 、 internal 、 private 。 其中函数默认的可见性是 public 。状态变量默认的可见性是 internal 。

函数的可见性默认是 public。因此,不指定任何可见性的函数就可以由用户在外部调用。 当开发人员错误地忽略应该是私有的功能(或只能在合约本身内调用)的可见性说明符时,问题就出现了。

3. 事件

Eventeum - 在微服务中监听以太坊合约事件

参考URL: http://blog.hubwiz.com/2020/02/21/eventeum-tutorial/

事件是以太坊虚拟机 ( EVM )日志基础设施提供的一个便利接口 。在 DApp 的应用中,如果监听了某个事件, 那么当事件发生时则会进行回调 。

以太坊智能合约中,有一类特殊的回调函数,没有函数体,以大写字母开头,一般用来记录函数状态,这类回调函数称为事件event。事件event由合约函数调用。

九、合约编译、部署、交互、调试

1. 合约编译

合约的源代码被编译为 EVM 字节码和 ABI 接口说明后, 才能够使用 Web3

部署。部署合约其实是一个交易。这个交易没有目标地址, 交易的附加数据是
编译出来的 EVM 宇节码 。当处理该交易时, EVM 会将输入的数据作为代码执行 。这时一个合约就被创建了。

2. 部署合约

把 Remix IDE 生产 的代码拷贝到 geth 控制台,按下回车键运行就可以部署合约了。合约成功部署后会有提示,如下所示 。

这时在 geth 控制台,输入创建的合约实例 simplestorage ,可以看到

simplestorage 的详细信息,如下所示 。

调用合约函数

在部署合约之后,可以直接使用实例 simplestm吨e 去调用函数,如下所示 。

simplesto 俨age.s et(3)

simplesto 「ag e . get()

使用 Remix+ MetaMask

另外一个方法是使用 Remix + MetaMask 部署,我们来看看这个过程 。

MetaMask 是一款浏览器插件形式的以太坊轻客户端,我们可以在开发过程中使用 MetaMask 和 DApp 进行交互 。 在官网 https://metamask.io/ 下载安装MetaMask 。安装完成后,浏览器工具条会显示一个小狐狸图标 。

十、应用程序二遏制接口( ABI)

在 以太坊( Ethereum )生态系统中,应用程序二进制接口( Application BinaryInterface, ABI )是从区块链外部与合约进行交互,以及合约与合约之间进行交互的一种标准方式 。 简单来说就是以太坊调用合约时的接口说明,即定义操作函数签名、参数编码、返回结果编码等。 当合约被编译后,那么它的 ABI 也就确定了 。

程序二进制接口 ABI 是从区块链外部与合约进行交互的,是合约与合约之间进行交互的一种标准方式 。

十一、智能合约最佳实践

编码规范

  • 合约、库、事件、枚举及结构体命名
    合约、库、事件及结构体命名应该使用单词首字母大写的方式 。 这个方式也称为“帕斯卡命名 法”或“大驼峰式命名法”,比如 : SimpleToken 、SmartBank、CertificateHashRepository 、 Player
  • 函数、参数、变量及修饰器
    函数、参数、变量及修饰器应该使用首字母小写,后面宇母大写的方式 。即小驼峰式命名法。

代码格式

  • 缩进
    使用 空格( space ) 而不是 Tab, 缩进应该是 4 个空格 。
  • 空行
    合约之间应该有空行

函数编写规范

在编写函数的时候,应该让大家容易找到构造函数 、 回退函数 。 官方推荐的函数顺序如下 。

  1. 构造函数 。
  2. 回退函数 。
  3. 外部函数 。
  4. 公有函数 。
  5. 内部函数 。
  6. 私有函数 。

明确函数的可见性

所有的函数(包括构造函数)应该在定义的时候明确函数的可见性。

// 不建议event T「 ans fer、(){}function t 「 ansfe「(){}// 建议event L ogT 「 ans 于e「(){}于unction t 「ansfe 「() exte 「nal {}

常量

常量应该使用全大写字母及下画线分割大词 的方式,如 : MAX BLOCKS 、TOKEN NAME 、 CONTRACT VERSION 。

安全性考虑

智能合约最佳实践

https://github.com/ConsenSys/smart-contract-best-practices

区块链是一把双刃剑,弊端在于它的不可篡改性。 不像我们现有的互联网应用,可以轻松升级,现在的互联网思维要求我们不断试错,快速迭代 。

在区块链上开发智能合约需要一个全新的思维,因为犯错的代价很大( 比如造成财产的直接损失〉 。 不能轻松升级会给开发带来更大的挑战 。 因此我们需要有新的开发理念。

以下为 Consensys 总结的几点原则 :

要对错误有所准备。任何合约都可能存在错误,需要我们在代码中预先处
理 出现的 bug 和漏洞 。
在这里插入图片描述在这里插入图片描述

十二、智能合约最佳实践

代币

代币( Token )现在也有人称为“通证”,利用以太坊的智能合约可以轻松编写、发行一个属于自己的代币,代币可以代表任何可以交易的东西,例如:积分 、财产,等等 。 因此不论是出于商业目的,还是兴趣爱好,很多人都想创建一个属于自己的代币 。

ERC20 Token

ERC20 是以太坊定义 的一个代币 标准,要求我们在实现代币的 时候必须要遵守的协议,如指定代 币名称、总量、实现代币交易函数等,只有支持了协议才能被以太坊钱包支持。

众筹( ICO )合约

区块链技术本来就非常适合解决众筹的信任 问题 。 借助智能合约,可 以实现当募资额完成时, 募资款自动打到指定账户的功能 ; 当募资额未完成时,可退款 。 这个过程不 需要看众筹发起者的人品,不用依靠第三方平台的信用担保 。

传统的众筹在参与之后通常不容易交易 (参与之后无法转给其他人 ),而通过用代币来参与众筹,则很容易进行交易 。 众筹 的参与人可随时进行买卖 , 待众筹项目实施完成肘,可根据代币持有量进行回馈 。

举例说明,大家会更容易理解 。 例如有这样一个众筹: A 有技术做一个能监测健康的指环,为此向公众募资 200 万元 。 募资时 100 元对应一个代币 。 约定在指环上市之后,代币的持有人可以用 一个代币来兑换一个指环 。 而指环的研发周期是一年,因此在指环还未上市的一年里,众筹的参与人可以随时交易所持有的代币 。

十三、去中心化应用开发

DApp (Decentralized App ,去中心化应用),则是运行在去中心化的网络节点上的,应用端其实和现有互联网应用 一样,不过应用的后端不再是中心化的服务器,而是去中心化的网络中的节点 。这个节点可以是网络中任意的节点,应用端发给节点的请求,节点收到交易请求之后,会把请求广播到整个网络,交易在网络达成共识之后,才算是真正的执行(即处理请求的是整个网络,连接的节点不能独立处理请求)。

在去中心化应用中,发送给节点的请求通常称为“交易”。交易和普通的请求有很大的不同,即交易的数据经过用户个人签名(因此需要关联钱包)之后发送到节点,另外普通的请求大多数都是同步的(及时拿到结果), 而交易大多数都是异步的(因为网络共识比较耗时〉,还有交易不是使用普通 HTTP JSON请求,而是使用 JSONRPC 请求 。

如何与以太坊节点进行通信

以太坊使用 JSON RPC 2 . 0 规范来和节点进行通信。

首先要求我们在启动节点时,加入geth --rpc选项

geth 会默认使用 8545 进行监听JSON RPC 请求,如果要更改端口,使用–rpcport<portnumber>向节点发送 JSONRPC 请求。

Web3.js

虽然通过使用 JSON RPC 请求虽然可以完成和节点的通信,但是这个请求比较烦琐,因为需要和原始的底层数据交互,参数很多,返回的数据也需要自己解析,比较容易出错 。 Web3.js 是以太坊官方提供的和节点交互的的 JavaScript SDK,可以帮助智能合约开发者使用 HTTP 或者 IPC 与本地的或者远程的以太坊节点进行交互。 当然 Web3扣同样是使用 JSON RPC 和节点进行通信的( Web3是对 JSON RPC 请求的封装),不过 Web3.js 提供了更友好的接口,实际上 Web3.js就是一个库的集合,主要包括下面几个库:

  • web3-eth 用来与以太坊区块链和智能合约交互。
  • web3-shh 用来控制 whisper 协议与 p2p 通信,以及广播。
  • web3-bzz 用来与 swarm 协议交互。
  • web3-utils 包含 了 一些 DApp 开发应用的功能 。

在 geth 中使用 Web3.js

geth 启动的时候会自动加载 Web3.js 库,因此可以在geth 交互控制台里直接使用 Web3.js 。

使用示例 :

> eth.accounts> eth.getBalance (”accountAddr '’)

通常我们在开发的时候,可以在 geth 控制台中进行一些接口的测试及验证 。

学习总结其他参考资料

《精通以太坊智能合约开发》书籍

Solidity合约开发十大常见安全问题
參考URL: https://blog.csdn.net/shebao3333/article/details/107128878
WF曲速未来:Solidity安全之默认可见性
参考URL: https://zhuanlan.zhihu.com/p/41756712
Eventeum - 在微服务中监听以太坊合约事件
参考URL: http://blog.hubwiz.com/2020/02/21/eventeum-tutorial/
投稿
半小时掌握新版Remix-以太坊Ethereum智能合约Solidity编程
https://www.bilibili.com/video/BV17A411q7p4
[推荐]智能合约开发课02,以太坊开发知识图谱
参考URL: https://www.bilibili.com/video/BV1LJ411U7Tw

转载地址:https://docker.blog.csdn.net/article/details/109861816 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Injective Protocol官方文档翻译(一) -介绍、架构、Injective 链
下一篇:spring boot-整合RabbitMq(RabbitMq基础)

发表评论

最新留言

做的很好,不错不错
[***.243.131.199]2024年04月30日 06时50分10秒