该系列文章概述了EOSIO的交易生命周期,重点介绍了主观计费功能以及可能导致的交易丢失。 首先,我们将了解有关主观计费的所有细节;其次,我们将阐述当前智能合约开发人员和节点运营商避免此类问题的最佳实践;第三,我们会再来阐述Mandel中的缓解此类问题的一些新功能。

本篇文章是该系列文章的第二篇,查看上一篇文章请点击:

概述

最近,EOSIO生态系统展现出不容忽视的协作和发展复苏的势头。

过去几个月,全球 EOSIO 网络上的开发人员和节点运营商,一直在努力为 Mandel 网络升级构建协议改进。 其中包括对主观计费 (SB) 和交易丢失的多项改进。

上一篇文章中,我们主要研究了主观计费,即允许节点限制失败交易的设置。 我们概述了它的历史,并探讨了让用户感到困惑和沮丧的极端情况。 本文将概述网络参与者该如何操作来尽量减少这些问题。

减少主观计费问题

EOSIO社区的许多成员都期待着Mandel升级对于交易生命周期改进,但EOSIO开发者和运营商针对此问题已经做好准备,可以防止主观计费最令人头疼的一些问题出现。

现有的主观计费功能包括几个nodeos选项,运营商可以通过它来减少普通用户的主观计费,这些选项包括:

  • 完全禁用主观计费;
  • 对特定账户禁用;
  • 专门为API或P2P端点禁用主观计费。

请注意,第三个选项是有缺陷的,运营商应该避免使用,除非他们已经在自身节点上部署了新的Mandel 3.1二进制代码。

其他配置选项可以通过修改链状态的存储位置,帮助节点更有效地处理交易。 

智能合约开发者也可以采取措施减少主观计费。 用户可以通过区块浏览器看到链上计费或「客观计费」,而主观计费则不可见。 为了避免无法检测到的交易失败,避免主观计费很重要。 开发者可以检测到会导致交易失败的条件,并尽早拒绝交易,以尽量减少主观计费。 或者,他们可以将合约设计为尽早失败,以减少失败交易的资源使用。

甚至用户也可以采取措施避免主观计费问题。 通过购买额外的账户 CPU 资源、使用第三方资源提供商或连接到可靠的 API 端点,用户就可以减少丢失交易的情况发生。

在 Mandel 带来修复方案和强大的新工具来优化用户体验之前,这些操作可以帮助缓解主观计费和丢失交易的问题。

修复主观计费问题和丢失交易的快速参考:

  • 用户可以购买额外的 CPU 资源或使用外部资源提供商,来减少由于过度主观计费而导致交易被拒绝的情况发生。 仔细选择 API 端点也可以防止交易被超额收费。
  • 节点运营商可以确定哪些账户不太可能发送太多失败的交易,并可以使用以下方法禁用这些账户的主观计费:
    • disable-subjective-account-billing = <accountname>
    • Greymass Fuel 就是一个例子。 节点运营商可能会决定 Greymass 是否有足够的rate-limiting(速率限制)或 Sybil resistance(女巫攻击防御)来获得「信任」。 运营商可以使用以下方法禁用 Greymass Fuel 的主观计费:
    • disable-subjective-account-billing = greymassfuel 
  • 由于 nodeos 2.x 中的实现存在已知问题,使用 disable_subjective_api_billing 和 disable_subjective_p2p_billing 可选参数的节点运营商应将两者设置为相同的Boolean value,均为 true 或均为 false。节点可以通过升级到 Mandel 3.1 来修复此错误。
  • 另外,运营商可以使用 disable-subjective-billing = true 选项来完全关闭主观计费。这个选项在未来的版本中可能会被弃用,或者不被鼓励,并被标记为可能被删除,因为它与之前提到的 disable-subjective-api-billing 和 disable-subjective-p2p-billing 选项重复。
  • 节点运营商,尤其是云节点上的节点运营商,可以使用 nodeos 选项、database-map-mode = heap 或 database-map-mode = locked 来减少磁盘读取和资源使用。 他们还可以使用 Linux 选项 tmpfs 将链状态目录挂载为临时文件系统,从而可能加速交易执行。
  • 智能合约开发者可以预先检测导致交易失败的条件,并尽早拒绝这些交易。 这并不能消除主观计费,但会降低其发生概率及其对用户的影响。
  • 开发者也可以构建合约,以便在产生大量账单之前尽早发生最可能出现的故障。

深度参考 – 详细修复

防止主观计费问题的用户策略

节点配置调整在解决主观计费问题方面最为有效。 但是用户可以进行一些小的更改,这可能会降低他们遇到问题的概率。

用户可以做的第一件事就是购买额外的 CPU 资源。 这些额外的 CPU 将解决交易在传播到活跃区块生产者的过程中可能遇到的主观计费余额不足问题。 用户在任何节点上都看不到他们的主观计费余额,也无法判断他们是否需要额外的资源来支付主观计费。 持有额外的 CPU 有助于确保主观计费不会阻止节点通过网络传递用户的交易。

另一个有效的做法是使用 Greymass Fuel 等资源提供者。 这些工具将资源管理的负担与用户体验分开。 资源提供者充当交易的第一个签名者,支付交易的资源成本并向用户收取费用。 由于这些工具的普及,节点运营商经常为这些账户禁用主观计费,这为用户提供了避免主观计费问题的简单解决方案。

更有经验的用户可以更改其首选钱包的选项,以确保连接到可靠的 API 端点。 虽然没有这些端点的官方列表,但是,用户仍可以从 Aloha EOS 的区块生产者基准数据中推断出 API 性能。 用户可以使用此工具,从执行时间持续较低的区块生产者(BP)中选择API端点,这些节点可能具有高性能的 API 节点。

随着节点运营商改进其节点配置,并且 Mandel 3.1 引入了对主观计费的改进,网络的许多问题可以得到缓解。 同时,这些策略可以帮助改善 EOSIO 用户的体验。

智能合约开发者对主观计费的注意事项

智能合约开发者可以通过特殊的开发注意事项来减少主观计费的问题。

像assert 之类的功能可能会导致整个交易失败从而产生主观计费。 失败前已经执行的交易越多,交易的第一个签名账户应用的主观计费就越多。

通过常见故障条件的早期检测,开发人员可以更早地退出失败的交易,并减少主观计费的应用。

另外,dApps可以加入更多的交易前检查,以避免发送参数无效的交易。

开发人员应注意,除了初始签名验证外,任何失败的智能合约功能都将被主观计费。

在交易的签名验证阶段后开始应用主观计费(详见 A-1 )。因此,智能合约开发人员可以通过对操作中的功能或交易进行重新排序来减少主观计费。

例如,如果检查功能更容易失败,只要不会影响智能合约的安全逻辑,则可以在交易的早期对其进行排序。开发者应该尽早评估这些函数,最好是在使用大量资源进行复杂计算之前。

节点运营商的配置选项

Nodeos 是 EOSIO 附带的交易验证器应用程序。 节点运营商使用它来操作链上的节点。 它包括启用、禁用或调整功能的可选参数。节点运营商可以使用这些选项来为其服务器架构优化nodeos(详见 A-3)。

禁用特定账户的主观计费

Nodeos有一个选项允许节点忽略个人账户的主观计费。

disable-subjective-account-billing = ACCTNAME

disable-subjective-account-billing(禁用主观账户计费)选项将关闭名称为ACTNAME的账户的主观计费。节点运营商可以使用这个选项,将他们预计资源过度使用风险较低的账户列入白名单。

例如,如果节点运营商认为 Greymass Fuel 是可靠的资源提供者,并配备了交易速率限制工具,他们可能会选择激活该选项:

disable-subjective-account-billing = greymassfuel

启用此选项后,节点将禁用greymassfuel 账户的主观计费工具。 此选项确保 Greymass Fuel 可以为存在与主观计费相关问题的账户提供备用选项。

禁用主观计费

一些节点运营商,比如那些运行高性能 API 节点或私有链的运营商,可能会完全关闭主观计费。 有两组配置选项可以实现这一点,但行为略有不同。 在未来的 Mandel 更新完成错误修复之前,运营商应避免使用第二种配置选项。

配置选项 1:

disable-subjective-billing = <BOOLEAN> 

如果设置为 1 (true),则禁用主观计费参数将完全关闭该节点的主观计费。 运营商可以在没有看到失败交易阻塞其带宽的节点上使用此选项。 默认值是true

配置选项 2:

disable_subjective_api_billing = <BOOLEAN>
or

disable_subjective_p2p_billing = <BOOLEAN>

disable_subjective_api_billing(禁用主观 api 计费)及disable_subjective_p2p_billing(禁用主观 p2p 计费配置)选项,可以分别单独关闭节点的 API 端点和 P2P 端点的主观计费。

需要注意的是,当一个设置为「true」而另一个设置为「false」时,会导致出现意想不到的情况。 Mandel 3.1 修复了这些问题。

例如在其中一个bug中,禁用主观计费的端点不会检查账户的现有主观计费余额,但如果交易失败,端点仍会添加主观计费。P2P端点和API端点共享相同的主观计费账本,因此P2P端点可以看到API端点应用的所有主观计费,反之亦然。此共享账本可能导致一个端点拒绝来自另一个端点无意中收取了主观计费的账户的交易。

这些选项的另一个bug更令人费解。 它仅在节点将disable_subjective_api_billing(禁用主观 api 计费)设置为 true 并且将disable-api-persisted-trx设置为 false 时发生。

disable_subjective_api_billing(禁用主观 api 计费)选项是为了忽略主观计费。 相反,如果交易成功,节点会在下一个区块检查账户的主观计费。

由于这些问题,运营商应将这两个选项设置为相同的值,直到在其节点上实施 Mandel 3.1。 运营商也可以使用禁用主观计费选项,尽管目前这是一种老套的做法,后期可能会被弃用。

云节点注意事项

云节点允许小型团队灵活可靠地运行。 许多节点运营商更喜欢云节点形式,因为云节点运行稳定且效率高。 通过将高级服务器操作交给专门的服务人员,他们可以获得与互联网顶尖公司相同的安全服务和网络服务。 但是,如果配置不理想,云节点可能会出现意外的交易故障及主观或客观的超额计费。

具体来说,这些故障涉及到大多数云供应商所规定的内存架构和有限的磁盘I/O通道。访问较慢的磁盘内存而不是服务器的RAM,会带来交易执行时间问题。

一些 nodeos 选项可以帮助解决由此引起的性能问题:

选项 1:

database-map-mode = heap 

or

database-map-mode = locked

节点运营商可以通过使用可选的配置参数database-map-mode = heap或database-map-mode = locked来减少磁盘I/O。这些选项改变了服务器存储链状态的方式。 

在 heap 模式下,节点将链状态预挂载到可交换内存中。 状态优先存储在 RAM 中,超出的物理 RAM 被推送到磁盘交换内存。 仅交换性能不足以进行有效的节点操作。 但是,如果有足够的物理 RAM,使用此选项的节点将加快对最常访问数据的数据库调用。 在 WAX 区块链上,一项测试发现节点可以在物理RAM中存储低至一半的状态下高效运行。

在 locked 模式下,节点将整个状态存储在保留的RAM分区中,无需交换内存。此选项要求物理RAM至少与状态大小一样大。

 heap 和 locked 模式都有服务器 RAM最低要求,因此 RAM 有限的节点不应使用这些选项。 随着即将发布的 Trust EVM 和其他 EOS 网络基金会 (ENF) 相关计划,运营商可能会考虑增加其资源来适应增加的使用量。

选项 2:

tmpfs <DIRECTORY/TO/CHAIN/state>

节点可以使用 Linux 命令 tmpfs 在物理内存和交换内存之间创建共享分区。运营商可以使用这个 tmpfs 分区来存储链状态,并从快照中构建它(详见 A-4)。

一旦节点从快照中建立了状态,tmpfs文件夹就不需要在nodeos每次重启时重建状态。节点只有在机器断电或临时文件夹被卸载时,才需要重新建立状态。

tmpfs 文件夹可以减少磁盘读取次数。 减少磁盘读取会降低交易等待从磁盘接收数据时使用所有可用 CPU 时间的概率。 而磁盘延迟是交易失败的常见原因。

这些工具应该可以帮助节点运营商防止主观计费问题。 Mandel 的采用将带来许多额外的功能和改进。

Mandel改进

上述方法是帮助节点运营商、开发者和用户避免丢失交易的最佳实践。

EOSIO核心网络开发人员期望协议的改进能使这些方法变得不那么必要。 EOSIO 软件的下一次迭代,以及Mandel 3.1 将实施多项交易生命周期改进。 我们将在下一篇文章中深入探讨详细改进内容,但我们在这里简要总结了四个主要的增加功能和更新:

  • 交易重试监控网络将自动重试未进入最终区块的交易。
  • 交易资源成本估算允许钱包和应用程序发送测试交易,估算资源使用情况,而无需将交易应用到链上。
  • 交易最终状态通过交易池跟踪传入交易。 跟踪每笔交易的状态,直到它在设定的区块数量上达到最终效果。
  • 主观计费改进解决了主观计费功能。 一个新参数允许调整主观计费衰减时间。另外,当一个账户在一个区块内发送的失败交易超过其允许的数量时,节点可以放弃该账户的剩余排队交易。

附录:技术细节和示例用法

A-1:节点的交易处理工作流程

以下是对节点在处理交易时所采取的步骤,及其主观计费影响的更详细描述:

流程如下:

账户最初签署交易,可能有一个或多个共同签名者,例如智能合约或资源提供商(1)。

当交易到达节点时,节点首先验证所有交易签名者的签名(2)。

如果签名验证失败,节点会放弃该交易,而不向账户收费(3)。

如果签名验证成功,则交易继续进行(4)。 

接着节点计算账户剩余资源配额。禁用主观计费的节点继续进行而不检查或应用主观计费(5)。

启用主观计费的节点 (6)检查其 主观计费(SB) 表 (7), 查看与交易的第一个签名人关联的账户。

如果账户没有足够的资源来支付其主观计费,则交易将被放弃,而不被计费(8)。

如果该账户有足够的资源,则交易进入下一步(9)。

接下来,节点执行交易(10)。并跟踪在执行交易时使用了多少CPU时间。

如果交易的一部分失败了,节点就会放弃该笔交易,并对交易失败前所使用的资源向账户主观计费(11)。

如果交易成功执行(12),则进入下一阶段。 

节点接下来将账户的主观计费余额添加到资源计费中,如计算的那样。 然后将其与账户的可用资源 (13) 进行比较。

如果账户的资源用完了,节点就会放弃交易,并对账户的资源使用情况进行主观计费(14)。

如果账户有足够的资源,节点会通过其P2P协议向网络中的其他节点发送交易(15)。 

或者,如果节点是活跃的区块生产者,它将交易和计算的计费添加到区块中(16)。

A-2:智能合约开发者的高级缓解措施

智能合约开发者涉及到assert()和check()函数的使用,后者会触发交易失败,而return 语句则不会。return 语句可以确保计费是可见的,而不是主观的。然而,应该谨慎使用这种做法,因为用户或智能合约通常认为错误的参数会导致交易失败,而不必检查return 语句。他们可能会看到一个成功的交易,而不检查return语句是否报告了成功或失败,并触发不应该触发的操作。

这种做法与其他常见的智能合约做法相悖,因此只能在没有其他有效的主观计费缓解技术时使用。

要在三振出局规则和主观计费的背景下,了解更多有关这种做法背后的动机,请参阅相应的GitHub问题

A-3: API节点运营商的推荐配置设置

以下是 API 节点的推荐配置示例。运营商将这些选项添加到 nodeos config.ini 文件中。 其他推荐的配置设置可以在 EOS Nation 关于该问题的主要文章中找到,网址为 :https://github.com/EOS-Nation/bpconfig/

wasm-runtime = eos-vm-jit

chain-state-db-size-mb = 32768

reversible-blocks-db-size-mb = 2048

http-max-response-time-ms = 300

read-mode = head

database-map-mode = heap

p2p-accept-transactions = false

disable-api-persisted-trx = true

http-validate-host = false

p2p-max-nodes-per-host = 2

agent-name = INSERT NAME OF OPERATOR HERE

max-clients = 0

net-threads = 5

http-threads = 8

verbose-http-errors = true

abi-serializer-max-time-ms = 2000

http-server-address = 0.0.0.0:8888

enable-account-queries = true

plugin = eosio::http_plugin

plugin = eosio::chain_api_plugin

A-4:tmpfs 用法示例

下面的示例概述了在文件系统表中创建tmpfs文件夹的过程,该文件夹在从快照生成链状态后,将被挂载并用于存储链状态。该示例改编自EOSphere关于在WAX区块链上运行nodeos实例的文章。可在此处查阅文章:https://medium.com/eosphere/wax-technical-how-to-11-43695f583e89 

创建和挂载 tmpfs 分区

以下示例使用zfs(“zettabyte文件系统”)创建tmpfs分区,该文件系统类似于Windows的ntfs或Apple的apfs文件系统,但能够管理物理卷和逻辑卷。Zfs并不是严格必需的,但通常是用来提高数据完整性和性能的首选。它改变了文件系统表中的一个值,即fstab。

> sudo nano /etc/fstab

tmpfs   <DIRECTORY/TO/state>  tmpfs rw,nodev,nosuid,size=129G,x-systemd.after=zfs-mount.service 0

> sudo mount -a

**检查是否已安装**

> df -h

设置Swap文件:

EOSphere 团队使用交换文件而不是分区来轻松调整交换大小。 使用 SSD,他们没有遇到使用交换文件的问题。 以下示例使用以下函数将交换文件配置为 128GB:

关闭可能是分区的现有交换

> sudo swapoff -a

> sudo fallocate -l 128G /swap.img

> sudo chmod 600 /swap.img

> sudo mkswap /swap.img

> sudo swapon /swap.img

***配置fstab并注释禁止旧的交换语句***

> sudo nano /etc/fstab

/swap.img   none    swap    sw    0   0

从快照中启动nodeos

接下来设置数据库大小并将快照加载到nodeos中。nodeos实例将快照状态存储在虚拟内存中,并且每次关闭主机或卸载tmpfs分区时,都需要重建快照状态。~/eosdata字段是用户定义的任意名称,如果运营商使用自定义目录名,则必须确保将/eosdata的每个实例都替换为自定义目录名。

启动时间比平时长,如果使用大量的交换存储,启动时间甚至更长。在40GB内存和128GB数据库大小的情况下,内存利用率为81.4GB,EOSphere发现重建大约需要30分钟。nodeos软件重启时,状态不必重建,在机器重启或tmpfs卸载之前都是可用的。

配置状态数据库大小

> cd ~/eosdata

> nano config.ini

chain-state-db-size-mb = 131072

如何下载快照:

许多地方都提供快照,例如 https://snapshots.eosnation.io/  运营商应将快照保存到 ~/eosdata/snapshots/snapshot.bin

从快照开始:

nodeos –data-dir ~/eosdata –config-dir ~/eosdata –snapshot ~/eosdata/snapshots/snapshot.bin

查看 / 下载API+蓝皮书:

关于EOS网络基金会

EOS网络基金会是一个非营利性的组织,旨在倾听社区声音、传达社区意愿并扶持社区优质项目发展,成为EOS社区的信息共享桥梁,并为EOS生态提供资金、技术、运营、未来规划、生态构建等关键基础设施支持,进一步发挥EOS作为世界速度最快的治理型区块链的全部潜力。