refactor: move hash memoization out of signed#1485
Conversation
| let mut buf = Vec::with_capacity(v.tx().encoded_len_with_signature(v.signature())); | ||
| v.tx().encode_with_signature_fields(v.signature(), &mut buf); | ||
| let h = keccak256(buf); |
There was a problem hiding this comment.
should all of those be Sealable impls?
There was a problem hiding this comment.
no, only the envelope knows the correct serialization for its components (tx types don't know their flag as it may be network dependent c.f. issue #1483)
e1b260a to
23a5505
Compare
c5d37ef to
2f04789
Compare
|
this is ready for re-review |
| pub enum TxEnvelope { | ||
| /// An untagged [`TxLegacy`]. | ||
| Legacy(Signed<TxLegacy>), | ||
| Legacy(Enveloped<TxLegacy>), | ||
| /// A [`TxEip2930`] tagged with type 1. | ||
| Eip2930(Signed<TxEip2930>), | ||
| Eip2930(Enveloped<TxEip2930>), | ||
| /// A [`TxEip1559`] tagged with type 2. | ||
| Eip1559(Signed<TxEip1559>), | ||
| Eip1559(Enveloped<TxEip1559>), | ||
| /// A TxEip4844 tagged with type 3. | ||
| /// An EIP-4844 transaction has two network representations: | ||
| /// 1 - The transaction itself, which is a regular RLP-encoded transaction and used to retrieve | ||
| /// historical transactions.. | ||
| /// | ||
| /// 2 - The transaction with a sidecar, which is the form used to | ||
| /// send transactions to the network. | ||
| Eip4844(Signed<TxEip4844Variant>), | ||
| Eip4844(Enveloped<TxEip4844Variant>), | ||
| /// A [`TxEip7702`] tagged with type 4. | ||
| Eip7702(Signed<TxEip7702>), | ||
| Eip7702(Enveloped<TxEip7702>), | ||
| } |
There was a problem hiding this comment.
excellent, but, what's the plan for alloy_consensus::TypedTransaction now? it's essentially the same type
There was a problem hiding this comment.
TypedTransaction is the unsigned version. As such neither signature or hash is known, and it just includes a signable version of the inner transaction and is used in the NetworkWallet::<N>::sign_transaction_from API
actually now that you mention it, we need to apply #1489 to TypedTransaction as well
| let mut buf = Vec::with_capacity(v.tx().encoded_len_with_signature(v.signature())); | ||
| v.tx().encode_with_signature_fields(v.signature(), &mut buf); |
There was a problem hiding this comment.
is there no other way to get the tx hash?
if the only solution is to go through the txenvelope enum this will be very inconvenient
There was a problem hiding this comment.
c.f. #1483. Technically it's legal for networks to make envelopes that do the following:
- use the same inner type, but a different serialization (e.g. a TxLegacy serialized borsht instead of RLP)
- use a different tx flag for the same inner type (e.g. a
TxEnvelopecontainingTxEip1559at23instead of2 - use the same inner type at multiple tx flags (e.g. a
TxEnvelopecontainingTxEip1559at both2and23)
So there is no way to correctly get the hash of a transaction without wrapping it in the specific network's envelope first
There was a problem hiding this comment.
imo if a network does this then that's on them, because the type id is even part of the eip itself, if they'd choose 23 then this would no longer be 1559
There was a problem hiding this comment.
all of those usecases can be solved by introducing a separate inner transaction type (e.g. network can provide its own TxLegacy)
right now it makes total sense for separate transaction types to know their full encoding because we don't yet have a case of network rolling out encoding of transaction conflicting with existing tx types. also given that most of the networks target for compatibility with ethereum I'd consider such case very unlikely
There was a problem hiding this comment.
I also consider it unlikely. But it's still the only correct abstraction of an EIP-2718 envelope if we want our code to be reusable.
because the type id is even part of the eip itself
This is a fair reading of the spec. And @klkvr is right that people downstream can just duplicate 500 lines of code per tx type to change a single constant. However, it costs us very little to have the envelope drive serialization and hashing and prevents future headaches when someone inevitably does something silly here
For another interesting example, consider the extension sentinel value in eip-2718 0xff 🙃 This is also unlikely ofc, but tx-association falls down in extended envelopes
|
At current state of alloy transactions do know their encoding and their type byte. I've seen a lot of examples of people using IMO this edge case (Ethereum transactions with different type byte) is very unlikely and already can be solved by introducing separate types |
yes, this is the logic bug in #1483. They do, but they should not, as the type byte is an envelope feature, not a transaction feature. See #1483 and #1485 (comment) I do not know of any network that do this, but i do think that the cost of implementing it correctly now is small, while the cost of fixing it later is large
This API is broken right now, and their usage is almost certainly incorrect. It's why the encoding/decoding functions were private before #529, and why #529 hides them from users. We deliberately set out to prevent people from doing this and made it officially not part of the public API. as |
could you please elaborate a bit on that? is it broken for 4844 case? |
There's that, yes. 4844 transaction with sidecars produce incorrect
I can continue, but basically this is a broken API that confuses multiple serialization schemes and is almost impossible to correctly use The long term fix is to change the RLP derive to allow flattening and field-only serialization |
|
actually this is a good time to just make a cleanup PR. I'll go do that |
|
holding off on rebasing this as it's better with #1496 |
|
closing per discussion in slack |
This is a breaking change
Motivation
See discussion in #1460 and #1483
Memoizing the hash in
Signedis inappropriate, as the transaction does not know its full 2718 serialization without being embedded in an envelope. This breaks the hash out into aSealedtype that is produced when theEnvelopeis constructed. The sealed type is transparent to the userSolution
Envelopedtype aliasFrom<>impls properlySealimpl Encodable2718 for TxEnvelopeproduces the correcttrie_hashby returning the memoized hash. This previously produced incorrect hashes for 4844 txns with sidecarsPR Checklist