一、外部账户EOA
外部账户(用户账户/普通账户)
有对应的以太币余额
可发送交易(转币或触发合约)
由用户私钥控制
没有关联代码
二、合约账户
内部账户
对应的以太币约
由关联代码
由代码控制
可通过交易或来自其他合约的调用进行代码执行
执行代码可以操作自己的存储空间,也可以调用其他合约
![](/qrcode.jpg)
三、以太坊交易
签名的数据包,由EOA发送到另一个账户
消息的接收方地址
发送方签名
金额
数据
START GAS
GAS PRICE
消息
合约可以向其他合约发送消息,消息只存在于EVM中
可以看作函数调用
消息发送方
消息接收方
金额
数据
START GAS
合约
可以读写自己的内部存储
可想其他合约发送消息,依次触发执行
一旦合约运行结束,并且由它发送的消息触发的所有子执行结束,EVM就会中止运行,直到下次交易被唤醒
合约应用一
维护一个数据存储,存储对其他合约或外部世界有用的内容
最典型的例子是模拟货币的合约
合约应用二
通过合约实现一种具有更复杂访问策略的EOA,一个人可以拥有一份转发合约,该合约会等待直到给定三个私钥中的两个确认后,再重新发送特定信息
钱包合约是这类应用中很好的例子
合约应用三
管理多个用户之间的持续合同或关系
这方面的例子包括金融合同,以及某些特定的托管合同或某种保险
交易本质
交易是由外部拥有的账户发起的签名消息,由以太坊网络传输,并被序列化后记录再以太坊区块链上。
交易时唯一可以触发状态更改或导致合约再EVM中执行的事物
以太坊时一个全局单例状态机,交易时唯一可以改变其状态的东西
合约不是自己运行的,以太坊也不会“在后台”运行。以太坊上的一切变化都始于交易。
交易数据结构
nonce:由发起人EOA发出的序列号,用于防止交易消息重播
不会明确存储为区块链中账户状态的一部分。相反,它时通过计算发送地址的已确认交易的数量来动态计算的。
防止错误计算账户约,强制来自任何地址的交易按顺序处理,没有间隔,无论节点接收它们的顺序如何
确保所有节点计算相同的余额和正确的序列交易,防止“双花”。
并发和nonce:
以太坊允许操作(节点,客户端,DApps)并发的系统,但强制执行单例状态。
如何设置nonce?
队列的方案,依然会产生中心化,能否采用分布式id的生成方式
gas price:交易发起人愿意支付的gas单价
start gas:交易发起人愿意支付的最大gas量
to:目的以太坊地址
value:要发送得到目的地的以太数量
data:可变长度二进制数据负载
v,r,s: 发起人EOA的ECDSA签名的三个组成部分
交易消息的结构使用递归长度前缀编码方案进行序列化,该方案专为在以太坊中准备却和字节完美的数据序列化而创建
交易Gas
gas是交易发起人需要为EVM上每项操作支付的成本名称。我们要从执行代码的矿工那里用以太币购买gas。
gas对应算力自然成本,以太币是虚拟产生的。gas价格需要和以太币确认,调整方式由矿工和卖币方确定的。
gas的计算
发起交易时的gas limit并不是要支付的gas数量,而只是给定了一个消耗gas的上限,相当于“押金”
实际支付的gas数量时执行过程中消耗的gas,gas limit中剩余的部分会返回给发送人
最终支付的gas费用时gasUsed对应的以太币费用,单价由设定的gasPrice而定
最终支付费用totalCost = gasPrice*gasUsed
totalCost会作为交易手续费支付给矿工
估算交易gas
使用geth中eth.estimateGas方法,手续费和value没太大关系。与交易体大小有关
eth.estimateGas({from:""0xfsafdfsadf.......fsdaff,to:"0xfasf....dfafasa",value:10000})
交易的接收者(to)
交易接收者在to字段中指定,是一个20字节的以太坊地址。地址可以是EOA或合约地址。
以太坊没有进一步的验证,任何20字节的值都被认为是有效的。如果20字节值对应于没有相应私钥的地址,或不存在的合约,则该交易仍然有效。以太坊无法直到地址是否是从公钥正确派生的
如果将交易发送到无效地址,将销毁发送的以太,使其永远无法访问。
验证接收人地址是否有效的工作,应该在用户界面一层完成。
交易的value和data
交易的主要“有效负载”包含在两个字段中:value和data。交易可以同时由value和data
value的交易是以太的付款
data交易一般是合约的调用
合约调用的同时,我们除了data之外还可以发送以太,从而交易中同时包含data和value
没有value也没有data的交易,只是在浪费gas,但它是有效的
向EOA或合约传递data
当交易包含数据有效负载时,它很可能是发送到合约地址的,但它同样可以发送给EOA
如果发送data给EOA,数据负载的解释取决于钱包
如果发送数据负载给合约地址,EVM会解释为函数调用,从payload里解码出函数名称和参数,调用该函数并传入参数
发送给合约的数据有效负载时32字节的十六进制序列化编码
函数选择器:函数原型的Keccak256哈希的前4个字节。这允许EVM明确地识别将要调用的函数
特殊交易:创建(部署)合约
有一种特殊的交易,具有数据负载且没有value,那就是一个创建新合约的交易
合约创建交易被发送到特殊目的地地址。该地址既不代表EOA也不代表合约。它永远不会花费以太或发起交易,它仅用坐目的地,具有特殊含义“创建合约”。
虽然零地址仅用于合约注册,但它有时会收到来自各种地址的付款。这种情况要么是偶然误操作,导致失去以太;要么是故意销毁以太。
合约注册交易不应包含以太值,只包含合约的已编译字节码的数据有效负载。此交易的唯一效果是注册合约。