以太坊研究系列【基本信息】
此文档为个人整理学习使用,部分内容来源于网络,也期待能给你带来益处。
帐户
20字节地址,160位标识符
- 外部拥有的帐户 Externally owned account
被私钥控制且没有任何代码与之关联
由一对公钥和私钥组成,公钥就是帐号地址。
创建私钥使用私钥来对交易进行签名,发送消息给另一个帐户(外部拥有帐户或合约帐户)。
- 合约帐户 Contract account
被合约代码控制且有代码与之关联
合约帐户不可以自己发起一个交易。被动接收交易消息后,响应交易处理。
也可以像外部帐户一样接收以太币,或者发放以太币,同时可以通过EVM执行智能合约里面的方法。
以太坊上任何的动作,总是被外部控制帐户触发的交易所发动的。
帐户状态
nonce:外部交易帐户,代表从此账户地址发送的交易序号;合约帐户,代表此帐户创建的合约序号。
balance:拥有Wei的数量。1Ether=10^18Wei
storageRoot:Merkle树的根节点Hash值。
codeHash:EVM代码的hash值。合约帐户就是Hash的代码并作为codeHash保存。
Merkle Tree
每个块都有一个头,保存了三个不同Merkle trie结构的根节点的Hash。
状态树 stateRoot
交易树 transactionsRoot
收据树 receiptsRoot
Merkle树中每项的hash值是向上传播的,恶意修改树底的交易hash变化会一直向上传播到root节点。
Radix树的改进:
- 每个节点通过他的hash被引用,而非内存地址;
- MPT树中的节点包括空节点、叶子节点、扩展节点为和分支节点。
节点
全节点
全节点下载整条链来同步,从创世纪块到当前块。
矿工通常需要使用全节点进行挖矿。轻节点
轻节点仅下载链的头,从创世纪块到当前块的头,不执行任何的交易或检索任何相关联的状态。
Ether币单位
Ether币最小的单位是Wei,然后每1000个进一个单位,依次是
kwei (1000 Wei)
mwei (1000 KWei)
gwei (1000 mwei)
szabo (1000 gwei)
finney (1000 szabo)
ether (1000 finney)
简单地说就是就是1 以太币 = 1000000000000000000 Wei
Gas和费用
以太坊网络上的交易而产生的每一次计算都会产生费用,用“gas”来支付。
1Ether表示10^18Wei. 1gwei是1,000,000,000 Wei。
对每个交易,发送者设置gas limit和gas price。gas limit和gas price就代表着发送者愿意为执行交易支付的Wei的最大值。
例如,假设发送者设置gas limit为50,000,gas price为20gwei。这就表示发送者愿意最多支付50,000*20gwei = 1,000,000,000,000,000 Wei = 0.001 Ether来执行此交易。
gas足够支付,交易结束未使用的gas将返回经发送者,以原始费率总换。
gas不够,交易会被终止,所有已改变的状态将会被恢复,但是gas会耗尽,并发送给“受益人”地址,通常是矿工的地址。
存储也有费用,存储的总费用与所使用的32位字节的最小倍数成比例。
费用的作用是防止执行占用太多资源,防止以太坊网络被蓄意攻击。
所以,以太坊智能合约最好是用来执行最简单的任务。
交易
两种类型的交易:消息通信和合约创建(也就是交易产生一个新的以太坊合约)。
不管什么类型的交易,都包含:
nonce:发送者发送交易数的计数
gasPrice:发送者愿意支付执行交易所需的每个gas的Wei数量
gasLimit:发送者愿意为执行交易支付gas数量的最大值。这个数量被设置之后在任何计算完成之前就会被提前扣掉
to:接收者的地址。在合约创建交易中,合约账户的地址还没有存在,所以值先空着
value:从发送者转移到接收者的Wei数量。在合约创建交易中,value作为新建合约账户的开始余额
v,r,s:用于产生标识交易发生着的签名
init(只有在合约创建交易中存在):用来初始化新合约账户的EVM代码片段。init值会执行一次,然后就会被丢弃。当init第一次执行的时候,它返回一个账户代码体,也就是永久与合约账户关联的一段代码。
data(可选域,只有在消息通信中存在):消息通话中的输入数据(也就是参数)。例如,如果智能合约就是一个域名注册服务,那么调用合约可能就会期待输入域例如域名和IP地址
交易是外部世界和以太坊内部状态的桥梁
帐户和帐户之间的交易,都是通过Transaction来执行的,智能合约的调用也是一个transaction,只不过是智能合约的地址,同时带上一个RawData。
消息或内部交易
以太坊的消息在某种程度上类似于比特币的交易,但是两者之间存在三点重要的不同。第一,以太坊的消息可以由外部实体或者合约创建,然而比特币的交易只能从外部创建。第二,以太坊消息可以选择包含数据。第三,如果以太坊消息的接受者是合约账户,可以选择进行回应,这意味着以太坊消息也包含函数概念。
在以太坊状态全局范围内的合约可以与在相同范围内的合约进行通信。
与交易有着最大的不同点—它们不是由外部拥有账户产生的。相反,他们是被合约产生的。
当一个合约发送一个内部交易给另一个合约,存在于接收者合约账户相关联的代码就会被执行。
一个重要需要注意的事情是内部交易或者消息不包含gasLimit。因为gas limit是由原始交易的外部创建者决定的(也就是外部拥有账户)。外部拥有账户设置的gas limit必须要高到足够将交易完成,包括由于此交易而长生的任何”子执行”,例如合约到合约的消息。如果,在一个交易或者信息链中,其中一个消息执行使gas已不足,那么这个消息的执行会被还原,包括任何被此执行触发的子消息。不过,父执行没必要被还原。
区块(Blocks)
所有的交易都被组到一个“区块”中,一系列的区块链在一起形成区块链。
任何帐户之间的变动,都必须被新挖出的区块计入他们的帐本,且被多个区块所认可,那么交易才算真正生效。
区块头
区块头是一个区块的一部分,包含了:
parentHash:父区块头的Hash值(这也是使得区块变成区块链的原因)
ommerHash:当前区块ommers列表的Hash值
beneficiary:接收挖此区块费用的账户地址
stateRoot:状态树根节点的Hash值
transactionsRoot:包含此区块所列的所有交易的树的根节点Hash值
receiptsRoot:包含此区块所列的所有交易收据的树的根节点Hash值
logsBloom:由日志信息组成的一个Bloom过滤器 (数据结构)
difficulty: 此区块的难度级别
number:当前区块的计数(创世纪块的区块序号为0,对于每个后续区块,区块序号都增加1)
gasLimit:每个区块的当前gas limit
gasUsed: 此区块中交易所用的总gas量
timestamp:此区块成立时的unix的时间戳
extraData:与此区块相关的附加数据
mixHash:一个Hash值,当与nonce组合时,证明此区块已经执行了足够的计算
nonce:一个Hash值,当与mixHash组合时,证明此区块已经执行了足够的计算
ommer 叔区块,以太坊每个区块生产时间大概15秒,交易处理更快,导致更多的竞争区块会被矿工发现(又被称为孤区块,被挖出来但是不会被添加到主链上的区块)。
Ommers的目的就是为了帮助奖励矿工纳入这些孤区块。矿工包含的ommers必须是有效的,也就是ommers必须在父区块的第6个子区块之内或更小范围内。在第6个子区块之后,陈旧的孤区块将不会再被引用(因为包含老旧的交易会使事情变得复杂一点)。
Ommer区块会收到比全区块少一点的奖励。
日志
以太坊允许日志可以跟踪各种交易和信息。一个合约可以通过定义“事件”来显示的生成日志。
一个日志的实体包含:
记录器的账户地址
代表本次交易执行的各种事件的一系列主题以及与这些事件相关的任何数据
日志被保存在bloom过滤器中,过滤器高效的保存了无尽的日志数据。
交易收据
以太坊为每笔交易都产生一个收据,每个收据包含关于交易的特定信息。
包括区块序号、区块Hash、交易Hash、当前交易使用了的gas、在当前交易执行完之后当前块使用的累计gas、执行当前交易时创建的日志
区块难度
区块的难度是被用来在验证区块时加强一致性。如果某个区块比前一个区块验证的更快,以太坊协议就会增加区块的难度。另一方面,如果验证时间变的越来越慢,协议就会降低难度。这样的话,验证时间自我调节以保持恒定的速率—平均每15s一个块。
区块的难度影响nonce,它是在挖矿时必须要使用proof-of-work算法来计算的一个hash值。
交易执行
- 所有交易必须符合最基础的一系列要求,包括:
交易必须是正确化的RLP;(RLP见消息协议)
有效的交易签名;
有效的交易序号,交易序号一定等于发送帐户中的nonce;
交易的gas limit一定要等于或者大于交易使用的intrinsic gas。
intrinsic gas包括:
1.执行交易预订费用为21,000gas
2.随交易发送的数据的gas费用(每字节数据或代码为0的费用为4gas,每个非零字节的数据或代码费用为68gas)
3.如果交易是合约创建交易,还需要额外的32,000gas
发送账户余额必须有足够的Ether来支付”前期”gas费用。前期gas费用的计算比较简单:首先,交易的gas limit乘以交易的gas价格得到最大的gas费用。然后,这个最大gas费用被加到从发送方传送给接收方的总值。
- 交易符合上面所有要求,进行下面步骤:
第一步,我们从发送者的余额中扣除执行的前期费用,并为当前交易将发送者账户中的nonce增加1。此时,我们可以计算剩余的gas,将交易的总gas减去使用的intrinsic gas。
第二步,开始执行交易。在交易执行的整个过程中,以太坊保持跟踪“子状态”。子状态是记录在交易中生成的信息的一种方式,当交易完成时会立即需要这些信息。具体来说,它包含:
自毁集:在交易完成之后会被丢弃的账户集(如果存在的话)
日志系列:虚拟机的代码执行的归档和可检索的检查点
退款余额:交易完成之后需要退还给发送账户的总额。回忆一下我们之前提到的以太坊中的存储需要付费,发送者要是清理了内存就会有退款。以太坊使用退款计数进行跟踪退款余额。退款计数从0开始并且每当合约删除了一些存储中的东西都会进行增加。
第三步,交易所需的各种计算开始被处理。
当交易所需的步骤全部处理完成,并假设没有无效状态,通过确定退还给发送者的未使用的gas量,最终的状态也被确定。除了未使用的gas,发送者还会得到上面所说的“退款余额”中退还的一些津贴。
- 合约创建(Contract creation)
使用下面的方法来初始化一个账户:
设置nonce为0
如果发送者通过交易发送了一定量的Ether作为value,那么设置账户的余额为value
将存储设置为0
设置合约的codeHash为一个空字符串的Hash值
一旦我们完成了账户的初始化,使用交易发送过来的init code,实际上就创造了一个账户。init code的执行过程是各种各样的。取决于合约的构造器,可能是更新账户的存储,也可能是创建另一个合约账户,或者发起另一个消息通信等等。
交易不允许使用的gas超过剩余gas,但是发送者随交易发送的Ether即使合约创建失败也会被退回来。
如果所有的都正常进行没有任何异常出现,那么任何剩余的未使用gas都会被退回给原始的交易发送者,现在改变的状态才被允许永久保存。
- 消息通信(Message calls)
消息通信的执行与合约创建比较类似,只不过有一点点区别。
由于没有新账户被创建,所以消息通信的执行不包含任何的init code。不过,它可以包含输入数据,如果交易发送者提供了此数据的话。一旦执行,消息通信同样会有一个额外的组件来包含输出数据,如果后续执行需要此数据的话就组件就会被使用。
执行模式
协议实际操作交易处理的部分是以太坊自己的虚拟机,称之为以太坊虚拟机(EVM)。
EVM昌图灵完备虚拟机器,唯一限制是被gas束缚,可以完成的计算总量本质上是被提供的gas总量限制的。
EVM具有基于堆栈的架构,每个堆栈项的大小为256位,堆栈有一个最大的大小,为1024位。
EVM有内存,项目按照可寻址字节数组来存储。
EVM也有一个存储器,并作为系统状态的一部分进行维护。一个秘钥/数值的存储,其中秘钥和数值都是32字节大小,与计算结束即重置的堆栈和内存不同,存储内容将长期保持。
EVM同样有属于它自己的语言:“EVM字节码”,智能合约通常都是用高级语言例如Solidity来编写代码,编译成EVM可以理解的EVM字节码。
代码可以象访问区块头数据一样访问数值,发送者和接受到的消息中的数据,代码还可以返回数据的字节队列作为输出。
完成一个区块
一个块的“完成”都有4个要求:
1)验证(或者,如果是挖矿的话,就是确定)ommers
在区块头中的每个ommer都必须是有效的头并且必须在当前块的6代之内
2)验证(或者,如果是挖矿的话,就是确定)交易
区块中的gasUsed数量必须与区块中所列交易使用的累积gas量相等。(回忆一下,当执行一个交易的时候,我们会跟踪区块的gas计数器,也就跟踪了区块中所有交易使用的gas总数量)
3)申请奖励(只有挖矿时)
受益人的地址会因为挖矿而获得5Ether(在以太坊EIP-649 提案中,5ETH很快将会被减少为3ETH)。另外,对于每个ommer,当前块的受益人会获得额外的1/32当前块奖励金的奖励。最近,每个ommer区块的受益人能够得到一定量的奖励(有个特殊公式可以进行计算)。
4)校验(或者,如果是挖矿的话,就是计算一个有效的)状态和nonce
确保所有的交易和改变的结果状态都被应用了,然后在区块奖励被应用于最终交易结果状态之后定义一个新块为状态。通过检查最终状态与存储在头中的状态树来进行验证。
挖矿
- 挖矿作为安全机制
Pow算法确保特定的区块链直到未来都一直保持着权威性,让攻击者创造一个新区块来重写某个历史部分(例如清除一个交易或者创建一个假的交易)或者保持一个分叉变得非常困难。
除非攻击者拥有超过一半的网络挖矿能力(这种场景也被称为大多数51%攻击 ),要不然这基本上是不可能的。
比特币集中到几个大矿场,算力已经有这方面的风险。
- 挖矿作为财富分配机制
PoW算法是一个SHA256哈希函数。这种函数的缺点就是它使用特殊的硬件(也被称之为ASCIs)可以更加快速高效的解决nonce问题。
以太坊选择让PoW算法(Ethhash) 提高内存级别难度。意思是此算法被设计为计算出要求的nonce需要大量的内存和带宽。这种方式降低了中心化的风险,并为正在进行验证的几点提供了更加公平的竞争环境。
ERC-20
ERC-20标准是在2015年11月份推出的,使用这种规则的代币,表现出一种通用的和可预测的方式。
简单地说,任何 ERC-20 代币都能立即兼容以太坊钱包(几乎所有支持以太币的钱包,包括Jaxx、MEW、imToken等,也支持 erc-20的代币),由于交易所已经知道这些代币是如何操作的,它们可以很容易地整合这些代币。这就意味着,在很多情况下,这些代币都是可以立即进行交易的。
https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
ERC223
ERC223令牌标准将向现有的ERC20标准引入一个新功能,以防止意外转移的发生。ERC223令牌标准可以防止令牌在以太坊网络上丢失。
钱包
钱包可以让你和整个数字加密货币世界进行交易。利用钱包中生成的地址你可以接收来自他人的数字加密货币,你也可以将你帐户上的数字加密货币转到他人的账户上。
MyEtherWallet
https://www.myetherwallet.com/
parity
https://github.com/paritytech/parity
mist
https://github.com/ethereum/mist
imToken
https://token.im/
助记词
它最早是由 BIP39提案产生的 , 可以是12个, 15个, 18个, 21个, 24个特定的单词。这些单词有一个统一的、固定的词库, 并不是凭空而来。可以将助记词理解为明文私钥, 即拥有助记词, 就相当于掌握了该钱包的使用权, 无需密码。助记词的好处是方便用户记忆和记录, 所以用户要妥善保管好自己的助记词。
钱包数量
如果所有币放在一个钱包里,风险会比较大,可以考虑建立多个钱包,一个用来花费,一个用来屯币,一个用来接收付款等等。
其它
合约地址
以太坊合约地址都是字符串代码或者用.eth的域名
所有符合ERC20标准的合约
https://etherscan.io/tokens
看币和交易所
http://www.feixiaohao.com
https://coinmarketcap.com
参考:
详解以太坊的工作原理
http://baijiahao.baidu.com/s?id=1581231980661527205&wfr=spider&for=pc
以太坊白皮书
http://ethfans.org/posts/ethereum-whitepaper
以太坊黄皮书
http://gavwood.com/paper.pdf
***************************************
作者简介
老鱼,从事互联网技术十余年,知名上市公司CTO;炒股十余年,从亏损几十万到略有盈利;顺应创业大潮多次创业,在传统行业和手游行业有所获;研习佛学易理,性格淡泊清净!
欢迎有兴趣的朋友加入微信群和电报群,一起学习探讨,一起实现咱们的小目标!
- 百分百区块链群,微信扫码后会再显示一个二维码,长按图片“识别图中二维码”加入!
- 电报群 https://t.me/blockchain100 希望以后能给先加入的人送一份大礼!
@chaimyu, 佩服!佩服!
刚过来steemit,转一些自己原来整理的内容过来!