如何在EOS中调度自动智能合约执行

  • mixbytes
  • 发布于 2020-02-25 17:55
  • 阅读 36

本文介绍了Cronos,一个为EOS智能合约提供定期任务处理的解决方案。文章深入阐述了Cronos的工作原理、使用方法以及后端逻辑,特别强调了如何通过智能合约实现类似于Unix系统中的cron功能,以满足DApp开发者的需求。该项目还提供了示例代码和潜在的改进方向。

作者: MixBytes 团队

简介

软件开发通常涉及需要定期执行的任务。例如,Unix 系统有 crond 来满足这些目的。

在我们开始讨论解决方案之前,先回答一下我们为什么在区块链中需要 cron。

有很多应用,以下是其中一些:

  • 你是一个 Dapp 开发者,在表中存储数据,占用了一些 RAM 空间。内存是需要付费的,因此应用需要定期清理这些表。

  • 你正在开发一个货币转换器,应用需要定期从预言机获取数据。

  • 你是一名加密基金经理,时时需要向客户发送一部分利润分成。

我们经常需要审核和编写智能合约,并且经常遇到上述问题。不幸的是,EOS 不允许创建定期任务,因此我们尝试通过编写我们的 cron 智能合约(Cronos)来填补这个空白。

什么是 Cronos

Cronos 是一个针对 EOS 的 cron 智能合约,帮助 DApps 执行定期任务。

当然,你可以手动调用合约方法或编写一个脚本来为你做到这一点。然而,支付少量费用以进行定期的 cronos 调用并停止担心要容易和安全得多。这样,你就得到了某种 cron-as-a-service :)

使用 Cronos(内存清理)

服务的工作原理如下:用户向智能合约发送所需数量的 EOS 代币。然后,智能合约使用调度函数创建任务。在任务执行过程中,合约将自动扣除一定量的 EOS 代币。

例如,如果你想每 42 秒清理智能合约存储,可以使用 Cronos 创建这样的任务:

cleos push action cron schedule '["andrew", "mydapp", "cleanup", 42]' -p andrew

如果开发者正确实现了合约的清理操作,则清理将成功进行。Cronos 表中将创建任务及其执行时间的条目。

底层实现

Cronos 相当简单。账号所有者在给定间隔(polling_interval)内调用一次 run。然后,在合约执行过程中,会创建一个带有相同 polling_interval 的 deferred transaction

你可以在 官方文档 中了解有关延迟交易的更多信息。别忘了查看 使用案例

注意,在 EOS 交易执行时间限制为 30 毫秒。因此,为单个交易中处理的记录数设置限制(rows_count)是合理的。

以下是带注释的代码库:

ACTION run(uint32_t polling_interval, uint32_t rows_count) {
    // 确保事务是由当前合约创建的
    require_auth(get_self());

    // 检查是否应停止执行
    if (stop_execution.get())
        return;

    // 记录处理
    scan_schedules(rows_count);
    // 在 polling_interval 秒后再次调用 run
    create_transaction(_self, _self, "run", polling_interval, make_tuple(polling_interval, rows_count));
}

template<class ...TParams>
void create_transaction(name payer, name account, const string &action, uint32_t delay,
        const std::tuple<TParams...>& args) {
    // 创建一个具有所需延迟的延迟事务
    eosio::transaction t;
    t.actions.emplace_back(
            permission_level(_code, "active"_n),
            account,
            name(action),
            args);

    t.delay_sec = delay;

    // 出于调试目的,你需要一个唯一 ID
    auto sender_id = unique_id.get();
    t.send(sender_id, payer);
    unique_id.set(sender_id + 1, _code);
}

表中任务的处理逻辑相当简单。Cronos 选择执行时间最短的任务,确保它必须被执行(即当前时间小于或等于执行时间),并在确保用户有足够的 EOS 代币余额后创建一个延迟交易。在任务处理结束时,Cronos 自动重新计算下一次调用的时间。

// 我们获取下一个区块创建的 unix 时间
time_point_sec current_time(now());

// 我们检查是否是执行任务的时间
if (current_time >= item.next_run) {
    const name& account_from = item.from;

    // 确保用户在他的钱包账户上有足够的资金
    if (get_balance(account_from) >= CALL_PRICE) {
        reduce_balance(account_from, CALL_PRICE);
        create_transaction(account_from, item.account, item.action, item.period, tuple<name>(account_from));

    // 刷新运行时间
    cron_table.modify(item, _self, [&](auto& row) {
        row.next_run = item.next_run + item.period;
    });
}

延迟交易的陷阱

我必须说,延迟交易的方法有一个显著缺点。例如,如果当前交易因某种原因失败,则不会创建延迟交易。为避免这种情况,你需要在调试时加倍小心。否则,mydapp 合约的所有者将不得不再次手动调用 run 操作。

下一步

我们的团队将添加一些功能,允许设置类似于原始 crond Unix 的任务规则。

参考

Github 仓库:

https://github.com/mixbytes/cronos

  • MixBytes 是谁?

MixBytes 是一支由专家区块链审计师和安全研究人员组成的团队,专注于为 EVM 兼容和 Substrate 基础的项目提供全面的智能合约审计和技术咨询服务。请加入我们 X,以随时了解最新的行业趋势和见解。

  • 原文链接: mixbytes.io/blog/schedul...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
mixbytes
mixbytes
Empowering Web3 businesses to build hack-resistant projects.