Skip to content
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: migrate to alloy TxLegacy #9593

Merged
merged 36 commits into from
Aug 30, 2024
Merged

Conversation

leruaa
Copy link
Contributor

@leruaa leruaa commented Jul 17, 2024

Cf #9484

@leruaa leruaa marked this pull request as draft July 17, 2024 20:52
Copy link
Collaborator

@mattsse mattsse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

amazing work so far!

crates/primitives/src/transaction/legacy.rs Outdated Show resolved Hide resolved
@@ -1172,7 +1176,8 @@ impl TransactionSigned {
/// only `true`.
pub(crate) fn payload_len_inner(&self) -> usize {
match &self.transaction {
Transaction::Legacy(legacy_tx) => legacy_tx.payload_len_with_signature(&self.signature),
Transaction::Legacy(legacy_tx) => legacy_tx
.encoded_len_with_signature(&self.signature.as_alloy_signature(legacy_tx.chain_id)),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe worth exploring if we can phase out the reth-prim signature type?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would be interesting, but can it be done in a followup?

crates/primitives/src/transaction/signature.rs Outdated Show resolved Hide resolved
crates/storage/codecs/src/alloy/transaction.rs Outdated Show resolved Hide resolved
crates/storage/codecs/src/alloy/transaction.rs Outdated Show resolved Hide resolved
@leruaa
Copy link
Contributor Author

leruaa commented Jul 18, 2024

@mattsse the test test_sending_invalid_transactions is failling because it's creating an invalid signature, but now with the conversion to alloy Signature we create a k256::ecdsa::Signature and it fails.

Should as_alloy_signature() returns a Result and also update the callers to also returns a Result?

Or maybe it's time to migrate to alloy signature per your comment above: #9593 (comment), but it wouldn't be possible to create invalid signatures anymore.

@mattsse
Copy link
Collaborator

mattsse commented Jul 18, 2024

but now with the conversion to alloy Signature we create a k256::ecdsa::Signature and it fails.

can you elaborate? unclear what fails, the default alloy Signature type is feature gated, imo we should use Signature<()> here

it wouldn't be possible to create invalid signatures anymore.

I think with Signature<()> this would still be possible, but perhaps we need to tune something for this type?

@leruaa
Copy link
Contributor Author

leruaa commented Jul 18, 2024

@leruaa
Copy link
Contributor Author

leruaa commented Jul 19, 2024

To add a bit of context:

The issue with the test test_sending_invalid_transactions is that it create an invalid signature here:

let tx = TransactionSigned::from_transaction_and_signature(tx.into(), Default::default());

Deeper in the code this signature is converted to an alloy Signature, but as the k256 feature is on, a k256::ecdsa::Signature is needed but can't be created from an invalid signature.

I fixed test_sending_invalid_transactions() by creating a valid signature, but more generally I guess we should be able to convert reth signatures to alloy ones even if they are invalid.

I think the main issue here is that the k256 feature on alloy-primitives is not additive (i.e. it remove the Signature<()> type when activated), and that is an issue in reth because we won't be able to make it off (it's needed in revm).

So I think we need to update alloy-primitives to never remove Signature<()> and rename Signature when k256 feature is enabled to something else.

@mattsse wdyt? I hope to have been clear :)

@mattsse
Copy link
Collaborator

mattsse commented Jul 19, 2024

i.e. it remove the Signature<()> type when activated), and that is an issue in reth because we won't be able to make it off (it's needed in revm).

yeah, tbh I find this behaviour in alloy-primitives a bit strange because this obfuscates things.
I'd like if we could add a simple alias for Signature<()> to alloy-primitives, like RawSignature or something,

but maybe you can use a type alias for this here for now?

we also need to change these functions

https://github.com/alloy-rs/alloy/blob/main/crates/consensus/src/transaction/legacy.rs#L120-L120

so they accept any Signature<S> because we only need the rsv fields

@leruaa
Copy link
Contributor Author

leruaa commented Jul 19, 2024

Unfortunately we can't use a type alias because Signature<S> is private.

@mattsse
Copy link
Collaborator

mattsse commented Jul 19, 2024

this is kinda stupid lol

let's change that

we also need an infallible constructor for Signature<S>::rsv

I find this type a bit strange...

@mattsse
Copy link
Collaborator

mattsse commented Aug 1, 2024

@leruaa just checking in, is this now only blocked by a new alloy release?

@mattsse mattsse added the C-debt Refactor of code section that is hard to understand or maintain label Aug 5, 2024
Copy link
Collaborator

@mattsse mattsse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a pretty huge unlock and should unblock further alloy changes.

ptal at the codec things @joshieDo

Copy link
Collaborator

@joshieDo joshieDo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, tried locally with no issues

@mattsse
Copy link
Collaborator

mattsse commented Aug 5, 2024

sweet, blocking this to go in after tmrw's release

really nice work @leruaa this unblocks us from migrating the other variants aswell

@mattsse mattsse added the S-blocked This cannot more forward until something else changes label Aug 5, 2024
crates/primitives/src/transaction/mod.rs Outdated Show resolved Hide resolved
Copy link
Collaborator

@mattsse mattsse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alright, let's finally do this.

tysm for kickstarting this.

only have two more qs

crates/primitives/src/transaction/mod.rs Outdated Show resolved Hide resolved
Comment on lines 231 to 245
#[test]
fn test_payload_len_with_eip155_chain_id() {
// Select 1 as an arbitrary nonzero value for R and S, as v() always returns 0 for (0, 0).
let signature = Signature { r: U256::from(1), s: U256::from(1), odd_y_parity: false };

assert_eq!(3, signature.payload_len_with_eip155_chain_id(None));
assert_eq!(3, signature.payload_len_with_eip155_chain_id(Some(1)));
assert_eq!(4, signature.payload_len_with_eip155_chain_id(Some(47)));
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why was this test removed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The corresponding method payload_len_with_eip155_chain_id() has been removed.

Comment on lines 253 to 260
#[test]
fn test_encode_and_decode_with_eip155_chain_id() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

encode_with_eip155_chain_id() has also been removed

Copy link
Collaborator

@mattsse mattsse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry I have to ask more questions because I'm a bit lost with the signature types

also would appreciate a closer look by @Rjected

Comment on lines 247 to 248
alloy_primitives::Parity::NonEip155(self.odd_y_parity)
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm unsure if this is correct.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was to reflect the "else" case here:

pub fn v(&self, chain_id: Option<u64>) -> u64 {
if let Some(chain_id) = chain_id {
// EIP-155: v = {0, 1} + CHAIN_ID * 2 + 35
self.odd_y_parity as u64 + chain_id * 2 + 35
} else {
#[cfg(feature = "optimism")]
// pre bedrock system transactions were sent from the zero address as legacy
// transactions with an empty signature
//
// NOTE: this is very hacky and only relevant for op-mainnet pre bedrock
if *self == Self::optimism_deposit_tx_signature() {
return 0
}
self.odd_y_parity as u64 + 27
}
}

Comment on lines 191 to 201
/// Returns a signature with the given chain ID applied to the `v` value.
pub(crate) fn as_signature_with_eip155_parity(
&self,
chain_id: Option<u64>,
) -> SignatureWithParity {
let parity = match chain_id {
Some(chain_id) => EncodableSignature::v(self).with_chain_id(chain_id),
None => EncodableSignature::v(self),
};

SignatureWithParity::new(self.r(), self.s(), parity)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did that to encode the tx + signature the exact same way as before, in encode_with_signature():

pub(crate) fn encode_with_signature(&self, signature: &Signature, out: &mut dyn bytes::BufMut) {
let payload_length =
self.fields_len() + signature.payload_len_with_eip155_chain_id(self.chain_id);
let header = Header { list: true, payload_length };
header.encode(out);
self.encode_fields(out);
signature.encode_with_eip155_chain_id(out, self.chain_id);
}

So I needed a way to carry the chain_id.

@leruaa
Copy link
Contributor Author

leruaa commented Aug 21, 2024

I realize this is not taken into account anymore:

#[cfg(feature = "optimism")]
// pre bedrock system transactions were sent from the zero address as legacy
// transactions with an empty signature
//
// NOTE: this is very hacky and only relevant for op-mainnet pre bedrock
if *self == Self::optimism_deposit_tx_signature() {
return 0
}

Let me add a commit

Copy link
Collaborator

@mattsse mattsse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm, let's send it this finally @klkvr

@klkvr klkvr added this pull request to the merge queue Aug 30, 2024
Merged via the queue into paradigmxyz:main with commit 71e0178 Aug 30, 2024
34 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-debt Refactor of code section that is hard to understand or maintain S-blocked This cannot more forward until something else changes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants