Skip to content

Commit

Permalink
Add cache storage layer and GetTransactionBy* RPCs (#1908)
Browse files Browse the repository at this point in the history
* Add cache storage and RPC impl

* Restore block flush()
  • Loading branch information
Jouzo authored Apr 13, 2023
1 parent 6675c1d commit 78a23aa
Show file tree
Hide file tree
Showing 14 changed files with 603 additions and 114 deletions.
33 changes: 32 additions & 1 deletion lib/Cargo.lock

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

3 changes: 3 additions & 0 deletions lib/ain-evm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,6 @@ jsonrpsee-core = "0.15"
jsonrpsee-http-server = "0.15"
jsonrpsee-types = "0.15"
tokio = { version = "1.1", features = ["rt-multi-thread"] }

# Cache dependencies
lru = "0.10.0"
124 changes: 124 additions & 0 deletions lib/ain-evm/src/cache.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
use std::{num::NonZeroUsize, sync::RwLock};

use ethereum::{BlockAny, TransactionV2};
use lru::LruCache;
use primitive_types::{H256, U256};
use std::borrow::ToOwned;

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

impl Cache {
const DEFAULT_CACHE_SIZE: usize = 1000;

pub fn new(cache_size: Option<usize>) -> Self {
Cache {
transactions: RwLock::new(LruCache::new(
NonZeroUsize::new(cache_size.unwrap_or(Self::DEFAULT_CACHE_SIZE)).unwrap(),
)),
blocks: RwLock::new(LruCache::new(
NonZeroUsize::new(cache_size.unwrap_or(Self::DEFAULT_CACHE_SIZE)).unwrap(),
)),
block_hashes: RwLock::new(LruCache::new(
NonZeroUsize::new(cache_size.unwrap_or(Self::DEFAULT_CACHE_SIZE)).unwrap(),
)),
latest_block: RwLock::new(None),
}
}
}

impl Cache {
pub fn extend_transactions_from_block(&self, block: &BlockAny) {
let mut cache = self.transactions.write().unwrap();

for transaction in &block.transactions {
let hash = transaction.hash();
cache.put(hash, transaction.clone());
}
}

pub fn get_transaction_by_hash(&self, hash: &H256) -> Option<TransactionV2> {
self.transactions
.write()
.unwrap()
.get(hash)
.map(ToOwned::to_owned)
}

pub fn get_transaction_by_block_hash_and_index(
&self,
block_hash: &H256,
index: usize,
) -> Option<TransactionV2> {
self.block_hashes
.write()
.unwrap()
.get(block_hash)
.and_then(|block_number| {
self.get_transaction_by_block_number_and_index(&block_number, index)
})
}

pub fn get_transaction_by_block_number_and_index(
&self,
block_number: &U256,
index: usize,
) -> Option<TransactionV2> {
self.blocks
.write()
.unwrap()
.get(block_number)?
.transactions
.get(index)
.map(ToOwned::to_owned)
}
}

// Block impl
impl Cache {
pub fn get_block_by_number(&self, number: &U256) -> Option<BlockAny> {
self.blocks
.write()
.unwrap()
.get(number)
.map(ToOwned::to_owned)
}

pub fn get_block_by_hash(&self, block_hash: &H256) -> Option<BlockAny> {
self.block_hashes
.write()
.unwrap()
.get(block_hash)
.and_then(|block_number| self.get_block_by_number(&block_number))
}

pub fn put_block(&self, block: BlockAny) {
self.extend_transactions_from_block(&block);

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

// Latest block impl
impl Cache {
pub fn get_latest_block(&self) -> Option<BlockAny> {
self.latest_block
.read()
.unwrap()
.as_ref()
.map(ToOwned::to_owned)
}

pub fn put_latest_block(&self, block: BlockAny) {
let mut cache = self.latest_block.write().unwrap();
*cache = Some(block);
}
}
31 changes: 19 additions & 12 deletions lib/ain-evm/src/handler.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use crate::block::BlockHandler;
use crate::evm::EVMHandler;
use crate::executor::AinExecutor;
use crate::storage::Storage;
use crate::traits::Executor;
use ethereum::{Block, PartialHeader, TransactionV2};
use ethereum::{Block, BlockAny, PartialHeader, TransactionV2};
use evm::backend::{MemoryBackend, MemoryVicinity};
use primitive_types::{H160, H256, U256};
use std::error::Error;
Expand All @@ -11,13 +12,15 @@ use std::time::{SystemTime, UNIX_EPOCH};
pub struct Handlers {
pub evm: EVMHandler,
pub block: BlockHandler,
pub storage: Storage,
}

impl Handlers {
pub fn new() -> Self {
Self {
evm: EVMHandler::new(),
block: BlockHandler::new(),
storage: Storage::new(),
}
}

Expand All @@ -26,7 +29,7 @@ impl Handlers {
context: u64,
update_state: bool,
miner_address: Option<H160>,
) -> Result<(Block<TransactionV2>, Vec<TransactionV2>), Box<dyn Error>> {
) -> Result<(BlockAny, Vec<TransactionV2>), Box<dyn Error>> {
let mut tx_hashes = Vec::with_capacity(self.evm.tx_queues.len(context));
let mut failed_tx_hashes = Vec::with_capacity(self.evm.tx_queues.len(context));
let vicinity = get_vicinity(None, None);
Expand All @@ -45,17 +48,13 @@ impl Handlers {

self.evm.tx_queues.remove(context);

if update_state {
let mut state = self.evm.state.write().unwrap();
*state = executor.backend().state().clone();
}

let (parent_hash, number) = {
let blocks = self.block.blocks.read().unwrap();
blocks
.first()
.and_then(|first_block| Some((first_block.header.hash(), blocks.len() + 1)))
.unwrap_or((H256::default(), 0))
self.storage
.get_latest_block()
.and_then(|first_block| {
Some((first_block.header.hash(), first_block.header.number + 1))
})
.unwrap_or((H256::default(), U256::zero()))
};

let block = Block::new(
Expand Down Expand Up @@ -83,6 +82,14 @@ impl Handlers {

self.block.connect_block(block.clone());

if update_state {
let mut state = self.evm.state.write().unwrap();
*state = executor.backend().state().clone();

self.storage.put_latest_block(block.clone());
self.storage.put_block(block.clone());
}

Ok((block, failed_tx_hashes))
}
}
Expand Down
2 changes: 2 additions & 0 deletions lib/ain-evm/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
mod block;
mod cache;
mod ecrecover;
mod evm;
pub mod executor;
pub mod handler;
pub mod runtime;
pub mod storage;
pub mod traits;
pub mod transaction;
mod tx_queue;
Expand Down
1 change: 1 addition & 0 deletions lib/ain-evm/src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ impl Runtime {
pub fn new() -> Self {
let r = Builder::new_multi_thread().enable_all().build().unwrap();
let (tx, mut rx) = mpsc::channel(1);

Runtime {
tx,
rt_handle: r.handle().clone(),
Expand Down
68 changes: 68 additions & 0 deletions lib/ain-evm/src/storage.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use crate::cache::Cache;
use ethereum::{BlockAny, TransactionV2};
use primitive_types::{H256, U256};

#[derive(Debug)]
pub struct Storage {
cache: Cache,
}

// TODO : Add DB and pull from DB when cache miss
impl Storage {
pub fn new() -> Self {
Self {
cache: Cache::new(None),
}
}
}

// Block storage
impl Storage {
pub fn get_block_by_number(&self, number: &U256) -> Option<BlockAny> {
self.cache.get_block_by_number(number)
}

pub fn get_block_by_hash(&self, block_hash: &H256) -> Option<BlockAny> {
self.cache.get_block_by_hash(block_hash)
}

pub fn put_block(&self, block: BlockAny) {
self.cache.put_block(block)
}
}

// Transaction storage
impl Storage {
pub fn get_transaction_by_hash(&self, hash: H256) -> Option<TransactionV2> {
self.cache.get_transaction_by_hash(&hash)
}

pub fn get_transaction_by_block_hash_and_index(
&self,
hash: H256,
index: usize,
) -> Option<TransactionV2> {
self.cache
.get_transaction_by_block_hash_and_index(&hash, index)
}

pub fn get_transaction_by_block_number_and_index(
&self,
hash: U256,
index: usize,
) -> Option<TransactionV2> {
self.cache
.get_transaction_by_block_number_and_index(&hash, index)
}
}

// Latest block storage
impl Storage {
pub fn get_latest_block(&self) -> Option<BlockAny> {
self.cache.get_latest_block()
}

pub fn put_latest_block(&self, block: BlockAny) {
self.cache.put_latest_block(block)
}
}
1 change: 1 addition & 0 deletions lib/ain-grpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ tokio = { version = "1.1", features = ["rt-multi-thread"] }
tonic = "0.8"
primitive-types = "0.12.1"
ethereum = "0.14.0"
hex = "0.4.3"

[build-dependencies]
cxx-gen = "0.7"
Expand Down
Loading

0 comments on commit 78a23aa

Please sign in to comment.