Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add EVM BlockHandler #1864

Merged
merged 10 commits into from
Apr 6, 2023
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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();
}
}
101 changes: 101 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,101 @@
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};
use ethereum::BlockAny;
use primitive_types::{H256, U256};
use crate::traits::PersistentState;


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