Skip to content

Commit

Permalink
EVM backend overlay (#2611)
Browse files Browse the repository at this point in the history
* Remove BlockTemplateMap

* Correctly init CrossBoundaryResult on success

* Use mut references instead of raw pointers

* Switch C++ ScopedQueue to use safer ref instead of ptr

* fmt

* Resolve lints

* Backend overlay

* Fix lint

* Restore TestBlockValidity

* Remove logs

* Handle overlay deletion

* Remove debug log

* Fix debug log

* Remove debug log

* fmt: Extend cpp fmt to miner, mempool and validation (#2619)

fmt

--amend

* Remove unused trie_restore

* Rename Suicide to SelfDestruct

---------

Co-authored-by: Prasanna Loganathar <pvl@prasannavl.com>
Co-authored-by: Niven <sieniven@gmail.com>
  • Loading branch information
3 people authored Oct 25, 2023
1 parent cbeac02 commit 07ba855
Show file tree
Hide file tree
Showing 17 changed files with 499 additions and 355 deletions.
293 changes: 203 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

0 comments on commit 07ba855

Please sign in to comment.