Web3 内部
警告
文档的这一部分面向高级用户。如果你不知道你在做什么,你可能应该远离这些 API。
Web3 库在 web3 对象公开的公共 api 和 web3 连接的后端或节点之间有多层抽象。
- 供应商负责与区块链的实际通信,比如通过 HTTP 或 IPC 套接字发送 JSON-RPC 请求。
- 中间件提供钩子来监控和修改请求以及来自供应商的响应。这些可以是在所有提供商上运行的全球 T2,也可以是特定于一个提供商的。
- 管理器提供线程安全和特权,允许异步使用 web3。
下面是您可能想对这些 API 做的一些常见事情。
- 将某些 RPC 请求重定向到不同的供应商,例如将所有的读操作发送到由 Infura 支持的供应商,将所有的写操作发送到您控制的 go-ethereum 节点。
- 透明地拦截通过
eth_sendTransaction
发送的交易,在本地签名,然后通过eth_sendRawTransaction
发送。 - 修改 RPC 请求的响应,使其以不同的格式返回,例如将所有整数值转换为十六进制表示。
- 验证 RPC 请求的输入
请求生命周期
每个 web3 RPC 调用以下列方式通过这些层。
*********** ************
| Request | | Response |
*********** ************
| ^
v |
+-----------------------------+
| Manager |
+-----------------------------+
| ^
v |
+-----------------------------+
| Global Middlewares |
+-----------------------------+
| ^
v |
+-----------------------------+
| Provider Middlewares |
+-----------------------------+
| ^
v |
+-----------------------------+
| Provider |
+-----------------------------+
您可以将这种关系想象成一个洋葱,以供应商为中心。请求来自洋葱之外的管理者,通过洋葱的每一层向下传递,直到到达中心的供应商。然后,供应商处理请求,产生一个响应,该响应将从洋葱的中心通过每一层传递回来,直到最终被管理器返回。
在 web3 与多个提供商合作的情况下,同样的生命周期适用。管理器将遍历每个供应商,从第一个返回响应的供应商返回响应。
供应商
提供商负责所有直接的区块链交互。在大多数情况下,这意味着通过 HTTP 或 IPC 套接字与以太坊节点的 JSON-RPC 服务器进行交互。然而,没有什么要求供应商是基于 RPC 的,允许供应商为测试目的而设计,使用内存中的 EVM 来完成请求。
编写您自己的提供程序
编写自己的供应商需要实现两个必需的方法,并设置供应商应该使用的中间件。
BaseProvider.make_request(*method*, *params*)
每个供应商类必须实现这个方法。这个方法应该在成功的情况下返回一个带有'result'
键的 JSON 对象,或者在失败的情况下返回一个'error'
键。
method
这将是一个表示被调用的 JSON-RPC 方法的字符串,比如'eth_sendTransaction'
。- 这将是被调用的 JSON-RPC 方法的参数列表或其他可迭代的参数。
BaseProvider.isConnected()
该函数应返回True
或False
,这取决于供应商是否应被视为与连接。例如,如果套接字是打开的,基于 IPC 套接字的供应商应该返回True
,如果套接字是关闭的,应该返回False
。
BaseProvider.middlewares
这应该是一个可迭代的中间件。
您可以通过分配给provider.middlewares
来设置一个新的中间件列表,将第一个处理请求的中间件放在列表的开头。
## 中间件
注意
web3 中的中间件 API 大量借鉴了 1.10.0 版本中引入的 Django 中间件 API
中间件为实现 web3 请求的业务逻辑层提供了一个简单而强大的 api。编写中间件很简单。
def simple_middleware(make_request, w3):
# do one-time setup operations here
def middleware(method, params):
# do pre-processing here
# perform the RPC request, getting the response
response = make_request(method, params)
# do post-processing here
# finally return the response
return response
return middleware
也可以将中间件实现为一个类。
class SimpleMiddleware:
def __init__(self, make_request, w3):
self.w3 = w3
self.make_request = make_request
def __call__(self, method, params):
# do pre-processing here
# perform the RPC request, getting the response
response = self.make_request(method, params)
# do post-processing here
# finally return the response
return response
make_request
参数是一个可调用的参数,它接受两个位置参数,method
和params
,它们对应于被调用的 RPC 方法。不要求调用make_request
函数。例如,如果您正在编写一个缓存某些方法响应的中间件,您的中间件可能不会调用make_request
方法,而是从某个本地缓存中获取响应。
默认情况下,Web3 将使用web3.middleware.pythonic_middleware
。这个中间件为请求和响应执行以下翻译。
- 数字请求参数将被转换为十六进制表示形式
- 数字响应将从十六进制表示转换为整数表示。
RequestManager
对象公开了middleware_onion
对象来管理中间件。为了方便起见,它也暴露在Web3
对象上。那个 API 在 配置中间件 中有详细介绍。
经理
管理器充当请求/响应生命周期的看门人。您不太可能需要更改管理器,因为大多数功能都可以在中间件层实现。