Filecoin 区块链中的 Actor 等同于以太坊虚拟机中的智能合约。Filecoin 虚拟机(VM)是负责执行所有参与者代码的系统组件。在 Filecoin VM 上执行参与者(即链上执行)会产生 GAS 费用。
在 Filecoin VM 上执行的任何操作都将以状态树的形式输出。最新的状态树是 Filecoin 区块链中的当前来源。
1
VM Actor 接口? v? ? ipfskj2020
Actor 是以太坊虚拟机中智能合约的 Filecoin 等效项。因此,Actor 是系统的核心组件。Filecoin 区块链当前状态的任何更改都必须通过参与者方法调用来触发。
以下会描述 Actor 与 Filecoin 虚拟机之间的接口。
(这意味着下面描述的大多数内容并不严格属于 VM。相反,逻辑位于 VM 和 Actors 逻辑之间的接口上)
总共有十一种类型的内置 Actor,但并非所有类型都与 VM 交互。一些 Actor 不会调用对区块链的 StateTree 的更改,因此不需要与 VM 的接口。
这里 Actor State 的结构由参与者的余额,参与者所拥有的令牌以及用于查询,检查链状态并与之交互的一组状态方法组成。
2
状态树
状态树是对 Filecoin 区块链应用的任何操作的执行输出。链上(即,VM)状态数据结构是将地址绑定到参与者状态的映射(以哈希数组映射树(HAMT)的形式)。VM 在每次执行 actor 方法时都会调用当前的 State Tree 函数。
3
VM 消息-Actor 方法调用
消息是两个参与者之间进行通信的单位,因此是状态变化的根本原因。一条消息结合了:
从发送方转移到接收方的令牌金额,以及具有在接收方上调用的参数的方法(可选 / 在适用的情况下)。
Actor 代码可以在处理收到的消息时向其他 Actor 发送其他消息。消息是同步处理的,也就是说,参与者在恢复控制之前等待发送的消息完成。
消息的处理消耗了计算和存储单位,两者均以瓦斯表示。消息的气体限制为处理该消息提供了所需的计算上限。消息的发件人以其确定的汽油价格来支付消息执行所消耗的 gas 单位(包括所有嵌套的消息)。区块生产者选择要包含在区块中的消息,并根据每个消息的 gas 价格和消耗量获得奖励,从而形成市场。
消息语法验证
语法无效的消息不得传输,保留在消息池中或包含在块中。如果收到无效消息,则应将其丢弃,并且不要进一步传播。
当单独发送时(在包含在块中之前) SignedMessage,无论使用哪种签名方案,都将消息打包为 。有效的签名邮件的序列化总大小不大于 message.MessageMaxSize。
v? ? ipfskj2020
语法上有效的 UnsignedMessage:
具有格式正确的非空 To 地址,
具有格式正确的非空 From 地址,
具有 Value 不小于零且不大于令牌总供给(2e9 * 1e18),并且
具有非负数 GasPrice,
具有 GasLimit 至少等于与消息的序列化字节关联的气体消耗的值,
具有 GasLimit 不大于区块气体限制网络参数的值。
从中提取信息 Message struct,例如发件人和收件人地址,要转移的值,执行消息所需的资金以及消息的 CID。
假定消息最终应包含在一个块中并添加到区块链中,则应检查消息的发送者和接收者的消息有效性,该值(应为非负值,并且始终小于循环供应),gas 费价格(该价格又应为非负数)且 BlockGasLimit 该价格不应大于该区块的 gas 费限额。
消息语义验证
语义验证是指需要消息本身之外的信息的验证。
语义上有效的 SignedMessage 必须带有签名,以验证有效载荷是否已被 From 地址标识的帐户执行者的公钥签名。请注意,当 From 地址是 ID 地址时,必须在块所标识的父状态下的发送帐户参与者的状态下查找公钥。
注意:发送方必须以包含消息的块所标识的父级状态存在。这意味着单个块包含创建新帐户 actor 的消息和来自同一 actor 的消息是无效的。来自该参与者的第一条消息必须等到下一个纪元。消息池可能会排除来自参与者的,尚未处于链状状态的消息。
消息没有进一步的语义验证,可能导致包含该消息的块无效。每个语法有效且正确签名的消息都可以包含在一个块中,并会从执行中产生一个收据。其中 MessageReceipt sturct 包括以下内容:
但是,消息可能无法执行到完成,在这种情况下,它不会触发所需的状态更改。
这种“无消息语义验证”策略的原因是,在消息作为提示集的一部分执行之前,将不知道消息将应用于的状态。块生产者不知道在提示集中是否有另一个块会在它之前,因此从声明的父状态更改了该块消息将应用到的状态。
4
VM 运行内部环境
Message Receipt 包含一个顶层消息执行的结果。每个语法有效且正确签名的消息都可以包含在一个块中,并会从执行中产生一个收据。
语法有效的 Message Receipt 具有:一个非负 ExitCode;Return 仅当退出代码为零时,才为非空值;并且非负数 GasUsed。
5
VM 解释器-外部消息调用
VM 解释器根据其父块状态上的提示集协调消息,从而产生新状态和一系列消息回执。此新状态的 CID 和收据集合的 CID 包含在后续区块中,这些区块必须同意这些 CID 才能形成新的提示集。
每个状态更改都由消息的执行来驱动。提示集中所有块中的消息必须执行才能产生下一个状态。来自第一个块的所有消息均在技巧集中的第二个和后续块的消息之前执行。对于每个块,首先执行 BLS 聚合的消息,然后执行 SECP 签名的消息。
隐式消息
除了显示包含在每个块中的消息之外,隐含消息还会在每个时期对状态进行一些更改。隐式消息不在节点之间传输,而是由解释器在评估时构造的。
对于提示集中的每个块,隐式消息:
调用区块生产者的矿工演员来处理(已验证的)选举 PoSt 提交,作为区块中的第一条消息;
调用奖励参与者将区块奖励支付给矿工的所有者帐户,作为区块中的最终消息;
对于每个提示集,一个隐式消息:
调用 cron actor 来处理自动支票和付款,作为提示集中的最后一条消息。
所有隐式消息的构造 From 地址都是杰出的系统帐户参与者。他们将汽油价格指定为零,但必须包含在计算中。为了计算新状态,它们必须成功(退出代码为零)。隐式邮件的收据不包括在收据列表中;只有明确的消息才有明确的回执。
GAS 费
在大多数情况下,消息的发送者向产生包含该消息的块的矿工支付执行该消息所需的 GAS 费。
执行该消息后,每次执行该消息所产生的 GAS 费将立即支付给矿工所有者帐户。所获得的集体奖励或汽油费没有任何负担:两者都可以立即花费。
邮件重复
由于不同的矿工在同一时期产生区块,因此单个提示集中的多个区块可能包含相同的消息(由相同的 CID 标识)。发生这种情况时,仅在第一次以提示集的规范顺序遇到该消息时才处理该消息。消息的后续实例将被忽略,不会导致任何状态突变,产生收据或向区块生产者支付费用。
总结一下提示集的执行顺序:
为第一块支付奖励
处理第一块的选举职位
第一个块的消息(SECP 之前的 BLS)
支付第二块奖励
处理第二个区块的选举职位
第二个块的消息(SECP 之前的 BLS,跳过任何已经遇到的消息)
[… subsequent blocks …]
定时刻度
消息有效性和失败
有效块中的每个消息都可以被处理并产生收据(请注意,块有效性表示所有消息在语法上均有效–请参阅 消息语法–并正确签名)。但是,执行成功与否取决于消息所应用的状态。如果消息执行失败,则相应的收据将携带非零的退出代码。
如果消息由于可以合理地归因于矿工的原因而失败,包括在父块状态中永远不可能成功的消息,或者由于发件人缺乏资金来支付最大消息成本,则矿工将通过烧钱来支付罚款 GAS 费(而不是发送方向大宗矿工支付费用)。
消息失败导致的唯一状态更改是:
发送方的增量 CallSeqNum,并从发送方向包含消息的区块矿主支付汽油费;
罚款等于失败消息的 GAS 费,由矿工烧掉(发件人 CallSeqNum 未更改)。
如果处于紧接的先前状态,则消息执行将失败:
该 From Actor 不存在于该州(受到矿工处罚)
该 From Actor 是不是帐号 Actor (的矿工处罚)
该 CallSeqNum 消息不匹配 CallSeqNum 的的 From Actor (的矿工处罚)
From Actor 不具有足够的平衡,以覆盖消息的总和 Value 加上最大 GAS 成本,GasLimit * GasPrice (矿工处罚)
该参与者不在 To 状态中,并且该 To 地址不是 pubkey 样式的地址
该 To actor 存在(或作为帐户隐式创建),但是没有对应于非零的方法 MethodNum
反序列化 Params 不是长度匹配数组 Toactor 的 MethodNum 方法的数组
反序列化 Params 对于 Toactor 的 MethodNum 方法指定的类型无效
所调用的方法消耗的 GAS 多于 Gas Limit 允许的量
调用的方法以非零代码(通过 Runtime.Abort())退出
由于上述任何原因,接收方发送的任何内部消息都会失败。
请注意,如果 To 参与者不在状态中并且该地址是有效 H(pubkey) 地址,则它将被创建为帐户参与者。