# 2022/05/31 区块链基础
> - 区块链基础
> - 以太坊虚拟机
---
### 区块链基础
> - 交易
> - 块
---
#### 交易
区块链是一个全球共享的交易数据库
**特点:**
- 每个人都可以通过参与网络来读取数据库中的条目
- 要更改数据库中的某些内容,则必须创建一个必须被所有其他人接受的所谓事务
- 事务要么根本没完成,要么完全应用
- 事务被应用到数据库时,没有其他事务可以更改它
#### 块
交易捆绑在的地方称之为"块"
**原因:**
如果网络中存在两个交易都想清空账户,这时候只有一个交易是有效的,通常是最先被接受的交易,问题在于:**点对点的网络当中"第一"不是一个客观的术语
**解决:**
- 交易将被捆绑到所谓的“块”中,然后它们将在所有参与节点之间执行和分发.如果两笔交易相互矛盾,则最终成为第二笔的交易将被拒绝,并且不会成为区块的一部分.
**块在时间上形成一个线性序列,这就是“区块链”这个词的来源**
**可能存在的问题:**
1. 区块以相当固定的间隔添加到链中
2. 会不时恢复块,但仅在链的“末端”.在特定块之上添加的块越多,该块被还原的可能性就越小
3. 交易不能保证包含在下一个区块或任何特定的未来区块中,它不取决于交易的提交者,而是取决于矿工来确定交易包含在哪个区块中
### 以太坊虚拟机
> - 概念
> - 账户
> - 交易
> - gas费用
> - 存储、内存、堆栈
> - 指令系统
> - 回调函数
> - 委托调用
> - 日志
> - 创建
> - 停用/自毁
---
#### 概念
**定义:**
以太坊中智能合约的运行时环境
**特点:**
1. 完全隔离 -> `EVM`内运行的代码无法访问网络、文件系统或其他进程
2. 智能合约对其他智能合约的访问权限有限
#### 账户
**账户分类:**
1. 外部账户 -> 由公钥确定
2. 合约账户 -> 合约创建时确定
**两种账户的特点:**
1. 每个账户都有一个持久的`key-value`存储,将256位字映射到256位字,称为`storage`
2. 无论账户是否存储代码,`EVM`都平等对待这两种类型
3. 每个账户都有一个`Ether`余额(准确地说是“Wei” -> 18位精度),可以通过发送包含`Ether`的交易进行修改.`1 ether = 10**18 wei`
**这两种账户共享相同的地址空间**
#### 交易
从一个账户发送到另一个账户的消息 -> 可以包括二进制数据和以太币
**特点:**
- 目标帐户包含代码,则执行该代码并将有效负载作为输入数据提供
- 如果没有设置目标账户(交易没有收款人或收款人设置为null),则交易创建一个新合约
#### gas
交易发起者支付的费用
#### 存储、内存、堆栈
- `storage`数据区域 -> 函数调用和事务之间是持久的,合约既不能读取也不能写入除了自己的存储之外的任何存储
- 内存 -> 读的长度限制为256位,写的长度为8~256位,访问之前未访问过的内存字时会消耗`gas`
- `EVM` -> 基于栈而非寄存器. 栈的特点:
- 栈最大有1024个元素,每个元素长度为一个字(256位)
- 对栈的访问限于栈顶
- 无法访问栈上指定深度的那个元素,只有先从栈顶移除让预期元素到达栈顶时候才可以访问
#### 指令集
**特点:**
- `EVM`指令集应少
- 所有指令针对于"256位的字"(基本数据类型)进行操作
#### 消息调用
**合约可以通过消息调用的方式来调用其它合约或者发送以太币到非合约账户**
**消息调用和交易的共同特点:**
1. 都包括了: `Core、target、data、coin、gas、returnData`六个要素
2. `Solidity`中,发起调用的合约默认触发一个手工异常,当内部消息调用发生了异常会将该手工异常从调用栈里冒泡出来
3. 被调用的合约会获得一块刚清空过的内存,可以访问调用的`payload`(`payload`是由被称为`calldatat`的独立区域提供的数据),调用执行结束后,返回的数据存放在**调用方预先分配好的一块内存中**,调用深度被限制为`1024`
#### 日志
特殊的可索引的数据结构,`Solidity`用它来实现事件(`events`)