Homestead

三条命令,拥有你自己的 Farcaster

租一台服务器,在上面运行 Snapchain 只读节点(read node),再用一个直接从这个节点读取、也通过它发帖的客户端。不需要任何人的 API 密钥。每个协议概念都会在你用到它的那一刻讲清楚。

快速开始

你需要一个带有 bash、curl、ssh 和 jq 的终端(Mac 自带这四个)、一个 Hetzner Cloud 或 DigitalOcean 账户,以及一个已经有存储空间的测试用 Farcaster 账户。

bash
git clone https://github.com/warfield2016/homestead && cd homestead
bash
./homestead provision   # 0. rent a server
./homestead node        # 1. start a read node
./homestead client      # 2. start your client
  1. provision:找到最便宜的、满足 4 核以上、16 GB 内存、2 TB 磁盘的服务器,显示实时价格,只有在你输入 PROVISION 后才会创建。
  2. node:以只读节点方式安装 Farcaster 官方的 Snapchain。先恢复快照,再追上最新区块:需要几个小时,无需值守。
  3. client:在你的服务器上构建客户端,打印出 https://<你的IP>.sslip.io 和登录口令。

在电脑或手机上打开这个网址,登录,连接你的测试账户。客户端会获得它自己的应用密钥(app key,不花 gas,不发交易),之后你就可以读时间线、发帖、关注、点赞、转发,并自己决定看哪些应用发出的内容。

用完之后:./homestead destroy。在 Hetzner 上测试一天大约花费 4–7 欧元,取决于当时哪些机型有货。

本页按这三条命令的顺序展开。每一步都会说明运行了什么、花多少钱、要多久,以及涉及协议的哪些部分。如果你只想跑起来,带框的内容可以跳过;如果你想把 Farcaster 理解到足以自己写一个客户端,请读它们。

开始之前

你需要什么

一台电脑macOS 或 Linux。Windows 可在 WSL 中使用。Mac 上无需安装任何东西。
一个云服务账户Hetzner Cloud(最便宜)或 DigitalOcean。或者任何你已有的、4 核 16 GB 内存、2 TB 空闲磁盘的 Linux 机器(自带机器)。
一个有存储空间的 Farcaster 测试账户任何你丢了也无所谓的账户。见获取测试账户。
时间大约 15 分钟的操作,加上节点同步时几个小时的等待。
费用按 Hetzner 2026 年 10 月的价格:每月约 130–200 欧元(取决于库存),按小时计费,测试一天约 4–7 欧元。大部分是 2 TB 存储卷的费用。脚本会先显示实时价格并等待你确认。

获取测试账户

Homestead 导入的是已有账户,不负责创建,因为创建账户需要在 OP Mainnet 上发一笔交易、花一点 ETH。两种简单的方法:

一张图看懂 Farcaster


0. 准备服务器

bash
./homestead provision            # Hetzner Cloud (default)
./homestead provision digitalocean
./homestead provision byo root@203.0.113.7

节点需要什么,为什么

这是 Snapchain 公布的配置要求:4 个 CPU 核心、16 GB 内存、2 TB 空闲磁盘,并且 3381–3383 端口可从外部访问。

磁盘这一项最值得说。2026-10-18 时,主网快照共 5,691 个分块,每块约 70 MB,压缩后约 400 GB;解包后的数据库约 550 GB。你需要的空间比两者之和还多,原因在于恢复的方式。根据 snapshot.rs,对每个分片,节点会:

  1. 把所有压缩分块下载到 .rocks.snapshot/;
  2. 把它们全部解压成一个 .tar 文件,同样放在 .rocks.snapshot/;
  3. 把 tar 解包到数据库目录;

并且直到最后一个分片完成后才删除 .rocks.snapshot/。峰值时,压缩分块、未压缩的 tar 和数据库同时存在:约 1.5 TB。之后数据库还会继续增长。

这条命令做了什么

在 Hetzner 上,./homestead provision 会:

  1. 请你输入 API 令牌(输入不回显,永不写入磁盘)。请在一个新的空项目里,于 Security → API tokens 下创建,这样令牌碰不到别的东西;
  2. 列出你所在地区此刻有货的机型,筛选出 4 核以上、16 GB 以上内存的,选最便宜的。Snapchain 同时发布 arm64 和 amd64 镜像,所以 ARM 机器也行。按 Hetzner 2026 年 10 月公布的价格,最便宜的是 CX43(每月 15.99 欧元)和 CAX31(20.99 欧元),但这两个系列自 9 月起经常缺货;缺货时,下一个选择是 CCX23(85.99 欧元)。2 TB 存储卷每月约 114 欧元;
  3. 从 API 读取实时价格,打印每月总价和一天的费用,然后等你输入 PROVISION;
  4. 依次创建:一把 Homestead 专用的 SSH 密钥(放在 .homestead/ssh/,不碰你的 ~/.ssh)、一个防火墙、一个 2 TB 存储卷,以及一台挂载了两者的 Ubuntu 24.04 服务器;
  5. 等到能 SSH 登录后,检查 CPU 和内存。

它创建的所有东西都记录在 .homestead/state(里面没有任何密钥),命令 1、2 和 destroy 就是靠它找到服务器的。

防火墙只开放这些端口:

端口用途谁来连接
22/tcpSSH你
80/tcp、443/tcp通过 HTTPS 访问客户端(80 用于证书验证)你,任何设备
3382/udpSnapchain gossip 通信(基于 QUIC 的 libp2p)其他节点。必需。
3381/tcpSnapchain HTTP API任何人。Snapchain 文档建议开放。
3383/tcpSnapchain gRPC API任何人。Snapchain 文档建议开放。

想不创建任何东西先看一遍?运行 HOMESTEAD_DRY_RUN=1 ./homestead provision:它会显示方案,并打印本来要发出的 API 请求。

自带机器

任何支持 Docker、4 核以上、16 GB 内存、2 TB 空闲磁盘的 Linux 机器都可以:家里的服务器、Netcup 或 OVH 的独立服务器、EC2 实例。

bash
./homestead provision byo root@your.server        # uses your normal SSH setup
./homestead provision byo ubuntu@your.server ~/.ssh/key.pem

请自行在路由器或云防火墙上开放 3382/udp(必需)和 80/443/tcp(客户端用)。


1. 运行 Snapchain 只读节点

bash
./homestead node

它会问你两件事,和 Farcaster 官方安装脚本问的一样:确认你知道运行节点没有奖励;以及(可选)你的 FID,它只用来决定节点在每周哪一天自动升级,避免所有节点同时升级。

Snapchain 是什么

这条命令做了什么

在服务器上,以 root 身份,./homestead node 会:

  1. 把 2 TB 存储卷挂载到 /root/snapchain(只有在卷上没有文件系统时才格式化);
  2. 用 Docker 官方的便捷脚本安装 Docker;
  3. 把你的两个回答写进 /root/snapchain/.env,让官方安装脚本不再停下来询问;
  4. 写一个 docker-compose.override.yml,把 Grafana(默认密码 admin)和 statsd 绑定到 127.0.0.1。官方 compose 文件会把它们暴露在所有网卡上,而 override 文件是官方文档推荐的修改方式;
  5. 下载并运行 Farcaster 自己的 snapchain.sh upgrade:它会获取主网 compose 文件和验证者列表、配置 Grafana、安装每周自动升级的 cron 任务,并启动节点。

Homestead 不 fork、不修改 Snapchain。Farcaster 发布新版本时,你的节点会通过每周的 cron 任务自动更新。

观察同步进度

bash
./homestead status --watch

同步分两个阶段。

1. 恢复快照(大部分等待时间)。 节点依次下载分片 1、2、0,并逐个解包。这时 HTTP API 还没有启动,status 会从节点日志中读取进度。输出类似这样(数字仅为示例):

console
node: container running (up since 2026-10-19T09:12:04)
snapshot: downloading shard 1: chunk 1204 of 2672 Shard ETA: 0h41m
          (shards restore one after another: 1, 2, then 0; each is unpacked right after it downloads)
disk: 141G used, 1.7T free

2. 追赶。 恢复完成后,节点从对等节点获取快照之后确定的所有区块并重放。这时 API 已经可以访问,blockDelay(每个分片最新区块落后当前时间的秒数)会逐渐减少。例如:

console
shard 0: height 48337984  catching up: 5120s behind
shard 1: height 49013206  in sync (1s behind)
shard 2: height 48848731  in sync (0s behind)

当每个分片都只落后几秒时,同步就完成了。在 Hetzner 上,总共大约需要几个小时,主要是下载。

你的第一次查询

节点的 HTTP API 就是普通的 JSON + GET。在服务器上(./homestead ssh):

bash
curl -s localhost:3381/v1/info | jq '.dbStats'
json
{
  "numMessages": 914249478,
  "numFidRegistrations": 3355205,
  "approxSize": 548710481099
}
bash
curl -s 'localhost:3381/v1/castsByFid?fid=1&pageSize=1&reverse=true' | jq '.messages[0]'

这就是一条原始消息,其他一切都由它构成:

json
{
  "data": {
    "type": "MESSAGE_TYPE_CAST_ADD",
    "fid": 1,
    "timestamp": 182710221,
    "network": "FARCASTER_NETWORK_MAINNET",
    "castAddBody": {
      "text": " ",
      "mentions": [14206, 19960],
      "mentionsPositions": [0, 1],
      "parentCastId": { "fid": 852612, "hash": "0x9d37ece822109756e40b8624abdb0c88e9e8a5d5" },
      "embeds": [],
      "type": "CAST"
    }
  },
  "hash": "0xa7cfccb85b71ecd53945dec4c53161a8a4aed77b",
  "hashScheme": "HASH_SCHEME_BLAKE3",
  "signature": "3muv+tUjyXsmLWMy8Js55K3Iu9dWVtXl3qqBgcn0eJefvYgzj6rA2ih9Ebp+oaH6vrslaowGNDQnV2Pi/peABQ==",
  "signatureScheme": "SIGNATURE_SCHEME_ED25519",
  "signer": "0xb85cf7feef230f30925b101223fd3e3dc4e1120bacd677f5ad3523288f8f7102"
}

2. 创建客户端

bash
./homestead client
console
Your client:   https://203-0-113-7.sslip.io
Passphrase:    k7pqm-2xw9v-hc4rt-b8nzf   (shown once — save it in your password manager)

节点还在同步时就可以运行这条命令。客户端会先启动,页面会告诉你它在等什么。

这条命令做了什么

  1. 把本仓库的 client/ 和 deploy/ 复制到服务器的 /opt/homestead。
  2. 在服务器上、用这份源码构建客户端的 Docker 镜像,并用 Docker Compose 启动。它与 Farcaster 的 compose 项目并列(而非嵌入其中),所以 snapchain.sh upgrade 永远不会覆盖它。
  3. 在前面启动 Caddy 提供 HTTPS。你不需要域名:203-0-113-7.sslip.io 是一个 sslip.io 域名,会解析到 203.0.113.7,Caddy 会自动为它申请 Let's Encrypt 证书。用 --domain 可以换成你自己的域名。
  4. 生成一个登录口令(约 95 位熵),通过 SSH 的标准输入发到服务器,这样它不会出现在进程列表里;服务器只保存它的 scrypt 哈希。

--private 会跳过 Caddy,把客户端绑定在服务器的 127.0.0.1 上。用 ./homestead tunnel 后访问 http://localhost:8080。

连接你的账户

登录后,客户端会请你连接一个账户。这里 Farcaster 的密钥模型就很关键了。

第一步:找到你的账户。 你可以粘贴助记词,也可以连接浏览器钱包。两种方式都由浏览器算出托管地址,只把地址发给你的服务器。服务器去问你的节点:

bash
curl -s 'localhost:3381/v1/onChainIdRegistryEventByAddress?address=0x6b0bda3f2ffed5efc83fa8c024acff1dd45793f1' | jq '{fid, to: .idRegisterEventBody.to}'

然后再核实这个地址仍是当前的托管地址(账户可以被转移),并且账户有存储空间。它会把找到的 FID、用户名和存储情况显示给你。

第二步:签两条消息。 服务器生成一对新的 Ed25519 密钥,请浏览器用托管密钥签署两个 EIP-712 结构化数据。页面会在你签名前把它们展示出来,内容类似这样:

json
[
  {
    "domain": { "name": "Farcaster KeyAdd", "version": "1", "chainId": 1 },
    "primaryType": "SignedKeyRequest",
    "message": { "requestFid": "1234567", "key": "0x7f3c…a21e", "deadline": "182796043" }
  },
  {
    "domain": { "name": "Farcaster KeyAdd", "version": "1", "chainId": 1 },
    "primaryType": "KeyAdd",
    "message": {
      "fid": "1234567", "key": "0x7f3c…a21e", "keyType": 1,
      "scopes": [1, 2, 3, 4, 5, 6], "ttl": 2592000,
      "nonce": 1, "deadline": "182796043"
    }
  }
]

第三步:服务器构建并提交 KEY_ADD。 它先验证两个签名都能恢复出你的托管地址,再把它们打包进一条 KEY_ADD 消息,用这把新的应用密钥自己给消息外层签名(证明提交者确实持有这把密钥),然后提交给你的节点,并等待节点报告这把密钥:

bash
curl -s 'localhost:3381/v1/signersByFid?fid=1234567' | jq '.signers[] | {source, key, requestFid, scopes, addedAt, expiresAt}'
json
{
  "source": "SIGNER_SOURCE_OFFCHAIN",
  "key": "0x7f3c…a21e",
  "requestFid": 1234567,
  "scopes": ["MESSAGE_TYPE_CAST_ADD", "MESSAGE_TYPE_CAST_REMOVE", "MESSAGE_TYPE_REACTION_ADD", "MESSAGE_TYPE_REACTION_REMOVE", "MESSAGE_TYPE_LINK_ADD", "MESSAGE_TYPE_LINK_REMOVE"],
  "addedAt": 1792350494,
  "expiresAt": 1794942494
}

读这些记录时有个坑:addedAt、lastUsedAt 和 expiresAt 是 Unix 秒,而消息时间戳是从 Farcaster 纪元起算的。expiresAt − lastUsedAt 就是 TTL。

没有交易,没有 gas,大约一秒。

关于助记词,实话实说

Balaji 在补充说明里说得好:开发者教程对待助记词,应当像 Unix 教程对待 rm -rf 一样。所以,直说:

Homestead 如何处理助记词,方便你核查:

  1. 助记词输入在你自己的服务器提供的页面里。相关代码全部在一个文件中:client/src/web/signing.ts,约 110 行。
  2. 浏览器在内存中推导出托管账户,签署上面两条数据,然后清空输入框。助记词不会被发送到任何地方:打开浏览器的网络面板,你只会看到发出了一个地址,然后是两个签名。
  3. 签名前,这个文件会检查数据是否恰好是 "Farcaster KeyAdd" 域上的这两种类型之一,其他一律拒绝。被攻破的服务器也无法骗这个页面去签别的东西,比如转移你的账户。
  4. 服务器只保存新的应用密钥,从不保存助记词或托管密钥。

万一出了问题,暴露的也只有应用密钥:在你撤销之前它能以你的名义发帖,但拿不走你的账户。客户端的 Keys 页面有一个撤销按钮,不需要助记词(见下文)。

读:时间线是怎么来的

Farcaster 没有"时间线 API"。客户端要用原始消息自己拼出来。Homestead 分三步,全部针对你的节点:

  1. 你关注了谁? GET /v1/linksByFid?fid=<你>&link_type=follow,读完所有分页。
  2. 回填。 对你关注的每个账户,GET /v1/castsByFid?fid=<对方>&reverse=true&pageSize=10,每次并发 8 个请求。对着 localhost 上的节点,即使关注了几千人也只要几秒。
  3. 保持实时。 对每个分片,从当前区块开始读取节点的事件流:GET /v1/events?shard_index=1&from_event_id=<高度 × 2^14>。每个 MERGE_MESSAGE 事件都是你的节点刚从某个区块中接受的消息。你关注的人的帖子进入时间线;删除的帖子移出;你自己的关注和点赞(即使来自别的应用)也会同步到客户端。

Live 标签页直接展示第 3 步:你的节点合并的每一条帖子,实时到达。这是你的节点所看到的网络,不排序、不推荐;对一个全新的测试账户来说,也是找人关注的最好地方。

写:你的帖子去了哪里

当你点击 Cast:

  1. 服务器用你的正文、提及(在你的节点上解析成 FID)和嵌入链接构建一条 CAST_ADD,用应用密钥签名,把 protobuf 字节 POST 到你节点的 /v1/submitMessage。
  2. 你的节点像验证者一样检查它:签名有效、密钥有效且有相应权限、存储空间足够。通过后,节点在 mempool 主题上把它 gossip 给验证者。只读节点没有自己的内存池,此时什么也不存。
  3. 某个验证者把它打包进区块,验证者们达成共识。你的节点收到这个区块并合并这条消息,它就出现在事件流里。

客户端会在角落显示一张回执,例如 accepted by your node in 40 ms → in block 49,013,227 (shard 1) after 1.6 s:前一个数字是你的节点验证所用的时间,后一个是直到你的节点在已确定区块中看到这条消息的时间。

不要用 /v1/validateMessage 来预判一次写入能否成功:它只检查编码、哈希和签名。2026-10-19 测试时,对一条由未授权密钥签名的帖子,它也返回了 "valid": true。

关注(LINK_ADD)、点赞和转发(REACTION_ADD)以及它们的取消,流程完全相同。删帖发送的是 CAST_REMOVE;原帖会变成一个"墓碑",在被挤出之前仍然占用你的存储额度。

存储租金

bash
curl -s 'localhost:3381/v1/storageLimitsByFid?fid=1' | jq '{units, unitDetails, casts: (.limits[] | select(.name == "CASTS"))}'
json
{
  "units": 22,
  "unitDetails": [
    { "unitType": "UnitTypeLegacy", "unitSize": 19 },
    { "unitType": "UnitType2024", "unitSize": 3 },
    { "unitType": "UnitType2025", "unitSize": 0 }
  ],
  "casts": { "name": "CASTS", "limit": 101000, "used": 3797 }
}

19 个 legacy 单元 × 5,000 + 3 个 2024 单元 × 2,000 = 101,000 条帖子。一个全新账户只有一个 2025 单元,只能存 100 条帖子,所以在测试账户上,旧帖子很快就会被修剪。

选择看哪些应用的内容

Homestead 里每条帖子都标明了是哪个应用发出的:via Warpcast、via Firefly App、via Neynar,或者 own key(作者在运行自己的客户端,就像你现在这样)。

消息里并没有"客户端"字段。Homestead 是通过应用密钥推算出来的,原理见上面的概念框:

cast.signer  →  GET /v1/signer?fid=<author>&signer=<key>  →  requestFid  →  that FID's profile

对免 gas 密钥,节点直接返回 requestFid。对旧的链上密钥,它藏在当初随 KeyRegistry 交易提交的、ABI 编码的 SignedKeyRequestMetadata 里,Homestead 会自己解码。例如 @dwr 的一把密钥的元数据解码后是 requestFid: 9152,即 Farcaster 应用。一把密钥对应的应用永不改变,所以每次查询结果都会永久缓存。

在 Filter apps 页面,你可以隐藏勾选的应用发出的帖子,或者只显示它们发出的帖子。屏蔽自动发帖的机器人,或者只看人们在小众独立客户端里写的内容。数据由你的节点提供,规则由你决定。

撤销密钥

三种方式,从温和到强硬:

  1. 不再使用。 免 gas 密钥在 TTL(这里是 30 天)内未使用就会过期。
  2. 紧急按钮。 Keys → Revoke this client's key 会发送一条由这把密钥自己签名的 KEY_REMOVE。免 gas 密钥可以在没有托管密钥的情况下撤销自己,并使用按申请应用区分的独立 nonce 计数器,因此被攻破的应用可以迅速废掉自己的所有密钥。
  3. 用托管地址。 由托管密钥签名的 KEY_REMOVE 可以删除免 gas 密钥;KeyRegistry 的 remove 交易可以删除链上密钥(Farcaster 钱包里"已连接应用"页面做的就是这个)。

Keys 页面还会列出你账户上的每一把密钥(链上的和免 gas 的),以及申请它的应用。值得看一眼:大多数人连接过的应用比自己记得的多。


日常使用

命令作用
./homestead status每个分片的同步状态
./homestead logs node · logs client查看日志
./homestead ssh登录服务器
./homestead tunnellocalhost:8080 → 客户端,localhost:3000 → Grafana(账号 admin/admin,请修改)
./homestead clientgit pull 后重新部署;保留口令和密钥(--new-passphrase 可更换口令)
./homestead destroy删除服务器、存储卷、防火墙和密钥,停止计费

升级。 节点每周自动升级(cron 运行 snapchain.sh autoupgrade)。协议升级按引擎版本和时间戳排期,长期不升级的节点最终会跟不上链。长时间离开后,请检查一下 ./homestead status。

备份。 节点数据库随时可以从快照重建。唯一值得备份的是客户端的 Docker 卷(homestead_client-data):里面是应用密钥和口令哈希。丢了也只需重新连接一次。

费用。 Hetzner 按小时计费,月费封顶。最大的一项是 2 TB 存储卷(按 2026 年 10 月价格每月约 114 欧元)。测试结束后,用 ./homestead destroy 删除一切。

故障排查

现象原因与解决
provision 提示没有可用机型该地区缺货。试试 HOMESTEAD_LOCATION=nbg1(或 hel1、ash、hil)。
status 长时间停在同一个分块下载卡住了。./homestead logs node;重启容器会断点续传。
恢复过程中磁盘不足空闲空间不到约 1.5 TB。扩容存储卷,或用更大的卷重来(HOMESTEAD_DISK_GB)。
HTTPS 一直起不来80/443 端口被挡,或 Let's Encrypt 限流。查看 ./homestead logs client。期间可用 --private。
No Farcaster account for this address助记词或账户序号不对,或者节点还没同步完。Farcaster 应用使用序号 0。
Signatures don't match this account's custody address钱包用来签名的地址与查询的地址不同。在钱包里切换账户后重试。
帖子一直没进区块gossip 中丢失了。重新提交;回执会显示它何时上链。
反复提示口令错误尝试 10 次后登录会暂停 10 分钟。./homestead client --new-passphrase 可以设置新口令。

参考

术语表

术语含义
FIDFarcaster ID:账户的永久编号,由 OP Mainnet 上的 IdRegistry 发放。
托管地址拥有某个 FID 的以太坊地址。它的私钥就是万能钥匙。
助记词推导出托管密钥的 12 或 24 个 BIP-39 单词。
恢复地址在托管地址丢失时,有权把 FID 转移到新托管地址的地址。
应用密钥 / signer被授权为某个 FID 签署消息的 Ed25519 密钥。分链上(KeyRegistry)和免 gas(KEY_ADD)两种。
requestFid申请某把应用密钥的应用的 FID。
消息一次签名的操作:CAST_ADD、REACTION_ADD、LINK_ADD、USER_DATA_ADD……
存储单元按 FID、按消息类型租用的容量。一年,约 0.2 美元。
fname链下用户名,如 @alice,由 Farcaster 的域名服务器签发。节点保存它的签名证明,任何客户端都能解析。
Snapchain把消息排序并按区块存储的网络。
分片Snapchain 的一个分区。分片 0 给其余分片排序;消息分片保存账户数据。
验证者需许可集合中负责提议区块并投票的节点。
只读节点跟随链但不投票的节点。会验证并转发写操作。
blockDelay你的节点上某个分片的最新区块比当前时间落后的秒数。
Farcaster 纪元2021-01-01T00:00:00Z。消息时间戳从此刻起计秒。

Homestead 用到的节点接口

每次读取都是一个你可以自己对 localhost:3381 运行的 GET 请求:

接口用途
/v1/info同步状态、分片高度
/v1/onChainIdRegistryEventByAddress?address=托管地址 → FID
/v1/onChainEventsByFid?fid=&event_type=EVENT_TYPE_ID_REGISTER这个地址还是托管地址吗?
/v1/storageLimitsByFid?fid=存储单元和上限
/v1/signersByFid?fid=所有应用密钥(链上和免 gas),以及下一个 KEY_ADD 的 nonce
/v1/signer?fid=&signer=单把密钥及其 requestFid
/v1/linksByFid?fid=&link_type=follow你关注的人
/v1/castsByFid、/v1/castById、/v1/castsByParent、/v1/castsByMention帖子、讨论串、提及
/v1/reactionsByFid、/v1/reactionsByCast点赞和转发
/v1/userDataByFid?fid=个人资料
/v1/userNameProofByName?name=@用户名 → FID,用于提及
/v1/events?shard_index=&from_event_id=实时事件流
POST /v1/submitMessage所有写操作,以 protobuf 字节提交

我们发现的过时文档

做这个项目时,我们把每个说法都对照了 Snapchain 源码。以下是文档已经过时的地方,以及我们准备的修正(详情与进展):

资料来源

测试情况

基于 Snapchain 0.14.2–0.14.3(引擎 V20)、@farcaster/core 0.20.0 和 Ubuntu 24.04。最后核对于 2026-10-19。