diff --git a/Cargo.lock b/Cargo.lock index 04d4a09c7..4d162a19a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1274,6 +1274,19 @@ dependencies = [ "libmdbx", ] +[[package]] +name = "reth-executor" +version = "0.1.0" + +[[package]] +name = "reth-interfaces" +version = "0.1.0" +dependencies = [ + "async-trait", + "reth-primitives", + "thiserror", +] + [[package]] name = "reth-p2p" version = "0.1.0" @@ -1282,6 +1295,7 @@ version = "0.1.0" name = "reth-primitives" version = "0.1.0" dependencies = [ + "bytes", "ethers-core", ] diff --git a/Cargo.toml b/Cargo.toml index 8f1a368d0..0bba41a19 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,13 +6,15 @@ edition = "2021" [workspace] members = [ "crate-template", + "crates/db", + "crates/executor", + "crates/interfaces", "crates/net/p2p", "crates/net/rpc", "crates/net/rpc-api", "crates/net/rpc-types", "crates/primitives", "crates/stages", - "crates/db" ] [dependencies] diff --git a/crates/executor/Cargo.toml b/crates/executor/Cargo.toml new file mode 100644 index 000000000..f1fe8ba34 --- /dev/null +++ b/crates/executor/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "reth-executor" +version = "0.1.0" +edition = "2021" +license = "MIT OR Apache-2.0" +repository = "https://github.com/foundry-rs/reth" +readme = "README.md" + +[dependencies] diff --git a/crates/executor/src/lib.rs b/crates/executor/src/lib.rs new file mode 100644 index 000000000..639ddcaea --- /dev/null +++ b/crates/executor/src/lib.rs @@ -0,0 +1,8 @@ +#![warn(missing_debug_implementations, missing_docs, unreachable_pub)] +#![deny(unused_must_use, rust_2018_idioms)] +#![doc(test( + no_crate_inject, + attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables)) +))] + +//! Reth executor executes transaction in block of data. diff --git a/crates/interfaces/Cargo.toml b/crates/interfaces/Cargo.toml new file mode 100644 index 000000000..fc66d9fed --- /dev/null +++ b/crates/interfaces/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "reth-interfaces" +version = "0.1.0" +edition = "2021" +license = "MIT OR Apache-2.0" +repository = "https://github.com/foundry-rs/reth" +readme = "README.md" + +[dependencies] +reth-primitives = { path = "../primitives" } +async-trait = "0.1.57" +thiserror = "1.0.37" \ No newline at end of file diff --git a/crates/interfaces/src/executor.rs b/crates/interfaces/src/executor.rs new file mode 100644 index 000000000..379c0112d --- /dev/null +++ b/crates/interfaces/src/executor.rs @@ -0,0 +1,20 @@ +use async_trait::async_trait; +use reth_primitives::Block; +use thiserror::Error; + +/// Takes block and executes it, returns error +#[async_trait] +pub trait BlockExecutor { + /// Execute block + async fn execute(&self, _block: Block) -> Error { + Error::VerificationFailed + } +} + +/// BlockExecutor Errors +#[derive(Error, Debug, Clone)] +pub enum Error { + /// Example of error + #[error("Example of error.")] + VerificationFailed, +} diff --git a/crates/interfaces/src/lib.rs b/crates/interfaces/src/lib.rs new file mode 100644 index 000000000..07c795a08 --- /dev/null +++ b/crates/interfaces/src/lib.rs @@ -0,0 +1,11 @@ +#![warn(missing_debug_implementations, missing_docs, unreachable_pub)] +#![deny(unused_must_use, rust_2018_idioms)] +#![doc(test( + no_crate_inject, + attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_variables)) +))] + +//! Reth interface bindings + +/// Block Execution traits. +pub mod executor; diff --git a/crates/net/rpc-api/src/debug.rs b/crates/net/rpc-api/src/debug.rs index 8282b8bcd..fcef62fca 100644 --- a/crates/net/rpc-api/src/debug.rs +++ b/crates/net/rpc-api/src/debug.rs @@ -1,5 +1,8 @@ use jsonrpsee::{core::RpcResult as Result, proc_macros::rpc}; -use reth_primitives::{BlockId, Bytes, H256}; +use reth_primitives::{ + rpc::{BlockId, Bytes}, + H256, +}; use reth_rpc_types::RichBlock; /// Debug rpc interface. diff --git a/crates/net/rpc-api/src/eth.rs b/crates/net/rpc-api/src/eth.rs index 3e84de20c..2d69c4899 100644 --- a/crates/net/rpc-api/src/eth.rs +++ b/crates/net/rpc-api/src/eth.rs @@ -3,8 +3,8 @@ use jsonrpsee::{ proc_macros::rpc, }; use reth_primitives::{ - transaction::eip2930::AccessListWithGasUsed, Address, BlockId, BlockNumber, Bytes, H256, H64, - U256, U64, + rpc::{transaction::eip2930::AccessListWithGasUsed, BlockId}, + Address, BlockNumber, Bytes, H256, H64, U256, U64, }; use reth_rpc_types::{ CallRequest, EIP1186AccountProofResponse, FeeHistory, Index, RichBlock, SyncStatus, diff --git a/crates/net/rpc-api/src/eth_filter.rs b/crates/net/rpc-api/src/eth_filter.rs index d76dbec64..b4357b66f 100644 --- a/crates/net/rpc-api/src/eth_filter.rs +++ b/crates/net/rpc-api/src/eth_filter.rs @@ -1,6 +1,6 @@ use jsonrpsee::{core::RpcResult as Result, proc_macros::rpc}; -use reth_primitives::U256; -use reth_rpc_types::{Filter, FilterChanges, Index, Log}; +use reth_primitives::{rpc::Filter, U256}; +use reth_rpc_types::{FilterChanges, Index, Log}; /// Rpc Interface for poll-based ethereum filter API. #[rpc(server)] diff --git a/crates/net/rpc-api/src/trace.rs b/crates/net/rpc-api/src/trace.rs index 7d990905a..fdea1c036 100644 --- a/crates/net/rpc-api/src/trace.rs +++ b/crates/net/rpc-api/src/trace.rs @@ -1,5 +1,5 @@ use jsonrpsee::{core::RpcResult as Result, proc_macros::rpc}; -use reth_primitives::{BlockId, Bytes, H256}; +use reth_primitives::{rpc::BlockId, Bytes, H256}; use reth_rpc_types::{ trace::{filter::TraceFilter, parity::*}, CallRequest, Index, diff --git a/crates/net/rpc-types/src/eth/block.rs b/crates/net/rpc-types/src/eth/block.rs index 00f977aa1..2650ca013 100644 --- a/crates/net/rpc-types/src/eth/block.rs +++ b/crates/net/rpc-types/src/eth/block.rs @@ -1,4 +1,5 @@ -use reth_primitives::{Address, Bloom, Bytes, Transaction, H256, H64, U256}; +use crate::Transaction; +use reth_primitives::{rpc::H64, Address, Bloom, Bytes, H256, U256}; use serde::{ser::Error, Serialize, Serializer}; use std::{collections::BTreeMap, ops::Deref}; diff --git a/crates/net/rpc-types/src/eth/call.rs b/crates/net/rpc-types/src/eth/call.rs index 568fd3a81..704f8d698 100644 --- a/crates/net/rpc-types/src/eth/call.rs +++ b/crates/net/rpc-types/src/eth/call.rs @@ -1,4 +1,4 @@ -use reth_primitives::{transaction::eip2930::AccessListItem, Address, Bytes, U256}; +use reth_primitives::{rpc::transaction::eip2930::AccessListItem, Address, Bytes, U256}; use serde::Deserialize; /// Call request diff --git a/crates/net/rpc-types/src/eth/filter.rs b/crates/net/rpc-types/src/eth/filter.rs index d1ac1c556..3b1bb19c5 100644 --- a/crates/net/rpc-types/src/eth/filter.rs +++ b/crates/net/rpc-types/src/eth/filter.rs @@ -1,6 +1,5 @@ use crate::Log; use reth_primitives::H256; -pub use reth_primitives::{Filter, FilteredParams}; use serde::{Serialize, Serializer}; /// Response of the `eth_getFilterChanges` RPC. diff --git a/crates/net/rpc-types/src/eth/pubsub.rs b/crates/net/rpc-types/src/eth/pubsub.rs index dfd187425..ba6fb006d 100644 --- a/crates/net/rpc-types/src/eth/pubsub.rs +++ b/crates/net/rpc-types/src/eth/pubsub.rs @@ -1,7 +1,7 @@ //! Ethereum types for pub-sub -use crate::{Filter, Log, RichHeader}; -use reth_primitives::H256; +use crate::{Log, RichHeader}; +use reth_primitives::{rpc::Filter, H256}; use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer}; /// Subscription result. diff --git a/crates/net/rpc-types/src/eth/transaction/mod.rs b/crates/net/rpc-types/src/eth/transaction/mod.rs index a698f3d63..272e10d2a 100644 --- a/crates/net/rpc-types/src/eth/transaction/mod.rs +++ b/crates/net/rpc-types/src/eth/transaction/mod.rs @@ -7,7 +7,7 @@ pub use request::TransactionRequest; pub use typed::*; use reth_primitives::{ - transaction::eip2930::AccessListItem, Address, Bytes, H256, H512, U256, U64, + rpc::transaction::eip2930::AccessListItem, Address, Bytes, H256, H512, U256, U64, }; use serde::Serialize; diff --git a/crates/net/rpc-types/src/eth/transaction/receipt.rs b/crates/net/rpc-types/src/eth/transaction/receipt.rs index fda645df4..af9ff2e54 100644 --- a/crates/net/rpc-types/src/eth/transaction/receipt.rs +++ b/crates/net/rpc-types/src/eth/transaction/receipt.rs @@ -1,4 +1,4 @@ -use reth_primitives::{Address, Bloom, Log, H256, U256, U64}; +use reth_primitives::{rpc::Log, Address, Bloom, H256, U256, U64}; use serde::Serialize; /// Transaction receipt diff --git a/crates/net/rpc-types/src/eth/transaction/request.rs b/crates/net/rpc-types/src/eth/transaction/request.rs index 3f53b7ba4..3027649ba 100644 --- a/crates/net/rpc-types/src/eth/transaction/request.rs +++ b/crates/net/rpc-types/src/eth/transaction/request.rs @@ -2,7 +2,7 @@ use crate::eth::transaction::typed::{ EIP1559TransactionRequest, EIP2930TransactionRequest, LegacyTransactionRequest, TransactionKind, TypedTransactionRequest, }; -use reth_primitives::{transaction::eip2930::AccessListItem, Address, Bytes, U256}; +use reth_primitives::{rpc::transaction::eip2930::AccessListItem, Address, Bytes, U256}; use serde::{Deserialize, Serialize}; /// Represents _all_ transaction requests received from RPC diff --git a/crates/net/rpc-types/src/eth/transaction/typed.rs b/crates/net/rpc-types/src/eth/transaction/typed.rs index 99235537f..c7e20e7d4 100644 --- a/crates/net/rpc-types/src/eth/transaction/typed.rs +++ b/crates/net/rpc-types/src/eth/transaction/typed.rs @@ -4,7 +4,7 @@ //! container type [`TypedTransactionRequest`]. use fastrlp::{RlpDecodable, RlpEncodable}; -use reth_primitives::{transaction::eip2930::AccessListItem, Address, Bytes, U256}; +use reth_primitives::{rpc::transaction::eip2930::AccessListItem, Address, Bytes, U256}; use serde::{Deserialize, Serialize}; /// Container type for various Ethereum transaction requests diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index 1fd479236..3a4307661 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -8,4 +8,5 @@ readme = "README.md" description = "Commonly used types in reth." [dependencies] -ethers-core = { git = "https://github.com/gakonst/ethers-rs", default-features = false } \ No newline at end of file +ethers-core = { git = "https://github.com/gakonst/ethers-rs", default-features = false } +bytes = "1.2" \ No newline at end of file diff --git a/crates/primitives/src/block.rs b/crates/primitives/src/block.rs new file mode 100644 index 000000000..395586c4e --- /dev/null +++ b/crates/primitives/src/block.rs @@ -0,0 +1,12 @@ +use crate::{Header, Receipt, Transaction}; + +/// Ethereum full block. +#[derive(Debug, Clone, PartialEq, Eq, Default)] +pub struct Block { + /// Block header. + pub header: Header, + /// Transactions in this block. + pub body: Vec, + /// Block receipts. + pub receipts: Vec, +} diff --git a/crates/primitives/src/header.rs b/crates/primitives/src/header.rs new file mode 100644 index 000000000..3b9be0cb7 --- /dev/null +++ b/crates/primitives/src/header.rs @@ -0,0 +1,100 @@ +use crate::{BlockNumber, Bytes, H160, H256, U256}; + +/// Block header +#[derive(Debug, Clone, PartialEq, Eq, Default)] +pub struct Header { + /// The Keccak 256-bit hash of the parent + /// block’s header, in its entirety; formally Hp. + pub parent_hash: H256, + /// The Keccak 256-bit hash of the ommers list portion of this block; formally Ho. + pub ommers_hash: H256, + /// The 160-bit address to which all fees collected from the successful mining of this block + /// be transferred; formally Hc. + pub beneficiary: H160, + /// The Keccak 256-bit hash of the root node of the state trie, after all transactions are + /// executed and finalisations applied; formally Hr. + pub state_root: H256, + /// The Keccak 256-bit hash of the root node of the trie structure populated with each + /// transaction in the transactions list portion of the + /// block; formally Ht. + pub transactions_root: H256, + /// The Keccak 256-bit hash of the root + /// node of the trie structure populated with the receipts of each transaction in the + /// transactions list portion of the block; formally He. + pub receipts_root: H256, + /// The Bloom filter composed from indexable information (logger address and log topics) + /// contained in each log entry from the receipt of each transaction in the transactions list; + /// formally Hb. + pub logs_bloom: H256, // change to Bloom + /// A scalar value corresponding to the difficulty level of this block. This can be calculated + /// from the previous block’s difficulty level and the timestamp; formally Hd. + pub difficulty: U256, + /// A scalar value equal to the number of ancestor blocks. The genesis block has a number of + /// zero; formally Hi. + pub number: BlockNumber, + /// A scalar value equal to the current limit of gas expenditure per block; formally Hl. + pub gas_limit: u64, + /// A scalar value equal to the total gas used in transactions in this block; formally Hg. + pub gas_used: u64, + /// A scalar value equal to the reasonable output of Unix’s time() at this block’s inception; + /// formally Hs. + pub timestamp: u64, + /// An arbitrary byte array containing data relevant to this block. This must be 32 bytes or + /// fewer; formally Hx. + pub extra_data: Bytes, + /// A 256-bit hash which, combined with the + /// nonce, proves that a sufficient amount of computation has been carried out on this block; + /// formally Hm. + pub mix_hash: H256, + /// A 64-bit value which, combined with the mixhash, proves that a sufficient amount of + /// computation has been carried out on this block; formally Hn. + pub nonce: u64, + /// A scalar representing EIP1559 base fee which can move up or down each block according + /// to a formula which is a function of gas used in parent block and gas target + /// (block gas limit divided by elasticity multiplier) of parent block. + /// The algorithm results in the base fee per gas increasing when blocks are + /// above the gas target, and decreasing when blocks are below the gas target. The base fee per + /// gas is burned. + pub base_fee_per_gas: Option, +} + +impl Header { + /// Heavy function that will calculate hash of data and will *not* save the change to metadata. + /// Use lock, HeaderLocked and unlock if you need hash to be persistent. + pub fn hash_slow(&self) -> H256 { + todo!() + } + + /// Calculate hash and lock the Header so that it can't be changed. + pub fn lock(self) -> HeaderLocked { + let hash = self.hash_slow(); + HeaderLocked { header: self, hash } + } +} + +#[derive(Debug, Clone, PartialEq, Eq, Default)] +/// HeaderLocked that has precalculated hash, use unlock if you want to modify header. +pub struct HeaderLocked { + /// Locked Header fields. + header: Header, + /// Locked Header hash. + hash: H256, +} + +impl AsRef
for HeaderLocked { + fn as_ref(&self) -> &Header { + &self.header + } +} + +impl HeaderLocked { + /// Extract raw header that can be modified. + pub fn unlock(self) -> Header { + self.header + } + + /// Return header/block hash. + pub fn hash(&self) -> H256 { + self.hash + } +} diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index b21cd285d..1c07d5274 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -7,4 +7,25 @@ //! Commonly used types in reth. -pub use ethers_core::types::*; +mod block; +mod header; +mod log; +mod receipt; +mod transaction; + +pub use block::Block; +pub use header::{Header, HeaderLocked}; +pub use log::Log; +pub use receipt::Receipt; +pub use transaction::{Transaction, TransactionSigned, TxType}; + +/// Block Number +pub type BlockNumber = u64; +/// Ethereum address +pub type Address = H160; + +// NOTE: There is a benefit of using wrapped Bytes as it gives us serde and debug +pub use ethers_core::{ + types as rpc, + types::{Bloom, Bytes, H160, H256, H512, H64, U256, U64}, +}; diff --git a/crates/primitives/src/log.rs b/crates/primitives/src/log.rs new file mode 100644 index 000000000..78b963180 --- /dev/null +++ b/crates/primitives/src/log.rs @@ -0,0 +1,12 @@ +use crate::{Address, Bytes, H256}; + +/// Ethereum Log +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Log { + /// Contract that emitted this log. + pub address: Address, + /// Topics of the log. The number of logs depend on what `LOG` opcode is used. + pub topics: Vec, + /// Arbitrary length data. + pub data: Bytes, +} diff --git a/crates/primitives/src/receipt.rs b/crates/primitives/src/receipt.rs new file mode 100644 index 000000000..25bba50cb --- /dev/null +++ b/crates/primitives/src/receipt.rs @@ -0,0 +1,16 @@ +use crate::{Log, TxType, H256}; + +/// Receipt containing result of transaction execution. +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct Receipt { + /// Receipt type. + pub tx_type: TxType, + /// If transaction is executed successfully. + pub success: bool, + /// Gas used + pub cumulative_gas_used: u64, + /// Bloom filter. + pub bloom: H256, + /// Log send from contracts. + pub logs: Vec, +} diff --git a/crates/primitives/src/transaction/mod.rs b/crates/primitives/src/transaction/mod.rs new file mode 100644 index 000000000..36abd1ce3 --- /dev/null +++ b/crates/primitives/src/transaction/mod.rs @@ -0,0 +1,45 @@ +mod signature; +mod tx_type; + +use signature::Signature; +pub use tx_type::TxType; + +/// Raw Transaction. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum Transaction { + /// Legacy transaciton. + Legacy { + /// Nonce. + nonce: u64, + }, + /// Transaction with AccessList. + Eip2930 { + /// nonce. + nonce: u64, + }, + /// Transaction with priority fee. + Eip1559 { + /// Nonce. + nonce: u64, + }, +} + +/// Signed transaction. +#[derive(Debug, Clone)] +pub struct TransactionSigned { + transaction: Transaction, + signature: Signature, +} + +impl AsRef for TransactionSigned { + fn as_ref(&self) -> &Transaction { + &self.transaction + } +} + +impl TransactionSigned { + /// Transaction signature. + pub fn signature(&self) -> &Signature { + &self.signature + } +} diff --git a/crates/primitives/src/transaction/signature.rs b/crates/primitives/src/transaction/signature.rs new file mode 100644 index 000000000..6153b11ee --- /dev/null +++ b/crates/primitives/src/transaction/signature.rs @@ -0,0 +1,9 @@ +use crate::H256; + +/// Signature still TODO +#[derive(Debug, Clone)] +pub struct Signature { + pub r: H256, + pub s: H256, + pub y_parity: u8, +} diff --git a/crates/primitives/src/transaction/tx_type.rs b/crates/primitives/src/transaction/tx_type.rs new file mode 100644 index 000000000..2f8fca27a --- /dev/null +++ b/crates/primitives/src/transaction/tx_type.rs @@ -0,0 +1,10 @@ +/// Transaction Type +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub enum TxType { + /// Legacy transaction pre EIP-2929 + Legacy = 0, + /// AccessList transaction + EIP2930 = 1, + /// Transaction with Priority fee + EIP1559 = 2, +}