-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
feat: implement conversion of optimism deposit tx from alloy to reth #8763
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.
can we add a test using:
{
"blockHash": "0xef664d656f841b5ad6a2b527b963f1eb48b97d7889d742f6cbff6950388e24cd",
"blockNumber": "0x73a78fd",
"depositReceiptVersion": "0x1",
"from": "0x36bde71c97b33cc4729cf772ae268934f7ab70b2",
"gas": "0xc27a8",
"gasPrice": "0x0",
"hash": "0x0bf1845c5d7a82ec92365d5027f7310793d53004f3c86aa80965c67bf7e7dc80",
"input": "0xd764ad0b000100000000000000000000000000000000000000000000000000000001cf5400000000000000000000000099c9fc46f92e8a1c0dec1b1747d010903e884be100000000000000000000000042000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007a12000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000e40166a07a0000000000000000000000000994206dfe8de6ec6920ff4d779b0d950605fb53000000000000000000000000d533a949740bb3306d119cc777fa900ba034cd52000000000000000000000000ca74f404e0c7bfa35b13b511097df966d5a65597000000000000000000000000ca74f404e0c7bfa35b13b511097df966d5a65597000000000000000000000000000000000000000000000216614199391dbba2ba00000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"mint": "0x0",
"nonce": "0x74060",
"r": "0x0",
"s": "0x0",
"sourceHash": "0x074adb22f2e6ed9bdd31c52eefc1f050e5db56eb85056450bccd79a6649520b3",
"to": "0x4200000000000000000000000000000000000007",
"transactionIndex": "0x1",
"type": "0x7e",
"v": "0x0",
"value": "0x0"
}
or pick any other deposit tx: https://optimistic.etherscan.io/address/0x4200000000000000000000000000000000000007
use crate::{ | ||
transaction::TxDeposit, | ||
constants::OP_SYSTEM_TX_FROM_ADDR, | ||
}; |
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'd like to use full paths and not feature gate imports
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.
confirmed.
Some(TxType::Deposit) => todo!(), | ||
Some(TxType::Deposit) => { | ||
Ok(Self::Deposit(TxDeposit { | ||
// TODO: Uses the wrong error here, need alloy ConversionError enum updated with new errors for this. |
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.
do you want to add a Custom(String)
variant to the alloy error?
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 best to just add ConversionError::MissingSourceHash
, ConversionError::InvalidSourceHash
, and ConversionError::InvalidMintValue
for consistency.
Some(TxType::Deposit) => { | ||
Ok(Self::Deposit(TxDeposit { | ||
// TODO: Uses the wrong error here, need alloy ConversionError enum updated with new errors for this. | ||
source_hash: match &tx.other["sourceHash"] { |
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.
otherfields has get_deserialized::<String>(key)
which we should use combined with Option::transpose
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.
thanks for the tip. what's the reasoning to use Option::transpose
since i'm going to have to unwrap to the String anyways in order to parse into B256?
i would think ideal would be something like:
source_hash: tx.other.get_deserialized::<String>("sourceHash")
.ok_or(ConversionError::MissingSourceHash)?
.map_err(|_| ConversionError::InvalidSourceHash)?
.parse()
.map_err(|_| ConversionError::InvalidSourceHash)?,
None => TxKind::Create, | ||
}, | ||
mint: match &tx.other["mint"] { | ||
serde_json::Value::String(mint) => mint.parse::<u128>().ok().and_then(|num| if num == 0 { None } else { Some(num) }), |
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 will fail because mint is U128
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.
is there a convenient way to convert U128 to u128?
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.
are you sure mint is U128
?
i see that is here: https://github.com/alloy-rs/alloy/blob/ed8a6baa2b1c404030a388633e9b7ee47825ed52/crates/rpc-types-eth/src/transaction/optimism.rs#L16
but i'm not sure if that struct is actually used. when i read the alloy block transactions, it's all strings and doesn't match the fields of that struct:
other: OtherFields {"depositReceiptVersion": String("0x1"), "mint": String("0x0"), "sourceHash": String("0x3a20754de0b2ef572fac9ca91ec3b182e61101c66d666897e8539e8b57b9a40c")}
i tried writing a test assuming it's a string and it works fine, see latest commit.
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.
these should be used in the test as raw string let input: &str = r#...#;
not extra file
mint: tx.other.get_deserialized::<String>("mint") | ||
.ok_or(ConversionError::MissingBlobVersionedHashes)? | ||
.map_err(|_| ConversionError::MissingMaxFeePerBlobGas)? | ||
.parse::<u128>() | ||
.ok() // TODO: This converts failure to None. Better to error instead? |
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 get be get_deserialized::
@mattsse I think this should be good to go, pending the Alloy errors (which we're discussing here: alloy-rs/alloy#875). Thank you for your help with this. Please let me know if you have any other feedback — otherwise will ping you when errors are updated for final approval. |
Head branch was pushed to by a user without write access
@mattsse Alloy error update was merged (alloy-rs/alloy#875) so updated this accordingly. It's ready to go but will need an Alloy version bump before it works. Is best practice just to let it wait until that time, or is there another way to handle it? |
mint: Option::transpose(tx.other.get_deserialized::<alloy_primitives::U128>("mint")) | ||
.map_err(|_| ConversionError::Custom(String::from("MissingMintValue")))? | ||
.and_then(|num| { | ||
if num.to::<u128>() == 0 { |
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.
.map(|num| num.to::<u128>())
.filter(|num| num > 0)
.ok_or(ConversionError::Custom(String::from("MissingSourceHash")))? | ||
.map_err(|_| ConversionError::Custom(String::from("MissingSourceHash")))? | ||
.parse() | ||
.map_err(|_| ConversionError::Custom(String::from("InvalidSourceHash")))?, |
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 .to_string()
source_hash: tx | ||
.other | ||
.get_deserialized::<String>("sourceHash") | ||
.ok_or(ConversionError::Custom(String::from("MissingSourceHash")))? |
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.
ok_or_else
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.
@DaniPopes Thanks for the notes. Made all changes and pushed commit, but I'm curious to learn from this one. Why the preference for ok_or_else
vs ok_or
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.
String::from
allocates, and ok_or
is eager which means the allocation is performed regardless of whether the Option
is Some
or None
.
See Option::ok_or
Arguments passed to
ok_or
are eagerly evaluated; if you are passing the result of a function call, it is recommended to useok_or_else
, which is lazily evaluated.
The
alloy_compat
feature inreth/primitives
contains conversion functions from Alloy types to Reth types. When converting transactions, the Optimism deposit tx type is currently unimplemented. This PR contains an implementation.Questions:
How do you all like to handle tests for functions like this? I've tested manually in another crate, but to add a test directly to the
alloy_compat.rs
file would require importing a lot of machinery. Is there a better way to handle it?The errors for this function are imported from Alloy, and the enum currently doesn't contain some errors I need. I've stubbed it out with inaccurate errors. I assume best process to submit PR to Alloy to add those errors, then update them here before merging?