feat(db): Make TransactionSigned compactable (#252)

This commit is contained in:
joshieDo
2022-11-28 15:29:30 +08:00
committed by GitHub
parent b02a5c4bbf
commit 3efc6ee67e
37 changed files with 545 additions and 391 deletions

View File

@@ -7,7 +7,7 @@ repository = "https://github.com/foundry-rs/reth"
readme = "README.md"
[features]
default = ["scale"]
default = ["compact"]
compact = ["codecs-derive/compact"]
scale = ["codecs-derive/scale"]
postcard = ["codecs-derive/postcard"]

View File

@@ -19,7 +19,7 @@ serde = { version = "1.0.*", default-features = false }
parity-scale-codec = { version = "3.2.1", features = ["derive", "bytes"] }
[features]
default = ["scale"]
default = ["compact"]
compact = []
scale = []
postcard = []

View File

@@ -71,6 +71,9 @@ fn build_struct_field_flags(
// Find out the adequate bit size for the length of each field, if applicable.
for (name, ftype, is_compact) in fields {
// This happens when dealing with a wrapper struct eg. Struct(pub U256).
let name = if name.is_empty() { "placeholder" } else { name };
if *is_compact {
if is_flag_type(ftype) {
let name = format_ident!("{name}_len");

View File

@@ -50,7 +50,13 @@ pub fn generate_from_to(ident: &Ident, fields: &FieldList) -> TokenStream2 {
/// Generates code to implement the [`Compact`] trait method `to_compact`.
fn generate_from_compact(fields: &FieldList, ident: &Ident) -> Vec<TokenStream2> {
let mut lines = vec![];
let known_types = ["H256", "H160", "Address", "Bloom", "Vec"];
let mut known_types = vec!["H256", "H160", "Address", "Bloom", "Vec"];
// Only types without `bytes::Bytes` should be added here. It's currently manually added, since
// it's hard to figure out with derive_macro which types have bytes::Bytes fields.
//
// This removes the requirement of the field to be placed last in the struct.
known_types.append(&mut vec!["TransactionKind", "AccessList", "Signature"]);
// let mut handle = FieldListHandler::new(fields);
let is_enum = fields.iter().any(|field| matches!(field, FieldTypes::EnumVariant(_)));
@@ -66,24 +72,31 @@ fn generate_from_compact(fields: &FieldList, ident: &Ident) -> Vec<TokenStream2>
};
});
} else {
lines.append(&mut StructHandler::new(fields).generate_from(known_types.as_slice()));
let fields = fields.iter().filter_map(|field| {
if let FieldTypes::StructField((name, _, _)) = field {
let ident = format_ident!("{name}");
return Some(quote! {
#ident: #ident,
})
}
None
});
let mut struct_handler = StructHandler::new(fields);
lines.append(&mut struct_handler.generate_from(known_types.as_slice()));
// Builds the object instantiation.
lines.push(quote! {
let obj = #ident {
#(#fields)*
};
});
if struct_handler.is_wrapper {
lines.push(quote! {
let obj = #ident(placeholder);
});
} else {
let fields = fields.iter().filter_map(|field| {
if let FieldTypes::StructField((name, _, _)) = field {
let ident = format_ident!("{name}");
return Some(quote! {
#ident: #ident,
})
}
None
});
lines.push(quote! {
let obj = #ident {
#(#fields)*
};
});
}
}
lines

View File

@@ -124,16 +124,14 @@ fn load_field(field: &syn::Field, fields: &mut FieldList, is_enum: bool) {
/// Given the field type in a string format, return the amount of bits necessary to save its maximum
/// length.
pub fn get_bit_size(ftype: &str) -> u8 {
if ftype == "u64" || ftype == "BlockNumber" || ftype == "TxNumber" || ftype == "ChainId" {
return 4
} else if ftype == "TxType" {
return 2
} else if ftype == "bool" || ftype == "Option" {
return 1
} else if ftype == "U256" {
return 6
match ftype {
"bool" | "Option" => 1,
"TxType" => 2,
"u64" | "BlockNumber" | "TxNumber" | "ChainId" => 4,
"u128" => 5,
"U256" | "TxHash" => 6,
_ => 0,
}
0
}
/// Given the field type in a string format, checks if its type should be added to the

View File

@@ -4,11 +4,16 @@ use super::*;
pub struct StructHandler<'a> {
fields_iterator: std::iter::Peekable<std::slice::Iter<'a, FieldTypes>>,
lines: Vec<TokenStream2>,
pub is_wrapper: bool,
}
impl<'a> StructHandler<'a> {
pub fn new(fields: &'a FieldList) -> Self {
StructHandler { lines: vec![], fields_iterator: fields.iter().peekable() }
StructHandler {
lines: vec![],
fields_iterator: fields.iter().peekable(),
is_wrapper: false,
}
}
pub fn next_field(&mut self) -> Option<&'a FieldTypes> {
@@ -18,8 +23,6 @@ impl<'a> StructHandler<'a> {
pub fn generate_to(mut self) -> Vec<TokenStream2> {
while let Some(field) = self.next_field() {
match field {
// The following method will advance the
// `fields_iterator` by itself and stop right before the next variant.
FieldTypes::EnumVariant(_) => unreachable!(),
FieldTypes::EnumUnnamedField(_) => unreachable!(),
FieldTypes::StructField(field_descriptor) => self.to(field_descriptor),
@@ -28,11 +31,9 @@ impl<'a> StructHandler<'a> {
self.lines
}
pub fn generate_from(mut self, known_types: &[&str]) -> Vec<TokenStream2> {
pub fn generate_from(&mut self, known_types: &[&str]) -> Vec<TokenStream2> {
while let Some(field) = self.next_field() {
match field {
// The following method will advance the
// `fields_iterator` by itself and stop right before the next variant.
FieldTypes::EnumVariant(_) => unreachable!(),
FieldTypes::EnumUnnamedField(_) => unreachable!(),
FieldTypes::StructField(field_descriptor) => {
@@ -40,13 +41,30 @@ impl<'a> StructHandler<'a> {
}
}
}
self.lines
self.lines.clone()
}
/// Generates `to_compact` code for a struct field.
fn to(&mut self, field_descriptor: &StructFieldDescriptor) {
let (name, ftype, is_compact) = field_descriptor;
// Should only happen on wrapper structs like `Struct(pub Field)`
if name.is_empty() {
self.is_wrapper = true;
self.lines.push(quote! {
let _len = self.0.to_compact(&mut buffer);
});
if is_flag_type(ftype) {
self.lines.push(quote! {
flags.set_placeholder_len(_len as u8);
})
}
return
}
let name = format_ident!("{name}");
let set_len_method = format_ident!("set_{name}_len");
let len = format_ident!("{name}_len");
@@ -77,8 +95,14 @@ impl<'a> StructHandler<'a> {
fn from(&mut self, field_descriptor: &StructFieldDescriptor, known_types: &[&str]) {
let (name, ftype, is_compact) = field_descriptor;
let name = format_ident!("{name}");
let len = format_ident!("{name}_len");
let (name, len) = if name.is_empty() {
self.is_wrapper = true;
// Should only happen on wrapper structs like `Struct(pub Field)`
(format_ident!("placeholder"), format_ident!("placeholder_len"))
} else {
(format_ident!("{name}"), format_ident!("{name}_len"))
};
assert!(
known_types.contains(&ftype.as_str()) ||

View File

@@ -12,7 +12,10 @@ pub fn derive(input: TokenStream) -> TokenStream {
#[proc_macro_attribute]
#[rustfmt::skip]
#[allow(unreachable_code)]
pub fn main_codec(args: TokenStream, input: TokenStream) -> TokenStream {
pub fn main_codec(args: TokenStream, input: TokenStream) -> TokenStream {
#[cfg(feature = "compact")]
return use_compact(args, input);
#[cfg(feature = "scale")]
return use_scale(args, input);
@@ -21,9 +24,6 @@ pub fn main_codec(args: TokenStream, input: TokenStream) -> TokenStream {
#[cfg(feature = "no_codec")]
return no_codec(args, input);
#[cfg(feature = "compact")]
return use_compact(args, input);
// no features
no_codec(args, input)

View File

@@ -28,26 +28,34 @@ pub trait Compact {
Self: Sized;
}
impl Compact for u64 {
fn to_compact(self, buf: &mut impl bytes::BufMut) -> usize {
let leading = self.leading_zeros() as usize / 8;
buf.put_slice(&self.to_be_bytes()[leading..]);
8 - leading
}
macro_rules! impl_uint_compact {
($($name:tt),+) => {
$(
impl Compact for $name {
fn to_compact(self, buf: &mut impl bytes::BufMut) -> usize {
let leading = self.leading_zeros() as usize / 8;
buf.put_slice(&self.to_be_bytes()[leading..]);
std::mem::size_of::<$name>() - leading
}
fn from_compact(mut buf: &[u8], len: usize) -> (Self, &[u8]) {
if len > 0 {
let mut arr = [0; 8];
arr[8 - len..].copy_from_slice(&buf[..len]);
fn from_compact(mut buf: &[u8], len: usize) -> (Self, &[u8]) {
if len > 0 {
let mut arr = [0; std::mem::size_of::<$name>()];
arr[std::mem::size_of::<$name>() - len..].copy_from_slice(&buf[..len]);
buf.advance(len);
buf.advance(len);
return (u64::from_be_bytes(arr), buf)
}
(0, buf)
}
return ($name::from_be_bytes(arr), buf)
}
(0, buf)
}
}
)+
};
}
impl_uint_compact!(u64, u128);
impl<T> Compact for Vec<T>
where
T: Compact + Default,
@@ -144,12 +152,12 @@ impl Compact for Bytes {
}
macro_rules! impl_hash_compact {
($(($name:tt, $size:tt)),+) => {
($($name:tt),+) => {
$(
impl Compact for $name {
fn to_compact(self, buf: &mut impl bytes::BufMut) -> usize {
buf.put_slice(&self.0);
$size
std::mem::size_of::<$name>()
}
fn from_compact(mut buf: &[u8], len: usize) -> (Self,&[u8]) {
@@ -158,9 +166,9 @@ macro_rules! impl_hash_compact {
}
let v = $name::from_slice(
buf.get(..$size).expect("size not matching"),
buf.get(..std::mem::size_of::<$name>()).expect("size not matching"),
);
buf.advance($size);
buf.advance(std::mem::size_of::<$name>());
(v, buf)
}
}
@@ -168,7 +176,7 @@ macro_rules! impl_hash_compact {
};
}
impl_hash_compact!((H256, 32), (H160, 20));
impl_hash_compact!(H256, H160);
impl Compact for Bloom {
fn to_compact(self, buf: &mut impl bytes::BufMut) -> usize {
@@ -337,7 +345,7 @@ mod tests {
assert_eq!(u64::from_compact(&buf, 8), (0xffffffffffffffffu64, vec![].as_slice()));
}
#[use_compact]
#[main_codec]
#[derive(Debug, PartialEq, Clone)]
pub struct TestStruct {
f_u64: u64,
@@ -389,7 +397,7 @@ mod tests {
);
}
#[use_compact]
#[main_codec]
#[derive(Debug, PartialEq, Clone, Default)]
pub enum TestEnum {
#[default]

View File

@@ -6,7 +6,8 @@ use reth_interfaces::{
Result as RethResult,
};
use reth_primitives::{
Account, BlockLocked, BlockNumber, SealedHeader, Transaction, EMPTY_OMMER_ROOT, H256, U256,
Account, BlockLocked, BlockNumber, SealedHeader, Transaction, TxEip1559, TxEip2930, TxLegacy,
EMPTY_OMMER_ROOT, H256, U256,
};
use std::time::SystemTime;
@@ -74,21 +75,26 @@ pub fn validate_transaction_regarding_header(
base_fee: Option<u64>,
) -> Result<(), Error> {
let chain_id = match transaction {
Transaction::Legacy { chain_id, .. } => {
Transaction::Legacy(TxLegacy { chain_id, .. }) => {
// EIP-155: Simple replay attack protection: https://eips.ethereum.org/EIPS/eip-155
if config.spurious_dragon_hard_fork_block <= at_block_number && chain_id.is_some() {
return Err(Error::TransactionOldLegacyChainId)
}
*chain_id
}
Transaction::Eip2930 { chain_id, .. } => {
Transaction::Eip2930(TxEip2930 { chain_id, .. }) => {
// EIP-2930: Optional access lists: https://eips.ethereum.org/EIPS/eip-2930 (New transaction type)
if config.berlin_hard_fork_block > at_block_number {
return Err(Error::TransactionEip2930Disabled)
}
Some(*chain_id)
}
Transaction::Eip1559 { chain_id, max_fee_per_gas, max_priority_fee_per_gas, .. } => {
Transaction::Eip1559(TxEip1559 {
chain_id,
max_fee_per_gas,
max_priority_fee_per_gas,
..
}) => {
// EIP-1559: Fee market change for ETH 1.0 chain https://eips.ethereum.org/EIPS/eip-1559
if config.berlin_hard_fork_block > at_block_number {
return Err(Error::TransactionEip1559Disabled)
@@ -130,13 +136,13 @@ pub fn validate_transaction_regarding_account(
}
let (nonce, gas_price, gas_limit, value) = match transaction {
Transaction::Legacy { nonce, gas_price, gas_limit, value, .. } => {
Transaction::Legacy(TxLegacy { nonce, gas_price, gas_limit, value, .. }) => {
(nonce, gas_price, gas_limit, value)
}
Transaction::Eip2930 { nonce, gas_price, gas_limit, value, .. } => {
Transaction::Eip2930(TxEip2930 { nonce, gas_price, gas_limit, value, .. }) => {
(nonce, gas_price, gas_limit, value)
}
Transaction::Eip1559 { nonce, gas_limit, max_fee_per_gas, value, .. } => {
Transaction::Eip1559(TxEip1559 { nonce, gas_limit, max_fee_per_gas, value, .. }) => {
(nonce, max_fee_per_gas, gas_limit, value)
}
};

View File

@@ -360,7 +360,7 @@ mod tests {
impl AccountProvider for StateProviderTest {
fn basic_account(&self, address: Address) -> reth_interfaces::Result<Option<Account>> {
let ret = Ok(self.accounts.get(&address).map(|(_, acc)| acc.clone()));
let ret = Ok(self.accounts.get(&address).map(|(_, acc)| *acc));
ret
}
}
@@ -374,8 +374,7 @@ mod tests {
Ok(self
.accounts
.get(&account)
.map(|(storage, _)| storage.get(&storage_key).cloned())
.flatten())
.and_then(|(storage, _)| storage.get(&storage_key).cloned()))
}
fn bytecode_by_hash(&self, code_hash: H256) -> reth_interfaces::Result<Option<Bytes>> {

View File

@@ -1,7 +1,7 @@
use reth_interfaces::{provider::StateProvider, Error};
use reth_primitives::{
Header, Transaction, TransactionKind, TransactionSignedEcRecovered, H160, H256, KECCAK_EMPTY,
U256,
Header, Transaction, TransactionKind, TransactionSignedEcRecovered, TxEip1559, TxEip2930,
TxLegacy, H160, H256, KECCAK_EMPTY, U256,
};
use revm::{
db::{CacheDB, DatabaseRef},
@@ -79,7 +79,15 @@ pub fn fill_block_env(block_env: &mut BlockEnv, header: &Header) {
pub fn fill_tx_env(tx_env: &mut TxEnv, transaction: &TransactionSignedEcRecovered) {
tx_env.caller = transaction.signer();
match transaction.as_ref().as_ref() {
Transaction::Legacy { nonce, chain_id, gas_price, gas_limit, to, value, input } => {
Transaction::Legacy(TxLegacy {
nonce,
chain_id,
gas_price,
gas_limit,
to,
value,
input,
}) => {
tx_env.gas_limit = *gas_limit;
tx_env.gas_price = (*gas_price).into();
tx_env.gas_priority_fee = None;
@@ -92,7 +100,7 @@ pub fn fill_tx_env(tx_env: &mut TxEnv, transaction: &TransactionSignedEcRecovere
tx_env.chain_id = *chain_id;
tx_env.nonce = Some(*nonce);
}
Transaction::Eip2930 {
Transaction::Eip2930(TxEip2930 {
nonce,
chain_id,
gas_price,
@@ -101,7 +109,7 @@ pub fn fill_tx_env(tx_env: &mut TxEnv, transaction: &TransactionSignedEcRecovere
value,
input,
access_list,
} => {
}) => {
tx_env.gas_limit = *gas_limit;
tx_env.gas_price = (*gas_price).into();
tx_env.gas_priority_fee = None;
@@ -124,7 +132,7 @@ pub fn fill_tx_env(tx_env: &mut TxEnv, transaction: &TransactionSignedEcRecovere
})
.collect();
}
Transaction::Eip1559 {
Transaction::Eip1559(TxEip1559 {
nonce,
chain_id,
gas_limit,
@@ -134,7 +142,7 @@ pub fn fill_tx_env(tx_env: &mut TxEnv, transaction: &TransactionSignedEcRecovere
value,
input,
access_list,
} => {
}) => {
tx_env.gas_limit = *gas_limit;
tx_env.gas_price = (*max_fee_per_gas).into();
tx_env.gas_priority_fee = Some((*max_priority_fee_per_gas).into());

View File

@@ -2,7 +2,9 @@ use crate::db::{
models::{accounts::AccountBeforeTx, StoredBlockBody},
Compress, Decompress, Error,
};
use reth_codecs::Compact;
use bytes::Buf;
use modular_bitfield::prelude::*;
use reth_codecs::{main_codec, Compact};
use reth_primitives::*;
/// Implements compression for Compact type.
@@ -33,4 +35,42 @@ macro_rules! impl_compression_for_compact {
}
impl_compression_for_compact!(Header, Account, Log, Receipt, TxType, StorageEntry, StoredBlockBody);
impl_compression_for_compact!(AccountBeforeTx);
impl_compression_for_compact!(AccountBeforeTx, TransactionSigned);
impl_compression_for_compact!(CompactU256);
/// Adds wrapper structs for some primitive types so they can use StructFlags from Compact, when
/// used as pure table values.
macro_rules! add_wrapper_struct {
($(($name:tt, $wrapper:tt)),+) => {
$(
/// Wrapper struct so it can use StructFlags from Compact, when used as pure table values.
#[main_codec]
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct $wrapper(pub $name);
impl From<$name> for $wrapper {
fn from(value: $name) -> Self {
$wrapper(value)
}
}
impl From<$wrapper> for $name {
fn from(value: $wrapper) -> Self {
value.0
}
}
impl std::ops::Deref for $wrapper {
type Target = $name;
fn deref(&self) -> &Self::Target {
&self.0
}
}
)+
};
}
add_wrapper_struct!((U256, CompactU256));
add_wrapper_struct!((u64, CompactU64));

View File

@@ -1,6 +1,8 @@
//! Integrates different codecs into table::Encode and table::Decode
mod compact;
pub use compact::CompactU256;
pub mod fuzz;
mod postcard;
#[cfg(not(feature = "bench-postcard"))]

View File

@@ -43,5 +43,4 @@ impl ScaleValue for Vec<u8> {}
impl sealed::Sealed for Vec<u8> {}
impl_compression_for_scale!(U256, H256, H160);
impl_compression_for_scale!(TransactionSigned);
impl_compression_for_scale!(u8, u32, u16, u64);

View File

@@ -8,12 +8,12 @@ use crate::{
impl_fixed_arbitrary,
};
use bytes::Bytes;
use reth_codecs::{use_compact, Compact};
use reth_codecs::{main_codec, Compact};
use reth_primitives::{Account, Address, TxNumber};
use serde::{Deserialize, Serialize};
/// Account as it is saved inside [`AccountChangeSet`]. [`Address`] is the subkey.
#[use_compact]
#[main_codec]
#[derive(Debug, Default, Clone, PartialEq)]
pub struct AccountBeforeTx {
/// Address for the account. Acts as `DupSort::SubKey`.

View File

@@ -9,7 +9,7 @@ use crate::{
};
use bytes::{Buf, Bytes};
use modular_bitfield::prelude::*;
use reth_codecs::{use_compact, Compact};
use reth_codecs::{main_codec, Compact};
use reth_primitives::{BlockHash, BlockNumber, Header, TxNumber, H256};
use serde::{Deserialize, Serialize};
@@ -24,7 +24,7 @@ pub type NumTransactions = u64;
/// The [TxNumber]s for all the transactions in the block are `base_tx_id..(base_tx_id +
/// tx_amount)`.
#[derive(Debug, Default, PartialEq, Clone)]
#[use_compact]
#[main_codec]
pub struct StoredBlockBody {
/// The ID of the first transaction in the block.
pub base_tx_id: TxNumber,

View File

@@ -17,11 +17,11 @@ use crate::db::{
/// Macro that implements [`Encode`] and [`Decode`] for uint types.
macro_rules! impl_uints {
($(($name:tt, $size:tt)),+) => {
($($name:tt),+) => {
$(
impl Encode for $name
{
type Encoded = [u8; $size];
type Encoded = [u8; std::mem::size_of::<$name>()];
fn encode(self) -> Self::Encoded {
self.to_be_bytes()
@@ -43,7 +43,7 @@ macro_rules! impl_uints {
};
}
impl_uints!((u64, 8), (u32, 4), (u16, 2), (u8, 1));
impl_uints!(u64, u32, u16, u8);
impl Encode for Vec<u8> {
type Encoded = Vec<u8>;

View File

@@ -1,6 +1,7 @@
//! Declaration of all Database tables.
use crate::db::{
codecs::CompactU256,
models::{
accounts::{AccountBeforeTx, TxNumberAddress},
blocks::{BlockNumHash, HeaderHash, NumTransactions, StoredBlockBody},
@@ -108,7 +109,7 @@ table!(
table!(
/// Stores the total difficulty from a block header.
HeaderTD => BlockNumHash => RlpTotalDifficulty);
HeaderTD => BlockNumHash => CompactU256);
table!(
/// Stores the block number corresponding to an header.
@@ -244,8 +245,6 @@ pub type ConfigValue = Vec<u8>;
/// Temporary placeholder type for DB.
pub type BlockNumHashTxNumber = Vec<u8>;
/// Temporary placeholder type for DB.
pub type RlpTotalDifficulty = Vec<u8>;
/// Temporary placeholder type for DB.
pub type AddressStorageKey = Vec<u8>;
/// Temporary placeholder type for DB.
pub type Bytecode = Vec<u8>;

View File

@@ -1,7 +1,7 @@
use rand::{thread_rng, Rng};
use reth_primitives::{
proofs, Address, BlockLocked, Bytes, Header, SealedHeader, Signature, Transaction,
TransactionKind, TransactionSigned, H256, U256,
TransactionKind, TransactionSigned, TxLegacy, H256, U256,
};
use secp256k1::{KeyPair, Message as SecpMessage, Secp256k1, SecretKey};
@@ -46,7 +46,7 @@ pub fn random_header(number: u64, parent: Option<H256>) -> SealedHeader {
/// - The chain ID, which is always 1
/// - The input, which is always nothing
pub fn random_tx() -> Transaction {
Transaction::Legacy {
Transaction::Legacy(TxLegacy {
chain_id: Some(1),
nonce: rand::random::<u16>().into(),
gas_price: rand::random::<u16>().into(),
@@ -54,7 +54,7 @@ pub fn random_tx() -> Transaction {
to: TransactionKind::Call(Address::random()),
value: rand::random::<u16>().into(),
input: Bytes::default(),
}
})
}
/// Generates a random legacy [Transaction] that is signed.
@@ -154,14 +154,14 @@ pub fn random_block_range(rng: std::ops::Range<u64>, head: H256) -> Vec<BlockLoc
mod test {
use super::*;
use hex_literal::hex;
use reth_primitives::{keccak256, AccessList, Address, TransactionKind};
use reth_primitives::{keccak256, AccessList, Address, TransactionKind, TxEip1559};
use secp256k1::KeyPair;
#[test]
fn test_sign_message() {
let secp = Secp256k1::new();
let tx = Transaction::Eip1559 {
let tx = Transaction::Eip1559(TxEip1559 {
chain_id: 1,
nonce: 0x42,
gas_limit: 44386,
@@ -171,7 +171,7 @@ mod test {
max_fee_per_gas: 0x4a817c800,
max_priority_fee_per_gas: 0x3b9aca00,
access_list: AccessList::default(),
};
});
let signature_hash = tx.signature_hash();
for _ in 0..100 {

View File

@@ -75,7 +75,7 @@ fn bench_put_rand(c: &mut Criterion) {
c.bench_function("bench_put_rand", |b| {
b.iter(|| {
let txn = env.begin_rw_txn().unwrap();
for &(ref key, ref data) in items.iter() {
for (key, data) in items.iter() {
txn.put(&db, key, data, WriteFlags::empty()).unwrap();
}
})
@@ -101,7 +101,7 @@ fn bench_put_rand_raw(c: &mut Criterion) {
mdbx_txn_begin_ex(env, ptr::null_mut(), 0, &mut txn, ptr::null_mut());
let mut i: ::libc::c_int = 0;
for &(ref key, ref data) in items.iter() {
for (key, data) in items.iter() {
key_val.iov_len = key.len() as size_t;
key_val.iov_base = key.as_bytes().as_ptr() as *mut _;
data_val.iov_len = data.len() as size_t;

View File

@@ -101,7 +101,8 @@ mod test {
};
use hex_literal::hex;
use reth_primitives::{
BlockHashOrNumber, Header, Signature, Transaction, TransactionKind, TransactionSigned, U256,
BlockHashOrNumber, Header, Signature, Transaction, TransactionKind, TransactionSigned,
TxLegacy, U256,
};
use reth_rlp::{Decodable, Encodable};
@@ -341,7 +342,7 @@ mod test {
message: BlockBodies(vec![
BlockBody {
transactions: vec![
TransactionSigned::from_transaction_and_signature(Transaction::Legacy {
TransactionSigned::from_transaction_and_signature(Transaction::Legacy(TxLegacy {
chain_id: Some(1),
nonce: 0x8u64,
gas_price: 0x4a817c808,
@@ -350,7 +351,7 @@ mod test {
TransactionKind::Call(hex!("3535353535353535353535353535353535353535").into()),
value: 0x200u64.into(),
input: Default::default(),
},
}),
Signature {
odd_y_parity: false,
r:
@@ -359,7 +360,7 @@ mod test {
U256::from_str("64b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10").unwrap(),
}
),
TransactionSigned::from_transaction_and_signature(Transaction::Legacy {
TransactionSigned::from_transaction_and_signature(Transaction::Legacy(TxLegacy {
chain_id: Some(1),
nonce: 0x9u64,
gas_price: 0x4a817c809,
@@ -368,7 +369,7 @@ mod test {
TransactionKind::Call(hex!("3535353535353535353535353535353535353535").into()),
value: 0x2d9u64.into(),
input: Default::default(),
}, Signature {
}), Signature {
odd_y_parity: false,
r:
U256::from_str("52f8f61201b2b11a78d6e866abc9c3db2ae8631fa656bfe5cb53668255367afb").unwrap(),
@@ -422,7 +423,7 @@ mod test {
message: BlockBodies(vec![
BlockBody {
transactions: vec![
TransactionSigned::from_transaction_and_signature(Transaction::Legacy {
TransactionSigned::from_transaction_and_signature(Transaction::Legacy(TxLegacy {
chain_id: Some(1),
nonce: 0x8u64,
gas_price: 0x4a817c808,
@@ -431,7 +432,7 @@ mod test {
TransactionKind::Call(hex!("3535353535353535353535353535353535353535").into()),
value: 0x200u64.into(),
input: Default::default(),
},
}),
Signature {
odd_y_parity: false,
r:
@@ -440,7 +441,7 @@ mod test {
U256::from_str("64b1702d9298fee62dfeccc57d322a463ad55ca201256d01f62b45b2e1c21c10").unwrap(),
}
),
TransactionSigned::from_transaction_and_signature(Transaction::Legacy {
TransactionSigned::from_transaction_and_signature(Transaction::Legacy(TxLegacy {
chain_id: Some(1),
nonce: 0x9u64,
gas_price: 0x4a817c809,
@@ -449,7 +450,7 @@ mod test {
TransactionKind::Call(hex!("3535353535353535353535353535353535353535").into()),
value: 0x2d9u64.into(),
input: Default::default(),
},
}),
Signature {
odd_y_parity: false,
r:

View File

@@ -97,7 +97,9 @@ mod test {
use crate::{message::RequestPair, GetPooledTransactions, PooledTransactions};
use hex_literal::hex;
use reth_primitives::{Signature, Transaction, TransactionKind, TransactionSigned, U256};
use reth_primitives::{
Signature, Transaction, TransactionKind, TransactionSigned, TxEip1559, TxLegacy, U256,
};
use reth_rlp::{Decodable, Encodable};
#[test]
@@ -142,7 +144,7 @@ mod test {
request_id: 1111,
message: vec![
TransactionSigned::from_transaction_and_signature(
Transaction::Legacy {
Transaction::Legacy(TxLegacy {
chain_id: Some(1),
nonce: 0x8u64,
gas_price: 0x4a817c808,
@@ -152,7 +154,7 @@ mod test {
),
value: 0x200u64.into(),
input: Default::default(),
},
}),
Signature {
odd_y_parity: false,
r: U256::from_str(
@@ -166,7 +168,7 @@ mod test {
},
),
TransactionSigned::from_transaction_and_signature(
Transaction::Legacy {
Transaction::Legacy(TxLegacy {
chain_id: Some(1),
nonce: 0x09u64,
gas_price: 0x4a817c809,
@@ -176,7 +178,7 @@ mod test {
),
value: 0x2d9u64.into(),
input: Default::default(),
},
}),
Signature {
odd_y_parity: false,
r: U256::from_str(
@@ -204,7 +206,7 @@ mod test {
request_id: 1111,
message: vec![
TransactionSigned::from_transaction_and_signature(
Transaction::Legacy {
Transaction::Legacy(TxLegacy {
chain_id: Some(1),
nonce: 0x8u64,
gas_price: 0x4a817c808,
@@ -214,7 +216,7 @@ mod test {
),
value: 0x200u64.into(),
input: Default::default(),
},
}),
Signature {
odd_y_parity: false,
r: U256::from_str(
@@ -228,7 +230,7 @@ mod test {
},
),
TransactionSigned::from_transaction_and_signature(
Transaction::Legacy {
Transaction::Legacy(TxLegacy {
chain_id: Some(1),
nonce: 0x09u64,
gas_price: 0x4a817c809,
@@ -238,7 +240,7 @@ mod test {
),
value: 0x2d9u64.into(),
input: Default::default(),
},
}),
Signature {
odd_y_parity: false,
r: U256::from_str(
@@ -269,7 +271,7 @@ mod test {
request_id: 0,
message: vec![
TransactionSigned::from_transaction_and_signature(
Transaction::Legacy {
Transaction::Legacy(TxLegacy {
chain_id: Some(4),
nonce: 15u64,
gas_price: 2200000000,
@@ -279,7 +281,7 @@ mod test {
),
value: 1234u64.into(),
input: Default::default(),
},
}),
Signature {
odd_y_parity: true,
r: U256::from_str(
@@ -293,7 +295,7 @@ mod test {
},
),
TransactionSigned::from_transaction_and_signature(
Transaction::Eip1559 {
Transaction::Eip1559(TxEip1559 {
chain_id: 4,
nonce: 26u64,
max_priority_fee_per_gas: 1500000000,
@@ -305,7 +307,7 @@ mod test {
value: 3000000000000000000u64.into(),
input: Default::default(),
access_list: Default::default(),
},
}),
Signature {
odd_y_parity: true,
r: U256::from_str(
@@ -319,7 +321,7 @@ mod test {
},
),
TransactionSigned::from_transaction_and_signature(
Transaction::Legacy {
Transaction::Legacy(TxLegacy {
chain_id: Some(4),
nonce: 3u64,
gas_price: 2000000000,
@@ -329,7 +331,7 @@ mod test {
),
value: 1000000000000000u64.into(),
input: Default::default(),
},
}),
Signature {
odd_y_parity: false,
r: U256::from_str(
@@ -343,7 +345,7 @@ mod test {
},
),
TransactionSigned::from_transaction_and_signature(
Transaction::Legacy {
Transaction::Legacy(TxLegacy {
chain_id: Some(4),
nonce: 1u64,
gas_price: 1000000000,
@@ -353,7 +355,7 @@ mod test {
),
value: 693361000000000u64.into(),
input: Default::default(),
},
}),
Signature {
odd_y_parity: false,
r: U256::from_str(
@@ -367,7 +369,7 @@ mod test {
},
),
TransactionSigned::from_transaction_and_signature(
Transaction::Legacy {
Transaction::Legacy(TxLegacy {
chain_id: Some(4),
nonce: 2u64,
gas_price: 1000000000,
@@ -377,7 +379,7 @@ mod test {
),
value: 1000000000000000u64.into(),
input: Default::default(),
},
}),
Signature {
odd_y_parity: false,
r: U256::from_str(
@@ -412,7 +414,7 @@ mod test {
request_id: 0,
message: vec![
TransactionSigned::from_transaction_and_signature(
Transaction::Legacy {
Transaction::Legacy(TxLegacy {
chain_id: Some(4),
nonce: 15u64,
gas_price: 2200000000,
@@ -422,7 +424,7 @@ mod test {
),
value: 1234u64.into(),
input: Default::default(),
},
}),
Signature {
odd_y_parity: true,
r: U256::from_str(
@@ -436,7 +438,7 @@ mod test {
},
),
TransactionSigned::from_transaction_and_signature(
Transaction::Eip1559 {
Transaction::Eip1559(TxEip1559 {
chain_id: 4,
nonce: 26u64,
max_priority_fee_per_gas: 1500000000,
@@ -448,7 +450,7 @@ mod test {
value: 3000000000000000000u64.into(),
input: Default::default(),
access_list: Default::default(),
},
}),
Signature {
odd_y_parity: true,
r: U256::from_str(
@@ -462,7 +464,7 @@ mod test {
},
),
TransactionSigned::from_transaction_and_signature(
Transaction::Legacy {
Transaction::Legacy(TxLegacy {
chain_id: Some(4),
nonce: 3u64,
gas_price: 2000000000,
@@ -472,7 +474,7 @@ mod test {
),
value: 1000000000000000u64.into(),
input: Default::default(),
},
}),
Signature {
odd_y_parity: false,
r: U256::from_str(
@@ -486,7 +488,7 @@ mod test {
},
),
TransactionSigned::from_transaction_and_signature(
Transaction::Legacy {
Transaction::Legacy(TxLegacy {
chain_id: Some(4),
nonce: 1u64,
gas_price: 1000000000,
@@ -496,7 +498,7 @@ mod test {
),
value: 693361000000000u64.into(),
input: Default::default(),
},
}),
Signature {
odd_y_parity: false,
r: U256::from_str(
@@ -510,7 +512,7 @@ mod test {
},
),
TransactionSigned::from_transaction_and_signature(
Transaction::Legacy {
Transaction::Legacy(TxLegacy {
chain_id: Some(4),
nonce: 2u64,
gas_price: 1000000000,
@@ -520,7 +522,7 @@ mod test {
),
value: 1000000000000000u64.into(),
input: Default::default(),
},
}),
Signature {
odd_y_parity: false,
r: U256::from_str(

View File

@@ -1,10 +1,10 @@
use crate::{H256, U256};
use bytes::Buf;
use modular_bitfield::prelude::*;
use reth_codecs::{use_compact, Compact};
use reth_codecs::{main_codec, Compact};
/// Account saved in database
#[use_compact]
#[main_codec]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
pub struct Account {
/// Nonce.

View File

@@ -5,12 +5,12 @@ use crate::{
use bytes::{Buf, BufMut, BytesMut};
use ethers_core::{types::H64, utils::keccak256};
use modular_bitfield::prelude::*;
use reth_codecs::{use_compact, Compact};
use reth_codecs::{main_codec, Compact};
use reth_rlp::{length_of_length, Decodable, Encodable};
use std::ops::Deref;
/// Block header
#[use_compact]
#[main_codec]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Header {
/// The Keccak 256-bit hash of the parent

View File

@@ -1,4 +1,4 @@
use reth_codecs::main_codec;
use reth_codecs::{main_codec, Compact};
use reth_rlp::{Decodable, DecodeError, Encodable};
use serde::{Deserialize, Deserializer, Serializer};
use std::{

View File

@@ -45,7 +45,8 @@ pub use receipt::Receipt;
pub use storage::StorageEntry;
pub use transaction::{
AccessList, AccessListItem, FromRecoveredTransaction, IntoRecoveredTransaction, Signature,
Transaction, TransactionKind, TransactionSigned, TransactionSignedEcRecovered, TxType,
Transaction, TransactionKind, TransactionSigned, TransactionSignedEcRecovered, TxEip1559,
TxEip2930, TxLegacy, TxType,
};
/// A block hash.

View File

@@ -1,9 +1,9 @@
use crate::{Address, H256};
use reth_codecs::{use_compact, Compact};
use reth_codecs::{main_codec, Compact};
use reth_rlp::{RlpDecodable, RlpEncodable};
/// Ethereum Log
#[use_compact]
#[main_codec]
#[derive(Clone, Debug, PartialEq, Eq, RlpDecodable, RlpEncodable, Default)]
pub struct Log {
/// Contract that emitted this log.

View File

@@ -1,12 +1,12 @@
use crate::{Bloom, Log, TxType};
use bytes::{Buf, BufMut, BytesMut};
use modular_bitfield::prelude::*;
use reth_codecs::{use_compact, Compact};
use reth_codecs::{main_codec, Compact};
use reth_rlp::{length_of_length, Decodable, Encodable};
use std::cmp::Ordering;
/// Receipt containing result of transaction execution.
#[use_compact]
#[main_codec]
#[derive(Clone, Debug, PartialEq, Eq, Default)]
pub struct Receipt {
/// Receipt type.

View File

@@ -1,11 +1,11 @@
use super::{H256, U256};
use bytes::Buf;
use modular_bitfield::prelude::*;
use reth_codecs::{use_compact, Compact};
use reth_codecs::{main_codec, Compact};
/// Account storage entry.
#[derive(Debug, Default, Clone, PartialEq, Eq)]
#[use_compact]
#[main_codec]
pub struct StorageEntry {
/// Storage key.
pub key: H256,

View File

@@ -1,6 +1,6 @@
use crate::{Address, H256};
use reth_codecs::main_codec;
use reth_codecs::{main_codec, Compact};
use reth_rlp::{RlpDecodable, RlpDecodableWrapper, RlpEncodable, RlpEncodableWrapper};
/// A list of addresses and storage keys that the transaction plans to access.

View File

@@ -3,7 +3,8 @@ pub use access_list::{AccessList, AccessListItem};
use bytes::{Buf, BytesMut};
use derive_more::{AsRef, Deref};
use ethers_core::utils::keccak256;
use reth_codecs::main_codec;
use modular_bitfield::prelude::*;
use reth_codecs::{main_codec, Compact};
use reth_rlp::{length_of_length, Decodable, DecodeError, Encodable, Header, EMPTY_STRING_CODE};
pub use signature::Signature;
pub use tx_type::TxType;
@@ -13,6 +14,152 @@ mod signature;
mod tx_type;
mod util;
/// Legacy transaction.
#[main_codec]
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
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 calls recipient or, for a contract creation
/// transaction, ∅, used here to denote the only member of B0 ; formally Tt.
pub to: TransactionKind,
/// A scalar value equal to the number of Wei to
/// be transferred to the message calls recipient or,
/// in the case of contract creation, as an endowment
/// to the newly created account; formally Tv.
///
/// 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 value: u128,
/// 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,
}
/// Transaction with an [`AccessList`] ([EIP-2930](https://eips.ethereum.org/EIPS/eip-2930)).
#[main_codec]
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
pub struct TxEip2930 {
/// Added as EIP-pub 155: Simple replay attack protection
pub chain_id: 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 calls recipient or, for a contract creation
/// transaction, ∅, used here to denote the only member of B0 ; formally Tt.
pub to: TransactionKind,
/// A scalar value equal to the number of Wei to
/// be transferred to the message calls recipient or,
/// in the case of contract creation, as an endowment
/// to the newly created account; formally Tv.
///
/// 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 value: u128,
/// The accessList specifies a list of addresses and storage keys;
/// these addresses and storage keys are added into the `accessed_addresses`
/// and `accessed_storage_keys` global sets (introduced in EIP-2929).
/// A gas cost is charged, though at a discount relative to the cost of
/// accessing outside the list.
pub access_list: AccessList,
/// 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,
}
/// A transaction with a priority fee ([EIP-1559](https://eips.ethereum.org/EIPS/eip-1559)).
#[main_codec]
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
pub struct TxEip1559 {
/// Added as EIP-pub 155: Simple replay attack protection
pub chain_id: u64,
/// A scalar value equal to the number of transactions sent by the sender; formally Tn.
pub nonce: u64,
/// 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,
/// 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.
///
/// 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 max_fee_per_gas: u128,
/// Max Priority fee that transaction is paying
///
/// 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 max_priority_fee_per_gas: u128,
/// The 160-bit address of the message calls recipient or, for a contract creation
/// transaction, ∅, used here to denote the only member of B0 ; formally Tt.
pub to: TransactionKind,
/// A scalar value equal to the number of Wei to
/// be transferred to the message calls recipient or,
/// in the case of contract creation, as an endowment
/// to the newly created account; formally Tv.
///
/// 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 value: u128,
/// The accessList specifies a list of addresses and storage keys;
/// these addresses and storage keys are added into the `accessed_addresses`
/// and `accessed_storage_keys` global sets (introduced in EIP-2929).
/// A gas cost is charged, though at a discount relative to the cost of
/// accessing outside the list.
pub access_list: AccessList,
/// 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,
}
/// A raw transaction.
///
/// Transaction types were introduced in [EIP-2718](https://eips.ethereum.org/EIPS/eip-2718).
@@ -20,142 +167,17 @@ mod util;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Transaction {
/// Legacy transaction.
Legacy {
/// Added as EIP-155: Simple replay attack protection
chain_id: Option<ChainId>,
/// A scalar value equal to the number of transactions sent by the sender; formally Tn.
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
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.
gas_limit: u64,
/// The 160-bit address of the message calls recipient or, for a contract creation
/// transaction, ∅, used here to denote the only member of B0 ; formally Tt.
to: TransactionKind,
/// A scalar value equal to the number of Wei to
/// be transferred to the message calls recipient or,
/// in the case of contract creation, as an endowment
/// to the newly created account; formally Tv.
///
/// 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
value: u128,
/// Input has two uses depending if transaction is Create or Call (if `to` field is None or
/// Some). 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.
input: Bytes,
},
Legacy(TxLegacy),
/// Transaction with an [`AccessList`] ([EIP-2930](https://eips.ethereum.org/EIPS/eip-2930)).
Eip2930 {
/// Added as EIP-155: Simple replay attack protection
chain_id: ChainId,
/// A scalar value equal to the number of transactions sent by the sender; formally Tn.
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
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.
gas_limit: u64,
/// The 160-bit address of the message calls recipient or, for a contract creation
/// transaction, ∅, used here to denote the only member of B0 ; formally Tt.
to: TransactionKind,
/// A scalar value equal to the number of Wei to
/// be transferred to the message calls recipient or,
/// in the case of contract creation, as an endowment
/// to the newly created account; formally Tv.
///
/// 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
value: u128,
/// Input has two uses depending if transaction is Create or Call (if `to` field is None or
/// Some). 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.
input: Bytes,
/// The accessList specifies a list of addresses and storage keys;
/// these addresses and storage keys are added into the `accessed_addresses`
/// and `accessed_storage_keys` global sets (introduced in EIP-2929).
/// A gas cost is charged, though at a discount relative to the cost of
/// accessing outside the list.
access_list: AccessList,
},
Eip2930(TxEip2930),
/// A transaction with a priority fee ([EIP-1559](https://eips.ethereum.org/EIPS/eip-1559)).
Eip1559 {
/// Added as EIP-155: Simple replay attack protection
chain_id: u64,
/// A scalar value equal to the number of transactions sent by the sender; formally Tn.
nonce: u64,
/// 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.
gas_limit: u64,
/// 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.
///
/// 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
max_fee_per_gas: u128,
/// Max Priority fee that transaction is paying
///
/// 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
max_priority_fee_per_gas: u128,
/// The 160-bit address of the message calls recipient or, for a contract creation
/// transaction, ∅, used here to denote the only member of B0 ; formally Tt.
to: TransactionKind,
/// A scalar value equal to the number of Wei to
/// be transferred to the message calls recipient or,
/// in the case of contract creation, as an endowment
/// to the newly created account; formally Tv.
///
/// 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
value: u128,
/// Input has two uses depending if transaction is Create or Call (if `to` field is None or
/// Some). 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.
input: Bytes,
/// The accessList specifies a list of addresses and storage keys;
/// these addresses and storage keys are added into the `accessed_addresses`
/// and `accessed_storage_keys` global sets (introduced in EIP-2929).
/// A gas cost is charged, though at a discount relative to the cost of
/// accessing outside the list.
access_list: AccessList,
},
Eip1559(TxEip1559),
}
impl Default for Transaction {
fn default() -> Self {
Self::Legacy(TxLegacy::default())
}
}
impl Transaction {
@@ -170,9 +192,9 @@ impl Transaction {
/// Sets the transaction's chain id to the provided value.
pub fn set_chain_id(&mut self, chain_id: u64) {
match self {
Transaction::Legacy { chain_id: ref mut c, .. } => *c = Some(chain_id),
Transaction::Eip2930 { chain_id: ref mut c, .. } => *c = chain_id,
Transaction::Eip1559 { chain_id: ref mut c, .. } => *c = chain_id,
Transaction::Legacy(TxLegacy { chain_id: ref mut c, .. }) => *c = Some(chain_id),
Transaction::Eip2930(TxEip2930 { chain_id: ref mut c, .. }) => *c = chain_id,
Transaction::Eip1559(TxEip1559 { chain_id: ref mut c, .. }) => *c = chain_id,
}
}
@@ -180,9 +202,9 @@ impl Transaction {
/// [`TransactionKind::Create`] if the transaction is a contract creation.
pub fn kind(&self) -> &TransactionKind {
match self {
Transaction::Legacy { to, .. } |
Transaction::Eip2930 { to, .. } |
Transaction::Eip1559 { to, .. } => to,
Transaction::Legacy(TxLegacy { to, .. }) |
Transaction::Eip2930(TxEip2930 { to, .. }) |
Transaction::Eip1559(TxEip1559 { to, .. }) => to,
}
}
@@ -198,46 +220,45 @@ impl Transaction {
/// Gets the transaction's value field.
pub fn value(&self) -> &u128 {
match self {
Transaction::Legacy { value, .. } => value,
Transaction::Eip2930 { value, .. } => value,
Transaction::Eip1559 { value, .. } => value,
Transaction::Legacy(TxLegacy { value, .. }) => value,
Transaction::Eip2930(TxEip2930 { value, .. }) => value,
Transaction::Eip1559(TxEip1559 { value, .. }) => value,
}
}
/// Get the transaction's nonce.
pub fn nonce(&self) -> u64 {
match self {
Transaction::Legacy { nonce, .. } => *nonce,
Transaction::Eip2930 { nonce, .. } => *nonce,
Transaction::Eip1559 { nonce, .. } => *nonce,
Transaction::Legacy(TxLegacy { nonce, .. }) => *nonce,
Transaction::Eip2930(TxEip2930 { nonce, .. }) => *nonce,
Transaction::Eip1559(TxEip1559 { nonce, .. }) => *nonce,
}
}
/// Get the gas limit of the transaction.
pub fn gas_limit(&self) -> u64 {
match self {
Transaction::Legacy { gas_limit, .. } |
Transaction::Eip2930 { gas_limit, .. } |
Transaction::Eip1559 { gas_limit, .. } => *gas_limit,
Transaction::Legacy(TxLegacy { gas_limit, .. }) |
Transaction::Eip2930(TxEip2930 { gas_limit, .. }) |
Transaction::Eip1559(TxEip1559 { gas_limit, .. }) => *gas_limit,
}
}
/// Max fee per gas for eip1559 transaction, for legacy transactions this is gas_price
pub fn max_fee_per_gas(&self) -> u128 {
match self {
Transaction::Legacy { gas_price, .. } | Transaction::Eip2930 { gas_price, .. } => {
*gas_price
}
Transaction::Eip1559 { max_fee_per_gas, .. } => *max_fee_per_gas,
Transaction::Legacy(TxLegacy { gas_price, .. }) |
Transaction::Eip2930(TxEip2930 { gas_price, .. }) => *gas_price,
Transaction::Eip1559(TxEip1559 { max_fee_per_gas, .. }) => *max_fee_per_gas,
}
}
/// Get the transaction's input field.
pub fn input(&self) -> &Bytes {
match self {
Transaction::Legacy { input, .. } => input,
Transaction::Eip2930 { input, .. } => input,
Transaction::Eip1559 { input, .. } => input,
Transaction::Legacy(TxLegacy { input, .. }) => input,
Transaction::Eip2930(TxEip2930 { input, .. }) => input,
Transaction::Eip1559(TxEip1559 { input, .. }) => input,
}
}
@@ -265,7 +286,7 @@ impl Transaction {
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 Transaction::Legacy { chain_id: Some(id), .. } = self {
if let Transaction::Legacy(TxLegacy { chain_id: Some(id), .. }) = self {
// EIP-155 encodes the chain ID and two zeroes
id.encode(out);
0x00u8.encode(out);
@@ -276,7 +297,7 @@ impl Transaction {
/// 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 Transaction::Legacy { chain_id: Some(id), .. } = self {
if let Transaction::Legacy(TxLegacy { chain_id: Some(id), .. }) = self {
// 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)
@@ -306,7 +327,15 @@ impl Transaction {
/// eip155 fields.
pub(crate) fn fields_len(&self) -> usize {
match self {
Transaction::Legacy { chain_id: _, nonce, gas_price, gas_limit, to, value, input } => {
Transaction::Legacy(TxLegacy {
chain_id: _,
nonce,
gas_price,
gas_limit,
to,
value,
input,
}) => {
let mut len = 0;
len += nonce.length();
len += gas_price.length();
@@ -316,7 +345,7 @@ impl Transaction {
len += input.0.length();
len
}
Transaction::Eip2930 {
Transaction::Eip2930(TxEip2930 {
chain_id,
nonce,
gas_price,
@@ -325,7 +354,7 @@ impl Transaction {
value,
input,
access_list,
} => {
}) => {
let mut len = 0;
len += chain_id.length();
len += nonce.length();
@@ -337,7 +366,7 @@ impl Transaction {
len += access_list.length();
len
}
Transaction::Eip1559 {
Transaction::Eip1559(TxEip1559 {
chain_id,
nonce,
gas_limit,
@@ -347,7 +376,7 @@ impl Transaction {
value,
input,
access_list,
} => {
}) => {
let mut len = 0;
len += chain_id.length();
len += nonce.length();
@@ -366,7 +395,15 @@ impl Transaction {
/// Encodes only the transaction's fields into the desired buffer, without a RLP header.
pub(crate) fn encode_fields(&self, out: &mut dyn bytes::BufMut) {
match self {
Transaction::Legacy { chain_id: _, nonce, gas_price, gas_limit, to, value, input } => {
Transaction::Legacy(TxLegacy {
chain_id: _,
nonce,
gas_price,
gas_limit,
to,
value,
input,
}) => {
nonce.encode(out);
gas_price.encode(out);
gas_limit.encode(out);
@@ -374,7 +411,7 @@ impl Transaction {
value.encode(out);
input.0.encode(out);
}
Transaction::Eip2930 {
Transaction::Eip2930(TxEip2930 {
chain_id,
nonce,
gas_price,
@@ -383,7 +420,7 @@ impl Transaction {
value,
input,
access_list,
} => {
}) => {
chain_id.encode(out);
nonce.encode(out);
gas_price.encode(out);
@@ -393,7 +430,7 @@ impl Transaction {
input.0.encode(out);
access_list.encode(out);
}
Transaction::Eip1559 {
Transaction::Eip1559(TxEip1559 {
chain_id,
nonce,
gas_limit,
@@ -403,7 +440,7 @@ impl Transaction {
value,
input,
access_list,
} => {
}) => {
chain_id.encode(out);
nonce.encode(out);
max_priority_fee_per_gas.encode(out);
@@ -449,9 +486,10 @@ impl Encodable for Transaction {
/// Whether or not the transaction is a contract creation.
#[main_codec]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum TransactionKind {
/// A transaction that creates a contract.
#[default]
Create,
/// A transaction that calls a contract or transfer.
Call(Address),
@@ -490,16 +528,16 @@ impl Decodable for TransactionKind {
/// Signed transaction.
#[main_codec]
#[derive(Debug, Clone, PartialEq, Eq, Hash, AsRef, Deref)]
#[derive(Debug, Clone, PartialEq, Eq, Hash, AsRef, Deref, Default)]
pub struct TransactionSigned {
/// Raw transaction info
#[deref]
#[as_ref]
pub transaction: Transaction,
/// Transaction hash
pub hash: TxHash,
/// The transaction signature values
pub signature: Signature,
/// Raw transaction info
#[deref]
#[as_ref]
pub transaction: Transaction,
}
impl Encodable for TransactionSigned {
@@ -540,7 +578,7 @@ impl Decodable for TransactionSigned {
// decode common fields
let transaction = match tx_type {
1 => Transaction::Eip2930 {
1 => Transaction::Eip2930(TxEip2930 {
chain_id: Decodable::decode(buf)?,
nonce: Decodable::decode(buf)?,
gas_price: Decodable::decode(buf)?,
@@ -549,8 +587,8 @@ impl Decodable for TransactionSigned {
value: Decodable::decode(buf)?,
input: Bytes(Decodable::decode(buf)?),
access_list: Decodable::decode(buf)?,
},
2 => Transaction::Eip1559 {
}),
2 => Transaction::Eip1559(TxEip1559 {
chain_id: Decodable::decode(buf)?,
nonce: Decodable::decode(buf)?,
max_priority_fee_per_gas: Decodable::decode(buf)?,
@@ -560,7 +598,7 @@ impl Decodable for TransactionSigned {
value: Decodable::decode(buf)?,
input: Bytes(Decodable::decode(buf)?),
access_list: Decodable::decode(buf)?,
},
}),
_ => return Err(DecodeError::Custom("unsupported typed transaction type")),
};
@@ -574,7 +612,7 @@ impl Decodable for TransactionSigned {
signed.hash = keccak256(&original_encoding[..first_header.payload_length]).into();
Ok(signed)
} else {
let mut transaction = Transaction::Legacy {
let mut transaction = Transaction::Legacy(TxLegacy {
nonce: Decodable::decode(buf)?,
gas_price: Decodable::decode(buf)?,
gas_limit: Decodable::decode(buf)?,
@@ -582,7 +620,7 @@ impl Decodable for TransactionSigned {
value: Decodable::decode(buf)?,
input: Bytes(Decodable::decode(buf)?),
chain_id: None,
};
});
let (signature, extracted_id) = Signature::decode_eip155_inner(buf)?;
if let Some(id) = extracted_id {
transaction.set_chain_id(id);
@@ -630,7 +668,7 @@ impl TransactionSigned {
/// Inner encoding function that is used for both rlp [`Encodable`] trait and for calculating
/// hash that for eip2728 does not require rlp header
pub(crate) fn encode_inner(&self, out: &mut dyn bytes::BufMut, with_header: bool) {
if let Transaction::Legacy { chain_id, .. } = self.transaction {
if let Transaction::Legacy(TxLegacy { chain_id, .. }) = self.transaction {
let header = Header { list: true, payload_length: self.payload_len() };
header.encode(out);
self.transaction.encode_fields(out);
@@ -688,7 +726,7 @@ impl TransactionSigned {
/// Output the length of the inner transaction and signature fields.
pub(crate) fn inner_tx_len(&self) -> usize {
let mut len = self.transaction.fields_len();
if let Transaction::Legacy { chain_id, .. } = self.transaction {
if let Transaction::Legacy(TxLegacy { chain_id, .. }) = self.transaction {
if let Some(id) = chain_id {
len += self.signature.eip155_payload_len(id);
} else {
@@ -719,14 +757,14 @@ impl TransactionSigned {
/// Signed transaction with recovered signer.
#[main_codec]
#[derive(Debug, Clone, PartialEq, Eq, Hash, AsRef, Deref)]
#[derive(Debug, Clone, PartialEq, Eq, Hash, AsRef, Deref, Default)]
pub struct TransactionSignedEcRecovered {
/// Signer of the transaction
signer: Address,
/// Signed transaction
#[deref]
#[as_ref]
signed_transaction: TransactionSigned,
/// Signer of the transaction
signer: Address,
}
impl Encodable for TransactionSignedEcRecovered {
@@ -792,7 +830,7 @@ impl IntoRecoveredTransaction for TransactionSignedEcRecovered {
#[cfg(test)]
mod tests {
use crate::{
transaction::{signature::Signature, TransactionKind},
transaction::{signature::Signature, TransactionKind, TxEip1559, TxEip2930, TxLegacy},
AccessList, Address, Bytes, Transaction, TransactionSigned, H256, U256,
};
use bytes::BytesMut;
@@ -803,7 +841,7 @@ mod tests {
#[test]
fn test_decode_create() {
// tests that a contract creation tx encodes and decodes properly
let request = Transaction::Eip2930 {
let request = Transaction::Eip2930(TxEip2930 {
chain_id: 1u64,
nonce: 0,
gas_price: 1,
@@ -812,7 +850,7 @@ mod tests {
value: 3,
input: Bytes::from(vec![1, 2]),
access_list: Default::default(),
};
});
let signature = Signature { odd_y_parity: true, r: U256::default(), s: U256::default() };
let tx = TransactionSigned::from_transaction_and_signature(request, signature);
@@ -834,7 +872,7 @@ mod tests {
#[test]
fn test_decode_call() {
let request = Transaction::Eip2930 {
let request = Transaction::Eip2930(TxEip2930 {
chain_id: 1u64,
nonce: 0,
gas_price: 1,
@@ -843,7 +881,7 @@ mod tests {
value: 3,
input: Bytes::from(vec![1, 2]),
access_list: Default::default(),
};
});
let signature = Signature { odd_y_parity: true, r: U256::default(), s: U256::default() };
@@ -871,7 +909,7 @@ mod tests {
#[test]
fn decode_multiple_network_txs() {
let bytes_first = &mut &hex::decode("f86b02843b9aca00830186a094d3e8763675e4c425df46cc3b5c0f6cbdac39604687038d7ea4c68000802ba00eb96ca19e8a77102767a41fc85a36afd5c61ccb09911cec5d3e86e193d9c5aea03a456401896b1b6055311536bf00a718568c744d8c1f9df59879e8350220ca18").unwrap()[..];
let expected_request = Transaction::Legacy {
let expected_request = Transaction::Legacy(TxLegacy {
chain_id: Some(4u64),
nonce: 2,
gas_price: 1000000000,
@@ -881,7 +919,7 @@ mod tests {
),
value: 1000000000000000,
input: Bytes::default(),
};
});
let expected_signature = Signature {
odd_y_parity: false,
r: U256::from_str("eb96ca19e8a77102767a41fc85a36afd5c61ccb09911cec5d3e86e193d9c5ae")
@@ -899,7 +937,7 @@ mod tests {
);
let bytes_second = &mut &hex::decode("f86b01843b9aca00830186a094d3e8763675e4c425df46cc3b5c0f6cbdac3960468702769bb01b2a00802ba0e24d8bd32ad906d6f8b8d7741e08d1959df021698b19ee232feba15361587d0aa05406ad177223213df262cb66ccbb2f46bfdccfdfbbb5ffdda9e2c02d977631da").unwrap()[..];
let expected_request = Transaction::Legacy {
let expected_request = Transaction::Legacy(TxLegacy {
chain_id: Some(4),
nonce: 1u64,
gas_price: 1000000000,
@@ -909,7 +947,7 @@ mod tests {
)),
value: 693361000000000u64.into(),
input: Default::default(),
};
});
let expected_signature = Signature {
odd_y_parity: false,
r: U256::from_str("e24d8bd32ad906d6f8b8d7741e08d1959df021698b19ee232feba15361587d0a")
@@ -923,7 +961,7 @@ mod tests {
assert_eq!(expected, TransactionSigned::decode(bytes_second).unwrap());
let bytes_third = &mut &hex::decode("f86b0384773594008398968094d3e8763675e4c425df46cc3b5c0f6cbdac39604687038d7ea4c68000802ba0ce6834447c0a4193c40382e6c57ae33b241379c5418caac9cdc18d786fd12071a03ca3ae86580e94550d7c071e3a02eadb5a77830947c9225165cf9100901bee88").unwrap()[..];
let expected_request = Transaction::Legacy {
let expected_request = Transaction::Legacy(TxLegacy {
chain_id: Some(4),
nonce: 3,
gas_price: 2000000000,
@@ -933,7 +971,7 @@ mod tests {
)),
value: 1000000000000000u64.into(),
input: Bytes::default(),
};
});
let expected_signature = Signature {
odd_y_parity: false,
@@ -948,7 +986,7 @@ mod tests {
assert_eq!(expected, TransactionSigned::decode(bytes_third).unwrap());
let bytes_fourth = &mut &hex::decode("b87502f872041a8459682f008459682f0d8252089461815774383099e24810ab832a5b2a5425c154d58829a2241af62c000080c001a059e6b67f48fb32e7e570dfb11e042b5ad2e55e3ce3ce9cd989c7e06e07feeafda0016b83f4f980694ed2eee4d10667242b1f40dc406901b34125b008d334d47469").unwrap()[..];
let expected = Transaction::Eip1559 {
let expected = Transaction::Eip1559(TxEip1559 {
chain_id: 4,
nonce: 26,
max_priority_fee_per_gas: 1500000000,
@@ -960,7 +998,7 @@ mod tests {
value: 3000000000000000000u64.into(),
input: Default::default(),
access_list: Default::default(),
};
});
let expected_signature = Signature {
odd_y_parity: true,
@@ -975,7 +1013,7 @@ mod tests {
assert_eq!(expected, TransactionSigned::decode(bytes_fourth).unwrap());
let bytes_fifth = &mut &hex::decode("f8650f84832156008287fb94cf7f9e66af820a19257a2108375b180b0ec491678204d2802ca035b7bfeb9ad9ece2cbafaaf8e202e706b4cfaeb233f46198f00b44d4a566a981a0612638fb29427ca33b9a3be2a0a561beecfe0269655be160d35e72d366a6a860").unwrap()[..];
let expected = Transaction::Legacy {
let expected = Transaction::Legacy(TxLegacy {
chain_id: Some(4),
nonce: 15,
gas_price: 2200000000,
@@ -985,7 +1023,7 @@ mod tests {
)),
value: 1234u64.into(),
input: Bytes::default(),
};
});
let signature = Signature {
odd_y_parity: true,
r: U256::from_str("35b7bfeb9ad9ece2cbafaaf8e202e706b4cfaeb233f46198f00b44d4a566a981")
@@ -1022,7 +1060,7 @@ mod tests {
let hash: H256 =
hex!("bb3a336e3f823ec18197f1e13ee875700f08f03e2cab75f0d0b118dabb44cba0").into();
let tx = Transaction::Legacy {
let tx = Transaction::Legacy(TxLegacy {
chain_id: Some(1),
nonce: 0x18,
gas_price: 0xfa56ea00,
@@ -1030,7 +1068,7 @@ mod tests {
to: TransactionKind::Call( hex!("06012c8cf97bead5deae237070f9587f8e7a266d").into()),
value: 0x1c6bf526340000u64.into(),
input: hex!("f7d8c88300000000000000000000000000000000000000000000000000000000000cee6100000000000000000000000000000000000000000000000000000000000ac3e1").into(),
};
});
let sig = Signature {
r: hex!("2a378831cf81d99a3f06a18ae1b6ca366817ab4d88a70053c41d7a8f0368e031").into(),
@@ -1051,7 +1089,7 @@ mod tests {
let hash: H256 =
hex!("0ec0b6a2df4d87424e5f6ad2a654e27aaeb7dac20ae9e8385cc09087ad532ee0").into();
let tx = Transaction::Eip1559 {
let tx = Transaction::Eip1559( TxEip1559 {
chain_id: 1,
nonce: 0x42,
gas_limit: 44386,
@@ -1061,7 +1099,7 @@ mod tests {
max_fee_per_gas: 0x4a817c800,
max_priority_fee_per_gas: 0x3b9aca00,
access_list: AccessList::default(),
};
});
let sig = Signature {
r: hex!("840cfc572845f5786e702984c2a582528cad4b49b2a10b9db1be7fca90058565").into(),

View File

@@ -1,12 +1,14 @@
use crate::{transaction::util::secp256k1, Address, H256, U256};
use reth_codecs::main_codec;
use bytes::Buf;
use modular_bitfield::prelude::*;
use reth_codecs::{main_codec, Compact};
use reth_rlp::{Decodable, DecodeError, Encodable};
/// r, s: Values corresponding to the signature of the
/// transaction and used to determine the sender of
/// the transaction; formally Tr and Ts. This is expanded in Appendix F of yellow paper.
#[main_codec]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
pub struct Signature {
/// The R field of the signature; the point on the curve.
pub r: U256,

View File

@@ -1,8 +1,8 @@
use reth_codecs::{main_codec, Compact};
use reth_codecs::Compact;
use serde::{Deserialize, Serialize};
/// Transaction Type
#[main_codec]
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Default)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Default, Serialize, Deserialize)]
pub enum TxType {
/// Legacy transaction pre EIP-2929
#[default]

View File

@@ -66,6 +66,12 @@ pub enum DatabaseIntegrityError {
/// The block number key
number: BlockNumber,
},
/// The total difficulty from the block header is missing.
#[error("Total difficulty not found for block #{number}")]
TotalDifficulty {
/// The block number key
number: BlockNumber,
},
}
/// A pipeline execution error.

View File

@@ -7,7 +7,7 @@ use reth_interfaces::{
db::{models::blocks::BlockNumHash, tables, Database, DbCursorRO, DbCursorRW, DbTx, DbTxMut},
p2p::headers::{client::HeadersClient, downloader::HeaderDownloader, error::DownloadError},
};
use reth_primitives::{rpc::BigEndianHash, BlockNumber, SealedHeader, H256, U256};
use reth_primitives::{BlockNumber, SealedHeader, H256, U256};
use std::{fmt::Debug, sync::Arc};
use tracing::*;
@@ -119,8 +119,10 @@ impl<D: HeaderDownloader, C: Consensus, H: HeadersClient> HeaderStage<D, C, H> {
height: BlockNumber,
) -> Result<(), StageError> {
let block_key = db.get_block_numhash(height)?;
let td: Vec<u8> = db.get::<tables::HeaderTD>(block_key)?.unwrap(); // TODO:
self.client.update_status(height, block_key.hash(), H256::from_slice(&td).into_uint());
let td: U256 = *db
.get::<tables::HeaderTD>(block_key)?
.ok_or(DatabaseIntegrityError::TotalDifficulty { number: height })?;
self.client.update_status(height, block_key.hash(), td);
Ok(())
}
@@ -144,7 +146,7 @@ impl<D: HeaderDownloader, C: Consensus, H: HeadersClient> HeaderStage<D, C, H> {
let mut cursor_header = db.cursor_mut::<tables::Headers>()?;
let mut cursor_canonical = db.cursor_mut::<tables::CanonicalHeaders>()?;
let mut cursor_td = db.cursor_mut::<tables::HeaderTD>()?;
let mut td = U256::from_big_endian(&cursor_td.last()?.map(|(_, v)| v).unwrap());
let mut td: U256 = cursor_td.last()?.map(|(_, v)| v).unwrap().into();
let mut latest = None;
// Since the headers were returned in descending order,
@@ -165,7 +167,7 @@ impl<D: HeaderDownloader, C: Consensus, H: HeadersClient> HeaderStage<D, C, H> {
db.put::<tables::HeaderNumbers>(block_hash, header.number)?;
cursor_header.append(key, header)?;
cursor_canonical.append(key.number(), key.hash())?;
cursor_td.append(key, H256::from_uint(&td).as_bytes().to_vec())?;
cursor_td.append(key, td.into())?;
}
Ok(latest)
@@ -380,12 +382,10 @@ mod tests {
let parent_td = tx.get::<tables::HeaderTD>(
(header.number - 1, header.parent_hash).into(),
)?;
let td = tx.get::<tables::HeaderTD>(key)?.unwrap();
let td: U256 = *tx.get::<tables::HeaderTD>(key)?.unwrap();
assert_eq!(
parent_td.map(
|td| U256::from_big_endian(&td) + header.difficulty
),
Some(U256::from_big_endian(&td))
parent_td.map(|td| *td + header.difficulty),
Some(td)
);
}
}

View File

@@ -5,7 +5,7 @@ use reth_db::{
use reth_interfaces::db::{
self, models::BlockNumHash, tables, DbCursorRO, DbCursorRW, DbTx, DbTxMut, Table,
};
use reth_primitives::{BigEndianHash, BlockNumber, SealedHeader, H256, U256};
use reth_primitives::{BlockNumber, SealedHeader, U256};
use std::{borrow::Borrow, sync::Arc};
use crate::db::StageDB;
@@ -167,9 +167,8 @@ impl TestStageDB {
self.commit(|tx| {
let headers = headers.collect::<Vec<_>>();
let mut td = U256::from_big_endian(
&tx.cursor::<tables::HeaderTD>()?.last()?.map(|(_, v)| v).unwrap_or_default(),
);
let mut td: U256 =
tx.cursor::<tables::HeaderTD>()?.last()?.map(|(_, v)| v).unwrap_or_default().into();
for header in headers {
let key: BlockNumHash = (header.number, header.hash()).into();
@@ -179,7 +178,7 @@ impl TestStageDB {
tx.put::<tables::Headers>(key, header.clone().unseal())?;
td += header.difficulty;
tx.put::<tables::HeaderTD>(key, H256::from_uint(&td).as_bytes().to_vec())?;
tx.put::<tables::HeaderTD>(key, td.into())?;
}
Ok(())

View File

@@ -12,8 +12,8 @@ use rand::{
prelude::Distribution,
};
use reth_primitives::{
Address, FromRecoveredTransaction, Transaction, TransactionSignedEcRecovered, TxHash, H256,
U256,
Address, FromRecoveredTransaction, Transaction, TransactionSignedEcRecovered, TxEip1559,
TxHash, TxLegacy, H256, U256,
};
use std::{ops::Range, sync::Arc, time::Instant};
@@ -342,17 +342,23 @@ impl FromRecoveredTransaction for MockTransaction {
let transaction = tx.into_signed();
let hash = transaction.hash;
match transaction.transaction {
Transaction::Legacy { chain_id, nonce, gas_price, gas_limit, to, value, input } => {
MockTransaction::Legacy {
hash,
sender,
nonce,
gas_price: gas_price.into(),
gas_limit,
value: value.into(),
}
}
Transaction::Eip1559 {
Transaction::Legacy(TxLegacy {
chain_id,
nonce,
gas_price,
gas_limit,
to,
value,
input,
}) => MockTransaction::Legacy {
hash,
sender,
nonce,
gas_price: gas_price.into(),
gas_limit,
value: value.into(),
},
Transaction::Eip1559(TxEip1559 {
chain_id,
nonce,
gas_limit,
@@ -362,7 +368,7 @@ impl FromRecoveredTransaction for MockTransaction {
value,
input,
access_list,
} => MockTransaction::Eip1559 {
}) => MockTransaction::Eip1559 {
hash,
sender,
nonce,