AO 合约概览和源码获取

  • PermaDAO
  • 更新于 2024-07-16 22:21
  • 阅读 430

想了解 AO 上应用的合约运行机制吗?那么来抓取合约代码一探究竟吧。用一个 python 小程序,轻松获取指定 Process 的合约。

1.png 作者: txohyeah

审阅:outprog

来源:内容公会 - 新闻


AO 简介

什么是 AO?

AO 测试网发布已经有小半年了,AO 的内容也有很多,本文的内容主要聚焦 Process 和智能合约,包括 AO 是什么,Process 是什么,Process 的生命周期。最后重点介绍下如何查看 Process 的合约代码。

AO 是 Arweave 在完善分布式存储基础上,进一步发展出的计算功能,旨在实现全面的去中心化应用支持,与以太坊先计算后存储的发展路径相对应。简单来说,AO 代表了 Arweave 平台上的智能合约或计算能力,是在其永久存储解决方案之上的逻辑层扩展。

AO 由三个单元组成,MU / SU / CU

MU:接收到用户发送的消息,以确保它们经过签名。

SU:对消息进行时间戳和排序,然后捆绑并发布到 Arweave。SU 也是我们今天会用到的主角,后面会在查看合约时,起到了重要的作用。

CU:处理消息并计算出结果。

2.png

什么是 AO 上运行的 Process?

AO 本质上是基于一个 Data Protocol 构建的超级并行计算机,其中 Data 的存在形式是 AO 中定义的基本元素 Message。那么 Process 在这其中扮演着处理 Message 的重要角色,是处理 AO 上消息的基本单元。Process 运行在 CU 上,可以看成是 CU 上的一个虚拟机。因此,Process 包含基本的能力就是在网络内接收和发送消息。然后开发者通过为 Process 添加 handler 的方式,为 Process 构建消息处理的能力。后面要讲到的合约,其实就是通过发送一条消息到 Process,再通过内置的 _eval handler 部署的。其中添加的 handler 可以理解为合约的消息处理函数。

3.png

Process 的生命周期

如果要在我们现有的世界中找到一个类比,那么我认为 docker 中容器(Container)可以很好的让人对比理解 Process。下面我会借助 docker 中 Container 的生命周期类比下 Process 的生命周期。

我们都知道 docker 中 Container 的创建会依赖一个镜像(Image),比如根据 mysql 的 Image 创建一个 mysql 的 Container,而后就可以在这个容器上调用 mysql 的服务了。AO 中的 Process 也是一样,Process 的创建依赖于 Module,并且也会存在不同功能的 Module,有最简单的 Module,有支持定时任务的 Module,也有包含 sqlite 的 Module。目前已经有上百个 Module,可供开发者选择去创建自己的 Process。另外,自己也可以去制作自定义的 Module。相信在不久的将来,也会出现支持 GPU 的 Module,支持各种 AI 能力的 Module。

AO 中的 Process 也存在与 docker 中 Container 不一样的地方。Docker 中的 Container 支持启动、停止、删除等各种动作。目前在 AO 的 Process 中是没有这些操作的,毕竟在去中心化应用的世界中,这些由中心化个人控制的功能就显得很不融洽了。在 AO 中 Process 的运行完全取决于 Process 自己的价值,如果有足够的价值,那么肯定会有更多的 CU 愿意去运行它,相反,一个 Process 如果没有价值,就没有 CU 愿意去运行它,那么这个 Process 就将默默的消失。

Eval 函数与 AO 合约部署

什么是 AO 合约?对比以太坊的智能合约。AO 上运行的 Process 中的 Lua 代码可以近似的看成智能合约。

我们创建 Process 时,加载的每一个 Module 都会带有两个默认的 handler(handler 可以被理解为对其他 Process 开放的函数),其中一个函数就是 _eval handler。这个 handler 的主要功能就是运行 Lua 代码。比如你在 aos 中输入1+1,返回一个2,就是通过这个 handler 处理的。那么部署合约实际上,就是给 Process 发送消息,通过 _eval handler 给这个 Process 中添加可以处理业务逻辑的自定义 Handler。

4.png

其中需要注意一点,请看下方代码。这是官方开源 AO 项目中 process.lua 中的代码段落。只有当消息的发送者与 Process 的 Owner(Owner为创建合约时的钱包地址)一致时,才能执行 _eval handler。也就是说,如果 Owner 被设置为 nil 时(即把该 Process 设置为没有 Owner),那么这个 Process 中的合约就成为了一个没有人可以再修改的合约了。

  Handlers.add("_eval", 
    function (msg)
      return msg.Action == "Eval" and Owner == msg.From
    end,
    require('.eval')(ao)
  )

另外,因为 AO 实际上是基于存储的共识范式(SCP,Storage-based Consensus Paradigm)构建的,所以运行的合约必定是可以在“存储共识”上找到,即在 Process 中运行的所有消息,包括通过 _eval handler 部署的合约代码,都存在了 Arweave 上。因此,任何人都可以在该“存储共识”上找到合约代码。

查看合约

那么来到了今天的主题,究竟如何找到合约代码呢?下面我介绍下两种方法,并给出一份抓取合约的 Python 程序。

Arweave

第一种方法当然就是直接在 Arweave 上查询(可以使用graphql https://arweave.net/graphql)。这种方法会要求在数据打包到 Arweave 后才能有用。

SU - 浏览器

第二种就是今天主要介绍的办法。由于所有的数据都会经过 SU 上链,因此也可以在 SU 上查询。个人认为每个 SU 会在自己本地有一份缓存,缓存了由自己上链的数据,因此就可以根据查询 SU 找到对应的合约代码。首先,可以根据浏览器输入地址直接查询。但是该方法的缺点也很明显:1. 有些 Process 发送和接受的消息量巨大,因此上链的数据量也巨大。但是浏览器可以加载的数据有限,经常会出现浏览器崩溃。 2. 很难从海量的数据中过滤出自己想要的合约数据。

如下图,展现的是两个时间戳内,process id 为 m3PaWzK4PTG9lAaqYQPaPdOcXdO8hYqi5Fe9NWqXd0w 的进程(AO token 进程)的所有消息。

5.png

SU - sdk

这边我写了一个小程序,借助业内大佬基于 python 写的一个 ao 的 sdk,把 Action 为 Eval 的消息过滤出来。(Action 为 Eval 的消息,即为所有由 _eval handler 处理的消息,也包括加载的合约代码。)如下图是我从SU 上面抓取的消息,其中 data 字段中的内容就是经过字符转义的一份合约代码。当然抓取的消息也会包含非部署合约代码的内容,比如执行个 1 + 1 等。但是过滤以后的消息数量已经不多了,完全可以人工选取出来合约的代码。

程序已经开源,这里是 github 的地址:https://github.com/txohyeah/ao-sc

6.png

AO token合约

那么让我们激动的来看看 ao token 的合约代码。(抓下来的合约代码也会一并放在开源的代码仓库中)

首先,初始化状态时,定义了 TotalSupply = "21000000000000000000" 与比特币一致的发行量。

Denomination = Denomination or 12 还定义了小数点为12位。

--[[
Initialize State

ao.id is equal to the Process.Id
]]
--
Variant = "0.0.3"

-- token should be idempotent and not change previous state updates
Denomination = Denomination or 12
Balances = Balances or {}
-- 21_000_000 AO Tokens
-- 21_000_000_000_000_000_000 Armstrongs
TotalSupply = "21000000000000000000"
Name = 'AO'
Ticker = 'AO'
Logo = Logo or 'SBCCXwwecBlDqRLUjb8dYABExTJXLieawf7m2aBJ-KY'

定义了在 100000 个区块产生之前,如果执行 transfer 函数,则直接返回 "Transfer is locked"。 由于五分钟产生一个区块,那么 100000 个区块就大约到了明年 2 月份了。

--[[
     Transfer
   ]]
--
token.transfer = function(msg)
  if MintCount < 100000 then
    Send({ Target = msg.From, Data = "Transfer is locked!" })
    return "Transfer is locked"
  end
  local status, err = pcall(function()
      ......

还有更多相关的信息,我就不啰嗦了。大家可以愉快的浏览这份经典的AO合约。

程序使用说明

上面我介绍了抓取的合约代码,接下来我简单介绍下这个程序。很简单,相信不懂代码的人也可以轻松使用。

第一步,安装 python 3.12 版本。程序是 python 写的,安装 python 是必须的。

第二步,安装所需要的包。本程序依赖业内大佬的 sdk,依赖于 everpay。

pip install requests everpay setuptools

第三步,修改 fetch_sc_record.py 中的 start_time / end_time / process。并执行 fetch_sc_record.py。 start_time 和 end_time 是你需要抓取的时间段。process 是你需要抓取合约的 Process 的 id。

python fetch_sc_record.py

7.png

第四步,对应的 Eval 消息,就会出现在 msg_eval.json 的文件中了。再浏览其中的消息,就可以找到你需要的合约代码啦! PS:也需要和运行 aos 一样。设置 HTTPS_PROXY。


关于 PermaDAOWebsite | Twitter | Telegram | DiscordMediumYoutube

0.png

点赞 0
收藏 0
分享

0 条评论

请先 登录 后评论
PermaDAO
PermaDAO
0x40F9...8718
Arweave 生态系统的共建者 DAO。 @ArweaveEco will be adopted by more developers. All projects of Arweave ecology can post their tasks and rewards here. @everVisionHQ@permaswap@ArweaveSCP