From 79d58dd56949ee0e540fb30c892cc998c76a9aeb Mon Sep 17 00:00:00 2001 From: nand Date: Fri, 20 Sep 2024 14:32:58 +0200 Subject: [PATCH 01/16] Resource request mode: Initial draft for caching --- ERCS/erc-7761.md | 115 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 ERCS/erc-7761.md diff --git a/ERCS/erc-7761.md b/ERCS/erc-7761.md new file mode 100644 index 0000000000..2386b5ff21 --- /dev/null +++ b/ERCS/erc-7761.md @@ -0,0 +1,115 @@ +--- +eip: 7761 +title: Caching in ERC-5219 mode Web3 URL +description: In ERC-5219 resolve mode, specify how to support caching similar to HTTP caching +author: Nicolas Deschildre (@nand2) +discussions-to: https://ethereum-magicians.org/t/eip-4804-web3-url-to-evm-call-message-translation/8300 +status: Draft +type: Standards Track +category: ERC +created: 2024-09-20 +requires: 5219, 6944 +--- + +## Abstract + +In the context of the [ERC-6860](./eip-6860.md) `web3://` standard, this ERC extends the [ERC-6944](./eip-6944.md) resolve mode: This standard specifies that the HTTP caching mechanism as defined in [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) can be reused, and add mechanisms to alleviate the fact that request HTTP headers are not forwarded to the smart contract. + +## Motivation + +Calls to an Ethereum RPC provider are costly: CPU-wise for local nodes, and money-wise for paid external RPC providers. Additionally, external RPC providers are rate-limited, and can quickly break the loading of `web3://` URLs. + +Thus, it makes sense to use a caching mechanism to limit RPC calls. + +## Specification + +In the [ERC-6944](./eip-6944.md) resolve mode, this standard indicates that the standard HTTP mechanism as defined in [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) can be reused : + +- HTTP request responses can contains HTTP caching headers, such as `Cache-Control`, `ETag`. +- Since HTTP request headers cannot be forwarded to the smart contract, cache validation headers such as `If-None-Match` and `If-Modified-Since` cannot be used. This ERC defines an alternate mechanism to broadcast cache invalidations with smart contract events. + +### Caching behavior + +The `web3://` client will have 2 possible states per chain and per smart contract regarding cache invalidation : + +- `Listening` : The `web3://` client MUST listen for cache invalidation events (defined in next section). It MUST try to stay as close to real time as possible. +- `Not listening` : The opposite of the above state, and the default constant state when this ERC is not implemented: the `web3://` client ignore all HTTP caching validation requests (the `If-None-Match`, `If-Modified-Since` request headers). + +The `web3://` client can switch between each state anytime, and MAY implement state-switching heuristics to optimize the RPC providers usage. + +The `web3://` client will host a caching key-value mapping, which MUST be cleared on any `Listening` to `Not listening` state change : + +``` +mapping( + (, , , )) + => + (, ) +) +``` + +In `Listening` state, when a incoming request arrives : + +- If a mapping entry does not exist : the `web3://` client query the smart contract. + - If the request response contains an `Etag` HTTP header, a mapping entry is created with the `Etag`. + - If the request response contains a `max-age` directive in a `Cache-Control` HTTP header, a mapping entry is created with the `last modified date` being : + - The content of the `Last-Modified` HTTP header, if present + - The content of the `Date` HTTP header, if present + - The date of the block at which the smart contract was queried otherwise + - If the request response match both cases above, then a single mapping entry is created with both the `Etag` and the `last modified date` fields filled. +- If a mapping entry already exists : + - If the request contains a valid `If-None-Match` HTTP header: + - If the mapping entry has the same `Etag` as the one provided by `If-None-Match`, then the `web3://` client returns a HTTP code `304 Not Modified` response right away. + - Otherwise if the mapping entry has a non-empty different `ETag`, the `web3://` client query the smart contract. The mapping entry is deleted, and the answer is processed as if there had been no mapping entry initially. + - Otherwise the `Etag` of the mapping entry is empty (and the `last modified date` is not). The `web3://` client query the smart contract. + - If the request response contains an `Etag` HTTP header, the mapping entry `ETag` is filled. + - If the request response contains a `max-age` directive in a `Cache-Control` HTTP header, the mapping entry `last modified date` field is updated with the date value computed as in the no-mapping-exists scenario above. + - If the request contains a valid `If-Modified-Since` HTTP header: + - If the mapping entry has a `last modified date`, and is before the date provided by `If-Modified-Since`, then the `web3://` client returns a HTTP code `304 Not Modified` response right away. + - Otherwise if the mapping entry has a `last modified date` which is after, the `web3://` client query the smart contract. The mapping entry is deleted, and the answer is processed as if there had been no mapping entry initially. + - Otherwise the `last modified date` field of the mapping entry is empty (and the `Etag` is not). The `web3://` client query the smart contract. + - If the request response contains an `Etag` HTTP header, the mapping entry `ETag` is updated. + - If the request response contains a `max-age` directive in a `Cache-Control` HTTP header, the mapping entry `last modified date` field is filled with the date value computed as in the no-mapping-exists scenario above. + - If the request does not have a `If-None-Match` or `If-Modified-Since` HTTP header (or are invalid): the `web3://` client query the smart contract. + - If the request response contains an `Etag` HTTP header, the mapping entry `Etag` field is updated. + - If the request response contains a `max-age` directive in a `Cache-Control` HTTP header, the mapping entry `last modified date` field is updated with the date value computed as in the no-mapping-exists scenario above. + +In `Listening` state, the `web3://` client listens the blockchain for the cache invalidation events which are defined in the next section. For each path match, it will delete their corresponding mapping entry. + +### Cache invalidation event + +Unlike standard HTTP, we can leverage the fact that the website can broadcast cache invalidations with a smart contract event. + +The event definition is : + +``` +event ClearPathCache(string[] paths); +``` + +A `path` contains the `pathQuery` part as defined in the ABNF definition of [ERC-6860](./eip-6860.md). They MAY contains `*` wildcards : + +- A wildcard can be used in a [ERC-5219](./eip-5219.md) resource entry. A wildcard CANNOT be used with other characters, or the path will be ignored. A wildcard require at least one character to match. Examples : + - `/*` will match `/test` but not `/test/abc` + - `/test/*` will match `/test/abc` but will not match `/test/` and not match `/test/abc/def` + - `/*/abc` will match `/test/abc`, but will not match `//abc` + - `/t*t/` is invalid, the path is ignored. +- A wildcard can be used in a [ERC-5219](./eip-5219.md) param value. A wildcard CANNOT be used with other characters, or it will the path be ignored. A wildcard require at least one character to match. Examples : + - `/abc?a=*` will match `/abc?a=zz` but will not match `/abc?a=` and not match `/abc?a=zz&b=cc` + - `/abc?a=*&b=*` will match `/abc?a=1&b=2` and `/abc?b=2&a=1` + - `/abc?a=z*` is invalid, the path is ignored. +- Special case: Global wildcard : A `path` containing a single `*` match every path of the smart contract. + +Wildcards are limited to these simple cases to simplify fast path lookup implementations. + +## Rationale + +We add this feature to the [ERC-6944](./eip-6944.md) resolve mode because it can be added without changes the interface. + +To stay as close as possible to standard HTTP, we don't introduce new HTTP headers but reuse the HTTP caching mechanism header. + +## Security Considerations + +No security considerations were found. + +## Copyright + +Copyright and related rights waived via [CC0](../LICENSE.md). From 2d9255f239a1a06b1479373fb9515703e6ac4792 Mon Sep 17 00:00:00 2001 From: nand Date: Fri, 20 Sep 2024 16:17:12 +0200 Subject: [PATCH 02/16] Draft part 2 --- ERCS/erc-7761.md | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/ERCS/erc-7761.md b/ERCS/erc-7761.md index 2386b5ff21..1c55b90823 100644 --- a/ERCS/erc-7761.md +++ b/ERCS/erc-7761.md @@ -1,6 +1,6 @@ --- eip: 7761 -title: Caching in ERC-5219 mode Web3 URL +title: Advanced caching in ERC-5219 mode Web3 URL description: In ERC-5219 resolve mode, specify how to support caching similar to HTTP caching author: Nicolas Deschildre (@nand2) discussions-to: https://ethereum-magicians.org/t/eip-4804-web3-url-to-evm-call-message-translation/8300 @@ -13,7 +13,7 @@ requires: 5219, 6944 ## Abstract -In the context of the [ERC-6860](./eip-6860.md) `web3://` standard, this ERC extends the [ERC-6944](./eip-6944.md) resolve mode: This standard specifies that the HTTP caching mechanism as defined in [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) can be reused, and add mechanisms to alleviate the fact that request HTTP headers are not forwarded to the smart contract. +In the context of the [ERC-6860](./eip-6860.md) `web3://` standard, this ERC extends the [ERC-6944](./eip-6944.md) resolve mode: This standard add mechanisms to alleviate limitations to the use of standard [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) HTTP caching. ## Motivation @@ -21,12 +21,23 @@ Calls to an Ethereum RPC provider are costly: CPU-wise for local nodes, and mone Thus, it makes sense to use a caching mechanism to limit RPC calls. +In the [ERC-6944](./eip-6944.md) resolve mode, smart contracts can already reply with standard [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) HTTP caching headers, such as `Cache-Control`, `ETag`. + +Unfortunately, due to the impossibility of reading request HTTP headers, they cannot act on the `If-None-Match` and `If-Modified-Since` cache validation headers. Thus they are limited to the `Cache-control: max-age=XX` mechanism, and each cache validation request ends up with RPC calls regenerating the whole response. + +This ERC defines a mechanism to bypass this limitation by having websites broadcast cache invalidations with smart contract events. + + ## Specification -In the [ERC-6944](./eip-6944.md) resolve mode, this standard indicates that the standard HTTP mechanism as defined in [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) can be reused : +When a [ERC-6944](./eip-6944.md) resolve mode website wants to use advanced caching for a request, it MUST : + +- Include the `Web3-Caching: advanced` header in the request response +- Include the `ETag` and/or `Cache-Control` headers in the request response, as in traditional [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) HTTP caching. +- Ensure that it emits a cache invalidation event (as defined in a later section) in the smart contract when it determines that the changes made to the body returned by the path warrants a cache clear. + +The use of the `Web3-Caching: advanced` header is necessary to avoid a situation where a website use traditional [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) HTTP caching headers, but does not implement this ERC (by using the events) : `web3://` clients implementing this ERC would end up serving stale content for this website indefinitely. -- HTTP request responses can contains HTTP caching headers, such as `Cache-Control`, `ETag`. -- Since HTTP request headers cannot be forwarded to the smart contract, cache validation headers such as `If-None-Match` and `If-Modified-Since` cannot be used. This ERC defines an alternate mechanism to broadcast cache invalidations with smart contract events. ### Caching behavior @@ -77,15 +88,13 @@ In `Listening` state, the `web3://` client listens the blockchain for the cache ### Cache invalidation event -Unlike standard HTTP, we can leverage the fact that the website can broadcast cache invalidations with a smart contract event. - The event definition is : ``` event ClearPathCache(string[] paths); ``` -A `path` contains the `pathQuery` part as defined in the ABNF definition of [ERC-6860](./eip-6860.md). They MAY contains `*` wildcards : +A single event can thus clear cache for multiple `path`. A `path` contains the `pathQuery` part as defined in the ABNF definition of [ERC-6860](./eip-6860.md). They MAY contains `*` wildcards : - A wildcard can be used in a [ERC-5219](./eip-5219.md) resource entry. A wildcard CANNOT be used with other characters, or the path will be ignored. A wildcard require at least one character to match. Examples : - `/*` will match `/test` but not `/test/abc` @@ -104,7 +113,7 @@ Wildcards are limited to these simple cases to simplify fast path lookup impleme We add this feature to the [ERC-6944](./eip-6944.md) resolve mode because it can be added without changes the interface. -To stay as close as possible to standard HTTP, we don't introduce new HTTP headers but reuse the HTTP caching mechanism header. +To stay as close as possible to standard HTTP, we reuse the HTTP caching mechanism headers. ## Security Considerations From e70972993f2509de7f6b509dcaacbd71b503d4f1 Mon Sep 17 00:00:00 2001 From: nand Date: Mon, 23 Sep 2024 10:06:01 +0200 Subject: [PATCH 03/16] Use a extension directive for Cache-Control --- ERCS/erc-7761.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/ERCS/erc-7761.md b/ERCS/erc-7761.md index 1c55b90823..b37445d6f5 100644 --- a/ERCS/erc-7761.md +++ b/ERCS/erc-7761.md @@ -30,25 +30,27 @@ This ERC defines a mechanism to bypass this limitation by having websites broadc ## Specification +This standard introduces the `evm-events` cache directive for the `Cache-Control` header, as an extension directive as defined in section 5.2.3 of [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111). + When a [ERC-6944](./eip-6944.md) resolve mode website wants to use advanced caching for a request, it MUST : -- Include the `Web3-Caching: advanced` header in the request response +- Include the `evm-events` directive in the `Cache-Control` header in the request response - Include the `ETag` and/or `Cache-Control` headers in the request response, as in traditional [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) HTTP caching. - Ensure that it emits a cache invalidation event (as defined in a later section) in the smart contract when it determines that the changes made to the body returned by the path warrants a cache clear. -The use of the `Web3-Caching: advanced` header is necessary to avoid a situation where a website use traditional [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) HTTP caching headers, but does not implement this ERC (by using the events) : `web3://` clients implementing this ERC would end up serving stale content for this website indefinitely. +The use of the `evm-events` directive is necessary to avoid a situation where a website use traditional [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) HTTP caching headers, but does not implement this ERC (by not emitting the events) : `web3://` clients implementing this ERC would end up serving stale content for this website indefinitely. ### Caching behavior The `web3://` client will have 2 possible states per chain and per smart contract regarding cache invalidation : -- `Listening` : The `web3://` client MUST listen for cache invalidation events (defined in next section). It MUST try to stay as close to real time as possible. -- `Not listening` : The opposite of the above state, and the default constant state when this ERC is not implemented: the `web3://` client ignore all HTTP caching validation requests (the `If-None-Match`, `If-Modified-Since` request headers). +- `Listening events` : The `web3://` client MUST listen for cache invalidation events (defined in next section). It MUST try to stay as close to real time as possible. +- `Not Listening events` : The opposite of the above state, and the default constant state when this ERC is not implemented: the `web3://` client ignore all HTTP caching validation requests (the `If-None-Match`, `If-Modified-Since` request headers). The `web3://` client can switch between each state anytime, and MAY implement state-switching heuristics to optimize the RPC providers usage. -The `web3://` client will host a caching key-value mapping, which MUST be cleared on any `Listening` to `Not listening` state change : +The `web3://` client will host a caching key-value mapping, which MUST be cleared on any `Listening events` to `Not Listening events` state change : ``` mapping( @@ -58,7 +60,7 @@ mapping( ) ``` -In `Listening` state, when a incoming request arrives : +In `Listening events` state, when a incoming request arrives : - If a mapping entry does not exist : the `web3://` client query the smart contract. - If the request response contains an `Etag` HTTP header, a mapping entry is created with the `Etag`. @@ -84,7 +86,7 @@ In `Listening` state, when a incoming request arrives : - If the request response contains an `Etag` HTTP header, the mapping entry `Etag` field is updated. - If the request response contains a `max-age` directive in a `Cache-Control` HTTP header, the mapping entry `last modified date` field is updated with the date value computed as in the no-mapping-exists scenario above. -In `Listening` state, the `web3://` client listens the blockchain for the cache invalidation events which are defined in the next section. For each path match, it will delete their corresponding mapping entry. +In `Listening events` state, the `web3://` client listens the blockchain for the cache invalidation events which are defined in the next section. For each path match, it will delete their corresponding mapping entry. ### Cache invalidation event From 392f73abe05fb1a1d2c51e989757d9ac5f7f1860 Mon Sep 17 00:00:00 2001 From: nand Date: Mon, 23 Sep 2024 10:32:00 +0200 Subject: [PATCH 04/16] Rewording --- ERCS/erc-7761.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/ERCS/erc-7761.md b/ERCS/erc-7761.md index b37445d6f5..72dbc7dd36 100644 --- a/ERCS/erc-7761.md +++ b/ERCS/erc-7761.md @@ -1,7 +1,7 @@ --- eip: 7761 -title: Advanced caching in ERC-5219 mode Web3 URL -description: In ERC-5219 resolve mode, specify how to support caching similar to HTTP caching +title: Cache invalidation events in ERC-5219 mode Web3 URL +description: In ERC-5219 resolve mode, add mechanisms to alleviate limitations to the use of standard RFC 9111 HTTP caching author: Nicolas Deschildre (@nand2) discussions-to: https://ethereum-magicians.org/t/eip-4804-web3-url-to-evm-call-message-translation/8300 status: Draft @@ -17,9 +17,9 @@ In the context of the [ERC-6860](./eip-6860.md) `web3://` standard, this ERC ext ## Motivation -Calls to an Ethereum RPC provider are costly: CPU-wise for local nodes, and money-wise for paid external RPC providers. Additionally, external RPC providers are rate-limited, and can quickly break the loading of `web3://` URLs. +Calls to an Ethereum RPC provider are costly: CPU-wise for local nodes, and money-wise for paid external RPC providers. Additionally, external RPC providers are rate-limited, and can quickly lead to the breaking of the loading of `web3://` URLs. -Thus, it makes sense to use a caching mechanism to limit RPC calls. +Thus, it makes sense to use a caching mechanism to limit RPC calls when possible. In the [ERC-6944](./eip-6944.md) resolve mode, smart contracts can already reply with standard [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) HTTP caching headers, such as `Cache-Control`, `ETag`. @@ -27,12 +27,13 @@ Unfortunately, due to the impossibility of reading request HTTP headers, they ca This ERC defines a mechanism to bypass this limitation by having websites broadcast cache invalidations with smart contract events. +Besides, even if the smart contract could read request HTTP headers, using smart contract events is more efficient as it will eliminate a significant proportion of RPC calls. ## Specification This standard introduces the `evm-events` cache directive for the `Cache-Control` header, as an extension directive as defined in section 5.2.3 of [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111). -When a [ERC-6944](./eip-6944.md) resolve mode website wants to use advanced caching for a request, it MUST : +When a [ERC-6944](./eip-6944.md) resolve mode website wants to use event-based caching for a request, it MUST : - Include the `evm-events` directive in the `Cache-Control` header in the request response - Include the `ETag` and/or `Cache-Control` headers in the request response, as in traditional [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) HTTP caching. From 91c14e57d183b158804c705312ed875d8b786e63 Mon Sep 17 00:00:00 2001 From: nand Date: Mon, 23 Sep 2024 10:49:30 +0200 Subject: [PATCH 05/16] Simplify some steps. --- ERCS/erc-7761.md | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/ERCS/erc-7761.md b/ERCS/erc-7761.md index 72dbc7dd36..6e85ffa72b 100644 --- a/ERCS/erc-7761.md +++ b/ERCS/erc-7761.md @@ -64,8 +64,8 @@ mapping( In `Listening events` state, when a incoming request arrives : - If a mapping entry does not exist : the `web3://` client query the smart contract. - - If the request response contains an `Etag` HTTP header, a mapping entry is created with the `Etag`. - - If the request response contains a `max-age` directive in a `Cache-Control` HTTP header, a mapping entry is created with the `last modified date` being : + - If the request response contains the `evm-events` cache directive in the `Cache-Control` header, and an `Etag` HTTP header, a mapping entry is created with the `Etag`. + - If the request response contains the `evm-events` cache directive in the `Cache-Control` header, and contains a `max-age` directive in a `Cache-Control` HTTP header, a mapping entry is created with the `last modified date` being : - The content of the `Last-Modified` HTTP header, if present - The content of the `Date` HTTP header, if present - The date of the block at which the smart contract was queried otherwise @@ -74,18 +74,12 @@ In `Listening events` state, when a incoming request arrives : - If the request contains a valid `If-None-Match` HTTP header: - If the mapping entry has the same `Etag` as the one provided by `If-None-Match`, then the `web3://` client returns a HTTP code `304 Not Modified` response right away. - Otherwise if the mapping entry has a non-empty different `ETag`, the `web3://` client query the smart contract. The mapping entry is deleted, and the answer is processed as if there had been no mapping entry initially. - - Otherwise the `Etag` of the mapping entry is empty (and the `last modified date` is not). The `web3://` client query the smart contract. - - If the request response contains an `Etag` HTTP header, the mapping entry `ETag` is filled. - - If the request response contains a `max-age` directive in a `Cache-Control` HTTP header, the mapping entry `last modified date` field is updated with the date value computed as in the no-mapping-exists scenario above. + - Otherwise the `Etag` of the mapping entry is empty (and the `last modified date` is not). The `web3://` client query the smart contract, and the answer is processed as if there had been no mapping entry initially, except that the mapping entry is updated instead of created. - If the request contains a valid `If-Modified-Since` HTTP header: - If the mapping entry has a `last modified date`, and is before the date provided by `If-Modified-Since`, then the `web3://` client returns a HTTP code `304 Not Modified` response right away. - Otherwise if the mapping entry has a `last modified date` which is after, the `web3://` client query the smart contract. The mapping entry is deleted, and the answer is processed as if there had been no mapping entry initially. - - Otherwise the `last modified date` field of the mapping entry is empty (and the `Etag` is not). The `web3://` client query the smart contract. - - If the request response contains an `Etag` HTTP header, the mapping entry `ETag` is updated. - - If the request response contains a `max-age` directive in a `Cache-Control` HTTP header, the mapping entry `last modified date` field is filled with the date value computed as in the no-mapping-exists scenario above. - - If the request does not have a `If-None-Match` or `If-Modified-Since` HTTP header (or are invalid): the `web3://` client query the smart contract. - - If the request response contains an `Etag` HTTP header, the mapping entry `Etag` field is updated. - - If the request response contains a `max-age` directive in a `Cache-Control` HTTP header, the mapping entry `last modified date` field is updated with the date value computed as in the no-mapping-exists scenario above. + - Otherwise the `last modified date` field of the mapping entry is empty (and the `Etag` is not). The `web3://` client query the smart contract, and the answer is processed as if there had been no mapping entry initially, except that the mapping entry is updated instead of created. + - If the request does not have a `If-None-Match` or `If-Modified-Since` HTTP header (or are invalid): the `web3://` client query the smart contract, and the answer is processed as if there had been no mapping entry initially, except that the mapping entry is updated instead of created. In `Listening events` state, the `web3://` client listens the blockchain for the cache invalidation events which are defined in the next section. For each path match, it will delete their corresponding mapping entry. @@ -97,14 +91,14 @@ The event definition is : event ClearPathCache(string[] paths); ``` -A single event can thus clear cache for multiple `path`. A `path` contains the `pathQuery` part as defined in the ABNF definition of [ERC-6860](./eip-6860.md). They MAY contains `*` wildcards : +A single event can thus clear cache for an array of `path`. A `path` contains the `pathQuery` part as defined in the ABNF definition of [ERC-6860](./eip-6860.md). They MAY contains `*` wildcards : -- A wildcard can be used in a [ERC-5219](./eip-5219.md) resource entry. A wildcard CANNOT be used with other characters, or the path will be ignored. A wildcard require at least one character to match. Examples : +- A wildcard can be used in a [ERC-5219](./eip-5219.md) resource entry. A wildcard CANNOT be used with other characters, or the `path` will be ignored. A wildcard require at least one character to match. Examples : - `/*` will match `/test` but not `/test/abc` - `/test/*` will match `/test/abc` but will not match `/test/` and not match `/test/abc/def` - `/*/abc` will match `/test/abc`, but will not match `//abc` - `/t*t/` is invalid, the path is ignored. -- A wildcard can be used in a [ERC-5219](./eip-5219.md) param value. A wildcard CANNOT be used with other characters, or it will the path be ignored. A wildcard require at least one character to match. Examples : +- A wildcard can be used in a [ERC-5219](./eip-5219.md) param value. A wildcard CANNOT be used with other characters, or it will the `path` be ignored. A wildcard require at least one character to match. Examples : - `/abc?a=*` will match `/abc?a=zz` but will not match `/abc?a=` and not match `/abc?a=zz&b=cc` - `/abc?a=*&b=*` will match `/abc?a=1&b=2` and `/abc?b=2&a=1` - `/abc?a=z*` is invalid, the path is ignored. From a641ef105afb80569da48f921087c1e45ae74ea9 Mon Sep 17 00:00:00 2001 From: nand Date: Mon, 23 Sep 2024 11:01:34 +0200 Subject: [PATCH 06/16] Fix EIP validation errors. --- ERCS/erc-7761.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ERCS/erc-7761.md b/ERCS/erc-7761.md index 6e85ffa72b..b309c2fcdf 100644 --- a/ERCS/erc-7761.md +++ b/ERCS/erc-7761.md @@ -1,7 +1,7 @@ --- eip: 7761 -title: Cache invalidation events in ERC-5219 mode Web3 URL -description: In ERC-5219 resolve mode, add mechanisms to alleviate limitations to the use of standard RFC 9111 HTTP caching +title: Cache invalidation in ERC-5219 mode Web3 URL +description: In ERC-5219 resolve mode, add mechanisms to alleviate limitations to the use of RFC 9111 HTTP caching author: Nicolas Deschildre (@nand2) discussions-to: https://ethereum-magicians.org/t/eip-4804-web3-url-to-evm-call-message-translation/8300 status: Draft From 5a62e60c544fb1725ad8a7d42481916eed2335ee Mon Sep 17 00:00:00 2001 From: nand2 Date: Thu, 3 Oct 2024 07:58:45 +0200 Subject: [PATCH 07/16] Update ERCS/erc-7761.md Co-authored-by: Andrew B Coathup <28278242+abcoathup@users.noreply.github.com> --- ERCS/erc-7761.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ERCS/erc-7761.md b/ERCS/erc-7761.md index b309c2fcdf..4b1b03693d 100644 --- a/ERCS/erc-7761.md +++ b/ERCS/erc-7761.md @@ -1,5 +1,5 @@ --- -eip: 7761 +eip: 7774 title: Cache invalidation in ERC-5219 mode Web3 URL description: In ERC-5219 resolve mode, add mechanisms to alleviate limitations to the use of RFC 9111 HTTP caching author: Nicolas Deschildre (@nand2) From 4109a58a427e46141d3e44c4396cb42462fe144f Mon Sep 17 00:00:00 2001 From: nand Date: Thu, 3 Oct 2024 08:05:22 +0200 Subject: [PATCH 08/16] Rename the ERC as requested, add a separate EM thread. --- ERCS/{erc-7761.md => erc-7774.md} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename ERCS/{erc-7761.md => erc-7774.md} (98%) diff --git a/ERCS/erc-7761.md b/ERCS/erc-7774.md similarity index 98% rename from ERCS/erc-7761.md rename to ERCS/erc-7774.md index 4b1b03693d..fa55ac2ec3 100644 --- a/ERCS/erc-7761.md +++ b/ERCS/erc-7774.md @@ -3,7 +3,7 @@ eip: 7774 title: Cache invalidation in ERC-5219 mode Web3 URL description: In ERC-5219 resolve mode, add mechanisms to alleviate limitations to the use of RFC 9111 HTTP caching author: Nicolas Deschildre (@nand2) -discussions-to: https://ethereum-magicians.org/t/eip-4804-web3-url-to-evm-call-message-translation/8300 +discussions-to: https://ethereum-magicians.org/t/erc-7774-cache-invalidation-in-erc-5219-mode-web3-url/21255 status: Draft type: Standards Track category: ERC From 950887f76c147e7f0556fe524aa0e23bc37fd5ca Mon Sep 17 00:00:00 2001 From: nand Date: Fri, 4 Oct 2024 14:09:39 +0200 Subject: [PATCH 09/16] WIP --- ERCS/erc-7774.md | 155 ++++++++++++++++++++++++++++++----------------- 1 file changed, 98 insertions(+), 57 deletions(-) diff --git a/ERCS/erc-7774.md b/ERCS/erc-7774.md index fa55ac2ec3..0083c5d2c0 100644 --- a/ERCS/erc-7774.md +++ b/ERCS/erc-7774.md @@ -1,7 +1,7 @@ --- eip: 7774 title: Cache invalidation in ERC-5219 mode Web3 URL -description: In ERC-5219 resolve mode, add mechanisms to alleviate limitations to the use of RFC 9111 HTTP caching +description: In ERC-5219 resolve mode, add mechanisms to alleviate limitations that prevent the use of RFC 9111 HTTP caching author: Nicolas Deschildre (@nand2) discussions-to: https://ethereum-magicians.org/t/erc-7774-cache-invalidation-in-erc-5219-mode-web3-url/21255 status: Draft @@ -13,21 +13,19 @@ requires: 5219, 6944 ## Abstract -In the context of the [ERC-6860](./eip-6860.md) `web3://` standard, this ERC extends the [ERC-6944](./eip-6944.md) resolve mode: This standard add mechanisms to alleviate limitations to the use of standard [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) HTTP caching. +In the context of the [ERC-6860](./eip-6860.md) `web3://` standard, this ERC extends the [ERC-6944](./eip-6944.md) resolve mode: This standard add mechanisms to alleviate limitations that prevent the use of standard [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) HTTP caching. ## Motivation -Calls to an Ethereum RPC provider are costly: CPU-wise for local nodes, and money-wise for paid external RPC providers. Additionally, external RPC providers are rate-limited, and can quickly lead to the breaking of the loading of `web3://` URLs. +Calls to an Ethereum RPC provider are costly: CPU-wise for local nodes, and money-wise for paid external RPC providers. Additionally, external RPC providers are rate-limited, which can quickly lead to disruptions when loading `web3://` URLs. -Thus, it makes sense to use a caching mechanism to limit RPC calls when possible. +Therefore, it makes sense to implement caching mechanisms to reduce RPC calls when possible. Since `web3://` aims to be as close to HTTP as possible, using standard [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) HTTP caching is the obvious choice. In the [ERC-6944](./eip-6944.md) resolve mode, smart contracts can already reply with standard HTTP caching headers like `Cache-Control` and `ETag`. -In the [ERC-6944](./eip-6944.md) resolve mode, smart contracts can already reply with standard [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) HTTP caching headers, such as `Cache-Control`, `ETag`. +However, due to the [ERC-6944](./eip-6944.md) resolve mode not forwarding request HTTP headers to the smart contract, smart contracts cannot respond to the `If-None-Match` and `If-Modified-Since` cache validation headers. As a result, they are limited to the `Cache-control: max-age=XX` mechanism, meaning each cache validation request leads to an RPC call that regenerates the entire response. -Unfortunately, due to the impossibility of reading request HTTP headers, they cannot act on the `If-None-Match` and `If-Modified-Since` cache validation headers. Thus they are limited to the `Cache-control: max-age=XX` mechanism, and each cache validation request ends up with RPC calls regenerating the whole response. +This ERC defines a mechanism to bypass this limitation by allowing websites to broadcast cache invalidations using smart contract events. -This ERC defines a mechanism to bypass this limitation by having websites broadcast cache invalidations with smart contract events. - -Besides, even if the smart contract could read request HTTP headers, using smart contract events is more efficient as it will eliminate a significant proportion of RPC calls. +Moreover, even if the smart contract could read request HTTP headers, using smart contract events is more efficient, as it shifts cache invalidation logic outside of the smart contract. ## Specification @@ -35,76 +33,119 @@ This standard introduces the `evm-events` cache directive for the `Cache-Control When a [ERC-6944](./eip-6944.md) resolve mode website wants to use event-based caching for a request, it MUST : -- Include the `evm-events` directive in the `Cache-Control` header in the request response -- Include the `ETag` and/or `Cache-Control` headers in the request response, as in traditional [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) HTTP caching. -- Ensure that it emits a cache invalidation event (as defined in a later section) in the smart contract when it determines that the changes made to the body returned by the path warrants a cache clear. +- Include the `evm-events` directive in the `Cache-Control` header in the response +- Include the `ETag` and/or `Cache-Control` headers in the response, as in traditional [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) HTTP caching. +- Ensure that it emits a cache invalidation event (as defined in a later section) in the smart contract when the output of the response changes and it determines that a cache clear is warranted. + +The use of the `evm-events` directive is necessary to avoid a situation where a website uses traditional [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) HTTP caching headers, but does not implement this ERC by failing to emit the events. In such cases, `web3://` clients implementing this ERC would serve stale content for that website indefinitely. + + +### Cache invalidation event + +The event is defined as follows : + +``` +event ClearPathCache(string[] paths); +``` + +This event can be used to clear the cache for an array of `paths`. Each `path` refers to the `pathQuery` part of the ABNF definition in [ERC-6860](./eip-6860.md). + +- A `path` MUST NOT end with a `/`, except for the root path, which is `/`. +- For two `paths` to be considered identical, they must have the same [ERC-5219](./eip-5219.md) resource entries, and their parameter values must match, regardless of the order. + +**Example**: +- `/test?a=1&b=2` and `/test?b=2&a=1` are considered identical. + +#### Wildcard usage + +`paths` may contain `*` wildcards with the following rules: -The use of the `evm-events` directive is necessary to avoid a situation where a website use traditional [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) HTTP caching headers, but does not implement this ERC (by not emitting the events) : `web3://` clients implementing this ERC would end up serving stale content for this website indefinitely. +1. **Wildcards in Resource Entries**: + - A wildcard (`*`) can be used on its own in an [ERC-5219](./eip-5219.md) resource entry. + - A wildcard CANNOT be combined with other characters in the same entry; if this happens, the `path` will be ignored. + - A wildcard requires at least one character to match. + + **Examples**: + - `/*` will match `/test` but not `/test/abc` and not `/`. + - `/test/*` will match `/test/abc` but will not match `/test/` or `/test/abc/def`. + - `/*/abc` will match `/test/abc`, but not `//abc`. + - `/t*t` is invalid, so the `path` will be ignored. + +2. **Wildcards in Parameter Values**: + - A wildcard can be used alone as a parameter value. + - A wildcard CANNOT be combined with other characters in the parameter value, or the `path` will be ignored. + - A wildcard in parameter values also requires at least one character to match. + + **Examples**: + - `/abc?a=*` will match `/abc?a=zz` but not `/abc?a=` or `/abc?a=zz&b=cc`. + - `/abc?a=*&b=*` will match `/abc?a=1&b=2` and `/abc?b=2&a=1`. + - `/abc?a=z*` is invalid, so the `path` will be ignored. + +3. **Special Case: Global Wildcard**: + - A `path` containing only a `*` will match every path within the smart contract. + +Wildcards are intentionally limited to these simple cases to facilitate efficient path lookup implementations. ### Caching behavior -The `web3://` client will have 2 possible states per chain and per smart contract regarding cache invalidation : +#### Cache Invalidation States for `web3://` Clients + +A `web3://` client can be in one of two cache invalidation states per chain and per smart contract: + +1. **Listening for Events**: + - The `web3://` client **MUST** listen for the cache invalidation events defined earlier and should aim to remain as close to real-time as possible. + +2. **Not Listening for Events**: + - This is the default state when this ERC is not implemented. In this state, the `web3://` client ignores all HTTP caching validation requests (e.g., `If-None-Match`, `If-Modified-Since` request headers). -- `Listening events` : The `web3://` client MUST listen for cache invalidation events (defined in next section). It MUST try to stay as close to real time as possible. -- `Not Listening events` : The opposite of the above state, and the default constant state when this ERC is not implemented: the `web3://` client ignore all HTTP caching validation requests (the `If-None-Match`, `If-Modified-Since` request headers). +The `web3://` client can switch between these states at any time and MAY implement heuristics to optimize the use of RPC providers by switching states when appropriate. -The `web3://` client can switch between each state anytime, and MAY implement state-switching heuristics to optimize the RPC providers usage. +#### Cache Key-Value Mapping -The `web3://` client will host a caching key-value mapping, which MUST be cleared on any `Listening events` to `Not Listening events` state change : +The `web3://` client maintains a caching key-value mapping that **MUST** be cleared whenever it transitions from "Listening for Events" to "Not Listening for Events." The mapping structure is as follows: ``` mapping( - (, , , )) + (, , ) => (, ) ) ``` -In `Listening events` state, when a incoming request arrives : - -- If a mapping entry does not exist : the `web3://` client query the smart contract. - - If the request response contains the `evm-events` cache directive in the `Cache-Control` header, and an `Etag` HTTP header, a mapping entry is created with the `Etag`. - - If the request response contains the `evm-events` cache directive in the `Cache-Control` header, and contains a `max-age` directive in a `Cache-Control` HTTP header, a mapping entry is created with the `last modified date` being : - - The content of the `Last-Modified` HTTP header, if present - - The content of the `Date` HTTP header, if present - - The date of the block at which the smart contract was queried otherwise - - If the request response match both cases above, then a single mapping entry is created with both the `Etag` and the `last modified date` fields filled. -- If a mapping entry already exists : - - If the request contains a valid `If-None-Match` HTTP header: - - If the mapping entry has the same `Etag` as the one provided by `If-None-Match`, then the `web3://` client returns a HTTP code `304 Not Modified` response right away. - - Otherwise if the mapping entry has a non-empty different `ETag`, the `web3://` client query the smart contract. The mapping entry is deleted, and the answer is processed as if there had been no mapping entry initially. - - Otherwise the `Etag` of the mapping entry is empty (and the `last modified date` is not). The `web3://` client query the smart contract, and the answer is processed as if there had been no mapping entry initially, except that the mapping entry is updated instead of created. - - If the request contains a valid `If-Modified-Since` HTTP header: - - If the mapping entry has a `last modified date`, and is before the date provided by `If-Modified-Since`, then the `web3://` client returns a HTTP code `304 Not Modified` response right away. - - Otherwise if the mapping entry has a `last modified date` which is after, the `web3://` client query the smart contract. The mapping entry is deleted, and the answer is processed as if there had been no mapping entry initially. - - Otherwise the `last modified date` field of the mapping entry is empty (and the `Etag` is not). The `web3://` client query the smart contract, and the answer is processed as if there had been no mapping entry initially, except that the mapping entry is updated instead of created. - - If the request does not have a `If-None-Match` or `If-Modified-Since` HTTP header (or are invalid): the `web3://` client query the smart contract, and the answer is processed as if there had been no mapping entry initially, except that the mapping entry is updated instead of created. - -In `Listening events` state, the `web3://` client listens the blockchain for the cache invalidation events which are defined in the next section. For each path match, it will delete their corresponding mapping entry. +Additional elements can be included in the mapping key when necessary. For example, the implementation of [ERC-7618](./eip-7618.md) requires the inclusion of the `Accept-Encoding` request header in the mapping key. -### Cache invalidation event +#### Handling Requests in "Listening for Events" State + +When a request is received in the "Listening for Events" state: + +1. **If no mapping entry exists**: + - The `web3://` client queries the smart contract. + - If the response includes the `evm-events` directive in the `Cache-Control` header along with an `ETag` header, a mapping entry is created using the `ETag`. + - If the response contains the `evm-events` directive and a `max-age=XX` directive in the `Cache-Control` header, the mapping entry is created with the `last modified date`, determined by the following, in order of priority: + - The `Last-Modified` header, if present. + - The `Date` header, if present. + - Otherwise, the block date when the smart contract was queried. + - If the response includes both an `ETag` and a `Cache-Control: evm-events max-age=XX` directive, a single mapping entry is created containing both the `ETag` and the `last modified date`. + +2. **If a mapping entry exists**: + - If the request contains a valid `If-None-Match` header: + - If the `ETag` in the mapping matches the `If-None-Match` value, the `web3://` client returns a `304 Not Modified` response immediately. + - If the `ETag` does not match, the client queries the smart contract, deletes the mapping entry, and processes the request as if no mapping entry existed. + + - If the request contains a valid `If-Modified-Since` header: + - If the `last modified date` in the mapping is earlier than the `If-Modified-Since` date, the client returns a `304 Not Modified` response immediately. + - Otherwise, the client queries the smart contract, deletes the mapping entry, and processes the request as if no mapping entry existed. + + - If the request contains neither `If-None-Match` nor `If-Modified-Since` headers (or they are invalid): + - The client queries the smart contract, deletes the mapping entry, and processes the request as if no mapping entry existed. -The event definition is : -``` -event ClearPathCache(string[] paths); -``` -A single event can thus clear cache for an array of `path`. A `path` contains the `pathQuery` part as defined in the ABNF definition of [ERC-6860](./eip-6860.md). They MAY contains `*` wildcards : +#### Cache Invalidation via Blockchain Events -- A wildcard can be used in a [ERC-5219](./eip-5219.md) resource entry. A wildcard CANNOT be used with other characters, or the `path` will be ignored. A wildcard require at least one character to match. Examples : - - `/*` will match `/test` but not `/test/abc` - - `/test/*` will match `/test/abc` but will not match `/test/` and not match `/test/abc/def` - - `/*/abc` will match `/test/abc`, but will not match `//abc` - - `/t*t/` is invalid, the path is ignored. -- A wildcard can be used in a [ERC-5219](./eip-5219.md) param value. A wildcard CANNOT be used with other characters, or it will the `path` be ignored. A wildcard require at least one character to match. Examples : - - `/abc?a=*` will match `/abc?a=zz` but will not match `/abc?a=` and not match `/abc?a=zz&b=cc` - - `/abc?a=*&b=*` will match `/abc?a=1&b=2` and `/abc?b=2&a=1` - - `/abc?a=z*` is invalid, the path is ignored. -- Special case: Global wildcard : A `path` containing a single `*` match every path of the smart contract. +In the "Listening for Events" state, the `web3://` client listens to the blockchain for the cache invalidation events defined in the previous section. For each path match, it deletes the corresponding mapping entry. -Wildcards are limited to these simple cases to simplify fast path lookup implementations. ## Rationale From 5245dc4ec3e8e43199a655987487dbce9b385728 Mon Sep 17 00:00:00 2001 From: nand Date: Fri, 4 Oct 2024 14:29:25 +0200 Subject: [PATCH 10/16] Rewording --- ERCS/erc-7774.md | 56 +++++++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/ERCS/erc-7774.md b/ERCS/erc-7774.md index 0083c5d2c0..df6a94ed3a 100644 --- a/ERCS/erc-7774.md +++ b/ERCS/erc-7774.md @@ -13,56 +13,55 @@ requires: 5219, 6944 ## Abstract -In the context of the [ERC-6860](./eip-6860.md) `web3://` standard, this ERC extends the [ERC-6944](./eip-6944.md) resolve mode: This standard add mechanisms to alleviate limitations that prevent the use of standard [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) HTTP caching. +In the context of the [ERC-6860](./eip-6860.md) `web3://` standard, this ERC extends the [ERC-6944](./eip-6944.md) resolve mode. It introduces mechanisms to address limitations that prevent the use of standard [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) HTTP caching. ## Motivation -Calls to an Ethereum RPC provider are costly: CPU-wise for local nodes, and money-wise for paid external RPC providers. Additionally, external RPC providers are rate-limited, which can quickly lead to disruptions when loading `web3://` URLs. +Calls to Ethereum RPC providers are costly—both CPU-wise for local nodes and monetarily for paid external RPC providers. Furthermore, external RPC providers are rate-limited, which can quickly cause disruptions when loading `web3://` URLs. -Therefore, it makes sense to implement caching mechanisms to reduce RPC calls when possible. Since `web3://` aims to be as close to HTTP as possible, using standard [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) HTTP caching is the obvious choice. In the [ERC-6944](./eip-6944.md) resolve mode, smart contracts can already reply with standard HTTP caching headers like `Cache-Control` and `ETag`. +Therefore, it makes sense to implement caching mechanisms to reduce RPC calls when possible. Since `web3://` aims to be as close to HTTP as possible, leveraging standard [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) HTTP caching is the natural choice. In the [ERC-6944](./eip-6944.md) resolve mode, smart contracts can already return standard HTTP caching headers like `Cache-Control` and `ETag`. -However, due to the [ERC-6944](./eip-6944.md) resolve mode not forwarding request HTTP headers to the smart contract, smart contracts cannot respond to the `If-None-Match` and `If-Modified-Since` cache validation headers. As a result, they are limited to the `Cache-control: max-age=XX` mechanism, meaning each cache validation request leads to an RPC call that regenerates the entire response. +However, due to the [ERC-6944](./eip-6944.md) resolve mode not forwarding request HTTP headers to the smart contract, smart contracts cannot handle `If-None-Match` and `If-Modified-Since` cache validation headers. Consequently, they are limited to using the `Cache-control: max-age=XX` mechanism, which causes each cache validation request to trigger an RPC call, regenerating the full response. -This ERC defines a mechanism to bypass this limitation by allowing websites to broadcast cache invalidations using smart contract events. +This ERC proposes a solution to bypass this limitation by allowing websites to broadcast cache invalidations via smart contract events. -Moreover, even if the smart contract could read request HTTP headers, using smart contract events is more efficient, as it shifts cache invalidation logic outside of the smart contract. +Additionally, even if smart contracts could read request HTTP headers, using smart contract events is more efficient, as it moves cache invalidation logic outside the contract. ## Specification This standard introduces the `evm-events` cache directive for the `Cache-Control` header, as an extension directive as defined in section 5.2.3 of [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111). -When a [ERC-6944](./eip-6944.md) resolve mode website wants to use event-based caching for a request, it MUST : +When a [ERC-6944](./eip-6944.md) resolve mode website wants to use event-based caching for a request, it MUST: -- Include the `evm-events` directive in the `Cache-Control` header in the response -- Include the `ETag` and/or `Cache-Control` headers in the response, as in traditional [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) HTTP caching. -- Ensure that it emits a cache invalidation event (as defined in a later section) in the smart contract when the output of the response changes and it determines that a cache clear is warranted. +- Include the `evm-events` directive in the `Cache-Control` header of the response. +- Include the `ETag` and/or `Cache-Control` headers in the response, as per traditional [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) HTTP caching. +- Emit a cache invalidation event (as defined below) in the smart contract when the output of the response changes and it deems cache clearing necessary. The use of the `evm-events` directive is necessary to avoid a situation where a website uses traditional [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) HTTP caching headers, but does not implement this ERC by failing to emit the events. In such cases, `web3://` clients implementing this ERC would serve stale content for that website indefinitely. - ### Cache invalidation event -The event is defined as follows : +The event is defined as: ``` event ClearPathCache(string[] paths); ``` -This event can be used to clear the cache for an array of `paths`. Each `path` refers to the `pathQuery` part of the ABNF definition in [ERC-6860](./eip-6860.md). +This event clears the cache for an array of `paths`. Each `path` refers to the `pathQuery` part of the ABNF definition in [ERC-6860](./eip-6860.md). -- A `path` MUST NOT end with a `/`, except for the root path, which is `/`. -- For two `paths` to be considered identical, they must have the same [ERC-5219](./eip-5219.md) resource entries, and their parameter values must match, regardless of the order. +- A `path` MUST NOT end with a `/`, except for the root path, which is `/`. +- Two `paths` are considered identical if they have the same [ERC-5219](./eip-5219.md) resource entries and their parameter values match, regardless of the order. **Example**: - `/test?a=1&b=2` and `/test?b=2&a=1` are considered identical. #### Wildcard usage -`paths` may contain `*` wildcards with the following rules: +`paths` may contain `*` wildcards, with the following rules: 1. **Wildcards in Resource Entries**: - A wildcard (`*`) can be used on its own in an [ERC-5219](./eip-5219.md) resource entry. - - A wildcard CANNOT be combined with other characters in the same entry; if this happens, the `path` will be ignored. + - A wildcard CANNOT be combined with other characters in the same entry; if it is, the `path` will be ignored. - A wildcard requires at least one character to match. **Examples**: @@ -74,7 +73,7 @@ This event can be used to clear the cache for an array of `paths`. Each `path` r 2. **Wildcards in Parameter Values**: - A wildcard can be used alone as a parameter value. - A wildcard CANNOT be combined with other characters in the parameter value, or the `path` will be ignored. - - A wildcard in parameter values also requires at least one character to match. + - A wildcard in parameter values requires at least one character to match. **Examples**: - `/abc?a=*` will match `/abc?a=zz` but not `/abc?a=` or `/abc?a=zz&b=cc`. @@ -86,24 +85,23 @@ This event can be used to clear the cache for an array of `paths`. Each `path` r Wildcards are intentionally limited to these simple cases to facilitate efficient path lookup implementations. - ### Caching behavior #### Cache Invalidation States for `web3://` Clients -A `web3://` client can be in one of two cache invalidation states per chain and per smart contract: +A `web3://` client can be in one of two cache invalidation states for each chain and smart contract: -1. **Listening for Events**: - - The `web3://` client **MUST** listen for the cache invalidation events defined earlier and should aim to remain as close to real-time as possible. +1. **Listening for Events**: + The `web3://` client MUST listen for the cache invalidation events defined earlier and should aim to stay as close to real-time as possible. -2. **Not Listening for Events**: - - This is the default state when this ERC is not implemented. In this state, the `web3://` client ignores all HTTP caching validation requests (e.g., `If-None-Match`, `If-Modified-Since` request headers). +2. **Not Listening for Events**: + This is the default state when this ERC is not implemented. In this state, the `web3://` client ignores all HTTP caching validation requests (e.g., `If-None-Match`, `If-Modified-Since` request headers). -The `web3://` client can switch between these states at any time and MAY implement heuristics to optimize the use of RPC providers by switching states when appropriate. +The `web3://` client can switch between these states at any time and MAY implement heuristics to optimize the use of RPC providers by switching states as appropriate. #### Cache Key-Value Mapping -The `web3://` client maintains a caching key-value mapping that **MUST** be cleared whenever it transitions from "Listening for Events" to "Not Listening for Events." The mapping structure is as follows: +The `web3://` client maintains a key-value mapping for caching, which MUST be cleared whenever it transitions from "Listening for Events" to "Not Listening for Events." The mapping is structured as follows: ``` mapping( @@ -113,7 +111,7 @@ mapping( ) ``` -Additional elements can be included in the mapping key when necessary. For example, the implementation of [ERC-7618](./eip-7618.md) requires the inclusion of the `Accept-Encoding` request header in the mapping key. +Additional elements can be included in the mapping key when necessary. For example, [ERC-7618](./eip-7618.md) requires the inclusion of the `Accept-Encoding` request header in the mapping key. #### Handling Requests in "Listening for Events" State @@ -121,8 +119,8 @@ When a request is received in the "Listening for Events" state: 1. **If no mapping entry exists**: - The `web3://` client queries the smart contract. - - If the response includes the `evm-events` directive in the `Cache-Control` header along with an `ETag` header, a mapping entry is created using the `ETag`. - - If the response contains the `evm-events` directive and a `max-age=XX` directive in the `Cache-Control` header, the mapping entry is created with the `last modified date`, determined by the following, in order of priority: + - If the response includes the `evm-events` directive in the `Cache-Control` header and an `ETag`, a mapping entry is created using the `ETag`. + - If the response contains the `evm-events` directive and a `max-age=XX` directive in the `Cache-Control` header, the mapping entry is created with the `last modified date`, determined in the following order of priority: - The `Last-Modified` header, if present. - The `Date` header, if present. - Otherwise, the block date when the smart contract was queried. From 591aa10feabf9591c1b44096e79e40aab193a88f Mon Sep 17 00:00:00 2001 From: nand Date: Thu, 17 Oct 2024 10:07:48 +0200 Subject: [PATCH 11/16] Add value to the cache directive. --- ERCS/erc-7774.md | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/ERCS/erc-7774.md b/ERCS/erc-7774.md index df6a94ed3a..004dbf2a69 100644 --- a/ERCS/erc-7774.md +++ b/ERCS/erc-7774.md @@ -29,15 +29,29 @@ Additionally, even if smart contracts could read request HTTP headers, using sma ## Specification -This standard introduces the `evm-events` cache directive for the `Cache-Control` header, as an extension directive as defined in section 5.2.3 of [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111). +This standard introduces the `evm-events` cache directive for the `Cache-Control` header of request responses, as an extension directive as defined in section 5.2.3 of [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111). When a [ERC-6944](./eip-6944.md) resolve mode website wants to use event-based caching for a request, it MUST: - Include the `evm-events` directive in the `Cache-Control` header of the response. - Include the `ETag` and/or `Cache-Control` headers in the response, as per traditional [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) HTTP caching. -- Emit a cache invalidation event (as defined below) in the smart contract when the output of the response changes and it deems cache clearing necessary. +- Emit a cache invalidation event (as defined below) for the path in the smart contract when the output of the response changes and it deems cache clearing necessary. -The use of the `evm-events` directive is necessary to avoid a situation where a website uses traditional [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) HTTP caching headers, but does not implement this ERC by failing to emit the events. In such cases, `web3://` clients implementing this ERC would serve stale content for that website indefinitely. +A value to the `evm-events` cache directive is optional, and can be used to specify to listen for events on another smart contract, and/or for another path. The cache directive value syntax in ABNF notation is : + +``` +cacheDirectiveValue = [ address ] [ path-absolute [ "?" query ] ] +address = "0x" 20( HEXDIG HEXDIG ) +path-absolute = +query = +``` + +**Examples**: + +- `Cache-control: evm-events` : The cache of the page returning this directive will be cleared when the contract having responded to the request emits a cache clearing event for the path of the page having been served. +- `Cache-control: evm-events="/path/path2"` : The cache of the page returning this directive will be cleared when the contract having responded to the request emits a cache clearing event for path `/path/path2`. +- `Cache-control: evm-events="0xe4ba0e245436b737468c206ab5c8f4950597ab7f/path/path2"` : The cache of the page returning this directive will be cleared when the contract `0xe4ba0e245436b737468c206ab5c8f4950597ab7f` emits a cache clearing event for path `/path/path2`. +- `Cache-control: evm-events="0xe4ba0e245436b737468c206ab5c8f4950597ab7f"` : The cache of the page returning this directive will be cleared when the contract `0xe4ba0e245436b737468c206ab5c8f4950597ab7f` emits a cache clearing event for the path of the page having been served. ### Cache invalidation event @@ -49,7 +63,7 @@ event ClearPathCache(string[] paths); This event clears the cache for an array of `paths`. Each `path` refers to the `pathQuery` part of the ABNF definition in [ERC-6860](./eip-6860.md). -- A `path` MUST NOT end with a `/`, except for the root path, which is `/`. +- A `path` MUST NOT end with a `/`, except when the whole path is the root path, which is `/`. - Two `paths` are considered identical if they have the same [ERC-5219](./eip-5219.md) resource entries and their parameter values match, regardless of the order. **Example**: @@ -151,6 +165,8 @@ We add this feature to the [ERC-6944](./eip-6944.md) resolve mode because it can To stay as close as possible to standard HTTP, we reuse the HTTP caching mechanism headers. +The use of the `evm-events` directive is necessary to avoid a situation where a website uses traditional [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) HTTP caching headers, but does not implement this ERC by failing to emit the events. In such cases, `web3://` clients implementing this ERC would serve stale content for that website indefinitely. + ## Security Considerations No security considerations were found. From 72490e7a2d9f5fb421834213b0bbc83b380e9952 Mon Sep 17 00:00:00 2001 From: nand Date: Mon, 11 Nov 2024 11:22:33 +0100 Subject: [PATCH 12/16] Event value: Can now have multiple values. Indicate that they specify additional places to listen for cache clearing, on top of the current contract+path. --- ERCS/erc-7774.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/ERCS/erc-7774.md b/ERCS/erc-7774.md index 004dbf2a69..cfcea0a611 100644 --- a/ERCS/erc-7774.md +++ b/ERCS/erc-7774.md @@ -37,21 +37,23 @@ When a [ERC-6944](./eip-6944.md) resolve mode website wants to use event-based c - Include the `ETag` and/or `Cache-Control` headers in the response, as per traditional [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) HTTP caching. - Emit a cache invalidation event (as defined below) for the path in the smart contract when the output of the response changes and it deems cache clearing necessary. -A value to the `evm-events` cache directive is optional, and can be used to specify to listen for events on another smart contract, and/or for another path. The cache directive value syntax in ABNF notation is : +A value to the `evm-events` cache directive is optional, and can be used to specify to listen for additional events on other smart contracts, and/or for other paths. The cache directive value syntax in ABNF notation is : ``` -cacheDirectiveValue = [ address ] [ path-absolute [ "?" query ] ] -address = "0x" 20( HEXDIG HEXDIG ) -path-absolute = -query = +cache-directive-value = [ address-path-absolute *( " " address-path-absolute ) ] +address-path-absolute = [ address ] path-absolute [ "?" query ] +address = "0x" 20( HEXDIG HEXDIG ) +path-absolute = +query = ``` **Examples**: - `Cache-control: evm-events` : The cache of the page returning this directive will be cleared when the contract having responded to the request emits a cache clearing event for the path of the page having been served. -- `Cache-control: evm-events="/path/path2"` : The cache of the page returning this directive will be cleared when the contract having responded to the request emits a cache clearing event for path `/path/path2`. -- `Cache-control: evm-events="0xe4ba0e245436b737468c206ab5c8f4950597ab7f/path/path2"` : The cache of the page returning this directive will be cleared when the contract `0xe4ba0e245436b737468c206ab5c8f4950597ab7f` emits a cache clearing event for path `/path/path2`. -- `Cache-control: evm-events="0xe4ba0e245436b737468c206ab5c8f4950597ab7f"` : The cache of the page returning this directive will be cleared when the contract `0xe4ba0e245436b737468c206ab5c8f4950597ab7f` emits a cache clearing event for the path of the page having been served. +- `Cache-control: evm-events="/path/path2"` : Same behavior than the first example, but additionally the cache of the page returning this directive will be cleared when the contract having responded to the request emits a cache clearing event for path `/path/path2`. +- `Cache-control: evm-events="0xe4ba0e245436b737468c206ab5c8f4950597ab7f/path/path2"` : Same behavior than the first example, but additionally the cache of the page returning this directive will be cleared when the contract `0xe4ba0e245436b737468c206ab5c8f4950597ab7f` emits a cache clearing event for path `/path/path2`. +- `Cache-control: evm-events="0xe4ba0e245436b737468c206ab5c8f4950597ab7f"` : Same behavior than the first example, but additionally the cache of the page returning this directive will be cleared when the contract `0xe4ba0e245436b737468c206ab5c8f4950597ab7f` emits a cache clearing event for the path of the page having been served. +- `Cache-control: evm-events="/path/path2 /path/path3"` : Same behavior than the first example, but additionally the cache of the page returning this directive will be cleared when the contract having responded to the request emits a cache clearing event for path `/path/path2` or `/path/path3`. ### Cache invalidation event From 586f7f45689b75f648862e9ec22744bbdcaa3969 Mon Sep 17 00:00:00 2001 From: nand2 Date: Thu, 14 Nov 2024 11:43:00 +0100 Subject: [PATCH 13/16] Update ERCS/erc-7774.md Co-authored-by: Sam Wilson <57262657+SamWilsn@users.noreply.github.com> --- ERCS/erc-7774.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ERCS/erc-7774.md b/ERCS/erc-7774.md index cfcea0a611..80ac6c9496 100644 --- a/ERCS/erc-7774.md +++ b/ERCS/erc-7774.md @@ -1,7 +1,7 @@ --- eip: 7774 title: Cache invalidation in ERC-5219 mode Web3 URL -description: In ERC-5219 resolve mode, add mechanisms to alleviate limitations that prevent the use of RFC 9111 HTTP caching +description: Introduce a new HTTP cache control method using EVM events for invalidation author: Nicolas Deschildre (@nand2) discussions-to: https://ethereum-magicians.org/t/erc-7774-cache-invalidation-in-erc-5219-mode-web3-url/21255 status: Draft From 5a70147d231527ac6a17bfb67712417848eba09c Mon Sep 17 00:00:00 2001 From: nand2 Date: Thu, 14 Nov 2024 11:43:22 +0100 Subject: [PATCH 14/16] Update ERCS/erc-7774.md Co-authored-by: Sam Wilson <57262657+SamWilsn@users.noreply.github.com> --- ERCS/erc-7774.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ERCS/erc-7774.md b/ERCS/erc-7774.md index 80ac6c9496..72d29cd3b7 100644 --- a/ERCS/erc-7774.md +++ b/ERCS/erc-7774.md @@ -31,7 +31,7 @@ Additionally, even if smart contracts could read request HTTP headers, using sma This standard introduces the `evm-events` cache directive for the `Cache-Control` header of request responses, as an extension directive as defined in section 5.2.3 of [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111). -When a [ERC-6944](./eip-6944.md) resolve mode website wants to use event-based caching for a request, it MUST: +When an [ERC-6944](./eip-6944.md) resolve mode website wants to use event-based caching for a request, it MUST: - Include the `evm-events` directive in the `Cache-Control` header of the response. - Include the `ETag` and/or `Cache-Control` headers in the response, as per traditional [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) HTTP caching. From 4ac12c9a249a1d0fdd3760cb03f97e5ad1349e67 Mon Sep 17 00:00:00 2001 From: nand2 Date: Thu, 14 Nov 2024 11:44:16 +0100 Subject: [PATCH 15/16] Update ERCS/erc-7774.md Co-authored-by: Sam Wilson <57262657+SamWilsn@users.noreply.github.com> --- ERCS/erc-7774.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ERCS/erc-7774.md b/ERCS/erc-7774.md index 72d29cd3b7..462247ddac 100644 --- a/ERCS/erc-7774.md +++ b/ERCS/erc-7774.md @@ -167,7 +167,7 @@ We add this feature to the [ERC-6944](./eip-6944.md) resolve mode because it can To stay as close as possible to standard HTTP, we reuse the HTTP caching mechanism headers. -The use of the `evm-events` directive is necessary to avoid a situation where a website uses traditional [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) HTTP caching headers, but does not implement this ERC by failing to emit the events. In such cases, `web3://` clients implementing this ERC would serve stale content for that website indefinitely. +The use of the `evm-events` directive is necessary to avoid a situation where a website uses traditional [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) HTTP caching headers, but the contract does not implement this ERC by failing to emit the events. In such cases, `web3://` clients implementing this ERC would serve stale content for that website indefinitely. ## Security Considerations From bf3eb938d82f3224b55178107c7ce57dde9d752e Mon Sep 17 00:00:00 2001 From: nand Date: Thu, 14 Nov 2024 12:09:25 +0100 Subject: [PATCH 16/16] Adding security considerations. --- ERCS/erc-7774.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/ERCS/erc-7774.md b/ERCS/erc-7774.md index 462247ddac..35d95eccdf 100644 --- a/ERCS/erc-7774.md +++ b/ERCS/erc-7774.md @@ -2,7 +2,7 @@ eip: 7774 title: Cache invalidation in ERC-5219 mode Web3 URL description: Introduce a new HTTP cache control method using EVM events for invalidation -author: Nicolas Deschildre (@nand2) +author: Nicolas Deschildre (@nand2), Sam Wilson (@SamWilsn) discussions-to: https://ethereum-magicians.org/t/erc-7774-cache-invalidation-in-erc-5219-mode-web3-url/21255 status: Draft type: Standards Track @@ -27,6 +27,8 @@ This ERC proposes a solution to bypass this limitation by allowing websites to b Additionally, even if smart contracts could read request HTTP headers, using smart contract events is more efficient, as it moves cache invalidation logic outside the contract. +We add this feature to the [ERC-6944](./eip-6944.md) resolve mode because it can be added without changes to the interface. Future resolve modes that allow for request HTTP headers may also implement this ERC. + ## Specification This standard introduces the `evm-events` cache directive for the `Cache-Control` header of request responses, as an extension directive as defined in section 5.2.3 of [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111). @@ -163,15 +165,17 @@ In the "Listening for Events" state, the `web3://` client listens to the blockch ## Rationale -We add this feature to the [ERC-6944](./eip-6944.md) resolve mode because it can be added without changes the interface. - To stay as close as possible to standard HTTP, we reuse the HTTP caching mechanism headers. The use of the `evm-events` directive is necessary to avoid a situation where a website uses traditional [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) HTTP caching headers, but the contract does not implement this ERC by failing to emit the events. In such cases, `web3://` clients implementing this ERC would serve stale content for that website indefinitely. ## Security Considerations -No security considerations were found. +Stale content will be served during the delay between a user transaction emitting a cache clearing event, and the `web3://` client picking and processing the event. + +For each cached page, websites must properly implement cache invalidation events; otherwise, stale content will be served indefinitely. + +In the event of a chain reorganization, the `web3://` client must roll back its caching state, or reverted content will be served until the next cache clearing event. ## Copyright