Skip to content

Commit

Permalink
feat(primitive): Signer recovery (#179)
Browse files Browse the repository at this point in the history
* feat(consensus): Signer recovery and tx validation

* Signature hash and use seckp256k1 over k256

* use deref_more for transactions

* cleanup and fix for eip1559 hash

* fix hash calculation on decoding
  • Loading branch information
rakita committed Nov 9, 2022
1 parent 836ad6a commit 9e35d58
Show file tree
Hide file tree
Showing 11 changed files with 357 additions and 78 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

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

4 changes: 3 additions & 1 deletion crates/consensus/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@ pub struct Config {
pub london_hard_fork_block: BlockNumber,
/// The Merge/Paris hard fork block number
pub paris_hard_fork_block: BlockNumber,
/// Blockchain identifier introduced in EIP-155: Simple replay attack protection
pub chain_id: u64,
}

impl Default for Config {
fn default() -> Self {
Self { london_hard_fork_block: 12965000, paris_hard_fork_block: 15537394 }
Self { london_hard_fork_block: 12965000, paris_hard_fork_block: 15537394, chain_id: 1 }
}
}
79 changes: 76 additions & 3 deletions crates/consensus/src/verification.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
//! ALl functions for verification of block
use crate::{config, Config};
use reth_interfaces::{consensus::Error, provider::HeaderProvider, Result as RethResult};
use reth_primitives::{BlockLocked, SealedHeader, TransactionSigned};
use reth_primitives::{
Account, Address, BlockLocked, SealedHeader, Transaction, TransactionSigned,
};
use std::time::SystemTime;

/// Validate header standalone
Expand Down Expand Up @@ -34,10 +36,81 @@ pub fn validate_header_standalone(

/// Validate transactions standlone
pub fn validate_transactions_standalone(
_transactions: &[TransactionSigned],
transaction: &Transaction,
config: &Config,
) -> Result<(), Error> {
let chain_id = match transaction {
Transaction::Legacy { chain_id, .. } => *chain_id,
Transaction::Eip2930 { chain_id, .. } => Some(*chain_id),
Transaction::Eip1559 { chain_id, max_fee_per_gas, max_priority_fee_per_gas, .. } => {
// EIP-1559: add more constraints to the tx validation
// https://github.com/ethereum/EIPs/pull/3594
if max_priority_fee_per_gas > max_fee_per_gas {
return Err(Error::TransactionPriorityFeeMoreThenMaxFee)
}
Some(*chain_id)
}
};
if let Some(chain_id) = chain_id {
if chain_id != config.chain_id {
return Err(Error::TransactionChainId)
}
}

// signature validation?

Ok(())
}

/// Validate transaction in regards to header
/// Only parametar from header that effects transaction is base_fee
pub fn validate_transaction_regarding_header(
transaction: &Transaction,
base_fee: Option<u64>,
) -> Result<(), Error> {
// check basefee and few checks that are related to that.
// https://github.com/ethereum/EIPs/pull/3594
if let Some(base_fee_per_gas) = base_fee {
if transaction.max_fee_per_gas() < base_fee_per_gas {
return Err(Error::TransactionMaxFeeLessThenBaseFee)
}
}

Ok(())
}

/// Account provider
pub trait AccountProvider {
/// Get basic account information.
fn basic_account(&self, address: Address) -> reth_interfaces::Result<Option<Account>>;
}

/// Validate transaction in regards of State
pub fn validate_transaction_regarding_state<AP: AccountProvider>(
_transaction: &TransactionSigned,
_config: &Config,
_account_provider: &AP,
) -> Result<(), Error> {
// TODO
// sanity check: if account has a bytecode. This is not allowed.s
// check nonce
// gas_price*gas_limit+value < account.balance

// let max_gas_cost = U512::from(message.gas_limit())
// * U512::from(ethereum_types::U256::from(message.max_fee_per_gas().to_be_bytes()));
// // See YP, Eq (57) in Section 6.2 "Execution"
// let v0 = max_gas_cost +
// U512::from(ethereum_types::U256::from(message.value().to_be_bytes()));
// let available_balance =
// ethereum_types::U256::from(self.state.get_balance(sender)?.to_be_bytes()).into();
// if available_balance < v0 {
// return Err(TransactionValidationError::Validation(
// BadTransactionError::InsufficientFunds {
// account: sender,
// available: available_balance,
// required: v0,
// },
// ));
// }
Ok(())
}

Expand Down
2 changes: 2 additions & 0 deletions crates/executor/src/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ impl Executor {
// create receipt
// bloom filter from logs

// Sum of the transaction’s gas limit and the gas utilized in this block prior

// Receipt outcome EIP-658: Embedding transaction status code in receipts
// EIP-658 supperseeded EIP-98 in Byzantium fork
}
Expand Down
7 changes: 6 additions & 1 deletion crates/interfaces/src/consensus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ pub enum Error {
TimestampIsInPast { parent_timestamp: u64, timestamp: u64 },
#[error("Block timestamp {timestamp:?} is in future in comparison of our clock time {present_timestamp:?}")]
TimestampIsInFuture { timestamp: u64, present_timestamp: u64 },
// TODO make better error msg :)
#[error("Child gas_limit {child_gas_limit:?} max increase is {parent_gas_limit}/1024")]
GasLimitInvalidIncrease { parent_gas_limit: u64, child_gas_limit: u64 },
#[error("Child gas_limit {child_gas_limit:?} max decrease is {parent_gas_limit}/1024")]
Expand All @@ -50,4 +49,10 @@ pub enum Error {
BaseFeeMissing,
#[error("Block base fee ({got:?}) is different then expected: ({expected:?})")]
BaseFeeDiff { expected: u64, got: u64 },
#[error("Transaction eip1559 priority fee is more then max fee")]
TransactionPriorityFeeMoreThenMaxFee,
#[error("Transaction chain_id does not match")]
TransactionChainId,
#[error("Transation max fee is less them block base fee")]
TransactionMaxFeeLessThenBaseFee,
}
4 changes: 2 additions & 2 deletions crates/net/eth-wire/src/types/transactions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -395,10 +395,10 @@ mod test {
};

// checking tx by tx for easier debugging if there are any regressions
for (expected, decoded) in
for (decoded, expected) in
decoded_transactions.message.0.iter().zip(expected_transactions.message.0.iter())
{
assert_eq!(expected, decoded);
assert_eq!(decoded, expected);
}

assert_eq!(decoded_transactions, expected_transactions);
Expand Down
6 changes: 6 additions & 0 deletions crates/primitives/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ ethers-core = { git = "https://github.com/gakonst/ethers-rs", default-features =
parity-scale-codec = { version = "3.2.1", features = ["derive", "bytes"] }
tiny-keccak = { version = "2.0", features = ["keccak"] }

# crypto
secp256k1 = { version = "0.24.0", default-features = false, features = ["alloc", "recovery"] }

#used for forkid
crc = "1"
maplit = "1"
Expand All @@ -29,6 +32,9 @@ sucds = "0.5.0"
arbitrary = { version = "1.1.7", features = ["derive"], optional = true}
hex = "0.4"
hex-literal = "0.3"
derive_more = "0.99"



[dev-dependencies]
arbitrary = { version = "1.1.7", features = ["derive"]}
Expand Down
5 changes: 4 additions & 1 deletion crates/primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ pub use log::Log;
pub use receipt::Receipt;
pub use storage::StorageEntry;
pub use transaction::{
AccessList, AccessListItem, Signature, Transaction, TransactionKind, TransactionSigned, TxType,
AccessList, AccessListItem, Signature, Transaction, TransactionKind, TransactionSigned,
TransactionSignedEcRecovered, TxType,
};

/// Block hash.
Expand All @@ -46,6 +47,8 @@ pub type BlockID = H256;
pub type TxHash = H256;
/// TxNumber is sequence number of all existing transactions
pub type TxNumber = u64;
/// Chain identifier type, introduced in EIP-155
pub type ChainId = u64;

/// Storage Key
pub type StorageKey = H256;
Expand Down

0 comments on commit 9e35d58

Please sign in to comment.