Skip to content

Commit

Permalink
EVM: Add Code to storage cache (#2692)
Browse files Browse the repository at this point in the history
* Switch LRU behind RwLock to Mutex

* Add code cache

* Rename code index name
  • Loading branch information
Jouzo committed Nov 23, 2023
1 parent 45f7e3a commit 042bd3c
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 36 deletions.
69 changes: 34 additions & 35 deletions lib/ain-evm/src/storage/cache.rs
Expand Up @@ -3,30 +3,35 @@ use std::{borrow::ToOwned, num::NonZeroUsize, sync::RwLock};
use ethereum::{BlockAny, TransactionV2};
use ethereum_types::{H256, U256};
use lru::LruCache;
use parking_lot::Mutex;

use super::traits::{BlockStorage, Rollback, TransactionStorage};
use crate::Result;

#[derive(Debug)]
pub struct Cache {
transactions: RwLock<LruCache<H256, TransactionV2>>,
blocks: RwLock<LruCache<U256, BlockAny>>,
block_hashes: RwLock<LruCache<H256, U256>>,
transactions: Mutex<LruCache<H256, TransactionV2>>,
blocks: Mutex<LruCache<U256, BlockAny>>,
block_hashes: Mutex<LruCache<H256, U256>>,
latest_block: RwLock<Option<BlockAny>>,
contract_code: Mutex<LruCache<H256, Vec<u8>>>,
}

impl Cache {
const DEFAULT_CACHE_SIZE: usize = 1000;

pub fn new(cache_size: Option<usize>) -> Self {
Cache {
transactions: RwLock::new(LruCache::new(
transactions: Mutex::new(LruCache::new(
NonZeroUsize::new(cache_size.unwrap_or(Self::DEFAULT_CACHE_SIZE)).unwrap(),
)),
blocks: RwLock::new(LruCache::new(
blocks: Mutex::new(LruCache::new(
NonZeroUsize::new(cache_size.unwrap_or(Self::DEFAULT_CACHE_SIZE)).unwrap(),
)),
block_hashes: RwLock::new(LruCache::new(
block_hashes: Mutex::new(LruCache::new(
NonZeroUsize::new(cache_size.unwrap_or(Self::DEFAULT_CACHE_SIZE)).unwrap(),
)),
contract_code: Mutex::new(LruCache::new(
NonZeroUsize::new(cache_size.unwrap_or(Self::DEFAULT_CACHE_SIZE)).unwrap(),
)),
latest_block: RwLock::new(None),
Expand All @@ -36,19 +41,13 @@ impl Cache {

impl BlockStorage for Cache {
fn get_block_by_number(&self, number: &U256) -> Result<Option<BlockAny>> {
let block = self
.blocks
.write()
.unwrap()
.get(number)
.map(ToOwned::to_owned);
let block = self.blocks.lock().get(number).map(ToOwned::to_owned);
Ok(block)
}

fn get_block_by_hash(&self, block_hash: &H256) -> Result<Option<BlockAny>> {
self.block_hashes
.write()
.unwrap()
.lock()
.get(block_hash)
.map_or(Ok(None), |block_number| {
self.get_block_by_number(block_number)
Expand All @@ -60,11 +59,8 @@ impl BlockStorage for Cache {

let block_number = block.header.number;
let hash = block.header.hash();
self.blocks
.write()
.unwrap()
.put(block_number, block.clone());
self.block_hashes.write().unwrap().put(hash, block_number);
self.blocks.lock().put(block_number, block.clone());
self.block_hashes.lock().put(hash, block_number);
Ok(())
}

Expand All @@ -87,7 +83,7 @@ impl BlockStorage for Cache {

impl TransactionStorage for Cache {
fn extend_transactions_from_block(&self, block: &BlockAny) -> Result<()> {
let mut cache = self.transactions.write().unwrap();
let mut cache = self.transactions.lock();

for transaction in &block.transactions {
let hash = transaction.hash();
Expand All @@ -97,12 +93,7 @@ impl TransactionStorage for Cache {
}

fn get_transaction_by_hash(&self, hash: &H256) -> Result<Option<TransactionV2>> {
let transaction = self
.transactions
.write()
.unwrap()
.get(hash)
.map(ToOwned::to_owned);
let transaction = self.transactions.lock().get(hash).map(ToOwned::to_owned);
Ok(transaction)
}

Expand All @@ -112,8 +103,7 @@ impl TransactionStorage for Cache {
index: usize,
) -> Result<Option<TransactionV2>> {
self.block_hashes
.write()
.unwrap()
.lock()
.get(block_hash)
.map_or(Ok(None), |block_number| {
self.get_transaction_by_block_number_and_index(block_number, index)
Expand All @@ -127,17 +117,15 @@ impl TransactionStorage for Cache {
) -> Result<Option<TransactionV2>> {
let transaction = self
.blocks
.write()
.unwrap()
.lock()
.get(block_number)
.and_then(|block| block.transactions.get(index).map(ToOwned::to_owned));
Ok(transaction)
}

fn put_transaction(&self, transaction: &TransactionV2) -> Result<()> {
self.transactions
.write()
.unwrap()
.lock()
.put(transaction.hash(), transaction.clone());
Ok(())
}
Expand All @@ -146,17 +134,28 @@ impl TransactionStorage for Cache {
impl Rollback for Cache {
fn disconnect_latest_block(&self) -> Result<()> {
if let Some(block) = self.get_latest_block()? {
let mut transaction_cache = self.transactions.write().unwrap();
let mut transaction_cache = self.transactions.lock();
for tx in &block.transactions {
transaction_cache.pop(&tx.hash());
}

self.block_hashes.write().unwrap().pop(&block.header.hash());
self.blocks.write().unwrap().pop(&block.header.number);
self.block_hashes.lock().pop(&block.header.hash());
self.blocks.lock().pop(&block.header.number);

let previous_block = self.get_block_by_hash(&block.header.parent_hash)?;
self.put_latest_block(previous_block.as_ref())?;
}
Ok(())
}
}

impl Cache {
pub fn get_code_by_hash(&self, hash: &H256) -> Result<Option<Vec<u8>>> {
Ok(self.contract_code.lock().get(hash).map(ToOwned::to_owned))
}

pub fn put_code(&self, hash: H256, code: &[u8]) -> Result<()> {
self.contract_code.lock().put(hash, code.to_vec());
Ok(())
}
}
12 changes: 11 additions & 1 deletion lib/ain-evm/src/storage/mod.rs
Expand Up @@ -193,7 +193,17 @@ impl FlushableStorage for Storage {

impl Storage {
pub fn get_code_by_hash(&self, address: H160, hash: H256) -> Result<Option<Vec<u8>>> {
self.blockstore.get_code_by_hash(address, &hash)
match self.cache.get_code_by_hash(&hash) {
Ok(Some(code)) => Ok(Some(code)),
Ok(None) => {
let code = self.blockstore.get_code_by_hash(address, &hash);
if let Ok(Some(ref code)) = code {
self.cache.put_code(hash, code)?;
}
code
}
Err(e) => Err(e),
}
}

pub fn put_code(
Expand Down

0 comments on commit 042bd3c

Please sign in to comment.