Skip to content

Commit

Permalink
Add EVM BlockHandler (#1864)
Browse files Browse the repository at this point in the history
* Make handlers extensible, add block handler

* Move EVMHandler

* Fix build errors

* Add connect_block

* Fix Eth_GetBlockByHash

* Fix incomplete merge

* Add bin files to gitignore

* Change RPC methods to lowerCamelCase

* Formatting
  • Loading branch information
shohamc1 authored and canonbrother committed Apr 10, 2023
1 parent b7ca3b2 commit 3ec5cc2
Show file tree
Hide file tree
Showing 13 changed files with 663 additions and 479 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -156,3 +156,4 @@ src/secp256k1/src/ecmult_static_context.h
# EVM
src/evm/Cargo.lock
src/evm/target/
*.bin
1 change: 1 addition & 0 deletions src/rust/Cargo.lock

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

14 changes: 7 additions & 7 deletions src/rust/crates/ain-evm-ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,38 +34,38 @@ mod ffi {
}

pub fn evm_add_balance(address: &str, amount: [u8; 32]) -> Result<(), Box<dyn Error>> {
RUNTIME.evm.add_balance(address, amount.into())
RUNTIME.handlers.evm.add_balance(address, amount.into())
}

pub fn evm_sub_balance(address: &str, amount: [u8; 32]) -> Result<(), Box<dyn Error>> {
RUNTIME.evm.sub_balance(address, amount.into())
RUNTIME.handlers.evm.sub_balance(address, amount.into())
}

pub fn evm_validate_raw_tx(tx: &str) -> Result<bool, Box<dyn Error>> {
match RUNTIME.evm.validate_raw_tx(tx) {
match RUNTIME.handlers.evm.validate_raw_tx(tx) {
Ok(_) => Ok(true),
Err(_) => Ok(false),
}
}

pub fn evm_get_context() -> u64 {
RUNTIME.evm.get_context()
RUNTIME.handlers.evm.get_context()
}

fn evm_discard_context(context: u64) {
// TODO discard
RUNTIME.evm.discard_context(context)
RUNTIME.handlers.evm.discard_context(context)
}

fn evm_queue_tx(context: u64, raw_tx: &str) -> Result<bool, Box<dyn Error>> {
match RUNTIME.evm.queue_tx(context, raw_tx) {
match RUNTIME.handlers.evm.queue_tx(context, raw_tx) {
Ok(_) => Ok(true),
Err(_) => Ok(false),
}
}

use rlp::Encodable;
fn evm_finalise(context: u64, update_state: bool) -> Result<Vec<u8>, Box<dyn Error>> {
let (block, _failed_tx) = RUNTIME.evm.finalize_block(context, update_state)?;
let (block, _failed_tx) = RUNTIME.handlers.evm.finalize_block(context, update_state)?;
Ok(block.header.rlp_bytes().into())
}
15 changes: 5 additions & 10 deletions src/rust/crates/ain-evm-runtime/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use ain_evm_state::handler::EVMHandler;
use ain_evm_state::handler::Handlers;
use ain_evm_state::traits::PersistentState;
use ain_evm_state::EVM_STATE_PATH;
use jsonrpsee_http_server::HttpServerHandle;
use std::sync::{Arc, Mutex};
use std::thread::{self, JoinHandle};
Expand All @@ -17,7 +16,7 @@ pub struct Runtime {
pub tx: Sender<()>,
pub handle: Mutex<Option<JoinHandle<()>>>,
pub jrpc_handle: Mutex<Option<HttpServerHandle>>, // dropping the handle kills server
pub evm: Arc<EVMHandler>,
pub handlers: Arc<Handlers>,
}

impl Runtime {
Expand All @@ -34,7 +33,7 @@ impl Runtime {
});
}))),
jrpc_handle: Mutex::new(None),
evm: Arc::new(EVMHandler::new()),
handlers: Arc::new(Handlers::new()),
}
}

Expand All @@ -49,11 +48,7 @@ impl Runtime {
.unwrap();

// Persist EVM State to disk
self.evm
.state
.write()
.unwrap()
.save_to_disk(EVM_STATE_PATH)
.unwrap();
self.handlers.evm.flush();
self.handlers.block.flush();
}
}
109 changes: 109 additions & 0 deletions src/rust/crates/ain-evm-state/src/block.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
use crate::traits::PersistentState;
use ethereum::BlockAny;
use primitive_types::{H256, U256};
use std::collections::HashMap;
use std::error::Error;
use std::fs::File;
use std::io::{Read, Write};
use std::ops::Index;
use std::path::Path;
use std::sync::{Arc, RwLock};

pub static BLOCK_MAP_PATH: &str = "block_map.bin";
pub static BLOCK_DATA_PATH: &str = "block_data.bin";

type BlockHashtoBlock = HashMap<H256, U256>;
type Blocks = Vec<BlockAny>;

pub struct BlockHandler {
pub block_map: Arc<RwLock<BlockHashtoBlock>>,
pub blocks: Arc<RwLock<Blocks>>,
}

impl PersistentState for BlockHashtoBlock {
fn save_to_disk(&self, path: &str) -> Result<(), String> {
let serialized_state = bincode::serialize(self).map_err(|e| e.to_string())?;
let mut file = File::create(path).map_err(|e| e.to_string())?;
file.write_all(&serialized_state).map_err(|e| e.to_string())
}

fn load_from_disk(path: &str) -> Result<Self, String> {
if Path::new(path).exists() {
let mut file = File::open(path).map_err(|e| e.to_string())?;
let mut data = Vec::new();
file.read_to_end(&mut data).map_err(|e| e.to_string())?;
let new_state: HashMap<H256, U256> =
bincode::deserialize(&data).map_err(|e| e.to_string())?;
Ok(new_state)
} else {
Ok(Self::new())
}
}
}

impl PersistentState for Blocks {
fn save_to_disk(&self, path: &str) -> Result<(), String> {
let serialized_state = bincode::serialize(self).map_err(|e| e.to_string())?;
let mut file = File::create(path).map_err(|e| e.to_string())?;
file.write_all(&serialized_state).map_err(|e| e.to_string())
}

fn load_from_disk(path: &str) -> Result<Self, String> {
if Path::new(path).exists() {
let mut file = File::open(path).map_err(|e| e.to_string())?;
let mut data = Vec::new();
file.read_to_end(&mut data).map_err(|e| e.to_string())?;
let new_state: Vec<BlockAny> =
bincode::deserialize(&data).map_err(|e| e.to_string())?;
Ok(new_state)
} else {
Ok(Self::new())
}
}
}

impl BlockHandler {
pub fn new() -> Self {
Self {
block_map: Arc::new(RwLock::new(
BlockHashtoBlock::load_from_disk(BLOCK_MAP_PATH).unwrap(),
)),
blocks: Arc::new(RwLock::new(
Blocks::load_from_disk(BLOCK_DATA_PATH).unwrap(),
)),
}
}

pub fn connect_block(&self, block: BlockAny) {
let mut blocks = self.blocks.write().unwrap();
blocks.push(block.clone());

let mut blockhash = self.block_map.write().unwrap();
blockhash.insert(block.header.hash(), block.header.number);
}

pub fn flush(&self) {
let _ = self
.block_map
.write()
.unwrap()
.save_to_disk(BLOCK_MAP_PATH)
.unwrap();
let _ = self
.blocks
.write()
.unwrap()
.save_to_disk(BLOCK_DATA_PATH)
.unwrap();
}

pub fn get_block_hash(&self, hash: H256) -> Result<BlockAny, Box<dyn Error>> {
let block_map = self.block_map.read().unwrap();
let block_number = block_map.get(&hash).unwrap().clone();

let blocks = self.blocks.read().unwrap();
let block = blocks.get(block_number.as_usize()).unwrap().clone();

Ok(block)
}
}
Loading

0 comments on commit 3ec5cc2

Please sign in to comment.