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
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
f561f8e
feat: migrate to alloy TxLegacy
leruaa Jul 17, 2024
4e7940c
fix: move TxLegacy bitflag_encoded_bytes test for optimism
leruaa Jul 17, 2024
8eacec3
fix: add optimism feature
leruaa Jul 17, 2024
fdb5636
fix: typo in as_alloy_signature()
leruaa Jul 17, 2024
51f257c
fix remove useless derive
leruaa Jul 17, 2024
d1aadb1
fix: Don't put EIP-155 parity to create signatures for legacy txs
leruaa Jul 18, 2024
2667755
Merge branch 'main' into alloy_tx_legacy
leruaa Jul 18, 2024
9ea88a6
fix: update AlloyTxLegacy Compact impl
leruaa Jul 18, 2024
a51f350
fix: set a valid signature for test_sending_invalid_transactions()
leruaa Jul 19, 2024
c9749c9
fix: set correct parity
leruaa Jul 21, 2024
92450b0
feat: impl EncodableSignature for Signature
leruaa Jul 28, 2024
e72d217
Merge branch 'main' into alloy_tx_legacy
leruaa Jul 28, 2024
622f1e7
fix: revert modified test
leruaa Jul 28, 2024
f3a7f4f
Merge branch 'main' into alloy_tx_legacy
leruaa Aug 2, 2024
3776207
feat: allow to encode signature with eip155 chain id
leruaa Aug 2, 2024
f43e062
fix: clippy
leruaa Aug 2, 2024
2f6da9f
fix: rlp encode/decode
leruaa Aug 2, 2024
fcda848
fix: revert 3 last commits and try something else
leruaa Aug 4, 2024
1a11d13
fix: take the chain id into account when encoding legacy tx
leruaa Aug 4, 2024
bdbf6d5
fix: TransactionSigned payload len
leruaa Aug 4, 2024
0a73fb8
fix: use signatures with EIP-155 parity from chain id
leruaa Aug 4, 2024
2a3634f
fix: limit alloy TxLegacy gas_limit to u64::MAX in tests
leruaa Aug 4, 2024
9f09198
fix: limit TransactionSignedNoHash gas_limit to u64::MAX in tests
leruaa Aug 4, 2024
194b873
Merge remote-tracking branch 'origin/main' into alloy_tx_legacy
leruaa Aug 17, 2024
b68146b
fix: remove add_arbitrary_tests on Transaction as they are on MockTra…
leruaa Aug 17, 2024
cd45602
fix: same for TransactionSignedNoHash
leruaa Aug 17, 2024
85d840e
fix: fmt
leruaa Aug 17, 2024
10b1ed9
fix: fmt
leruaa Aug 18, 2024
e40b470
nit: move mocks in tests mod
leruaa Aug 21, 2024
9eb604e
fix: handle optimism pre bedrock system transactions
leruaa Aug 21, 2024
5b89127
fix: embed chain_id in optimism deposit tx signature
leruaa Aug 21, 2024
2675355
rm impl EncodableSignature for Signature
klkvr Aug 28, 2024
7bf8e72
Merge branch 'main' into pr/leruaa/9593
klkvr Aug 28, 2024
2503b78
fmt
klkvr Aug 28, 2024
d3d8a7d
Merge branch 'main' into alloy_tx_legacy
klkvr Aug 29, 2024
a8d154b
rm mock types
klkvr Aug 29, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions crates/net/eth-wire-types/src/blocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ mod tests {
chain_id: Some(1),
nonce: 0x8u64,
gas_price: 0x4a817c808,
gas_limit: 0x2e248u64,
gas_limit: 0x2e248,
to: TxKind::Call(hex!("3535353535353535353535353535353535353535").into()),
value: U256::from(0x200u64),
input: Default::default(),
Expand All @@ -379,7 +379,7 @@ mod tests {
chain_id: Some(1),
nonce: 0x9u64,
gas_price: 0x4a817c809,
gas_limit: 0x33450u64,
gas_limit: 0x33450,
to: TxKind::Call(hex!("3535353535353535353535353535353535353535").into()),
value: U256::from(0x2d9u64),
input: Default::default(),
Expand Down Expand Up @@ -438,7 +438,7 @@ mod tests {
chain_id: Some(1),
nonce: 0x8u64,
gas_price: 0x4a817c808,
gas_limit: 0x2e248u64,
gas_limit: 0x2e248,
to: TxKind::Call(hex!("3535353535353535353535353535353535353535").into()),
value: U256::from(0x200u64),
input: Default::default(),
Expand All @@ -454,7 +454,7 @@ mod tests {
chain_id: Some(1),
nonce: 0x9u64,
gas_price: 0x4a817c809,
gas_limit: 0x33450u64,
gas_limit: 0x33450,
to: TxKind::Call(hex!("3535353535353535353535353535353535353535").into()),
value: U256::from(0x2d9u64),
input: Default::default(),
Expand Down
24 changes: 12 additions & 12 deletions crates/net/eth-wire-types/src/transactions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ mod tests {
chain_id: Some(1),
nonce: 0x8u64,
gas_price: 0x4a817c808,
gas_limit: 0x2e248u64,
gas_limit: 0x2e248,
to: TxKind::Call(hex!("3535353535353535353535353535353535353535").into()),
value: U256::from(0x200u64),
input: Default::default(),
Expand All @@ -149,7 +149,7 @@ mod tests {
chain_id: Some(1),
nonce: 0x09u64,
gas_price: 0x4a817c809,
gas_limit: 0x33450u64,
gas_limit: 0x33450,
to: TxKind::Call(hex!("3535353535353535353535353535353535353535").into()),
value: U256::from(0x2d9u64),
input: Default::default(),
Expand Down Expand Up @@ -193,7 +193,7 @@ mod tests {
chain_id: Some(1),
nonce: 0x8u64,
gas_price: 0x4a817c808,
gas_limit: 0x2e248u64,
gas_limit: 0x2e248,
to: TxKind::Call(hex!("3535353535353535353535353535353535353535").into()),
value: U256::from(0x200u64),
input: Default::default(),
Expand All @@ -215,7 +215,7 @@ mod tests {
chain_id: Some(1),
nonce: 0x09u64,
gas_price: 0x4a817c809,
gas_limit: 0x33450u64,
gas_limit: 0x33450,
to: TxKind::Call(hex!("3535353535353535353535353535353535353535").into()),
value: U256::from(0x2d9u64),
input: Default::default(),
Expand Down Expand Up @@ -260,7 +260,7 @@ mod tests {
chain_id: Some(4),
nonce: 15u64,
gas_price: 2200000000,
gas_limit: 34811u64,
gas_limit: 34811,
to: TxKind::Call(hex!("cf7f9e66af820a19257a2108375b180b0ec49167").into()),
value: U256::from(1234u64),
input: Default::default(),
Expand Down Expand Up @@ -306,7 +306,7 @@ mod tests {
chain_id: Some(4),
nonce: 3u64,
gas_price: 2000000000,
gas_limit: 10000000u64,
gas_limit: 10000000,
to: TxKind::Call(hex!("d3e8763675e4c425df46cc3b5c0f6cbdac396046").into()),
value: U256::from(1000000000000000u64),
input: Default::default(),
Expand All @@ -328,7 +328,7 @@ mod tests {
chain_id: Some(4),
nonce: 1u64,
gas_price: 1000000000,
gas_limit: 100000u64,
gas_limit: 100000,
to: TxKind::Call(hex!("d3e8763675e4c425df46cc3b5c0f6cbdac396046").into()),
value: U256::from(693361000000000u64),
input: Default::default(),
Expand All @@ -350,7 +350,7 @@ mod tests {
chain_id: Some(4),
nonce: 2u64,
gas_price: 1000000000,
gas_limit: 100000u64,
gas_limit: 100000,
to: TxKind::Call(hex!("d3e8763675e4c425df46cc3b5c0f6cbdac396046").into()),
value: U256::from(1000000000000000u64),
input: Default::default(),
Expand Down Expand Up @@ -399,7 +399,7 @@ mod tests {
chain_id: Some(4),
nonce: 15u64,
gas_price: 2200000000,
gas_limit: 34811u64,
gas_limit: 34811,
to: TxKind::Call(hex!("cf7f9e66af820a19257a2108375b180b0ec49167").into()),
value: U256::from(1234u64),
input: Default::default(),
Expand Down Expand Up @@ -445,7 +445,7 @@ mod tests {
chain_id: Some(4),
nonce: 3u64,
gas_price: 2000000000,
gas_limit: 10000000u64,
gas_limit: 10000000,
to: TxKind::Call(hex!("d3e8763675e4c425df46cc3b5c0f6cbdac396046").into()),
value: U256::from(1000000000000000u64),
input: Default::default(),
Expand All @@ -467,7 +467,7 @@ mod tests {
chain_id: Some(4),
nonce: 1u64,
gas_price: 1000000000,
gas_limit: 100000u64,
gas_limit: 100000,
to: TxKind::Call(hex!("d3e8763675e4c425df46cc3b5c0f6cbdac396046").into()),
value: U256::from(693361000000000u64),
input: Default::default(),
Expand All @@ -489,7 +489,7 @@ mod tests {
chain_id: Some(4),
nonce: 2u64,
gas_price: 1000000000,
gas_limit: 100000u64,
gas_limit: 100000,
to: TxKind::Call(hex!("d3e8763675e4c425df46cc3b5c0f6cbdac396046").into()),
value: U256::from(1000000000000000u64),
input: Default::default(),
Expand Down
2 changes: 1 addition & 1 deletion crates/primitives/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ reth-chainspec = { workspace = true, optional = true }
reth-codecs = { workspace = true, optional = true }

# ethereum
alloy-consensus.workspace = true
alloy-primitives = { workspace = true, features = ["rand", "rlp"] }
alloy-rlp = { workspace = true, features = ["arrayvec"] }
alloy-rpc-types = { workspace = true, optional = true }
Expand Down Expand Up @@ -111,4 +112,3 @@ harness = false
name = "validate_blob_tx"
required-features = ["arbitrary", "c-kzg"]
harness = false

5 changes: 1 addition & 4 deletions crates/primitives/src/alloy_compat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,7 @@ impl TryFrom<alloy_rpc_types::Transaction> for Transaction {
chain_id,
nonce: tx.nonce,
gas_price: tx.gas_price.ok_or(ConversionError::MissingGasPrice)?,
gas_limit: tx
.gas
.try_into()
.map_err(|_| ConversionError::Eip2718Error(RlpError::Overflow.into()))?,
gas_limit: tx.gas,
to: tx.to.map_or(TxKind::Create, TxKind::Call),
value: tx.value,
input: tx.input,
Expand Down
2 changes: 1 addition & 1 deletion crates/primitives/src/transaction/compat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ impl FillTxEnv for TransactionSigned {
tx_env.caller = sender;
match self.as_ref() {
Transaction::Legacy(tx) => {
tx_env.gas_limit = tx.gas_limit;
tx_env.gas_limit = tx.gas_limit as u64;
tx_env.gas_price = U256::from(tx.gas_price);
tx_env.gas_priority_fee = None;
tx_env.transact_to = tx.to;
Expand Down
178 changes: 1 addition & 177 deletions crates/primitives/src/transaction/legacy.rs
leruaa marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -1,180 +1,4 @@
use crate::{keccak256, Bytes, ChainId, Signature, TxKind, TxType, B256, U256};
use alloy_rlp::{length_of_length, Encodable, Header};
use core::mem;

#[cfg(any(test, feature = "reth-codec"))]
use reth_codecs::Compact;

#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
use serde::{Deserialize, Serialize};

/// Legacy transaction.
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default, Serialize, Deserialize)]
#[cfg_attr(any(test, feature = "arbitrary"), derive(arbitrary::Arbitrary))]
#[cfg_attr(any(test, feature = "reth-codec"), derive(Compact))]
#[cfg_attr(any(test, feature = "reth-codec"), reth_codecs::add_arbitrary_tests(compact))]
pub struct TxLegacy {
/// Added as EIP-155: Simple replay attack protection
pub chain_id: Option<ChainId>,
/// A scalar value equal to the number of transactions sent by the sender; formally Tn.
pub nonce: u64,
/// A scalar value equal to the number of
/// Wei to be paid per unit of gas for all computation
/// costs incurred as a result of the execution of this transaction; formally Tp.
///
/// As ethereum circulation is around 120mil eth as of 2022 that is around
/// 120000000000000000000000000 wei we are safe to use u128 as its max number is:
/// 340282366920938463463374607431768211455
pub gas_price: u128,
/// A scalar value equal to the maximum
/// amount of gas that should be used in executing
/// this transaction. This is paid up-front, before any
/// computation is done and may not be increased
/// later; formally Tg.
pub gas_limit: u64,
/// The 160-bit address of the message call’s recipient or, for a contract creation
/// transaction, ∅, used here to denote the only member of B0 ; formally Tt.
pub to: TxKind,
/// A scalar value equal to the number of Wei to
/// be transferred to the message call’s recipient or,
/// in the case of contract creation, as an endowment
/// to the newly created account; formally Tv.
pub value: U256,
/// Input has two uses depending if transaction is Create or Call (if `to` field is None or
/// Some). pub init: An unlimited size byte array specifying the
/// EVM-code for the account initialisation procedure CREATE,
/// data: An unlimited size byte array specifying the
/// input data of the message call, formally Td.
pub input: Bytes,
}

impl TxLegacy {
/// Calculates a heuristic for the in-memory size of the [`TxLegacy`] transaction.
#[inline]
pub fn size(&self) -> usize {
mem::size_of::<Option<ChainId>>() + // chain_id
mem::size_of::<u64>() + // nonce
mem::size_of::<u128>() + // gas_price
mem::size_of::<u64>() + // gas_limit
self.to.size() + // to
mem::size_of::<U256>() + // value
self.input.len() // input
}

/// Outputs the length of the transaction's fields, without a RLP header or length of the
/// eip155 fields.
pub(crate) fn fields_len(&self) -> usize {
self.nonce.length() +
self.gas_price.length() +
self.gas_limit.length() +
self.to.length() +
self.value.length() +
self.input.0.length()
}

/// Encodes only the transaction's fields into the desired buffer, without a RLP header or
/// eip155 fields.
pub(crate) fn encode_fields(&self, out: &mut dyn bytes::BufMut) {
self.nonce.encode(out);
self.gas_price.encode(out);
self.gas_limit.encode(out);
self.to.encode(out);
self.value.encode(out);
self.input.0.encode(out);
}

/// Inner encoding function that is used for both rlp [`Encodable`] trait and for calculating
/// hash.
///
/// This encodes the transaction as:
/// `rlp(nonce, gas_price, gas_limit, to, value, input, v, r, s)`
///
/// The `v` value is encoded according to EIP-155 if the `chain_id` is not `None`.
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);
}

/// Output the length of the RLP signed transaction encoding.
pub(crate) fn payload_len_with_signature(&self, signature: &Signature) -> usize {
let payload_length =
self.fields_len() + signature.payload_len_with_eip155_chain_id(self.chain_id);
// 'header length' + 'payload length'
length_of_length(payload_length) + payload_length
}

/// Get transaction type
pub(crate) const fn tx_type(&self) -> TxType {
TxType::Legacy
}

/// Encodes EIP-155 arguments into the desired buffer. Only encodes values for legacy
/// transactions.
///
/// If a `chain_id` is `Some`, this encodes the `chain_id`, followed by two zeroes, as defined
/// by [EIP-155](https://eips.ethereum.org/EIPS/eip-155).
pub(crate) fn encode_eip155_fields(&self, out: &mut dyn bytes::BufMut) {
// if this is a legacy transaction without a chain ID, it must be pre-EIP-155
// and does not need to encode the chain ID for the signature hash encoding
if let Some(id) = self.chain_id {
// EIP-155 encodes the chain ID and two zeroes
id.encode(out);
0x00u8.encode(out);
0x00u8.encode(out);
}
}

/// Outputs the length of EIP-155 fields. Only outputs a non-zero value for EIP-155 legacy
/// transactions.
pub(crate) fn eip155_fields_len(&self) -> usize {
if let Some(id) = self.chain_id {
// EIP-155 encodes the chain ID and two zeroes, so we add 2 to the length of the chain
// ID to get the length of all 3 fields
// len(chain_id) + (0x00) + (0x00)
id.length() + 2
} else {
// this is either a pre-EIP-155 legacy transaction or a typed transaction
0
}
}

/// Encodes the legacy transaction in RLP for signing, including the EIP-155 fields if possible.
///
/// If a `chain_id` is `Some`, this encodes the transaction as:
/// `rlp(nonce, gas_price, gas_limit, to, value, input, chain_id, 0, 0)`
///
/// Otherwise, this encodes the transaction as:
/// `rlp(nonce, gas_price, gas_limit, to, value, input)`
pub(crate) fn encode_for_signing(&self, out: &mut dyn bytes::BufMut) {
Header { list: true, payload_length: self.fields_len() + self.eip155_fields_len() }
.encode(out);
self.encode_fields(out);
self.encode_eip155_fields(out);
}

/// Outputs the length of the signature RLP encoding for the transaction, including the length
/// of the EIP-155 fields if possible.
pub(crate) fn payload_len_for_signature(&self) -> usize {
let payload_length = self.fields_len() + self.eip155_fields_len();
// 'header length' + 'payload length'
length_of_length(payload_length) + payload_length
}

/// Outputs the signature hash of the transaction by first encoding without a signature, then
/// hashing.
///
/// See [`Self::encode_for_signing`] for more information on the encoding format.
pub(crate) fn signature_hash(&self) -> B256 {
let mut buf = Vec::with_capacity(self.payload_len_for_signature());
self.encode_for_signing(&mut buf);
keccak256(&buf)
}
}
pub use alloy_consensus::TxLegacy;

#[cfg(test)]
mod tests {
Expand Down
Loading
Loading