3 交易的生命周期
交易在其生命周期中经历以下阶段:
1、在应用程序或类似cleos的EOSIO客户端中创建交易
2、交易被发送到本地连接的节点,该节点再将其转发给活动的生产这,通过p2p网络进行验证和执行
3、活动生产者将验证后的交易与其他交易一起按预定时间放到一个块中
4、包含脚印的块被广播到所有其他节点进行验证
当绝大多数生产者已经验证了块,块就会变得不可逆,交易将被永久地记录在区块链中,并且它被认为是不可变的。
3.1 创建交易
交易被app创建,初始化交易对象,使用相关的操作实例列表。操作实例包括操作名字、接收者账号、发送者账号和权限等信息。一个操作实例的字段如下:
https://developers.eos.io/welcome/latest/protocol/transactions_protocol/#action-schema
注意这里的创建类似与编程中对一个对象new,还达不到一个具备完整信息的交易。所以,创建好之后,接下来就是对交易进行完善信息,即对交易进行签名,然后将交易发送出去,待生产者验证和执行。
3.2 签名交易
交易必须由操作者进行签名才能被验证通过。具体来说,要求对交易的操作者actor和对应的权限进行校验,是否是操作者对应的私钥进行签名(eosio是如何校验密钥对和账号是对应关系?个人理解,eosio能用的信息都是存储在区块链中的,因此,创建账号的那条交易包含账户名和公钥,且已经变成了不可逆状态,eosio直接去区块链中查询就行了),actor是否有权限等。实际的签名密钥是通过运行应用程序的客户机上查询与签名帐户关联的钱包获得的。
签名过程依赖三个参数:交易实例,链id(chain ID),公钥(利用公钥可以通过钱包api在钱包应用中获取私钥,其实签名需要私钥)。链id标识实际的eosio链,由创世状态的hash值组成。签名之前,需要计算交易的hash值。hash值是链id、交易实例和上下文无关的操作数据的sha-256值。任何实例字段在计算hash之前都会被序列化,以避免在计算中包含引用字段。hash计算和sign过程如下图:

可以看出,签名是由wallet manager执行的。钱包管理器提供了一个虚拟的安全飞地(?enclave)来执行数字签名,因此在生成消息签名时不会有私钥离开钱包。
3.3 推送交易
签名之后,先生成签名交易实例,然后生成打包交易实例。
这里的推送(push)是指将打包交易实例推动到本地节点(nodeos),本地节点再将交易广播到其他活跃的生产者节点。生产者节点收到交易后,会执行签名校验,执行和验证。
每一个收到的交易的BP在将交易广播给其他BP之前,会先在本地尝试执行和校验交易。只有有效的交易才会被广播出去。这在一定程度上防止了恶意操作者产生的假交易在整个网络中泛滥。
不管当前节点是否是正处于出块状态,节点都会校验交易的。唯一区别是出块的BP会尝试将交易放到块中,然后将块提交到本地链且广播出去。
3.4 验证交易
首先,通过交易中的签名信息可以恢复出相关的公钥。eos使用的是ecdsa(elliptic curve digital signature algorithm椭圆曲线数字签名算法),这为从签名恢复公钥提供了可能性。细节见扩展部分。
其次,检查上一步恢复出的公钥是否满足条件。(是否是对应账号的公钥?)
第三,根据相关的actor:contract::action对权限进行检查,是否满足阈值。
在操作(action)被执行之前,会在操作(action)级别进行最后一步检查。
3.4.1 交易上下文
公钥被恢复之后,通过交易实例就会产生交易上下文。上下文记录所有的操作和操作被执行后产生的操作收据(action receipt)。
操作收据是在交易执行和确认(即前面说的块生产过程中的确认阶段)之后产生的。
3.4.2 权限检查
由于交易中多个操作必须被作为一个整体,符合原子性,即要么都成功,要么都失败,从性能角度出发,需要提前对操作中的actor和权限进行检查。在一定程度上,避免需要对已执行的操作进行撤回。数据库会话在操作内存和资源时是非常昂贵的。检查主要包括两部分:
● 在每个操作实例中指定的每个actor的权限
● 合约中指定的和actor:contract::action相对应的权限
3.4.3 操作实例
操作实例由接收者账号,操作名,actor及对应权限的列表,操作包含的data。可以通过eospark,点开任意一个交易中的操作就能容易理解。
3.4.4 权限检查
在检查了最低权限级别之后,将检查与操作实例中每个actor的权限相匹配的接收帐户的权限表。(不理解?)
3.5 执行交易
交易是具有原子性的。为了执行交易,链数据库会被启动,当前快照会被捕获。
如果执行过程中发生任何错误,可以做数据回滚。交易中的每一个操作会被会被调度去执行。如果存在无上下文的操作(context free actions),会先于普通操作被执行。
3.5.1 应用上下文
执行操作之前,会先为每个操作创建一个应用上下文(apply context)。顾名思义,每个应用上下文包括“应用操作”的必要信息:链控制器、链数据库、交易上下文、操作实例等等。
3.5.2 操作轨迹/痕迹(action trace)
实在不知道action trace如何正确翻译。执行操作之前,会初始化操作收据和操作轨迹。
首先,计算操作实例自身的hash值,存储到操作收据中
其次,操作轨迹包括该操作所在的交易将要被推送到的块,因此,操作能够被跟踪到实际的包含该操作的块和交易
最后,通过handler名称、接收这帐户和actor帐户与生产节点内的链控制器维护的操作handlers匹配来定位操作handler。
当系统合约和客户端程序被加载时,这些操作handlers被应用(被初始化)。
handler需要用到接收方帐户名称、合约名称、操作名称和操作handler。
3.5.3 操作执行
一旦合适的操作handler被定位到,就开始检查一系列的白名单和黑名单。
如果当前节点是正在出块的节点,如果接收者账号和操作名字都检查通过,就开始通过操作handler执行操作。(擦,具体是咋执行的?更新db吗)
个人理解,一个交易被发到eos网络中之后,每个BP都好校验交易,校验成功才会将交易转发出去。但是只会有出块节点才会执行这笔交易。
扩展
1、为啥eosio中可以通过签名恢复公钥?
参考:https://segmentfault.com/a/1190000017060251
需要深厚的数学知识,看的云里雾里。目前只需要知道结论就行了。
网友评论