ERC-7774: Web3 URL 中 ERC-5219 模式下的缓存失效
引入一种新的 HTTP 缓存控制方法,使用 EVM 事件进行失效处理
Authors | Nicolas Deschildre (@nand2), Sam Wilson (@SamWilsn) |
---|---|
Created | 2024-09-20 |
Discussion Link | https://ethereum-magicians.org/t/erc-7774-cache-invalidation-in-erc-5219-mode-web3-url/21255 |
Requires | EIP-5219, EIP-6944 |
摘要
在 ERC-6860 web3://
标准的上下文中,此 ERC 扩展了 ERC-6944 解析模式。它引入了解决限制的机制,这些限制阻止了标准 RFC 9111 HTTP 缓存的使用。
动机
调用以太坊 RPC 提供商代价高昂——无论是对于本地节点的 CPU 而言,还是对于付费外部 RPC 提供商而言。此外,外部 RPC 提供商受到速率限制,这在加载 web3://
URL 时可能会迅速导致中断。
因此,实现缓存机制以尽可能减少 RPC 调用是有意义的。由于 web3://
旨在尽可能接近 HTTP,因此利用标准 RFC 9111 HTTP 缓存是自然的选择。在 ERC-6944 解析模式中,智能合约已经可以返回标准的 HTTP 缓存头,如 Cache-Control
和 ETag
。
然而,由于 ERC-6944 解析模式不将请求 HTTP 标头转发到智能合约,因此智能合约无法处理 If-None-Match
和 If-Modified-Since
缓存验证标头。 因此,它们仅限于使用 Cache-control: max-age=XX
机制,这会导致每个缓存验证请求都触发 RPC 调用,从而重新生成完整响应。
此 ERC 提出了一种解决方案,通过允许网站通过智能合约事件广播缓存失效来绕过此限制。
此外,即使智能合约可以读取请求 HTTP 标头,使用智能合约事件也更有效,因为它将缓存失效逻辑移到了合约外部。
我们将此功能添加到 ERC-6944 解析模式中,因为它可以在不更改接口的情况下添加。 未来允许请求 HTTP 标头的解析模式也可以实现此 ERC。
规范
此标准为请求响应的 Cache-Control
标头引入了 evm-events
缓存指令,作为 RFC 9111 第 5.2.3 节中定义的扩展指令。
当 ERC-6944 解析模式网站想要对请求使用基于事件的缓存时,它必须:
- 在响应的
Cache-Control
标头中包含evm-events
指令。 - 按照传统的 RFC 9111 HTTP 缓存,在响应中包含
ETag
和/或Cache-Control
标头。 - 当响应的输出发生变化并且它认为需要清除缓存时,在智能合约中为该路径发出缓存失效事件(如下定义)。
evm-events
缓存指令的值是可选的,可用于指定侦听其他智能合约上的其他事件,和/或其他路径。 ABNF 符号中的缓存指令值语法为:
cache-directive-value = [ address-path-absolute *( " " address-path-absolute ) ]
address-path-absolute = [ address ] path-absolute [ "?" query ]
address = "0x" 20( HEXDIG HEXDIG )
path-absolute = <path-absolute, see RFC 3986, Section 3.3>
query = <query, see RFC 3986, Section 3.4>
示例:
Cache-control: evm-events
:当响应请求的合约为已服务的页面路径发出缓存清除事件时,返回此指令的页面的缓存将被清除。Cache-control: evm-events="/path/path2"
:与第一个示例的行为相同,但此外,当响应请求的合约为路径/path/path2
发出缓存清除事件时,返回此指令的页面的缓存将被清除。Cache-control: evm-events="0xe4ba0e245436b737468c206ab5c8f4950597ab7f/path/path2"
:与第一个示例的行为相同,但此外,当合约0xe4ba0e245436b737468c206ab5c8f4950597ab7f
为路径/path/path2
发出缓存清除事件时,返回此指令的页面的缓存将被清除。Cache-control: evm-events="0xe4ba0e245436b737468c206ab5c8f4950597ab7f"
:与第一个示例的行为相同,但此外,当合约0xe4ba0e245436b737468c206ab5c8f4950597ab7f
为已服务的页面路径发出缓存清除事件时,返回此指令的页面的缓存将被清除。Cache-control: evm-events="/path/path2 /path/path3"
:与第一个示例的行为相同,但此外,当响应请求的合约为路径/path/path2
或/path/path3
发出缓存清除事件时,返回此指令的页面的缓存将被清除。
缓存失效事件
该事件定义为:
event ClearPathCache(string[] paths);
此事件清除 paths
数组的缓存。 每个 path
引用 ERC-6860 中 ABNF 定义的 pathQuery
部分。
path
必须不能以/
结尾,除非整个路径是根路径,即/
。- 如果两个
paths
具有相同的 ERC-5219 资源条目并且它们的参数值匹配(无论顺序如何),则认为它们是相同的。
示例:
/test?a=1&b=2
和/test?b=2&a=1
被认为是相同的。
通配符用法
paths
可能包含 *
通配符,规则如下:
- 资源条目中的通配符:
- 通配符 (
*
) 可以在 ERC-5219 资源条目中单独使用。 - 通配符不能与同一条目中的其他字符组合使用; 如果是,则将忽略
path
。 - 通配符至少需要匹配一个字符。
示例:
/*
将匹配/test
,但不匹配/test/abc
,也不匹配/
。/test/*
将匹配/test/abc
,但不匹配/test/
或/test/abc/def
。/*/abc
将匹配/test/abc
,但不匹配//abc
。/t*t
无效,因此将忽略path
。
- 通配符 (
- 参数值中的通配符:
- 通配符可以单独用作参数值。
- 通配符不能与参数值中的其他字符组合使用,否则将忽略
path
。 - 参数值中的通配符至少需要匹配一个字符。
示例:
/abc?a=*
将匹配/abc?a=zz
,但不匹配/abc?a=
或/abc?a=zz&b=cc
。/abc?a=*&b=*
将匹配/abc?a=1&b=2
和/abc?b=2&a=1
。/abc?a=z*
无效,因此将忽略path
。
- 特殊情况:全局通配符:
- 仅包含
*
的path
将匹配智能合约中的每个路径。
- 仅包含
通配符有意限制于这些简单情况,以方便高效的路径查找实现。
缓存行为
web3://
客户端的缓存失效状态
对于每个链和智能合约,web3://
客户端可以处于以下两种缓存失效状态之一:
-
侦听事件:
web3://
客户端必须侦听前面定义的缓存失效事件,并应尽可能接近实时。 -
不侦听事件: 这是未实现此 ERC 时的默认状态。 在这种状态下,
web3://
客户端会忽略所有 HTTP 缓存验证请求(例如,If-None-Match
、If-Modified-Since
请求标头)。
web3://
客户端可以随时在这些状态之间切换,并且可以实现启发式方法,通过根据需要切换状态来优化 RPC 提供商的使用。
缓存键值映射
web3://
客户端维护用于缓存的键值映射,每当它从“侦听事件”过渡到“不侦听事件”时,必须清除该映射。 该映射的结构如下:
mapping(
(<链 ID>, <合约地址>, <ERC-6860 pathQuery>)
=>
(<上次修改日期>, <ETag>)
)
必要时,可以将其他元素包含在映射键中。 例如,ERC-7618 要求在映射键中包含 Accept-Encoding
请求标头。
处理“侦听事件”状态下的请求
当在“侦听事件”状态下收到请求时:
- 如果不存在映射条目:
web3://
客户端查询智能合约。- 如果响应在
Cache-Control
标头中包含evm-events
指令和一个ETag
,则使用ETag
创建一个映射条目。 - 如果响应在
Cache-Control
标头中包含evm-events
指令和max-age=XX
指令,则使用“上次修改日期”创建一个映射条目,该日期按以下优先级顺序确定:Last-Modified
标头(如果存在)。Date
标头(如果存在)。- 否则,为查询智能合约的区块日期。
- 如果响应同时包含
ETag
和Cache-Control: evm-events max-age=XX
指令,则会创建一个包含ETag
和“上次修改日期”的单个映射条目。
- 如果存在映射条目:
- 如果请求包含有效的
If-None-Match
标头:- 如果映射中的
ETag
与If-None-Match
值匹配,则web3://
客户端会立即返回304 Not Modified
响应。 - 如果
ETag
不匹配,则客户端会查询智能合约,删除映射条目,并像不存在映射条目一样处理请求。
- 如果映射中的
- 如果请求包含有效的
If-Modified-Since
标头:- 如果映射中的“上次修改日期”早于
If-Modified-Since
日期,则客户端会立即返回304 Not Modified
响应。 - 否则,客户端会查询智能合约,删除映射条目,并像不存在映射条目一样处理请求。
- 如果映射中的“上次修改日期”早于
- 如果请求既不包含
If-None-Match
标头,也不包含If-Modified-Since
标头(或者它们无效):- 客户端会查询智能合约,删除映射条目,并像不存在映射条目一样处理请求。
- 如果请求包含有效的
通过区块链事件进行缓存失效
在“侦听事件”状态下,web3://
客户端侦听区块链中上一节中定义的缓存失效事件。 对于每个路径匹配,它都会删除相应的映射条目。
理由
为了尽可能接近标准 HTTP,我们重用了 HTTP 缓存机制标头。
使用 evm-events
指令是必要的,以避免网站使用传统的 RFC 9111 HTTP 缓存标头,但合约未能通过不发出事件来实现此 ERC 的情况。 在这种情况下,实现此 ERC 的 web3://
客户端将无限期地为该网站提供过时的内容。
安全考虑
在用户交易发出缓存清除事件与 web3://
客户端选取和处理该事件之间的延迟期间,将提供过时的内容。
对于每个缓存的页面,网站必须正确实现缓存失效事件; 否则,将无限期地提供过时的内容。
如果发生链重组,web3://
客户端必须回滚其缓存状态,否则将提供已回滚的内容,直到发生下一次缓存清除事件。
版权
根据 CC0 放弃版权和相关权利。
Citation
Please cite this document as:
Nicolas Deschildre (@nand2), Sam Wilson (@SamWilsn), "ERC-7774: Web3 URL 中 ERC-5219 模式下的缓存失效 [DRAFT]," Ethereum Improvement Proposals, no. 7774, September 2024. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7774.