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

EVM backend overlay #2611

Merged
merged 24 commits into from
Oct 25, 2023
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
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
291 changes: 201 additions & 90 deletions lib/ain-evm/src/backend.rs

Large diffs are not rendered by default.

41 changes: 14 additions & 27 deletions lib/ain-evm/src/blocktemplate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ use ethereum::{Block, ReceiptV3, TransactionV2};
use ethereum_types::{Bloom, H160, H256, U256};

use crate::{
backend::Vicinity, core::XHash, evm::ExecTxState, receipt::Receipt, transaction::SignedTx,
backend::{EVMBackend, Vicinity},
core::XHash,
evm::ExecTxState,
receipt::Receipt,
transaction::SignedTx,
};

type Result<T> = std::result::Result<T, BlockTemplateError>;
Expand All @@ -13,9 +17,8 @@ pub type ReceiptAndOptionalContractAddress = (ReceiptV3, Option<H160>);
pub struct TemplateTxItem {
pub tx: Box<SignedTx>,
pub tx_hash: XHash,
pub gas_used: U256,
pub gas_fees: U256,
pub state_root: H256,
pub gas_used: U256,
pub logs_bloom: Bloom,
pub receipt_v3: ReceiptAndOptionalContractAddress,
}
Expand All @@ -24,15 +27,13 @@ impl TemplateTxItem {
pub fn new_system_tx(
tx: Box<SignedTx>,
receipt_v3: ReceiptAndOptionalContractAddress,
state_root: H256,
logs_bloom: Bloom,
) -> Self {
TemplateTxItem {
tx,
tx_hash: Default::default(),
gas_used: U256::zero(),
gas_fees: U256::zero(),
state_root,
gas_used: U256::zero(),
logs_bloom,
receipt_v3,
}
Expand All @@ -52,11 +53,10 @@ pub struct BlockData {
/// 4. Backend vicinity
/// 5. Block template timestamp
/// 6. DVM block number
/// 7. Initial state root
/// 7. EVM backend
///
/// The template is used to construct a valid EVM block.
///
#[derive(Clone, Debug, Default)]
pub struct BlockTemplate {
pub transactions: Vec<TemplateTxItem>,
pub block_data: Option<BlockData>,
Expand All @@ -65,7 +65,7 @@ pub struct BlockTemplate {
pub parent_hash: H256,
pub dvm_block: u64,
pub timestamp: u64,
pub initial_state_root: H256,
pub backend: EVMBackend,
}

impl BlockTemplate {
Expand All @@ -74,7 +74,7 @@ impl BlockTemplate {
parent_hash: H256,
dvm_block: u64,
timestamp: u64,
initial_state_root: H256,
backend: EVMBackend,
) -> Self {
Self {
transactions: Vec::new(),
Expand All @@ -84,7 +84,7 @@ impl BlockTemplate {
parent_hash,
dvm_block,
timestamp,
initial_state_root,
backend,
}
}

Expand All @@ -97,9 +97,8 @@ impl BlockTemplate {
self.transactions.push(TemplateTxItem {
tx: tx_update.tx,
tx_hash,
gas_used: tx_update.gas_used,
gas_fees: tx_update.gas_fees,
state_root: tx_update.state_root,
gas_used: tx_update.gas_used,
logs_bloom: tx_update.logs_bloom,
receipt_v3: tx_update.receipt,
});
Expand All @@ -123,25 +122,13 @@ impl BlockTemplate {
self.total_gas_used = self.transactions.iter().try_fold(U256::zero(), |acc, tx| {
acc.checked_add(tx.gas_used)
.ok_or(BlockTemplateError::ValueOverflow)
})?
})?;
self.backend.reset_from_tx(index);
}

Ok(removed_txs)
}

pub fn get_state_root_from_native_hash(&self, hash: XHash) -> Option<H256> {
self.transactions
.iter()
.find(|tx_item| tx_item.tx_hash == hash)
.map(|tx_item| tx_item.state_root)
}

pub fn get_latest_state_root(&self) -> H256 {
self.transactions
.last()
.map_or(self.initial_state_root, |tx_item| tx_item.state_root)
}

pub fn get_latest_logs_bloom(&self) -> Bloom {
self.transactions
.last()
Expand Down
7 changes: 3 additions & 4 deletions lib/ain-evm/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ pub fn bridge_dst20_in(
let contract_balance_storage_index = get_address_storage_index(H256::zero(), fixed_address);

let total_supply_index = H256::from_low_u64_be(2);
let total_supply = backend.get_contract_storage(contract, total_supply_index.as_bytes())?;
let total_supply = backend.get_contract_storage(contract, total_supply_index)?;

let new_total_supply = total_supply
.checked_add(amount)
Expand Down Expand Up @@ -265,7 +265,7 @@ pub fn bridge_dst20_out(
let contract_balance_storage_index = get_address_storage_index(H256::zero(), fixed_address);

let total_supply_index = H256::from_low_u64_be(2);
let total_supply = backend.get_contract_storage(contract, total_supply_index.as_bytes())?;
let total_supply = backend.get_contract_storage(contract, total_supply_index)?;

let new_total_supply = total_supply
.checked_sub(amount)
Expand Down Expand Up @@ -310,8 +310,7 @@ pub fn bridge_dfi(
let FixedContract { fixed_address, .. } = get_transfer_domain_contract();

let total_supply_index = H256::from_low_u64_be(1);
let total_supply =
backend.get_contract_storage(fixed_address, total_supply_index.as_bytes())?;
let total_supply = backend.get_contract_storage(fixed_address, total_supply_index)?;

let new_total_supply = if direction == TransferDirection::EvmOut {
total_supply.checked_sub(amount)
Expand Down
71 changes: 8 additions & 63 deletions lib/ain-evm/src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ impl SignedTxCache {
}

struct TxValidationCache {
validated: spin::Mutex<LruCache<(H256, String), ValidateTxInfo>>,
stateless: spin::Mutex<LruCache<String, ValidateTxInfo>>,
}

Expand All @@ -94,37 +93,19 @@ impl Default for TxValidationCache {
impl TxValidationCache {
pub fn new(capacity: usize) -> Self {
Self {
validated: spin::Mutex::new(LruCache::new(NonZeroUsize::new(capacity).unwrap())),
stateless: spin::Mutex::new(LruCache::new(NonZeroUsize::new(capacity).unwrap())),
}
}

pub fn get(&self, key: &(H256, String)) -> Option<ValidateTxInfo> {
self.validated.lock().get(key).cloned()
}

pub fn get_stateless(&self, key: &str) -> Option<ValidateTxInfo> {
self.stateless.lock().get(key).cloned()
}

pub fn set(&self, key: (H256, String), value: ValidateTxInfo) -> ValidateTxInfo {
let mut cache = self.validated.lock();
cache.put(key, value.clone());
value
}

pub fn set_stateless(&self, key: String, value: ValidateTxInfo) -> ValidateTxInfo {
let mut cache = self.stateless.lock();
cache.put(key, value.clone());
value
}

// To be used on new block or any known state changes. Only clears fully validated TX cache.
// Stateless cache can be kept across blocks and is handled by LRU itself
pub fn clear(&self) {
let mut cache = self.validated.lock();
cache.clear()
}
}

pub struct EVMCoreService {
Expand Down Expand Up @@ -341,16 +322,6 @@ impl EVMCoreService {
tx: &str,
template: &BlockTemplate,
) -> Result<ValidateTxInfo> {
let state_root = template.get_latest_state_root();
debug!("[validate_raw_tx] state_root : {:#?}", state_root);

if let Some(tx_info) = self
.tx_validation_cache
.get(&(state_root, String::from(tx)))
{
return Ok(tx_info);
}

debug!("[validate_raw_tx] raw transaction : {:#?}", tx);

let ValidateTxInfo {
Expand Down Expand Up @@ -410,7 +381,7 @@ impl EVMCoreService {

// Start of stateful checks
// Validate tx prepay fees with account balance
let backend = self.get_backend(state_root)?;
let backend = &template.backend;
let balance = backend.get_balance(&signed_tx.sender);
debug!("[validate_raw_tx] Account balance : {:x?}", balance);
if balance < max_prepay_fee {
Expand All @@ -434,13 +405,10 @@ impl EVMCoreService {
.into());
}

Ok(self.tx_validation_cache.set(
(state_root, String::from(tx)),
ValidateTxInfo {
signed_tx,
max_prepay_fee,
},
))
Ok(ValidateTxInfo {
signed_tx,
max_prepay_fee,
})
}

/// Validates a raw transfer domain tx.
Expand Down Expand Up @@ -495,12 +463,6 @@ impl EVMCoreService {
tx
);

let state_root = template.get_latest_state_root();
debug!(
"[validate_raw_transferdomain_tx] state_root : {:#?}",
state_root
);

let ValidateTxInfo {
signed_tx,
max_prepay_fee,
Expand Down Expand Up @@ -695,7 +657,7 @@ impl EVMCoreService {
}
};

let backend = self.get_backend(state_root)?;
let backend = &template.backend;

let nonce = backend.get_nonce(&signed_tx.sender);
debug!(
Expand Down Expand Up @@ -771,9 +733,7 @@ impl EVMCoreService {
template: &BlockTemplate,
address: H160,
) -> Result<U256> {
let state_root = template.get_latest_state_root();
let backend = self.get_backend(state_root)?;
let nonce = backend.get_nonce(&address);
let nonce = template.backend.get_nonce(&address);
trace!("[get_next_valid_nonce_in_block_template] Account {address:x?} nonce {nonce:x?}");
Ok(nonce)
}
Expand Down Expand Up @@ -807,18 +767,6 @@ impl EVMCoreService {
Ok(backend.get_account(&address))
}

pub fn get_latest_contract_storage(&self, contract: H160, storage_index: H256) -> Result<U256> {
let state_root = self.get_state_root()?;
let backend = EVMBackend::from_root(
state_root,
Arc::clone(&self.trie_store),
Arc::clone(&self.storage),
Vicinity::default(),
)?;

backend.get_contract_storage(contract, storage_index.as_bytes())
}

pub fn get_code(&self, address: H160, block_number: U256) -> Result<Option<Vec<u8>>> {
self.get_account(address, block_number)?
.map_or(Ok(None), |account| {
Expand Down Expand Up @@ -884,6 +832,7 @@ impl EVMCoreService {
block_number,
state_root
);

EVMBackend::from_root(
state_root,
Arc::clone(&self.trie_store),
Expand Down Expand Up @@ -962,8 +911,4 @@ impl EVMCoreService {
let mut nonce_store = self.nonce_store.lock();
nonce_store.clear()
}

pub fn clear_transaction_cache(&self) {
self.tx_validation_cache.clear()
}
}
Loading
Loading