#ipc #forge #client #foundry #client-server

app forge-exec-ipc-client

在执行Solidity代码时,允许Forge连接到IPC服务器的ipc客户端

4个版本

0.1.1 2023年4月30日
0.1.0 2023年4月29日
0.0.2 2023年4月28日
0.0.1 2023年4月28日

#2785魔法豆

每月 38 次下载

MIT 许可证

15KB
138

forge-exec-ipc-client

以单独的进程执行程序并通过IPC连接到它。

forge-exec 使用以建立与 forge 的双向通信通道

因为Forge期望在程序退出后将ffi输出提供给stdout,所以每次收到程序回复时都会执行forge-exec-ipc-client

它是如何工作的?

forge-exec 被用于你的Forge项目中,并将执行以下操作

  • 将执行 forge-exec-ipc-client init <program> [...<args>]
  • forge-exec-ipc-client (此包) 将执行程序并附带提供的参数,并为其创建一个新的进程
  • 在执行此操作时,它还将附加一个随机生成的套接字/命名管道路径/名称,我们称之为 socketID(以 ipc: 前缀)
  • 因此,程序将通过 <program> [...<args>] ipc:<socketID> 调用
  • 该程序需要尽快创建一个ipc服务器,以监听给定的 socketID
  • forge-exec-ipc-client 将尝试在 3 秒内连接到该套接字/命名管道,成功后会将 socketID 作为 abi 编码的字符串打印到 stdout 并退出。
  • forge 会捕获该信息,并执行新的 ffi 调用:forge-exec-ipc-client exec <> 0x
  • forge-exec-ipc-client 会检测到第一个参数为 exec,并连接到由 program 创建的 ipc 服务器。
  • 连接成功后,它将发送数据参数(第一次调用总是 0x)到该服务器。
  • 这意味着该 program 可以(并且需要)保持活跃状态,监听这些调用。
  • 在接收到第一个调用 0x 后,程序应开始执行其用户代码。
  • 当它需要向 forge 发送请求时,它只需在通过 abi 编码的数据建立的 ipc 套接字上回复即可(见下方的 格式)。
  • forge-exec-ipc-client 将在接收后将其写入 stdin 并立即退出(尽管 program 继续运行,除非它执行了最后的回复(终止))。
  • forge-exec 会捕获数据并将其解释为请求。其中之一是终止请求,可能包含 program 可能希望返回的数据。
  • 如果数据不是终止请求,forge-exec 将执行请求(目前只支持 send_transaction 和 getBalance)并将数据返回。
  • 它将通过以下方式返回数据:forge-exec-ipc-client exec <> <>
  • 直到程序发送终止请求,此过程会重复。
  • 在某些错误情况下,forge-exec 也可以调用 terminate 请求,要求程序停止,这将导致 forge 侧发生回滚。
  • 目前,在 forge-exec 侧,abi 解码可能会失败,程序将无法接收到通知。因此,程序应处理超时情况,以停止其 ipc 服务器,避免在操作系统资源上挂起。

ipc-server 实现

虽然您可以在 forge-exec-ipc-client 执行的程序中自行编写 ipc 处理,但您可能希望将其抽象化。

目前有一个用 TypeScript 实现的版本,它抽象了流程,让您可以编写以下内容:

import { execute } from "forge-exec-ipc-server";
execute(async (forge) => {
  const address = await forge.create({
    from: "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
    data: "0x608060405234801561001057600080fd5b5060f78061001f6000396000f3fe6080604052348015600f57600080fd5b5060043610603c5760003560e01c80633fb5c1cb1460415780638381f58a146053578063d09de08a14606d575b600080fd5b6051604c3660046083565b600055565b005b605b60005481565b60405190815260200160405180910390f35b6051600080549080607c83609b565b9190505550565b600060208284031215609457600080fd5b5035919050565b60006001820160ba57634e487b7160e01b600052601160045260246000fd5b506001019056fea2646970667358221220f0cfb2159c518c3da0ad864362bad5dc0715514a9ab679237253d506773a0a1b64736f6c63430008130033",
  });
  return {
    types: [{ type: "address" }],
    values: [address],
  };
});

forge-exec-ipc-server 也处理超时。

请注意,尽管 Node.js 有启动开销,但一旦程序执行,它就会保持活跃状态,因此可以执行复杂的脚本。

格式

ipc 客户端和服务器之间的通信格式如下

来自程序

作为 ipc 服务器的程序只能向 ipc 客户端发送一种类型的信息。

它们都必须以 \n 字符结束,该字符作为 ipc 信息分隔符。

这些都是表示为十六进制字符串的 abi 编码消息,并将原样(除去 \n 字符)转发到 forge-exec 的 solidity 代码。

编码的格式是一个元组 (uint32, bytes),其中uint32表示请求类型,bytes是特定于请求类型的abi编码数据。

请求类型 0 是终止信号,表示程序已执行完成,bytes 数据表示程序想要的内容,是 forge-exec execute 函数调用返回的内容。

否则,目前还有2种请求,很快还会添加更多。

请参阅 请求列表

来自 forge

发送到 ipc 服务器的只有两种类型的数据:responseterminate

所有这些都必须以 \n 字符结尾

响应

响应以 response: 开头

程序实际接收到的第一条消息是一个特殊的消息: response:0x\n,仅表示程序可以开始执行并将请求发送回 forge。

除了这个特殊请求之外,目前程序可以向 forge 发送两种类型的请求,因此目前只有两种类型的响应

请参阅 请求列表

示例
  • "response:\n"

终止

终止请求以 terminate: 开头

在前面是错误消息

示例
  • "terminate:Something Wrong Happened\n"

请求列表

终止

来自程序

示例

编码(["uint32", "bytes"],[0, "0x01"])

这将终止执行并返回 0x1 作为 bytes

forge 不会返回任何内容

发送交易

来自程序

示例

编码(["uint32", "bytes"],[1, 编码(["","","",""], [])])

来自 forge-exec-ipc-client

示例

"response:0xFFEEFFEEFFEEFFEEFFEEFFEEFFEEFFEEFFEEFFEE\n"

这返回了部署的合约地址

依赖

~2.5MB
~36K SLoC