学区块链做的笔记Day1,大部分内容来自《精通以太坊》。

区块链的组件

一个公开的公共区块链通常包含以下组件:

  • 一个连接参与各方的点对点网络,用于传播交易和区块数据包,基于标准的“gossip”协议。
  • 以交易形式体现的消息,代表状态的转换。
  • 一组共识规则,用于管理构成交易的内容以及实现有效的状态转换。
  • 一个状态机,根据共识规则交易。
  • 一组串联在一起的、由加密算法保证其安全的区块,这些区块是所有已验证和已接受的状态转换的记录日志
  • 一个共识算法,用于在区块链上实现控制的去中心化,这类算法通过强制参与者之间的合作以实现共识规则的有效执行。
  • 在博弈论上合理的激励方案(列如:工作量证明、区块奖励),以在开放环境中经济地保护状态机。
  • 上述一个或多个开源软件实现(客户端)

以太坊的组件

  • 点对点(P2P)网络

    以太坊运行在Ethereum Main Network上,这是一个通过TCP 30303端口寻址的网络,网络层运行的协议名为-DΞVp2p。

  • 共识规则

    以太坊的共识规则,由以太坊黄皮书(见后文中的“扩展阅读”)中的参考标准进行精确定义

  • 交易

    以太坊交易是一个网络消息,主要包含交易的发送方、接收方、价值和数据载荷。

  • 状态机

    以太坊的状态转换由以太坊虚拟机(EVM)处理,这是一个基于栈的虚拟机,执行bytecode(字节码指令)。被称为“智能合约”的EVM程序采用高级语言(例如Solidity)编写,并编译为通过EVM执行的字节码。

  • 数据结构

    以太坊的区块链以数据库(通常采用Google的LevelDB)的方式保存在每一个节点之上,区块链内包含了交易和系统的状态,经过哈希处理的数据保存在Merkle Patricia Tree数据结构之内。

  • 共识算法

    以太坊使用比特币的共识模型 Nakamoto Consensus,它使用顺序单一签名块,由PoW加权重要性来确定最长链,从而确定当前状态。但是,有计划在不久的将来转向代号为Casper的PoS加权投票系统。

  • 经济安全性

    以太坊当前使用名为Ethash的工作量证明算法,这个算法迟早将被放弃,并切换到PoS。

  • 客户端

    以太坊有多个可以交互的客户端软件实现,其中最广泛使用的是Go-Ethereum(Geth)和Parity。

一个简单的智能合约:Faucet

书上用的是Ropsten测试网络,但是这条网络已经被关停了

image-20231206005050471

然后比较出名的几个测试网络已经被薅的不成样子了

image-20231206005300957

所以这里选择用Ganache自己搭一个测试网络进行测试

搭建Ganache的教程网上有很多,这里不细讲

合约代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 编译时的版本要对上
pragma solidity 0.6.4;

contract Faucet {
// 用于接收以太币
receive() external payable {}

function withdraw(uint withdraw_amount) public {
// 限制提款金额
require(withdraw_amount <= 100000000000000000);

// 发送到地址
msg.sender.transfer(withdraw_amount);
}
}

这里的 _receive() external payable {}_ 在书中为 _function() public payable {}_ 描述为:

这个函数被称为回退函数或默认函数,它会在一些特殊情况下被调用,比如触发这个合约的交易没有指定调用哪一个具体函数,或者合约本身没有定义任何函数,再或者交易没有包含任何数据。合约可以有一个这样的默认函数(没有名字),通常也使用这个函数来接收以太币。这也是为什么这个函数的定义包含public和payable属性,这意味着这个合约可以接收以太币。如函数声明的空花括号所显示的,除了接收以太币,这个合约什么也不会做。如果我们发起一个针对合约地址的交易,就像是把合约地址当作钱包使用,这个函数就会处理。

receive()函数:

  1. 一个合约至多含有一个receive()函数
  2. 没有function关键字
  3. 必须含有payable关键字
  4. 没有参数,没有返回值
  5. 可见性必须声明为external
  6. 允许使用modifier修改器
  7. 该函数通过.send()和.transfer()转发以太币
  8. 若想要让你的contract(即合约账户)接收以太币,在未定义fallback() external payable{}函数时,需实现receive()函数
  9. 在gasLimit允许范围内可执行复杂操作

还有一个专门的回退函数

fallback()函数:

  1. 一个合约至多含有一个fallback()函数
  2. 没有function关键字
  3. payable关键字是可选项,取决于该函数是否需要接收以太币
  4. 该函数可代替receive()函数以实现合约接受转发以太币的功能
  5. 可见性必须声明为external
  6. 允许使用modifier修改器
  7. 在gasLimit允许范围内可执行复杂操作

具体使用先不管,大概可以看成合约用于存放以太币的地方,可以对合约内的以太币进行转账等操作。

编译部署合约

image-20231206013025151

在这可以看到编译好的程序的详细信息

部署上程序后因为使用的是本地的Ganache作为测试网络

所以要查看已经部署上的合约可以上Ganache客户端进行查看

image-20231206013438736

向合约充值

image-20231206013640079

直接向合约地址转账

可以看到合约内的钱增加了

image-20231206013748675

从合约提币

这里试了半天,一直出错

image-20231206022030253

搞了半天才发现是这里的限制

image-20231206022102460

100000000000000000wei 才 0.1eth

这里改成小于这个数就可以提款成功了

1e18wei = 1eth

顺便一提,如果数太大导致没有转账,但是交易还是进行了,也就是说手续费会照样扣,所以如果不是自己搭建的测试网络,在交易前还是先确认好交易信息比较好(