-
Notifications
You must be signed in to change notification settings - Fork 16
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
[multi-chain] Implement a generic chain spec #653
Conversation
|
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## feat/multichain #653 +/- ##
==================================================
Coverage ? 63.24%
==================================================
Files ? 210
Lines ? 23618
Branches ? 23618
==================================================
Hits ? 14938
Misses ? 7766
Partials ? 914 ☔ View full report in Codecov by Sentry. |
aef02e2
to
e271b2f
Compare
e271b2f
to
d95eb9a
Compare
Ah, d95eb9a regressed the |
Simple mistake, I specialized the block to a concrete tx type but lost support for 32-byte hashes, instead. This brings back the original generic approach and hopefully everything works again 🤞 |
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.
Overall, this looks good! Thank you for the changes. The feedback on the chain spec trait design was also very helpful!
A couple of small comments/suggestions.
Once you have integrated this into Hardhat and validated that the Hardhat test suite passes with the generic chain type, this is good to merge - as far as I am concerned.
// TODO: Should we properly decode the transaction type? | ||
TypedEnvelope::Unrecognized(_) => transaction::Type::Unrecognized(0xFF), |
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.
We might change this behaviour in Hardhat v3, but in main
we don't return the source transaction type number. It gets lost in the conversion to a Legacy transaction. I think we should match that internally for now.
In the future, I would be in favour of returning the source transaction type number.
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.
So I'm torn here, as in practice it shouldn't matter but for example you use the library to RLP-decode the typed envelope and saturate to transaction::Type::Legacy
here, it would not be roundtrippable per se; maybe that's okay.
Do you want me to return transaction::Type::Legacy
with a note or unreachable!
or something else here, specifically?
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.
That's correct. Internally, we never actually decoded anything that we didn't encode ourselves. That's why the guarantee holds in real use cases.
So the tricky case here is the ChainSpecT::PooledTransaction::decode
in pub fn handle_send_raw_transaction_request
. This should return an invalid transaction type error for any non-supported transaction types. As long as you return that for TypedEnvelope::Unrecognized
, we should not be changing behaviour inadvertently.
It seems that the current implementation does that.
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.
Hm, that is tricky - the ChainSpecT::PooledTransaction
uses its decode impl but it's only compared against a alloy_rlp::Error::Custom(&'static str)
and checks the string contents using a edr_eth::transaction::Signed::is_invalid_transaction_type_error
.
While the ProviderSpec
impl for GenericChainSpec
has the PooledTransaction the same as edr_eth's, so we're safe, the interaction seems somewhat flimsy as we're crossing from the ChainSpec abstraction to the concrete edr_eth impls and use string checks, no less.
I'm also wary of introducing yet another type param but maybe, since we're already using generic and type-safe impls, we should introduce something like TransactionDecodeError
and add our InvalidType
variant on top of the RLP error or something like that? We seem to be recovering/handling this exact case often enough to uplift it to the type system but I'm curious to see what you think. I can also see a perspective where this is only a single additional variant and it's more trouble than it's worth to pile abstraction over a lean RLP decode trait.
I took the liberty of matching on the const str value rather than using the if guard on the pattern in 31f123e for consistency - I hope you don't mind.
use crate::{rpc::transaction::TransactionWithSignature, GenericChainSpec}; | ||
|
||
#[tokio::test(flavor = "current_thread")] | ||
async fn test_allow_missing_nonce_or_mix_hash() { |
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.
❤️
|
||
use crate::GenericChainSpec; | ||
|
||
// We need to use a newtype here as `RpcTypeFrom` cannot be implemented here, |
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.
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.
In general there were few cases where it was not possible to re-use the original traits as we did depend on the actual trait implementation or the associated type was set for a given impl, rather than be generic (and so pluggable by potential other impls, like (Fake)Sign
).
How often that's the case I'm not sure, as this was a very specific case of "do everything that L1 does except these few tiny bits" but I'd assume that we should provide sensible defaults or building blocks that the other implementers can more easily re-use what we have rather than copy the impls in some cases.
What's the ergonomic solution I'm not yet sure and I'm mostly just thinking out loud. Maybe allow for more generic impls and use the final marker trait impls that tie all of these together to validate that the intermediate types are compatible and expected?
For instance, I found it hard to wrap my head around what to implement as often the traits felt like they were circular, like in the case of satisfying both the RpcSpec
and ChainSpec
for a type. Another case is that some types like EthBlockData
only use a single associated type from the ChainSpec
and the ChainSpec
feels like this tie-all/validation trait (which makes sense) but it made me harder to understand what's actually used and why. I had trouble deciphering some of the compiler errors and figuring out which trait impls are required because it felt so intertwined.
Maybe I just missed a proper mental model but I have to admit that it took me longer than it should 🙈
Co-authored-by: Wodann <Wodann@users.noreply.github.com>
Co-authored-by: Wodann <Wodann@users.noreply.github.com>
I have implemented the |
@Wodann I hope everything looks good now! The tests are passing and I applied the patch; let me know if I should add or change anything. Thanks! |
a784ee4
to
78f08c6
Compare
52396d2
to
a7cfee7
Compare
While going through the changes I noticed that there was a failing test in the EDR TS bindings but it wasn't being triggered in the CI. I added CI support, causing the failure, and pushed a fix for it. I also re-added the implementation of the |
) -> napi::Result<Response> { | ||
let response = jsonrpc::ResponseData::from(response.map(|response| response.result)); | ||
|
||
serde_json::to_string(&response) |
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.
This code duplication will be removed in https://github.com/NomicFoundation/edr/pull/659/files#diff-bd82f1c79ac0cc9d088b3262a78277433ed1667e6f519c2ac84215247a6fcf61R154
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 made some changes to fix a failing test that wasn't running in CI. Other than that it LGTM!
There is one open discussion thread regarding a TODO. If my understanding is correct, feel free to proceed with merging, if you're happy with the changes that I made.
This is more consistent with the other uses and increases visibility to the underlying static str value.
Closes #635
For now this does not error out on unknown transaction types and interprets it as EIP-155 for the transactions and EIP-568 for the receipts, doing what we do on main. The integration test listed in #635 passes. What's left is not erroring out on missing nonce/mixHash for remote blocks. EDIT: That's now done in d95eb9a.
@Wodann this is up for preliminary review if you feel like it, I tried to clean it up more or less and retain the existing structure found in edr_optimism.