-
Notifications
You must be signed in to change notification settings - Fork 80
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
refactor: migrate to jsonrpsee
+ zksync_web3_decl
#497
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly looks good
@@ -249,7 +249,7 @@ pub struct Cli { | |||
pub allow_origin: String, | |||
|
|||
/// Disable CORS. | |||
#[arg(long, default_missing_value = "true", num_args(0..=1), conflicts_with = "allow_origin", help_heading = "Server options")] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
$ anvil --no-cors --allow-origin http://google.com
error: the argument '--no-cors' cannot be used with '--allow-origin <ALLOW_ORIGIN>'
I guess this was taken from the upstream, not sure if we want to keep it just because it's there (OTOH I guess logically those options are in conflict)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I think I see where all of the confusion is coming from: --no-cors
is false
by default for anvil but it is true
for us to keep backwards compatibility. In our case these two options are not in conflict as the only way to enable cors is weirdly to pass --no-cors=false
in CLI. So, we need to do a couple of things here:
- Enabled CORS in anvil does not imply host filtering like what was done in feat: add cli options for server configuration #487, it is purely about HTTP headers. We should do the same
- We should understand if we are okay with enabling CORS by default. It's somewhat of a grey area for what I would consider a breaking change
@Romsters could you double check my understanding here and give your thoughts? If we are aligned I can make the change in this PR, no need to backport this for jsonrpc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@itegulov, @popzxc No, --no-cors
is false by default, same as in anvil. default_missing_value
is only applied if you specify --no-cors
without value, which should be reasonably set to true.
- Enabled CORS in anvil mirrors origin in response CORS headers, same as I've done. Disabled CORS in anvil doesn't check origin indeed, but it stops processing OPTIONS requests. I couldn't get the same behaviour with
jsonrpc_http_server
that's why I simply blocked all origins, which essentially is the same in terms of behaviour in browser, in both cases request will be blocked. - We definitely should enable CORS by default, it was enabled by default even before my changes. If you don't provide cors instructions to
jsonrpc_http_server
builder it still enables CORS by default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
default_missing_value
is only applied if you specify--no-cors
without value, which should be reasonably set to true
Yes, sorry I misunderstood that part after a long day of refactoring so the difference slipped my mind. I think what confused me is that it is IMHO a weird pattern to do Option<bool>
with default missing value so I refactored it to just be bool
with no extra clap options (except conflicts_with
). The behaviour should be the same; hope you don't mind.
Disabled CORS in anvil doesn't check origin indeed, but it stops processing OPTIONS requests
I don't understand what you mean by this. CORS protocol relies on the client side (i.e. browser) respecting the access list options meaning server does not enforce them. Not sure what anvil's behaviour you are referring to but I just ran anvil with --allow-origin mydomain.com
and made a curl request like this:
$ curl http://localhost:8011 -H "Origin: http://zksync-era.com" -X OPTIONS -v
< HTTP/1.1 200 OK
< access-control-allow-origin: mydomain.com
< vary: origin, access-control-request-method, access-control-request-headers
< access-control-allow-methods: GET,POST
< access-control-allow-headers: content-type
< allow: POST,GET,HEAD
< content-length: 0
< date: Wed, 18 Dec 2024 04:44:40 GMT
<
As you can see everything worked fine and nothing was blocked.
it was enabled by default even before my changes
I don't think this is true. I have just tried running era_test_node@0.1.0-alpha.33
and this is what I get:
$ curl http://localhost:8011 \
-X POST \
-H "Content-Type: application/json" \
--data '{"method":"eth_getBlockByNumber","params":["latest", true],"id":1,"jsonrpc":"2.0"}' -v
...
* upload completely sent off: 82 bytes
< HTTP/1.1 200 OK
< content-type: application/json; charset=utf-8
< content-length: 1489
< date: Wed, 18 Dec 2024 04:31:19 GMT
<
...
With OPTIONS
:
$ curl http://localhost:8011 -X OPTIONS -v
...
< HTTP/1.1 200 OK
< content-type: application/json; charset=utf-8
< allow: OPTIONS, POST
< accept: application/json
< content-length: 0
< date: Wed, 18 Dec 2024 04:35:37 GMT
<
The server only reports plain Allow
, nothing about access control as supposed to happen when CORS is enabled.
In any case I aligned the code with anvil: I am using the same tower
CORS middleware they are using. Please check out d7f6147. It also includes significant refactoring of integration tests as the behaviour I wanted to assert was different from what you implemented.
# TODO: Depending on `clap` here is not the worst thing for now but need to reconsider if this is strictly necessary | ||
clap.workspace = true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's quite surprising indeed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's needed for clap-specific derivations. I could make it optional and hide it behind clap
flag but at the same time I don't want to eventually arrive at the situation we have in zksync-era with the recently discussed feature flag hell.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the right approach here would be to define two types (one that derives ValueEnum
in CLI and one agnostic in types) and implement conversion for them rather than introduce flags, but it can wait.
.into_boxed_future() | ||
impl InMemoryNode { | ||
pub async fn estimate_fee_impl(&self, req: CallRequest) -> Result<Fee, Web3Error> { | ||
// TODO: Burn with fire |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
# Conflicts: # crates/cli/src/cli.rs # crates/config/src/types/mod.rs # crates/core/src/node/eth.rs # crates/core/src/node/in_memory.rs # e2e-tests-rust/tests/lib.rs
# TODO: Depending on `clap` here is not the worst thing for now but need to reconsider if this is strictly necessary | ||
clap.workspace = true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the right approach here would be to define two types (one that derives ValueEnum
in CLI and one agnostic in types) and implement conversion for them rather than introduce flags, but it can wait.
What 💻
Closes #495
Apologies for the big PR but I tried to keep functional changes to the minimum. Brief overview of the new crates:
api_decl
- a combination of re-exported namespaces fromzksync_web3_decl
andjsonrpsee
server bindings for other namespaces not supported there (anvil
,evm
,config
, one method frometh
)api_server
- implementations for the aforementioned namespaces; all of the methods are either "return a constant" or a single invocation of the corresponding method fromInMemoryNode
types
- just a collection of basic types we use, some stuff fromconfig
was moved hereThe few functional changes made on purpose:
zks_getTokenPrice
as it was deprecated for a bit and removed from core in feat(api): Remove unused and obsolete token info zksync-era#1071hardhat_impersonateAccount
andhardhat_stopImpersonatingAccount
no longer returnbool
- I didn't find any reference on why they should and theanvil
version does notHost
nowlogging_middleware
was replaced by the jsonrpsee's built-inRpcLogger
. Format is different but arguably not a part of external API so does not matter as long as the semantics are the same.Work that purposefully has not been done in this PR but should be done in the future:
RpcError
which is eitheranyhow
,Web3Error
from core orLoadStateError
which is the only custom error type we haveInMemoryNode
toApiServer
(name WIP) and move it toapi_server
. Essentially we don't wantcore
to care too much about what kind of requests it will need to be able to answer.Why ✋
jsonrpc
crate has been deprecated for a while and we should align ourselves with core as much as we can