mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
Transaction type and some wrap over revm (#19)
* Transaction and wip db binding * simple revm wrapper * nits and small sig change
This commit is contained in:
@ -1,20 +1,19 @@
|
|||||||
#![allow(missing_debug_implementations)]
|
use crate::{revm_wrap, Config};
|
||||||
|
|
||||||
use crate::Config;
|
|
||||||
use reth_interfaces::{
|
use reth_interfaces::{
|
||||||
consensus::Consensus,
|
consensus::Consensus,
|
||||||
executor::{BlockExecutor, Error, ExecutorDb},
|
executor::{BlockExecutor, Error, ExecutorDb},
|
||||||
};
|
};
|
||||||
use reth_primitives::Block;
|
use reth_primitives::BlockLocked;
|
||||||
|
use revm::{db::EmptyDB, AnalysisKind, Env, SpecId};
|
||||||
|
|
||||||
/// Main block executor
|
/// Main block executor
|
||||||
pub struct Executor {
|
pub struct Executor {
|
||||||
/// Configuration, Spec and optional flags.
|
/// Configuration, Spec and optional flags.
|
||||||
config: Config,
|
pub config: Config,
|
||||||
/// Database
|
/// Database
|
||||||
db: Box<dyn ExecutorDb>,
|
pub db: Box<dyn ExecutorDb>,
|
||||||
/// Consensus
|
/// Consensus
|
||||||
consensus: Box<dyn Consensus>,
|
pub consensus: Box<dyn Consensus>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Executor {
|
impl Executor {
|
||||||
@ -23,13 +22,22 @@ impl Executor {
|
|||||||
Self { config, db, consensus }
|
Self { config, db, consensus }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Verify block (TODO)
|
/// Verify block. Execute all transaction and compare results.
|
||||||
pub fn verify(&self, block: &Block) -> Result<(), Error> {
|
pub fn verify(&self, block: &BlockLocked) -> Result<(), Error> {
|
||||||
// TODO example
|
let mut env = Env::default();
|
||||||
let _ = self.consensus.validate_header(&block.header);
|
env.cfg.chain_id = 1.into();
|
||||||
if self.config.example {
|
env.cfg.spec_id = SpecId::LATEST;
|
||||||
let _block_exist = self.db.get_block(block.header.number);
|
env.cfg.perf_all_precompiles_have_balance = true;
|
||||||
|
env.cfg.perf_analyse_created_bytecodes = AnalysisKind::Raw;
|
||||||
|
|
||||||
|
revm_wrap::fill_block_env(&mut env.block, block);
|
||||||
|
|
||||||
|
let _database = revm_wrap::TempStateDb::new(EmptyDB::default());
|
||||||
|
|
||||||
|
for transaction in block.body.iter() {
|
||||||
|
revm_wrap::fill_tx_env(&mut env.tx, transaction.as_ref());
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(Error::VerificationFailed)
|
Err(Error::VerificationFailed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
#![warn(missing_debug_implementations, missing_docs, unreachable_pub)]
|
#![warn(missing_docs, unreachable_pub)]
|
||||||
#![deny(unused_must_use, rust_2018_idioms)]
|
#![deny(unused_must_use, rust_2018_idioms)]
|
||||||
#![doc(test(
|
#![doc(test(
|
||||||
no_crate_inject,
|
no_crate_inject,
|
||||||
@ -10,5 +10,7 @@
|
|||||||
mod cfg;
|
mod cfg;
|
||||||
/// Executor
|
/// Executor
|
||||||
pub mod executor;
|
pub mod executor;
|
||||||
|
/// Wrapper around revm database and types
|
||||||
|
pub mod revm_wrap;
|
||||||
|
|
||||||
pub use cfg::Config;
|
pub use cfg::Config;
|
||||||
|
|||||||
128
crates/executor/src/revm_wrap.rs
Normal file
128
crates/executor/src/revm_wrap.rs
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
use reth_interfaces::executor::ExecutorDb;
|
||||||
|
use reth_primitives::{BlockLocked, Transaction, H160, H256, U256};
|
||||||
|
use revm::{
|
||||||
|
db::{CacheDB, Database, EmptyDB},
|
||||||
|
BlockEnv, TransactTo, TxEnv,
|
||||||
|
};
|
||||||
|
use std::convert::Infallible;
|
||||||
|
|
||||||
|
/// Temporary stateDB TODO
|
||||||
|
pub type TempStateDb = CacheDB<EmptyDB>;
|
||||||
|
|
||||||
|
/// Wrapper around ExeuctorDb that implements revm database trait
|
||||||
|
pub struct Wrapper<'a>(&'a dyn ExecutorDb);
|
||||||
|
|
||||||
|
impl<'a> Database for Wrapper<'a> {
|
||||||
|
type Error = Infallible;
|
||||||
|
|
||||||
|
fn basic(&mut self, address: H160) -> Result<Option<revm::AccountInfo>, Self::Error> {
|
||||||
|
Ok(self.0.basic_account(address).map(|account| revm::AccountInfo {
|
||||||
|
balance: account.balance,
|
||||||
|
nonce: account.nonce,
|
||||||
|
code_hash: account.bytecode_hash,
|
||||||
|
code: None,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn code_by_hash(&mut self, code_hash: H256) -> Result<revm::Bytecode, Self::Error> {
|
||||||
|
let (bytecode, size) = self.0.bytecode_by_hash(code_hash).unwrap_or_default();
|
||||||
|
Ok(unsafe { revm::Bytecode::new_checked(bytecode.0, size, Some(code_hash)) })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn storage(&mut self, address: H160, index: U256) -> Result<U256, Self::Error> {
|
||||||
|
let mut h_index = H256::zero();
|
||||||
|
index.to_big_endian(h_index.as_bytes_mut());
|
||||||
|
|
||||||
|
Ok(U256::from_big_endian(self.0.storage(address, h_index).unwrap_or_default().as_ref()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn block_hash(&mut self, number: U256) -> Result<H256, Self::Error> {
|
||||||
|
Ok(self.0.block_hash(number).unwrap_or_default())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fill block environment from Block.
|
||||||
|
pub fn fill_block_env(block_env: &mut BlockEnv, block: &BlockLocked) {
|
||||||
|
block_env.number = block.header.number.into();
|
||||||
|
block_env.coinbase = block.header.beneficiary;
|
||||||
|
block_env.timestamp = block.header.timestamp.into();
|
||||||
|
block_env.difficulty = block.header.difficulty;
|
||||||
|
block_env.basefee = block.header.base_fee_per_gas.unwrap_or_default().into();
|
||||||
|
block_env.gas_limit = block.header.gas_limit.into();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fill transaction environment from Transaction.
|
||||||
|
pub fn fill_tx_env(tx_env: &mut TxEnv, transaction: &Transaction) {
|
||||||
|
match transaction {
|
||||||
|
Transaction::Legacy { 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;
|
||||||
|
tx_env.transact_to =
|
||||||
|
if let Some(to) = to { TransactTo::Call(*to) } else { TransactTo::create() };
|
||||||
|
tx_env.value = *value;
|
||||||
|
tx_env.data = input.0.clone();
|
||||||
|
tx_env.chain_id = *chain_id;
|
||||||
|
tx_env.nonce = Some(*nonce);
|
||||||
|
}
|
||||||
|
Transaction::Eip2930 {
|
||||||
|
nonce,
|
||||||
|
chain_id,
|
||||||
|
gas_price,
|
||||||
|
gas_limit,
|
||||||
|
to,
|
||||||
|
value,
|
||||||
|
input,
|
||||||
|
access_list,
|
||||||
|
} => {
|
||||||
|
tx_env.gas_limit = *gas_limit;
|
||||||
|
tx_env.gas_price = (*gas_price).into();
|
||||||
|
tx_env.gas_priority_fee = None;
|
||||||
|
tx_env.transact_to =
|
||||||
|
if let Some(to) = to { TransactTo::Call(*to) } else { TransactTo::create() };
|
||||||
|
tx_env.value = *value;
|
||||||
|
tx_env.data = input.0.clone();
|
||||||
|
tx_env.chain_id = Some(*chain_id);
|
||||||
|
tx_env.nonce = Some(*nonce);
|
||||||
|
tx_env.access_list = access_list
|
||||||
|
.iter()
|
||||||
|
.map(|l| {
|
||||||
|
(
|
||||||
|
l.address,
|
||||||
|
l.storage_keys.iter().map(|k| U256::from_big_endian(k.as_ref())).collect(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
}
|
||||||
|
Transaction::Eip1559 {
|
||||||
|
nonce,
|
||||||
|
chain_id,
|
||||||
|
gas_limit,
|
||||||
|
max_fee_per_gas,
|
||||||
|
max_priority_fee_per_gas,
|
||||||
|
to,
|
||||||
|
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());
|
||||||
|
tx_env.transact_to =
|
||||||
|
if let Some(to) = to { TransactTo::Call(*to) } else { TransactTo::create() };
|
||||||
|
tx_env.value = *value;
|
||||||
|
tx_env.data = input.0.clone();
|
||||||
|
tx_env.chain_id = Some(*chain_id);
|
||||||
|
tx_env.nonce = Some(*nonce);
|
||||||
|
tx_env.access_list = access_list
|
||||||
|
.iter()
|
||||||
|
.map(|l| {
|
||||||
|
(
|
||||||
|
l.address,
|
||||||
|
l.storage_keys.iter().map(|k| U256::from_big_endian(k.as_ref())).collect(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,7 @@
|
|||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use reth_primitives::{Address, Block, BlockNumber, StorageKey, StorageValue};
|
use reth_primitives::{
|
||||||
|
Account, Address, Block, BlockNumber, Bytes, StorageKey, StorageValue, H256, U256,
|
||||||
|
};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
/// Takes block and executes it, returns error
|
/// Takes block and executes it, returns error
|
||||||
@ -22,8 +24,17 @@ pub enum Error {
|
|||||||
/// Function needed for executor
|
/// Function needed for executor
|
||||||
pub trait ExecutorDb {
|
pub trait ExecutorDb {
|
||||||
/// Get Block by BlockNumber.
|
/// Get Block by BlockNumber.
|
||||||
fn get_block(&self, _height: BlockNumber) -> Option<Block>;
|
fn block(&self, _height: BlockNumber) -> Option<Block>;
|
||||||
|
|
||||||
/// Get storage.
|
/// Get storage.
|
||||||
fn get_storage(&self, account: Address, storage_key: StorageKey) -> Option<StorageValue>;
|
fn storage(&self, account: Address, storage_key: StorageKey) -> Option<StorageValue>;
|
||||||
|
|
||||||
|
/// Get basic account information.
|
||||||
|
fn basic_account(&self, adderss: Address) -> Option<Account>;
|
||||||
|
|
||||||
|
/// Get account code by its hash
|
||||||
|
fn bytecode_by_hash(&self, code_hash: H256) -> Option<(Bytes, usize)>;
|
||||||
|
|
||||||
|
/// Get block hash by number.
|
||||||
|
fn block_hash(&self, number: U256) -> Option<H256>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,12 @@
|
|||||||
|
use crate::{H256, U256};
|
||||||
|
|
||||||
|
/// Account saved in database
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
pub struct Account {
|
pub struct Account {
|
||||||
|
/// Nonce.
|
||||||
pub nonce: u64,
|
pub nonce: u64,
|
||||||
|
/// Account balance.
|
||||||
pub balance: U256,
|
pub balance: U256,
|
||||||
|
/// Hash of the bytecode.
|
||||||
pub bytecode_hash: H256,
|
pub bytecode_hash: H256,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
use crate::{Header, Receipt, Transaction};
|
use crate::{Header, HeaderLocked, Receipt, Transaction, TransactionSigned};
|
||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
/// Ethereum full block.
|
/// Ethereum full block.
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Default)]
|
#[derive(Debug, Clone, PartialEq, Eq, Default)]
|
||||||
@ -10,3 +11,28 @@ pub struct Block {
|
|||||||
/// Block receipts.
|
/// Block receipts.
|
||||||
pub receipts: Vec<Receipt>,
|
pub receipts: Vec<Receipt>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Deref for Block {
|
||||||
|
type Target = Header;
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.header
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sealed Ethereum full block.
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Default)]
|
||||||
|
pub struct BlockLocked {
|
||||||
|
/// Locked block header.
|
||||||
|
pub header: HeaderLocked,
|
||||||
|
/// Transactions with signatures.
|
||||||
|
pub body: Vec<TransactionSigned>,
|
||||||
|
/// Block receipts.
|
||||||
|
pub receipts: Vec<Receipt>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for BlockLocked {
|
||||||
|
type Target = Header;
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
self.header.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
use crate::{BlockNumber, Bytes, H160, H256, U256};
|
use crate::{BlockNumber, Bytes, H160, H256, U256};
|
||||||
|
|
||||||
/// Block header
|
/// Block header
|
||||||
@ -87,6 +89,14 @@ impl AsRef<Header> for HeaderLocked {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Deref for HeaderLocked {
|
||||||
|
type Target = Header;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.header
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl HeaderLocked {
|
impl HeaderLocked {
|
||||||
/// Extract raw header that can be modified.
|
/// Extract raw header that can be modified.
|
||||||
pub fn unlock(self) -> Header {
|
pub fn unlock(self) -> Header {
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
//! Commonly used types in reth.
|
//! Commonly used types in reth.
|
||||||
|
|
||||||
|
mod account;
|
||||||
mod block;
|
mod block;
|
||||||
mod chain;
|
mod chain;
|
||||||
mod header;
|
mod header;
|
||||||
@ -14,11 +15,12 @@ mod log;
|
|||||||
mod receipt;
|
mod receipt;
|
||||||
mod transaction;
|
mod transaction;
|
||||||
|
|
||||||
pub use block::Block;
|
pub use account::Account;
|
||||||
|
pub use block::{Block, BlockLocked};
|
||||||
pub use header::{Header, HeaderLocked};
|
pub use header::{Header, HeaderLocked};
|
||||||
pub use log::Log;
|
pub use log::Log;
|
||||||
pub use receipt::Receipt;
|
pub use receipt::Receipt;
|
||||||
pub use transaction::{Transaction, TransactionSigned, TxType};
|
pub use transaction::{AccessList, AccessListItem, Transaction, TransactionSigned, TxType};
|
||||||
|
|
||||||
/// Block Number is height of chain
|
/// Block Number is height of chain
|
||||||
pub type BlockNumber = u64;
|
pub type BlockNumber = u64;
|
||||||
|
|||||||
14
crates/primitives/src/transaction/access_list.rs
Normal file
14
crates/primitives/src/transaction/access_list.rs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
use crate::{Address, H256};
|
||||||
|
|
||||||
|
/// A list of addresses and storage keys that the transaction plans to access.
|
||||||
|
/// Accesses outside the list are possible, but become more expensive.
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct AccessListItem {
|
||||||
|
/// Account addresses that would be loaded at the start of execution
|
||||||
|
pub address: Address,
|
||||||
|
/// Keys of storage that would be loaded at the start of execution
|
||||||
|
pub storage_keys: Vec<H256>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// AccessList as defined in EIP-2930
|
||||||
|
pub type AccessList = Vec<AccessListItem>;
|
||||||
@ -1,33 +1,142 @@
|
|||||||
|
mod access_list;
|
||||||
mod signature;
|
mod signature;
|
||||||
mod tx_type;
|
mod tx_type;
|
||||||
|
|
||||||
|
use crate::{Address, Bytes, TxHash, U256};
|
||||||
|
pub use access_list::{AccessList, AccessListItem};
|
||||||
use signature::Signature;
|
use signature::Signature;
|
||||||
|
use std::ops::Deref;
|
||||||
pub use tx_type::TxType;
|
pub use tx_type::TxType;
|
||||||
|
|
||||||
/// Raw Transaction.
|
/// Raw Transaction.
|
||||||
|
/// Transaction type is introduced in EIP-2718: https://eips.ethereum.org/EIPS/eip-2718
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum Transaction {
|
pub enum Transaction {
|
||||||
/// Legacy transaciton.
|
/// Legacy transaciton.
|
||||||
Legacy {
|
Legacy {
|
||||||
/// Nonce.
|
/// Added as EIP-155: Simple replay attack protection
|
||||||
|
chain_id: Option<u64>,
|
||||||
|
/// A scalar value equal to the number of transactions sent by the sender; formally Tn.
|
||||||
nonce: u64,
|
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.
|
||||||
|
gas_price: 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,
|
||||||
|
/// 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.
|
||||||
|
to: Option<Address>,
|
||||||
|
/// 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.
|
||||||
|
value: U256,
|
||||||
|
/// 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,
|
||||||
},
|
},
|
||||||
/// Transaction with AccessList.
|
/// Transaction with AccessList. https://eips.ethereum.org/EIPS/eip-2930
|
||||||
Eip2930 {
|
Eip2930 {
|
||||||
/// nonce.
|
/// 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,
|
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.
|
||||||
|
gas_price: 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,
|
||||||
|
/// 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.
|
||||||
|
to: Option<Address>,
|
||||||
|
/// 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.
|
||||||
|
value: U256,
|
||||||
|
/// 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,
|
||||||
},
|
},
|
||||||
/// Transaction with priority fee.
|
/// Transaction with priority fee. https://eips.ethereum.org/EIPS/eip-1559
|
||||||
Eip1559 {
|
Eip1559 {
|
||||||
/// Nonce.
|
/// 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,
|
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.
|
||||||
|
max_fee_per_gas: u64,
|
||||||
|
/// Max Priority fee that transaction is paying
|
||||||
|
max_priority_fee_per_gas: 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.
|
||||||
|
to: Option<Address>,
|
||||||
|
/// 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.
|
||||||
|
value: U256,
|
||||||
|
/// 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,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Transaction {
|
||||||
|
/// Heavy operation that return hash over rlp encoded transaction.
|
||||||
|
/// It is only used for signature signing.
|
||||||
|
pub fn signature_hash(&self) -> TxHash {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Signed transaction.
|
/// Signed transaction.
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct TransactionSigned {
|
pub struct TransactionSigned {
|
||||||
transaction: Transaction,
|
transaction: Transaction,
|
||||||
|
hash: TxHash,
|
||||||
signature: Signature,
|
signature: Signature,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,9 +146,22 @@ impl AsRef<Transaction> for TransactionSigned {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Deref for TransactionSigned {
|
||||||
|
type Target = Transaction;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.transaction
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl TransactionSigned {
|
impl TransactionSigned {
|
||||||
/// Transaction signature.
|
/// Transaction signature.
|
||||||
pub fn signature(&self) -> &Signature {
|
pub fn signature(&self) -> &Signature {
|
||||||
&self.signature
|
&self.signature
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Transaction hash. Used to identify transaction.
|
||||||
|
pub fn hash(&self) -> TxHash {
|
||||||
|
self.hash
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,15 @@
|
|||||||
use crate::H256;
|
use crate::U256;
|
||||||
|
|
||||||
/// Signature still TODO
|
/// Signature TODO
|
||||||
#[derive(Debug, Clone)]
|
/// 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.
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct Signature {
|
pub struct Signature {
|
||||||
pub r: H256,
|
/// The R field of the signature; the point on the curve.
|
||||||
pub s: H256,
|
pub r: U256,
|
||||||
|
/// The S field of the signature; the point on the curve.
|
||||||
|
pub s: U256,
|
||||||
|
/// yParity: Signature Y parity; forma Ty
|
||||||
pub y_parity: u8,
|
pub y_parity: u8,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user