From adfa7502ad772df216f374b2dbd4057253625464 Mon Sep 17 00:00:00 2001 From: Shoham Chakraborty Date: Mon, 29 May 2023 15:58:53 +0800 Subject: [PATCH 01/16] Fix block gas limit --- lib/ain-evm/src/handler.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/ain-evm/src/handler.rs b/lib/ain-evm/src/handler.rs index f5e406d3ea..dbc035f936 100644 --- a/lib/ain-evm/src/handler.rs +++ b/lib/ain-evm/src/handler.rs @@ -9,7 +9,7 @@ use crate::traits::Executor; use crate::transaction::bridge::{BalanceUpdate, BridgeTx}; use crate::tx_queue::QueueTx; -use ethereum::{Block, PartialHeader, ReceiptV3}; +use ethereum::{Block, PartialHeader, ReceiptV3, TransactionV2}; use ethereum_types::{Bloom, H160, H64, U256}; use log::debug; use primitive_types::H256; @@ -55,6 +55,7 @@ impl Handlers { let mut failed_transactions = Vec::with_capacity(self.evm.tx_queues.len(context)); let mut receipts_v3: Vec = Vec::with_capacity(self.evm.tx_queues.len(context)); let mut gas_used = 0u64; + let mut total_gas_limit = 0u64; let mut logs_bloom: Bloom = Bloom::default(); let (parent_hash, parent_number) = self.block.get_latest_block_hash_and_number(); @@ -101,8 +102,11 @@ impl Handlers { failed_transactions.push(hex::encode(hash)); } - all_transactions.push(signed_tx); + all_transactions.push(signed_tx.clone()); + total_gas_limit += match signed_tx.transaction { + TransactionV2::Legacy(t) | TransactionV2::EIP2930(t) | TransactionV2::EIP1559(t) => {t.gas_limit} + }; gas_used += used_gas; EVMHandler::logs_bloom(logs, &mut logs_bloom); receipts_v3.push(receipt); @@ -148,7 +152,7 @@ impl Handlers { logs_bloom, difficulty: U256::from(difficulty), number: parent_number + 1, - gas_limit: U256::from(30_000_000), + gas_limit: U256::from(total_gas_limit), gas_used: U256::from(gas_used), timestamp, extra_data: Vec::default(), From 9d41baeb0ae3f058d6f7abcc4ab418f81ee7a3fa Mon Sep 17 00:00:00 2001 From: Shoham Chakraborty Date: Mon, 29 May 2023 16:05:43 +0800 Subject: [PATCH 02/16] Fix build --- lib/ain-evm/src/handler.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/ain-evm/src/handler.rs b/lib/ain-evm/src/handler.rs index dbc035f936..a241e0fdd5 100644 --- a/lib/ain-evm/src/handler.rs +++ b/lib/ain-evm/src/handler.rs @@ -55,7 +55,7 @@ impl Handlers { let mut failed_transactions = Vec::with_capacity(self.evm.tx_queues.len(context)); let mut receipts_v3: Vec = Vec::with_capacity(self.evm.tx_queues.len(context)); let mut gas_used = 0u64; - let mut total_gas_limit = 0u64; + let mut total_gas_limit = U256::zero(); let mut logs_bloom: Bloom = Bloom::default(); let (parent_hash, parent_number) = self.block.get_latest_block_hash_and_number(); @@ -105,7 +105,9 @@ impl Handlers { all_transactions.push(signed_tx.clone()); total_gas_limit += match signed_tx.transaction { - TransactionV2::Legacy(t) | TransactionV2::EIP2930(t) | TransactionV2::EIP1559(t) => {t.gas_limit} + TransactionV2::Legacy(t) => t.gas_limit, + TransactionV2::EIP2930(t) => t.gas_limit, + TransactionV2::EIP1559(t) => t.gas_limit, }; gas_used += used_gas; EVMHandler::logs_bloom(logs, &mut logs_bloom); @@ -152,7 +154,7 @@ impl Handlers { logs_bloom, difficulty: U256::from(difficulty), number: parent_number + 1, - gas_limit: U256::from(total_gas_limit), + gas_limit: total_gas_limit, gas_used: U256::from(gas_used), timestamp, extra_data: Vec::default(), From 03cb99fd71f3c2b606f2f90d4fb99f3af0d43e3d Mon Sep 17 00:00:00 2001 From: Shoham Chakraborty Date: Mon, 29 May 2023 16:38:31 +0800 Subject: [PATCH 03/16] Add base_fee_per_gas to block output --- lib/ain-evm/src/block.rs | 3 ++- lib/ain-evm/src/handler.rs | 4 +++- lib/ain-evm/src/storage/cache.rs | 13 +++++++++++++ lib/ain-evm/src/storage/data_handler.rs | 14 ++++++++++++++ lib/ain-evm/src/storage/mod.rs | 15 +++++++++++++++ lib/ain-evm/src/storage/traits.rs | 3 +++ lib/ain-grpc/src/block.rs | 4 +++- lib/ain-grpc/src/rpc/eth.rs | 6 ++++-- 8 files changed, 57 insertions(+), 5 deletions(-) diff --git a/lib/ain-evm/src/block.rs b/lib/ain-evm/src/block.rs index e3f00f3a93..c11d06c865 100644 --- a/lib/ain-evm/src/block.rs +++ b/lib/ain-evm/src/block.rs @@ -29,8 +29,9 @@ impl BlockHandler { .unwrap_or_default() } - pub fn connect_block(&self, block: BlockAny) { + pub fn connect_block(&self, block: BlockAny, base_fee: U256) { self.storage.put_latest_block(Some(&block)); self.storage.put_block(&block); + self.storage.set_base_fee(block.header.hash(), base_fee); } } diff --git a/lib/ain-evm/src/handler.rs b/lib/ain-evm/src/handler.rs index a241e0fdd5..ae6ee869bf 100644 --- a/lib/ain-evm/src/handler.rs +++ b/lib/ain-evm/src/handler.rs @@ -175,12 +175,14 @@ impl Handlers { block.header.number, ); + // calculate base fee + if update_state { debug!( "[finalize_block] Finalizing block number {:#x}, state_root {:#x}", block.header.number, block.header.state_root ); - self.block.connect_block(block.clone()); + self.block.connect_block(block.clone(), U256::zero()); // TODO: replace with base fee self.receipt.put_receipts(receipts); } diff --git a/lib/ain-evm/src/storage/cache.rs b/lib/ain-evm/src/storage/cache.rs index 2885f0bc22..9c516d8c4e 100644 --- a/lib/ain-evm/src/storage/cache.rs +++ b/lib/ain-evm/src/storage/cache.rs @@ -12,6 +12,7 @@ pub struct Cache { transactions: RwLock>, blocks: RwLock>, block_hashes: RwLock>, + base_fee: RwLock>, latest_block: RwLock>, } @@ -29,6 +30,9 @@ impl Cache { block_hashes: RwLock::new(LruCache::new( NonZeroUsize::new(cache_size.unwrap_or(Self::DEFAULT_CACHE_SIZE)).unwrap(), )), + base_fee: RwLock::new(LruCache::new( + NonZeroUsize::new(cache_size.unwrap_or(Self::DEFAULT_CACHE_SIZE)).unwrap(), + )), latest_block: RwLock::new(None), } } @@ -75,6 +79,15 @@ impl BlockStorage for Cache { let mut cache = self.latest_block.write().unwrap(); *cache = block.cloned(); } + + fn get_base_fee(&self, block_hash: &H256) -> Option { + self.base_fee.write().unwrap().get(block_hash).map(ToOwned::to_owned) + } + + fn set_base_fee(&self, block_hash: H256, base_fee: U256) { + let mut cache = self.base_fee.write().unwrap(); + cache.put(block_hash, base_fee); + } } impl TransactionStorage for Cache { diff --git a/lib/ain-evm/src/storage/data_handler.rs b/lib/ain-evm/src/storage/data_handler.rs index 9e74f651da..30ccba1d9b 100644 --- a/lib/ain-evm/src/storage/data_handler.rs +++ b/lib/ain-evm/src/storage/data_handler.rs @@ -20,12 +20,14 @@ pub static LATEST_BLOCK_DATA_PATH: &str = "latest_block_data.bin"; pub static RECEIPT_MAP_PATH: &str = "receipt_map.bin"; pub static CODE_MAP_PATH: &str = "code_map.bin"; pub static TRANSACTION_DATA_PATH: &str = "transaction_data.bin"; +pub static BASE_FEE_MAP_PATH: &str = "base_fee_map.bin"; type BlockHashtoBlock = HashMap; type Blocks = HashMap; type TxHashToTx = HashMap; type LatestBlockNumber = U256; type TransactionHashToReceipt = HashMap; +type BlockHashtoBaseFee = HashMap; impl PersistentState for BlockHashtoBlock {} impl PersistentState for Blocks {} @@ -43,6 +45,7 @@ pub struct BlockchainDataHandler { block_map: RwLock, blocks: RwLock, latest_block_number: RwLock>, + base_fee_map: RwLock, code_map: RwLock, } @@ -68,6 +71,7 @@ impl BlockchainDataHandler { TransactionHashToReceipt::load_from_disk(RECEIPT_MAP_PATH) .expect("Error loading receipts data"), ), + base_fee_map: RwLock::new(BlockHashtoBaseFee::load_from_disk(BASE_FEE_MAP_PATH).unwrap_or_default()), code_map: RwLock::new(CodeHistory::load_from_disk(CODE_MAP_PATH).unwrap_or_default()), } } @@ -169,6 +173,15 @@ impl BlockStorage for BlockchainDataHandler { let mut latest_block_number = self.latest_block_number.write().unwrap(); *latest_block_number = block.map(|b| b.header.number); } + + fn get_base_fee(&self, block_hash: &H256) -> Option { + self.base_fee_map.read().unwrap().get(block_hash).map(ToOwned::to_owned) + } + + fn set_base_fee(&self, block_hash: H256, base_fee: U256) { + let mut base_fee_map = self.base_fee_map.write().unwrap(); + base_fee_map.insert(block_hash, base_fee); + } } impl ReceiptStorage for BlockchainDataHandler { @@ -243,6 +256,7 @@ impl Rollback for BlockchainDataHandler { } self.block_map.write().unwrap().remove(&block.header.hash()); + self.base_fee_map.write().unwrap().remove(&block.header.hash()); self.blocks.write().unwrap().remove(&block.header.number); self.code_map.write().unwrap().rollback(block.header.number); diff --git a/lib/ain-evm/src/storage/mod.rs b/lib/ain-evm/src/storage/mod.rs index 90a3457e50..bf4e510bf5 100644 --- a/lib/ain-evm/src/storage/mod.rs +++ b/lib/ain-evm/src/storage/mod.rs @@ -78,6 +78,21 @@ impl BlockStorage for Storage { self.cache.put_latest_block(block); self.blockchain_data_handler.put_latest_block(block); } + + fn get_base_fee(&self, block_hash: &H256) -> Option { + self.cache.get_base_fee(block_hash).or_else(|| { + let base_fee = self.blockchain_data_handler.get_base_fee(block_hash); + if let Some(base_fee) = base_fee { + self.cache.set_base_fee(*block_hash, base_fee); + } + base_fee + }) + } + + fn set_base_fee(&self, block_hash: H256, base_fee: U256) { + self.cache.set_base_fee(block_hash, base_fee); + self.blockchain_data_handler.set_base_fee(block_hash, base_fee); + } } impl TransactionStorage for Storage { diff --git a/lib/ain-evm/src/storage/traits.rs b/lib/ain-evm/src/storage/traits.rs index a893adffc9..e43d86625b 100644 --- a/lib/ain-evm/src/storage/traits.rs +++ b/lib/ain-evm/src/storage/traits.rs @@ -18,6 +18,9 @@ pub trait BlockStorage { fn put_block(&self, block: &BlockAny); fn get_latest_block(&self) -> Option; fn put_latest_block(&self, block: Option<&BlockAny>); + + fn get_base_fee(&self, block_hash: &H256) -> Option; + fn set_base_fee(&self, block_hash: H256, base_fee: U256); } pub trait TransactionStorage { diff --git a/lib/ain-grpc/src/block.rs b/lib/ain-grpc/src/block.rs index 28ecdb6dfb..b8761c6eb0 100644 --- a/lib/ain-grpc/src/block.rs +++ b/lib/ain-grpc/src/block.rs @@ -31,10 +31,11 @@ pub struct RpcBlock { pub sha3_uncles: H256, pub logs_bloom: String, pub size: String, + pub base_fee_per_gas: U256, } impl RpcBlock { - pub fn from_block_with_tx(block: BlockAny, full_transactions: bool) -> Self { + pub fn from_block_with_tx(block: BlockAny, full_transactions: bool, base_fee: U256) -> Self { let header_size = block.header.rlp_bytes().len(); RpcBlock { hash: block.header.hash(), @@ -77,6 +78,7 @@ impl RpcBlock { sha3_uncles: H256::default(), logs_bloom: format!("{:#x}", block.header.logs_bloom), size: format!("{header_size:#x}"), + base_fee_per_gas: base_fee } } } diff --git a/lib/ain-grpc/src/rpc/eth.rs b/lib/ain-grpc/src/rpc/eth.rs index 3d2ff0c217..531e3f38e6 100644 --- a/lib/ain-grpc/src/rpc/eth.rs +++ b/lib/ain-grpc/src/rpc/eth.rs @@ -341,8 +341,9 @@ impl MetachainRPCServer for MetachainRPCModule { .get_block_by_hash(&hash) .map_or(Ok(None), |block| { Ok(Some(RpcBlock::from_block_with_tx( - block, + block.clone(), full_transactions.unwrap_or_default(), + self.handler.storage.get_base_fee(&hash).unwrap_or_default() ))) }) } @@ -382,8 +383,9 @@ impl MetachainRPCServer for MetachainRPCModule { .get_block_by_number(&block_number) .map_or(Ok(None), |block| { Ok(Some(RpcBlock::from_block_with_tx( - block, + block.clone(), full_transactions.unwrap_or_default(), + self.handler.storage.get_base_fee(&block.header.hash()).unwrap_or_default() ))) }) } From 010021199054fa63886cca914dfc574da0623d2d Mon Sep 17 00:00:00 2001 From: Shoham Chakraborty Date: Mon, 29 May 2023 16:39:02 +0800 Subject: [PATCH 04/16] Formatting --- lib/ain-evm/src/storage/cache.rs | 6 +++++- lib/ain-evm/src/storage/data_handler.rs | 15 ++++++++++++--- lib/ain-evm/src/storage/mod.rs | 3 ++- lib/ain-grpc/src/block.rs | 2 +- lib/ain-grpc/src/rpc/eth.rs | 7 +++++-- 5 files changed, 25 insertions(+), 8 deletions(-) diff --git a/lib/ain-evm/src/storage/cache.rs b/lib/ain-evm/src/storage/cache.rs index 9c516d8c4e..02d4859ecc 100644 --- a/lib/ain-evm/src/storage/cache.rs +++ b/lib/ain-evm/src/storage/cache.rs @@ -81,7 +81,11 @@ impl BlockStorage for Cache { } fn get_base_fee(&self, block_hash: &H256) -> Option { - self.base_fee.write().unwrap().get(block_hash).map(ToOwned::to_owned) + self.base_fee + .write() + .unwrap() + .get(block_hash) + .map(ToOwned::to_owned) } fn set_base_fee(&self, block_hash: H256, base_fee: U256) { diff --git a/lib/ain-evm/src/storage/data_handler.rs b/lib/ain-evm/src/storage/data_handler.rs index 30ccba1d9b..bdf7a2ab6e 100644 --- a/lib/ain-evm/src/storage/data_handler.rs +++ b/lib/ain-evm/src/storage/data_handler.rs @@ -71,7 +71,9 @@ impl BlockchainDataHandler { TransactionHashToReceipt::load_from_disk(RECEIPT_MAP_PATH) .expect("Error loading receipts data"), ), - base_fee_map: RwLock::new(BlockHashtoBaseFee::load_from_disk(BASE_FEE_MAP_PATH).unwrap_or_default()), + base_fee_map: RwLock::new( + BlockHashtoBaseFee::load_from_disk(BASE_FEE_MAP_PATH).unwrap_or_default(), + ), code_map: RwLock::new(CodeHistory::load_from_disk(CODE_MAP_PATH).unwrap_or_default()), } } @@ -175,7 +177,11 @@ impl BlockStorage for BlockchainDataHandler { } fn get_base_fee(&self, block_hash: &H256) -> Option { - self.base_fee_map.read().unwrap().get(block_hash).map(ToOwned::to_owned) + self.base_fee_map + .read() + .unwrap() + .get(block_hash) + .map(ToOwned::to_owned) } fn set_base_fee(&self, block_hash: H256, base_fee: U256) { @@ -256,7 +262,10 @@ impl Rollback for BlockchainDataHandler { } self.block_map.write().unwrap().remove(&block.header.hash()); - self.base_fee_map.write().unwrap().remove(&block.header.hash()); + self.base_fee_map + .write() + .unwrap() + .remove(&block.header.hash()); self.blocks.write().unwrap().remove(&block.header.number); self.code_map.write().unwrap().rollback(block.header.number); diff --git a/lib/ain-evm/src/storage/mod.rs b/lib/ain-evm/src/storage/mod.rs index bf4e510bf5..4bec3b79ed 100644 --- a/lib/ain-evm/src/storage/mod.rs +++ b/lib/ain-evm/src/storage/mod.rs @@ -91,7 +91,8 @@ impl BlockStorage for Storage { fn set_base_fee(&self, block_hash: H256, base_fee: U256) { self.cache.set_base_fee(block_hash, base_fee); - self.blockchain_data_handler.set_base_fee(block_hash, base_fee); + self.blockchain_data_handler + .set_base_fee(block_hash, base_fee); } } diff --git a/lib/ain-grpc/src/block.rs b/lib/ain-grpc/src/block.rs index b8761c6eb0..94163e92fd 100644 --- a/lib/ain-grpc/src/block.rs +++ b/lib/ain-grpc/src/block.rs @@ -78,7 +78,7 @@ impl RpcBlock { sha3_uncles: H256::default(), logs_bloom: format!("{:#x}", block.header.logs_bloom), size: format!("{header_size:#x}"), - base_fee_per_gas: base_fee + base_fee_per_gas: base_fee, } } } diff --git a/lib/ain-grpc/src/rpc/eth.rs b/lib/ain-grpc/src/rpc/eth.rs index 531e3f38e6..7e54520863 100644 --- a/lib/ain-grpc/src/rpc/eth.rs +++ b/lib/ain-grpc/src/rpc/eth.rs @@ -343,7 +343,7 @@ impl MetachainRPCServer for MetachainRPCModule { Ok(Some(RpcBlock::from_block_with_tx( block.clone(), full_transactions.unwrap_or_default(), - self.handler.storage.get_base_fee(&hash).unwrap_or_default() + self.handler.storage.get_base_fee(&hash).unwrap_or_default(), ))) }) } @@ -385,7 +385,10 @@ impl MetachainRPCServer for MetachainRPCModule { Ok(Some(RpcBlock::from_block_with_tx( block.clone(), full_transactions.unwrap_or_default(), - self.handler.storage.get_base_fee(&block.header.hash()).unwrap_or_default() + self.handler + .storage + .get_base_fee(&block.header.hash()) + .unwrap_or_default(), ))) }) } From 0546ea4f76196e606c2f6c78a2a37ff4a7226432 Mon Sep 17 00:00:00 2001 From: Shoham Chakraborty Date: Mon, 29 May 2023 17:45:10 +0800 Subject: [PATCH 05/16] Calculate base fee --- lib/ain-evm/src/block.rs | 47 ++++++++++++++++++++++++++++++++++++++ lib/ain-evm/src/handler.rs | 3 ++- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/lib/ain-evm/src/block.rs b/lib/ain-evm/src/block.rs index c11d06c865..30dbabc692 100644 --- a/lib/ain-evm/src/block.rs +++ b/lib/ain-evm/src/block.rs @@ -1,6 +1,7 @@ use ethereum::BlockAny; use keccak_hash::H256; use primitive_types::U256; +use std::cmp::max; use std::sync::Arc; use crate::storage::{traits::BlockStorage, Storage}; @@ -34,4 +35,50 @@ impl BlockHandler { self.storage.put_block(&block); self.storage.set_base_fee(block.header.hash(), base_fee); } + + pub fn calculate_base_fee(&self, parent_hash: H256) -> U256 { + // constants + let initial_base_fee: U256 = U256::from(1_000_000_000); // wei + let base_fee_max_change_denominator: U256 = U256::from(8); + let elasticity_multiplier: U256 = U256::from(2); + + // first block has 1 gwei base fee + if parent_hash == H256::zero() { + return initial_base_fee; + } + + // get parent gas usage, + // https://eips.ethereum.org/EIPS/eip-1559#:~:text=fee%20is%20correct-,if%20INITIAL_FORK_BLOCK_NUMBER%20%3D%3D%20block.number%3A,-expected_base_fee_per_gas%20%3D%20INITIAL_BASE_FEE + let parent_block = self + .storage + .get_block_by_hash(&parent_hash) + .expect("Parent block not found"); + let parent_base_fee = self + .storage + .get_base_fee(&parent_block.header.hash()) + .expect("Parent base fee not found"); + let parent_gas_used = parent_block.header.gas_used; + let parent_gas_target = parent_block.header.gas_limit / elasticity_multiplier; + + return if parent_gas_used == parent_gas_target { + parent_base_fee + } else if parent_gas_used > parent_gas_target { + let gas_used_delta = parent_gas_used - parent_gas_target; + let base_fee_per_gas_delta = max( + parent_base_fee * gas_used_delta + / parent_gas_target + / base_fee_max_change_denominator, + U256::from(1), + ); + + parent_base_fee + base_fee_per_gas_delta + } else { + let gas_used_delta = parent_gas_target - parent_gas_used; + let base_fee_per_gas_delta = parent_base_fee * gas_used_delta + / parent_gas_target + / base_fee_max_change_denominator; + + parent_base_fee - base_fee_per_gas_delta + }; + } } diff --git a/lib/ain-evm/src/handler.rs b/lib/ain-evm/src/handler.rs index ae6ee869bf..bc18202853 100644 --- a/lib/ain-evm/src/handler.rs +++ b/lib/ain-evm/src/handler.rs @@ -176,13 +176,14 @@ impl Handlers { ); // calculate base fee + let base_fee = self.block.calculate_base_fee(parent_hash); if update_state { debug!( "[finalize_block] Finalizing block number {:#x}, state_root {:#x}", block.header.number, block.header.state_root ); - self.block.connect_block(block.clone(), U256::zero()); // TODO: replace with base fee + self.block.connect_block(block.clone(), base_fee); self.receipt.put_receipts(receipts); } From fd1a244ce08f80ce9593283f122564a7a5ca7d6e Mon Sep 17 00:00:00 2001 From: Shoham Chakraborty Date: Tue, 30 May 2023 14:15:43 +0800 Subject: [PATCH 06/16] Save base fee map --- lib/ain-evm/src/storage/data_handler.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/ain-evm/src/storage/data_handler.rs b/lib/ain-evm/src/storage/data_handler.rs index bdf7a2ab6e..44e72d8f16 100644 --- a/lib/ain-evm/src/storage/data_handler.rs +++ b/lib/ain-evm/src/storage/data_handler.rs @@ -223,7 +223,8 @@ impl FlushableStorage for BlockchainDataHandler { .write() .unwrap() .save_to_disk(TRANSACTION_DATA_PATH)?; - self.code_map.write().unwrap().save_to_disk(CODE_MAP_PATH) + self.code_map.write().unwrap().save_to_disk(CODE_MAP_PATH)?; + self.base_fee_map.write().unwrap().save_to_disk(BASE_FEE_MAP_PATH) } } From c2a37813b08618ffcecd5f2eb39195f0d2c86984 Mon Sep 17 00:00:00 2001 From: Shoham Chakraborty Date: Tue, 30 May 2023 14:15:54 +0800 Subject: [PATCH 07/16] eth_feeHistory implementation --- lib/Cargo.lock | 120 ++++++++++++++++++++++++++++++++++++ lib/ain-evm/Cargo.toml | 1 + lib/ain-evm/src/block.rs | 120 +++++++++++++++++++++++++++++++++++- lib/ain-evm/src/lib.rs | 2 +- lib/ain-grpc/src/block.rs | 21 +++++++ lib/ain-grpc/src/rpc/eth.rs | 10 ++- 6 files changed, 271 insertions(+), 3 deletions(-) diff --git a/lib/Cargo.lock b/lib/Cargo.lock index 8369db2905..ddd21e6049 100644 --- a/lib/Cargo.lock +++ b/lib/Cargo.lock @@ -115,6 +115,7 @@ dependencies = [ "serde", "sha3", "sp-core", + "statrs", "tempdir", "tokio", "vsdb_core", @@ -204,6 +205,15 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33954243bd79057c2de7338850b85983a44588021f8a5fee574a8888c6de4344" +[[package]] +name = "approx" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" +dependencies = [ + "num-traits", +] + [[package]] name = "array-bytes" version = "4.2.0" @@ -3526,6 +3536,16 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b87248edafb776e59e6ee64a79086f65890d3510f2c656c000bf2a7e8a0aea40" +[[package]] +name = "matrixmultiply" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "090126dc04f95dc0d1c1c91f61bdd474b3930ca064c1edc8a849da2c6cbe1e77" +dependencies = [ + "autocfg", + "rawpointer", +] + [[package]] name = "memchr" version = "2.5.0" @@ -3672,6 +3692,35 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" +[[package]] +name = "nalgebra" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d506eb7e08d6329505faa8a3a00a5dcc6de9f76e0c77e4b75763ae3c770831ff" +dependencies = [ + "approx", + "matrixmultiply", + "nalgebra-macros", + "num-complex", + "num-rational", + "num-traits", + "rand 0.8.5", + "rand_distr", + "simba", + "typenum", +] + +[[package]] +name = "nalgebra-macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01fcc0b8149b4632adc89ac3b7b31a12fb6099a0317a4eb2ebff574ef7de7218" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "ndk" version = "0.6.0" @@ -3766,6 +3815,15 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-complex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e0d21255c828d6f128a1e41534206671e8c3ea0c62f32291e808dc82cff17d" +dependencies = [ + "num-traits", +] + [[package]] name = "num-format" version = "0.4.4" @@ -3805,6 +3863,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -4466,6 +4525,16 @@ dependencies = [ "getrandom 0.2.9", ] +[[package]] +name = "rand_distr" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" +dependencies = [ + "num-traits", + "rand 0.8.5", +] + [[package]] name = "rand_hc" version = "0.2.0" @@ -4490,6 +4559,12 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" +[[package]] +name = "rawpointer" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" + [[package]] name = "rdrand" version = "0.4.0" @@ -4768,6 +4843,15 @@ version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +[[package]] +name = "safe_arch" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "794821e4ccb0d9f979512f9c1973480123f9bd62a90d74ab0f9426fcf8f4a529" +dependencies = [ + "bytemuck", +] + [[package]] name = "same-file" version = "1.0.6" @@ -5112,6 +5196,19 @@ dependencies = [ "libc", ] +[[package]] +name = "simba" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0b7840f121a46d63066ee7a99fc81dcabbc6105e437cae43528cea199b5a05f" +dependencies = [ + "approx", + "num-complex", + "num-traits", + "paste", + "wide", +] + [[package]] name = "simd-adler32" version = "0.3.5" @@ -5451,6 +5548,19 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "statrs" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d08e5e1748192713cc281da8b16924fb46be7b0c2431854eadc785823e5696e" +dependencies = [ + "approx", + "lazy_static", + "nalgebra", + "num-traits", + "rand 0.8.5", +] + [[package]] name = "stretch2" version = "0.4.3" @@ -6831,6 +6941,16 @@ dependencies = [ "once_cell", ] +[[package]] +name = "wide" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cd0496a71f3cc6bc4bf0ed91346426a5099e93d89807e663162dc5a1069ff65" +dependencies = [ + "bytemuck", + "safe_arch", +] + [[package]] name = "winapi" version = "0.3.9" diff --git a/lib/ain-evm/Cargo.toml b/lib/ain-evm/Cargo.toml index a0f6c5f619..d0dd4e9bc6 100644 --- a/lib/ain-evm/Cargo.toml +++ b/lib/ain-evm/Cargo.toml @@ -22,6 +22,7 @@ keccak-hash = "0.10.0" serde = { version = "1.0", features = ["derive"] } ethbloom = "0.13.0" ethereum-types = "0.14.1" +statrs = "0.16.0" # Trie dependencies hash-db = "0.16.0" diff --git a/lib/ain-evm/src/block.rs b/lib/ain-evm/src/block.rs index 30dbabc692..681b29eaac 100644 --- a/lib/ain-evm/src/block.rs +++ b/lib/ain-evm/src/block.rs @@ -1,8 +1,10 @@ -use ethereum::BlockAny; +use ethereum::{BlockAny, TransactionAny}; use keccak_hash::H256; use primitive_types::U256; use std::cmp::max; use std::sync::Arc; +use log::debug; +use statrs::statistics::{Data, OrderStatistics}; use crate::storage::{traits::BlockStorage, Storage}; @@ -10,6 +12,13 @@ pub struct BlockHandler { storage: Arc, } +pub struct FeeHistoryData { + pub oldest_block: H256, + pub base_fee_per_gas: Vec, + pub gas_used_ratio: Vec, + pub reward: Option>>, +} + impl BlockHandler { pub fn new(storage: Arc) -> Self { Self { storage } @@ -81,4 +90,113 @@ impl BlockHandler { parent_base_fee - base_fee_per_gas_delta }; } + + pub fn fee_history( + &self, + block_count: usize, + first_block: U256, + descending: bool, + priority_fee_percentile: Vec, + ) -> FeeHistoryData { + let mut blocks = Vec::with_capacity(block_count); + let mut block_number = first_block; + + for _ in 0..=block_count { + blocks.push( + self.storage + .get_block_by_number(&block_number) + .expect(&format!("Block {} out of range", block_number)), + ); + + match descending { + true => block_number -= U256::from(1), + false => block_number += U256::from(1), + } + } + + let oldest_block = match descending { + true => blocks.last().unwrap().header.hash(), + false => blocks.first().unwrap().header.hash(), + }; + + let (base_fee_per_gas, gas_used_ratio): (Vec, Vec) = blocks + .iter() + .map(|block| { + debug!("Processing block {}", block.header.number); + let base_fee = self + .storage + .get_base_fee(&block.header.hash()) + .expect(&format!("No base fee for block {}", block.header.number)); + + let gas_ratio = if block.header.gas_limit == U256::zero() { + f64::default() // empty block + } else { + block.header.gas_used.as_u64() as f64 / block.header.gas_limit.as_u64() as f64 + }; + + return (base_fee, gas_ratio); + }) + .unzip(); + + let reward = if priority_fee_percentile.len() == 0 { + None + } else { + let mut eip_transactions = Vec::new(); + + for block in blocks { + let mut block_eip_transaction = Vec::new(); + for tx in block.transactions { + match tx { + TransactionAny::Legacy(_) | TransactionAny::EIP2930(_) => { + continue; + } + TransactionAny::EIP1559(t) => { + block_eip_transaction.push(t); + } + } + } + block_eip_transaction + .sort_by(|a, b| a.max_priority_fee_per_gas.cmp(&b.max_priority_fee_per_gas)); + eip_transactions.push(block_eip_transaction); + } + + /* + TODO: assumption here is that max priority fee = priority fee paid, however + priority fee can be lower if gas costs hit max_fee_per_gas. + we will need to check the base fee paid to get the actual priority fee paid + */ + + let mut reward = Vec::new(); + + for block_eip_tx in eip_transactions { + if block_eip_tx.is_empty() { + reward.push(vec![U256::zero()]); + continue; + } + + let mut block_rewards = Vec::new(); + let priority_fees = block_eip_tx.iter().map(|tx| tx.max_priority_fee_per_gas.as_u64() as f64).collect::>(); + let mut data = Data::new(priority_fees); + + for pct in priority_fee_percentile.iter() { + block_rewards.push(U256::from(data.percentile(*pct).ceil() as u64)); + } + + reward.push(block_rewards); + } + + Some(reward) + }; + + for x in gas_used_ratio.iter() { + debug!("used ratio: {}", x); + } + + return FeeHistoryData { + oldest_block, + base_fee_per_gas, + gas_used_ratio, + reward, + }; + } } diff --git a/lib/ain-evm/src/lib.rs b/lib/ain-evm/src/lib.rs index f9e24b4227..18561b9e9b 100644 --- a/lib/ain-evm/src/lib.rs +++ b/lib/ain-evm/src/lib.rs @@ -1,5 +1,5 @@ mod backend; -mod block; +pub mod block; mod ecrecover; pub mod evm; pub mod executor; diff --git a/lib/ain-grpc/src/block.rs b/lib/ain-grpc/src/block.rs index 94163e92fd..7b0f57fbf3 100644 --- a/lib/ain-grpc/src/block.rs +++ b/lib/ain-grpc/src/block.rs @@ -252,6 +252,7 @@ impl<'a> Visitor<'a> for BlockNumberVisitor { } use std::str::FromStr; +use ain_evm::block::FeeHistoryData; use crate::codegen::types::EthTransactionInfo; @@ -325,3 +326,23 @@ impl Serialize for BlockTransactions { } } } + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] +#[serde(rename_all = "camelCase")] +pub struct RpcFeeHistory { + pub oldest_block: H256, + pub base_fee_per_gas: Vec, + pub gas_used_ratio: Vec, + pub reward: Option>>, +} + +impl From for RpcFeeHistory { + fn from(value: FeeHistoryData) -> Self { + Self { + oldest_block: value.oldest_block, + base_fee_per_gas: value.base_fee_per_gas, + gas_used_ratio: value.gas_used_ratio, + reward: value.reward, + } + } +} \ No newline at end of file diff --git a/lib/ain-grpc/src/rpc/eth.rs b/lib/ain-grpc/src/rpc/eth.rs index 7e54520863..097e51e905 100644 --- a/lib/ain-grpc/src/rpc/eth.rs +++ b/lib/ain-grpc/src/rpc/eth.rs @@ -1,4 +1,4 @@ -use crate::block::{BlockNumber, RpcBlock}; +use crate::block::{BlockNumber, RpcBlock, RpcFeeHistory}; use crate::bytes::Bytes; use crate::call_request::CallRequest; use crate::codegen::types::EthTransactionInfo; @@ -8,6 +8,7 @@ use crate::transaction_request::{TransactionMessage, TransactionRequest}; use ain_cpp_imports::get_eth_priv_key; use ain_evm::executor::TxResponse; use ain_evm::handler::Handlers; +use ain_evm::block::FeeHistoryData; use ain_evm::storage::traits::{BlockStorage, ReceiptStorage, TransactionStorage}; use ain_evm::transaction::{SignedTx, TransactionError}; @@ -192,6 +193,9 @@ pub trait MetachainRPC { /// Returns current gas_price. #[method(name = "gasPrice")] fn gas_price(&self) -> RpcResult; + + #[method(name = "feeHistory")] + fn fee_history(&self, block_count: usize, first_block: U256, descending: bool, priority_fee_percentile: Vec) -> RpcResult; } pub struct MetachainRPCModule { @@ -672,6 +676,10 @@ impl MetachainRPCServer for MetachainRPCModule { fn eth_submithashrate(&self, _hashrate: String, _id: String) -> RpcResult { Ok(false) } + + fn fee_history(&self, block_count: usize, first_block: U256, descending: bool, priority_fee_percentile: Vec) -> RpcResult { + Ok(RpcFeeHistory::from(self.handler.block.fee_history(block_count, first_block, true, priority_fee_percentile))) + } } fn sign( From bbc6c24d7e7bf68e3167a31db80145e350e0047a Mon Sep 17 00:00:00 2001 From: Shoham Chakraborty Date: Tue, 30 May 2023 14:16:28 +0800 Subject: [PATCH 08/16] Formatting --- lib/ain-evm/src/block.rs | 9 ++++++--- lib/ain-evm/src/storage/data_handler.rs | 5 ++++- lib/ain-grpc/src/block.rs | 4 ++-- lib/ain-grpc/src/rpc/eth.rs | 25 +++++++++++++++++++++---- 4 files changed, 33 insertions(+), 10 deletions(-) diff --git a/lib/ain-evm/src/block.rs b/lib/ain-evm/src/block.rs index 681b29eaac..b06ce25077 100644 --- a/lib/ain-evm/src/block.rs +++ b/lib/ain-evm/src/block.rs @@ -1,10 +1,10 @@ use ethereum::{BlockAny, TransactionAny}; use keccak_hash::H256; +use log::debug; use primitive_types::U256; +use statrs::statistics::{Data, OrderStatistics}; use std::cmp::max; use std::sync::Arc; -use log::debug; -use statrs::statistics::{Data, OrderStatistics}; use crate::storage::{traits::BlockStorage, Storage}; @@ -175,7 +175,10 @@ impl BlockHandler { } let mut block_rewards = Vec::new(); - let priority_fees = block_eip_tx.iter().map(|tx| tx.max_priority_fee_per_gas.as_u64() as f64).collect::>(); + let priority_fees = block_eip_tx + .iter() + .map(|tx| tx.max_priority_fee_per_gas.as_u64() as f64) + .collect::>(); let mut data = Data::new(priority_fees); for pct in priority_fee_percentile.iter() { diff --git a/lib/ain-evm/src/storage/data_handler.rs b/lib/ain-evm/src/storage/data_handler.rs index 44e72d8f16..f4f2ba2cff 100644 --- a/lib/ain-evm/src/storage/data_handler.rs +++ b/lib/ain-evm/src/storage/data_handler.rs @@ -224,7 +224,10 @@ impl FlushableStorage for BlockchainDataHandler { .unwrap() .save_to_disk(TRANSACTION_DATA_PATH)?; self.code_map.write().unwrap().save_to_disk(CODE_MAP_PATH)?; - self.base_fee_map.write().unwrap().save_to_disk(BASE_FEE_MAP_PATH) + self.base_fee_map + .write() + .unwrap() + .save_to_disk(BASE_FEE_MAP_PATH) } } diff --git a/lib/ain-grpc/src/block.rs b/lib/ain-grpc/src/block.rs index 7b0f57fbf3..e45c88fa88 100644 --- a/lib/ain-grpc/src/block.rs +++ b/lib/ain-grpc/src/block.rs @@ -251,8 +251,8 @@ impl<'a> Visitor<'a> for BlockNumberVisitor { } } -use std::str::FromStr; use ain_evm::block::FeeHistoryData; +use std::str::FromStr; use crate::codegen::types::EthTransactionInfo; @@ -345,4 +345,4 @@ impl From for RpcFeeHistory { reward: value.reward, } } -} \ No newline at end of file +} diff --git a/lib/ain-grpc/src/rpc/eth.rs b/lib/ain-grpc/src/rpc/eth.rs index 097e51e905..86b4e3d652 100644 --- a/lib/ain-grpc/src/rpc/eth.rs +++ b/lib/ain-grpc/src/rpc/eth.rs @@ -6,9 +6,9 @@ use crate::codegen::types::EthTransactionInfo; use crate::receipt::ReceiptResult; use crate::transaction_request::{TransactionMessage, TransactionRequest}; use ain_cpp_imports::get_eth_priv_key; +use ain_evm::block::FeeHistoryData; use ain_evm::executor::TxResponse; use ain_evm::handler::Handlers; -use ain_evm::block::FeeHistoryData; use ain_evm::storage::traits::{BlockStorage, ReceiptStorage, TransactionStorage}; use ain_evm::transaction::{SignedTx, TransactionError}; @@ -195,7 +195,13 @@ pub trait MetachainRPC { fn gas_price(&self) -> RpcResult; #[method(name = "feeHistory")] - fn fee_history(&self, block_count: usize, first_block: U256, descending: bool, priority_fee_percentile: Vec) -> RpcResult; + fn fee_history( + &self, + block_count: usize, + first_block: U256, + descending: bool, + priority_fee_percentile: Vec, + ) -> RpcResult; } pub struct MetachainRPCModule { @@ -677,8 +683,19 @@ impl MetachainRPCServer for MetachainRPCModule { Ok(false) } - fn fee_history(&self, block_count: usize, first_block: U256, descending: bool, priority_fee_percentile: Vec) -> RpcResult { - Ok(RpcFeeHistory::from(self.handler.block.fee_history(block_count, first_block, true, priority_fee_percentile))) + fn fee_history( + &self, + block_count: usize, + first_block: U256, + descending: bool, + priority_fee_percentile: Vec, + ) -> RpcResult { + Ok(RpcFeeHistory::from(self.handler.block.fee_history( + block_count, + first_block, + true, + priority_fee_percentile, + ))) } } From d6913f8bac7fa1e8e05ea1856275d3e29d0be34b Mon Sep 17 00:00:00 2001 From: Shoham Chakraborty Date: Tue, 30 May 2023 14:19:54 +0800 Subject: [PATCH 09/16] Fix block_count type, remove debug param --- lib/ain-evm/src/block.rs | 10 +--------- lib/ain-grpc/src/rpc/eth.rs | 6 ++---- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/lib/ain-evm/src/block.rs b/lib/ain-evm/src/block.rs index b06ce25077..cb9d63d065 100644 --- a/lib/ain-evm/src/block.rs +++ b/lib/ain-evm/src/block.rs @@ -95,7 +95,6 @@ impl BlockHandler { &self, block_count: usize, first_block: U256, - descending: bool, priority_fee_percentile: Vec, ) -> FeeHistoryData { let mut blocks = Vec::with_capacity(block_count); @@ -108,10 +107,7 @@ impl BlockHandler { .expect(&format!("Block {} out of range", block_number)), ); - match descending { - true => block_number -= U256::from(1), - false => block_number += U256::from(1), - } + block_number -= U256::from(1); } let oldest_block = match descending { @@ -191,10 +187,6 @@ impl BlockHandler { Some(reward) }; - for x in gas_used_ratio.iter() { - debug!("used ratio: {}", x); - } - return FeeHistoryData { oldest_block, base_fee_per_gas, diff --git a/lib/ain-grpc/src/rpc/eth.rs b/lib/ain-grpc/src/rpc/eth.rs index 86b4e3d652..cb03e88e81 100644 --- a/lib/ain-grpc/src/rpc/eth.rs +++ b/lib/ain-grpc/src/rpc/eth.rs @@ -685,15 +685,13 @@ impl MetachainRPCServer for MetachainRPCModule { fn fee_history( &self, - block_count: usize, + block_count: U256, first_block: U256, - descending: bool, priority_fee_percentile: Vec, ) -> RpcResult { Ok(RpcFeeHistory::from(self.handler.block.fee_history( - block_count, + block_count.as_usize(), first_block, - true, priority_fee_percentile, ))) } From 684c837e5b40d2b28bfe822fe71be9dc1369290d Mon Sep 17 00:00:00 2001 From: Shoham Chakraborty Date: Tue, 30 May 2023 14:52:36 +0800 Subject: [PATCH 10/16] Fix build --- lib/ain-evm/src/block.rs | 5 +---- lib/ain-grpc/src/rpc/eth.rs | 4 +--- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/lib/ain-evm/src/block.rs b/lib/ain-evm/src/block.rs index cb9d63d065..e286de7304 100644 --- a/lib/ain-evm/src/block.rs +++ b/lib/ain-evm/src/block.rs @@ -110,10 +110,7 @@ impl BlockHandler { block_number -= U256::from(1); } - let oldest_block = match descending { - true => blocks.last().unwrap().header.hash(), - false => blocks.first().unwrap().header.hash(), - }; + let oldest_block = blocks.last().unwrap().header.hash(); let (base_fee_per_gas, gas_used_ratio): (Vec, Vec) = blocks .iter() diff --git a/lib/ain-grpc/src/rpc/eth.rs b/lib/ain-grpc/src/rpc/eth.rs index cb03e88e81..3c1d5d220c 100644 --- a/lib/ain-grpc/src/rpc/eth.rs +++ b/lib/ain-grpc/src/rpc/eth.rs @@ -6,7 +6,6 @@ use crate::codegen::types::EthTransactionInfo; use crate::receipt::ReceiptResult; use crate::transaction_request::{TransactionMessage, TransactionRequest}; use ain_cpp_imports::get_eth_priv_key; -use ain_evm::block::FeeHistoryData; use ain_evm::executor::TxResponse; use ain_evm::handler::Handlers; @@ -197,9 +196,8 @@ pub trait MetachainRPC { #[method(name = "feeHistory")] fn fee_history( &self, - block_count: usize, + block_count: U256, first_block: U256, - descending: bool, priority_fee_percentile: Vec, ) -> RpcResult; } From adc518b435690c7c34fd28c4e726b4ad76b9b5c6 Mon Sep 17 00:00:00 2001 From: Shoham Chakraborty Date: Tue, 30 May 2023 16:36:17 +0800 Subject: [PATCH 11/16] Implement eth_maxPriorityFeePerGas --- lib/ain-evm/src/block.rs | 48 +++++++++++++++++++++++++++++++++++++ lib/ain-grpc/src/rpc/eth.rs | 7 ++++++ 2 files changed, 55 insertions(+) diff --git a/lib/ain-evm/src/block.rs b/lib/ain-evm/src/block.rs index e286de7304..e0bdad14fc 100644 --- a/lib/ain-evm/src/block.rs +++ b/lib/ain-evm/src/block.rs @@ -191,4 +191,52 @@ impl BlockHandler { reward, }; } + + /// Returns the 60th percentile priority fee for the last 20 blocks + /// Ref: https://github.com/ethereum/go-ethereum/blob/c57b3436f4b8aae352cd69c3821879a11b5ee0fb/eth/ethconfig/config.go#L41 + /// TODO: these should be configurable by the user + pub fn suggested_priority_fee(&self) -> U256 { + let mut blocks = Vec::with_capacity(20); + let block = self + .storage + .get_latest_block() + .expect("Unable to find latest block"); + blocks.push(block.clone()); + + loop { + let parent_hash = block.header.hash(); + let blk = self.storage.get_block_by_hash(&parent_hash); + if blk.is_none() || blocks.len() == blocks.capacity() { + break; + } + + blocks.push(block.clone()); + } + + /* + TODO: assumption here is that max priority fee = priority fee paid, however + priority fee can be lower if gas costs hit max_fee_per_gas. + we will need to check the base fee paid to get the actual priority fee paid + */ + + let mut priority_fees = Vec::new(); + + for block in blocks { + for tx in block.transactions { + match tx { + TransactionAny::Legacy(_) | TransactionAny::EIP2930(_) => { + continue; + } + TransactionAny::EIP1559(t) => { + priority_fees.push(t.max_priority_fee_per_gas.as_u64() as f64); + } + } + } + } + + priority_fees.sort_by(|a, b| a.partial_cmp(b).expect("Invalid f64 value")); + let mut data = Data::new(priority_fees); + + U256::from(data.percentile(60).ceil() as u64) + } } diff --git a/lib/ain-grpc/src/rpc/eth.rs b/lib/ain-grpc/src/rpc/eth.rs index 3c1d5d220c..8bbc07fe81 100644 --- a/lib/ain-grpc/src/rpc/eth.rs +++ b/lib/ain-grpc/src/rpc/eth.rs @@ -200,6 +200,9 @@ pub trait MetachainRPC { first_block: U256, priority_fee_percentile: Vec, ) -> RpcResult; + + #[method(name = "maxPriorityFeePerGas")] + fn max_priority_fee_per_gas(&self) -> RpcResult; } pub struct MetachainRPCModule { @@ -693,6 +696,10 @@ impl MetachainRPCServer for MetachainRPCModule { priority_fee_percentile, ))) } + + fn max_priority_fee_per_gas(&self) -> RpcResult { + Ok(self.handler.block.suggested_priority_fee()) + } } fn sign( From 20d9d30e98bc87c8aacf46d62e2ad3343f949739 Mon Sep 17 00:00:00 2001 From: Shoham Chakraborty Date: Tue, 30 May 2023 18:06:46 +0800 Subject: [PATCH 12/16] Fix suggested_priority_fee loop --- lib/ain-evm/src/block.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/lib/ain-evm/src/block.rs b/lib/ain-evm/src/block.rs index e0bdad14fc..dfdb453fbb 100644 --- a/lib/ain-evm/src/block.rs +++ b/lib/ain-evm/src/block.rs @@ -202,15 +202,16 @@ impl BlockHandler { .get_latest_block() .expect("Unable to find latest block"); blocks.push(block.clone()); + let mut parent_hash = block.header.parent_hash; - loop { - let parent_hash = block.header.hash(); - let blk = self.storage.get_block_by_hash(&parent_hash); - if blk.is_none() || blocks.len() == blocks.capacity() { - break; + while blocks.len() <= blocks.capacity() { + match self.storage.get_block_by_hash(&parent_hash) { + Some(block) => { + blocks.push(block.clone()); + parent_hash = block.header.parent_hash; + } + None => break, } - - blocks.push(block.clone()); } /* From 65a0630156c6b06e2db14cc0c85468573f5b4153 Mon Sep 17 00:00:00 2001 From: Shoham Chakraborty Date: Tue, 30 May 2023 18:14:21 +0800 Subject: [PATCH 13/16] Address issues --- lib/ain-evm/src/block.rs | 8 ++++---- lib/ain-evm/src/handler.rs | 12 ++++++------ lib/ain-grpc/src/block.rs | 6 +++++- lib/ain-grpc/src/rpc/eth.rs | 11 ++++++----- 4 files changed, 21 insertions(+), 16 deletions(-) diff --git a/lib/ain-evm/src/block.rs b/lib/ain-evm/src/block.rs index dfdb453fbb..6ecf099fd9 100644 --- a/lib/ain-evm/src/block.rs +++ b/lib/ain-evm/src/block.rs @@ -69,7 +69,7 @@ impl BlockHandler { let parent_gas_used = parent_block.header.gas_used; let parent_gas_target = parent_block.header.gas_limit / elasticity_multiplier; - return if parent_gas_used == parent_gas_target { + if parent_gas_used == parent_gas_target { parent_base_fee } else if parent_gas_used > parent_gas_target { let gas_used_delta = parent_gas_used - parent_gas_target; @@ -88,7 +88,7 @@ impl BlockHandler { / base_fee_max_change_denominator; parent_base_fee - base_fee_per_gas_delta - }; + } } pub fn fee_history( @@ -184,12 +184,12 @@ impl BlockHandler { Some(reward) }; - return FeeHistoryData { + FeeHistoryData { oldest_block, base_fee_per_gas, gas_used_ratio, reward, - }; + } } /// Returns the 60th percentile priority fee for the last 20 blocks diff --git a/lib/ain-evm/src/handler.rs b/lib/ain-evm/src/handler.rs index bc18202853..4bfc79831e 100644 --- a/lib/ain-evm/src/handler.rs +++ b/lib/ain-evm/src/handler.rs @@ -102,13 +102,13 @@ impl Handlers { failed_transactions.push(hex::encode(hash)); } - all_transactions.push(signed_tx.clone()); - - total_gas_limit += match signed_tx.transaction { + total_gas_limit += match &signed_tx.transaction { TransactionV2::Legacy(t) => t.gas_limit, TransactionV2::EIP2930(t) => t.gas_limit, TransactionV2::EIP1559(t) => t.gas_limit, }; + + all_transactions.push(signed_tx.clone()); gas_used += used_gas; EVMHandler::logs_bloom(logs, &mut logs_bloom); receipts_v3.push(receipt); @@ -175,14 +175,14 @@ impl Handlers { block.header.number, ); - // calculate base fee - let base_fee = self.block.calculate_base_fee(parent_hash); - if update_state { debug!( "[finalize_block] Finalizing block number {:#x}, state_root {:#x}", block.header.number, block.header.state_root ); + // calculate base fee + let base_fee = self.block.calculate_base_fee(parent_hash); + self.block.connect_block(block.clone(), base_fee); self.receipt.put_receipts(receipts); } diff --git a/lib/ain-grpc/src/block.rs b/lib/ain-grpc/src/block.rs index e45c88fa88..3791a90003 100644 --- a/lib/ain-grpc/src/block.rs +++ b/lib/ain-grpc/src/block.rs @@ -35,7 +35,11 @@ pub struct RpcBlock { } impl RpcBlock { - pub fn from_block_with_tx(block: BlockAny, full_transactions: bool, base_fee: U256) -> Self { + pub fn from_block_with_tx_and_base_fee( + block: BlockAny, + full_transactions: bool, + base_fee: U256, + ) -> Self { let header_size = block.header.rlp_bytes().len(); RpcBlock { hash: block.header.hash(), diff --git a/lib/ain-grpc/src/rpc/eth.rs b/lib/ain-grpc/src/rpc/eth.rs index 8bbc07fe81..d2ee8d35d6 100644 --- a/lib/ain-grpc/src/rpc/eth.rs +++ b/lib/ain-grpc/src/rpc/eth.rs @@ -351,8 +351,8 @@ impl MetachainRPCServer for MetachainRPCModule { .storage .get_block_by_hash(&hash) .map_or(Ok(None), |block| { - Ok(Some(RpcBlock::from_block_with_tx( - block.clone(), + Ok(Some(RpcBlock::from_block_with_tx_and_base_fee( + block, full_transactions.unwrap_or_default(), self.handler.storage.get_base_fee(&hash).unwrap_or_default(), ))) @@ -393,12 +393,13 @@ impl MetachainRPCServer for MetachainRPCModule { .storage .get_block_by_number(&block_number) .map_or(Ok(None), |block| { - Ok(Some(RpcBlock::from_block_with_tx( - block.clone(), + let tx_hash = &block.header.hash(); + Ok(Some(RpcBlock::from_block_with_tx_and_base_fee( + block, full_transactions.unwrap_or_default(), self.handler .storage - .get_base_fee(&block.header.hash()) + .get_base_fee(tx_hash) .unwrap_or_default(), ))) }) From 3b155fd7bccd5e18f3bf7b0ed1146e0169018f48 Mon Sep 17 00:00:00 2001 From: Shoham Chakraborty Date: Wed, 31 May 2023 11:41:18 +0800 Subject: [PATCH 14/16] Increase initial base fee, set minimum base fee, fix feeHistory output order --- lib/ain-evm/src/block.rs | 12 ++++++++---- lib/ain-evm/src/handler.rs | 9 +-------- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/lib/ain-evm/src/block.rs b/lib/ain-evm/src/block.rs index 6ecf099fd9..919c74caf9 100644 --- a/lib/ain-evm/src/block.rs +++ b/lib/ain-evm/src/block.rs @@ -47,7 +47,7 @@ impl BlockHandler { pub fn calculate_base_fee(&self, parent_hash: H256) -> U256 { // constants - let initial_base_fee: U256 = U256::from(1_000_000_000); // wei + let initial_base_fee: U256 = U256::from(10_000_000_000 as u64); // wei let base_fee_max_change_denominator: U256 = U256::from(8); let elasticity_multiplier: U256 = U256::from(2); @@ -80,14 +80,14 @@ impl BlockHandler { U256::from(1), ); - parent_base_fee + base_fee_per_gas_delta + max(parent_base_fee + base_fee_per_gas_delta, initial_base_fee) } else { let gas_used_delta = parent_gas_target - parent_gas_used; let base_fee_per_gas_delta = parent_base_fee * gas_used_delta / parent_gas_target / base_fee_max_change_denominator; - parent_base_fee - base_fee_per_gas_delta + max(parent_base_fee - base_fee_per_gas_delta, initial_base_fee) } } @@ -112,7 +112,7 @@ impl BlockHandler { let oldest_block = blocks.last().unwrap().header.hash(); - let (base_fee_per_gas, gas_used_ratio): (Vec, Vec) = blocks + let (mut base_fee_per_gas, mut gas_used_ratio): (Vec, Vec) = blocks .iter() .map(|block| { debug!("Processing block {}", block.header.number); @@ -181,9 +181,13 @@ impl BlockHandler { reward.push(block_rewards); } + reward.reverse(); Some(reward) }; + base_fee_per_gas.reverse(); + gas_used_ratio.reverse(); + FeeHistoryData { oldest_block, base_fee_per_gas, diff --git a/lib/ain-evm/src/handler.rs b/lib/ain-evm/src/handler.rs index 4bfc79831e..01d78f9abd 100644 --- a/lib/ain-evm/src/handler.rs +++ b/lib/ain-evm/src/handler.rs @@ -55,7 +55,6 @@ impl Handlers { let mut failed_transactions = Vec::with_capacity(self.evm.tx_queues.len(context)); let mut receipts_v3: Vec = Vec::with_capacity(self.evm.tx_queues.len(context)); let mut gas_used = 0u64; - let mut total_gas_limit = U256::zero(); let mut logs_bloom: Bloom = Bloom::default(); let (parent_hash, parent_number) = self.block.get_latest_block_hash_and_number(); @@ -102,12 +101,6 @@ impl Handlers { failed_transactions.push(hex::encode(hash)); } - total_gas_limit += match &signed_tx.transaction { - TransactionV2::Legacy(t) => t.gas_limit, - TransactionV2::EIP2930(t) => t.gas_limit, - TransactionV2::EIP1559(t) => t.gas_limit, - }; - all_transactions.push(signed_tx.clone()); gas_used += used_gas; EVMHandler::logs_bloom(logs, &mut logs_bloom); @@ -154,7 +147,7 @@ impl Handlers { logs_bloom, difficulty: U256::from(difficulty), number: parent_number + 1, - gas_limit: total_gas_limit, + gas_limit: U256::from(30_000_000), gas_used: U256::from(gas_used), timestamp, extra_data: Vec::default(), From fc3e2192e480572c8cb9aa9c2b37efd79fbe9872 Mon Sep 17 00:00:00 2001 From: Shoham Chakraborty Date: Wed, 31 May 2023 17:21:14 +0800 Subject: [PATCH 15/16] Refactor to use match --- lib/ain-evm/src/block.rs | 45 ++++++++++++++++++++------------------ lib/ain-evm/src/handler.rs | 2 +- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/lib/ain-evm/src/block.rs b/lib/ain-evm/src/block.rs index 919c74caf9..bd42d599e0 100644 --- a/lib/ain-evm/src/block.rs +++ b/lib/ain-evm/src/block.rs @@ -3,7 +3,7 @@ use keccak_hash::H256; use log::debug; use primitive_types::U256; use statrs::statistics::{Data, OrderStatistics}; -use std::cmp::max; +use std::cmp::{max, Ordering}; use std::sync::Arc; use crate::storage::{traits::BlockStorage, Storage}; @@ -66,28 +66,31 @@ impl BlockHandler { .storage .get_base_fee(&parent_block.header.hash()) .expect("Parent base fee not found"); - let parent_gas_used = parent_block.header.gas_used; - let parent_gas_target = parent_block.header.gas_limit / elasticity_multiplier; - - if parent_gas_used == parent_gas_target { - parent_base_fee - } else if parent_gas_used > parent_gas_target { - let gas_used_delta = parent_gas_used - parent_gas_target; - let base_fee_per_gas_delta = max( - parent_base_fee * gas_used_delta + let parent_gas_used = parent_block.header.gas_used.as_u64(); + let parent_gas_target = + parent_block.header.gas_limit.as_u64() / elasticity_multiplier.as_u64(); + + match parent_gas_used.cmp(&parent_gas_target) { + Ordering::Less => parent_base_fee, + Ordering::Equal => { + let gas_used_delta = parent_gas_used - parent_gas_target; + let base_fee_per_gas_delta = max( + parent_base_fee * gas_used_delta + / parent_gas_target + / base_fee_max_change_denominator, + U256::from(1), + ); + + max(parent_base_fee + base_fee_per_gas_delta, initial_base_fee) + } + Ordering::Greater => { + let gas_used_delta = parent_gas_target - parent_gas_used; + let base_fee_per_gas_delta = parent_base_fee * gas_used_delta / parent_gas_target - / base_fee_max_change_denominator, - U256::from(1), - ); + / base_fee_max_change_denominator; - max(parent_base_fee + base_fee_per_gas_delta, initial_base_fee) - } else { - let gas_used_delta = parent_gas_target - parent_gas_used; - let base_fee_per_gas_delta = parent_base_fee * gas_used_delta - / parent_gas_target - / base_fee_max_change_denominator; - - max(parent_base_fee - base_fee_per_gas_delta, initial_base_fee) + max(parent_base_fee - base_fee_per_gas_delta, initial_base_fee) + } } } diff --git a/lib/ain-evm/src/handler.rs b/lib/ain-evm/src/handler.rs index 01d78f9abd..e0b7135584 100644 --- a/lib/ain-evm/src/handler.rs +++ b/lib/ain-evm/src/handler.rs @@ -9,7 +9,7 @@ use crate::traits::Executor; use crate::transaction::bridge::{BalanceUpdate, BridgeTx}; use crate::tx_queue::QueueTx; -use ethereum::{Block, PartialHeader, ReceiptV3, TransactionV2}; +use ethereum::{Block, PartialHeader, ReceiptV3}; use ethereum_types::{Bloom, H160, H64, U256}; use log::debug; use primitive_types::H256; From d4fe0cf9dd0cfb1c1881a5937775b472273447f6 Mon Sep 17 00:00:00 2001 From: Shoham Chakraborty Date: Tue, 6 Jun 2023 12:10:38 +0800 Subject: [PATCH 16/16] Use EIP1559 for eth_gasPrice estimation --- lib/ain-evm/src/block.rs | 13 +++++++++++++ lib/ain-grpc/src/rpc/eth.rs | 4 ++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/lib/ain-evm/src/block.rs b/lib/ain-evm/src/block.rs index bd42d599e0..0dcc8f938a 100644 --- a/lib/ain-evm/src/block.rs +++ b/lib/ain-evm/src/block.rs @@ -247,4 +247,17 @@ impl BlockHandler { U256::from(data.percentile(60).ceil() as u64) } + + pub fn get_legacy_fee(&self) -> U256 { + let priority_fee = self.suggested_priority_fee(); + let latest_block_hash = self + .storage + .get_latest_block() + .expect("Unable to get latest block") + .header + .hash(); + let base_fee = self.storage.get_base_fee(&latest_block_hash).unwrap(); + + base_fee + priority_fee + } } diff --git a/lib/ain-grpc/src/rpc/eth.rs b/lib/ain-grpc/src/rpc/eth.rs index d2ee8d35d6..8d1ac12631 100644 --- a/lib/ain-grpc/src/rpc/eth.rs +++ b/lib/ain-grpc/src/rpc/eth.rs @@ -657,9 +657,9 @@ impl MetachainRPCServer for MetachainRPCModule { } fn gas_price(&self) -> RpcResult { - let gas_price = ain_cpp_imports::get_min_relay_tx_fee().unwrap_or(10); + let gas_price = self.handler.block.get_legacy_fee(); debug!(target:"rpc","gasPrice: {:#?}", gas_price); - Ok(U256::from(gas_price)) + Ok(gas_price) } fn get_receipt(&self, hash: H256) -> RpcResult> {