Skip to content

Commit 016bfec

Browse files
authored
Add EvmMapping fragment handling (#772)
1 parent 77776f7 commit 016bfec

File tree

13 files changed

+501
-133
lines changed

13 files changed

+501
-133
lines changed

chain-evm/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@ pub mod state;
77
#[cfg(test)]
88
mod tests;
99

10-
pub use machine::{Address, BlockGasLimit, Config, Environment, GasLimit, GasPrice};
10+
pub use machine::{Address, BlockGasLimit, Config, Environment, ExitError, GasLimit, GasPrice};

chain-evm/src/machine.rs

Lines changed: 73 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,22 @@
88
//! ## Handler <- EVM Context Handler
99
//! ## StackState<'config>
1010
//!
11+
use crate::{
12+
precompiles::Precompiles,
13+
state::{Account, Balance, ByteCode, Key},
14+
};
1115
use ethereum_types::{H160, H256, U256};
1216
use evm::{
1317
backend::{Backend, Basic},
1418
executor::stack::{Accessed, StackExecutor, StackState, StackSubstateMetadata},
15-
Context, ExitError, ExitFatal, ExitReason, ExitRevert, Transfer,
19+
Context, ExitFatal, ExitReason, ExitRevert, Transfer,
1620
};
1721
use std::collections::{BTreeMap, BTreeSet};
18-
1922
use thiserror::Error;
2023

21-
use crate::{
22-
precompiles::Precompiles,
23-
state::{Account, Balance, ByteCode, Key},
24-
};
25-
2624
/// Export EVM types
2725
pub use evm::backend::Log;
26+
pub use evm::ExitError;
2827

2928
/// An address of an EVM account.
3029
pub type Address = H160;
@@ -125,11 +124,11 @@ pub enum Error {
125124
pub trait EvmState {
126125
fn environment(&self) -> &Environment;
127126

128-
fn account(&self, address: Address) -> Option<Account>;
127+
fn account(&self, address: &Address) -> Option<Account>;
129128

130-
fn contains(&self, address: Address) -> bool;
129+
fn contains(&self, address: &Address) -> bool;
131130

132-
fn modify_account<F>(&mut self, address: Address, f: F)
131+
fn modify_account<F>(&mut self, address: Address, f: F) -> Result<(), ExitError>
133132
where
134133
F: FnOnce(Account) -> Option<Account>;
135134

@@ -181,7 +180,7 @@ impl<'a> VirtualMachineSubstate<'a> {
181180
let account = self
182181
.known_account(&address)
183182
.cloned()
184-
.unwrap_or_else(|| state.account(address).unwrap_or_default());
183+
.unwrap_or_else(|| state.account(&address).unwrap_or_default());
185184
self.accounts.entry(address).or_insert(account)
186185
}
187186
}
@@ -245,12 +244,18 @@ where
245244
let vm = executor.into_state();
246245

247246
// pay gas fees
248-
if let Some(mut account) = vm.state.account(vm.origin) {
247+
if let Some(mut account) = vm.state.account(&vm.origin) {
249248
account.balance = account
250249
.balance
251-
.checked_sub(gas_fees)
250+
.checked_sub(
251+
gas_fees
252+
.try_into()
253+
.map_err(|_| Error::TransactionError(ExitError::OutOfFund))?,
254+
)
252255
.ok_or(Error::TransactionError(ExitError::OutOfFund))?;
253-
vm.state.modify_account(vm.origin, |_| Some(account));
256+
vm.state
257+
.modify_account(vm.origin, |_| Some(account))
258+
.map_err(Error::TransactionError)?;
254259
}
255260

256261
// exit_reason
@@ -369,50 +374,64 @@ impl<'a, State: EvmState> Backend for VirtualMachine<'a, State> {
369374
self.state.environment().chain_id
370375
}
371376
fn exists(&self, address: H160) -> bool {
372-
self.substate.known_account(&address).is_some() || self.state.contains(address)
377+
self.substate.known_account(&address).is_some() || self.state.contains(&address)
373378
}
374379
fn basic(&self, address: H160) -> Basic {
375380
self.substate
376381
.known_account(&address)
377382
.map(|account| Basic {
378383
balance: account.balance.into(),
379-
nonce: account.nonce,
384+
nonce: account.state.nonce,
380385
})
381386
.unwrap_or_else(|| {
382387
self.state
383-
.account(address)
388+
.account(&address)
384389
.map(|account| Basic {
385390
balance: account.balance.into(),
386-
nonce: account.nonce,
391+
nonce: account.state.nonce,
387392
})
388393
.unwrap_or_default()
389394
})
390395
}
391396
fn code(&self, address: H160) -> Vec<u8> {
392397
self.substate
393398
.known_account(&address)
394-
.map(|account| account.code.clone())
399+
.map(|account| account.state.code.clone())
395400
.unwrap_or_else(|| {
396401
self.state
397-
.account(address)
398-
.map(|account| account.code)
402+
.account(&address)
403+
.map(|account| account.state.code)
399404
.unwrap_or_default()
400405
})
401406
}
402407
fn storage(&self, address: H160, index: H256) -> H256 {
403408
self.substate
404409
.known_account(&address)
405-
.map(|account| account.storage.get(&index).cloned().unwrap_or_default())
410+
.map(|account| {
411+
account
412+
.state
413+
.storage
414+
.get(&index)
415+
.cloned()
416+
.unwrap_or_default()
417+
})
406418
.unwrap_or_else(|| {
407419
self.state
408-
.account(address)
409-
.map(|account| account.storage.get(&index).cloned().unwrap_or_default())
420+
.account(&address)
421+
.map(|account| {
422+
account
423+
.state
424+
.storage
425+
.get(&index)
426+
.cloned()
427+
.unwrap_or_default()
428+
})
410429
.unwrap_or_default()
411430
})
412431
}
413432
fn original_storage(&self, address: H160, index: H256) -> Option<H256> {
414-
match self.state.account(address) {
415-
Some(account) => account.storage.get(&index).cloned(),
433+
match self.state.account(&address) {
434+
Some(account) => account.state.storage.get(&index).cloned(),
416435
None => None,
417436
}
418437
}
@@ -461,7 +480,8 @@ impl<'a, State: EvmState> StackState<'a> for VirtualMachine<'a, State> {
461480
let mut account = account.clone();
462481
// cleanup storage from zero values
463482
// ref: https://github.com/rust-blockchain/evm/blob/8b1875c83105f47b74d3d7be7302f942e92eb374/src/backend/memory.rs#L185
464-
account.storage = account
483+
account.state.storage = account
484+
.state
465485
.storage
466486
.iter()
467487
.filter(|(_, v)| v != &&Default::default())
@@ -474,12 +494,12 @@ impl<'a, State: EvmState> StackState<'a> for VirtualMachine<'a, State> {
474494
} else {
475495
Some(account)
476496
}
477-
});
497+
})?;
478498
}
479499

480500
// delete account
481501
for address in self.substate.deletes.iter() {
482-
self.state.modify_account(*address, |_| None);
502+
self.state.modify_account(*address, |_| None)?;
483503
}
484504

485505
// save the logs
@@ -515,7 +535,7 @@ impl<'a, State: EvmState> StackState<'a> for VirtualMachine<'a, State> {
515535
fn is_empty(&self, address: H160) -> bool {
516536
match self.substate.known_account(&address) {
517537
Some(account) => account.is_empty(),
518-
None => match self.state.account(address) {
538+
None => match self.state.account(&address) {
519539
Some(account) => account.is_empty(),
520540
None => true,
521541
},
@@ -537,16 +557,16 @@ impl<'a, State: EvmState> StackState<'a> for VirtualMachine<'a, State> {
537557
}
538558

539559
fn inc_nonce(&mut self, address: H160) {
540-
self.substate.account_mut(address, self.state).nonce += U256::one();
560+
self.substate.account_mut(address, self.state).state.nonce += U256::one();
541561
}
542562

543563
fn set_storage(&mut self, address: H160, key: H256, value: H256) {
544564
let account = self.substate.account_mut(address, self.state);
545-
account.storage = account.storage.clone().put(key, value);
565+
account.state.storage = account.state.storage.clone().put(key, value);
546566
}
547567

548568
fn reset_storage(&mut self, address: H160) {
549-
self.substate.account_mut(address, self.state).storage = Default::default();
569+
self.substate.account_mut(address, self.state).state.storage = Default::default();
550570
}
551571

552572
fn log(&mut self, address: H160, topics: Vec<H256>, data: Vec<u8>) {
@@ -562,19 +582,29 @@ impl<'a, State: EvmState> StackState<'a> for VirtualMachine<'a, State> {
562582
}
563583

564584
fn set_code(&mut self, address: H160, code: Vec<u8>) {
565-
self.substate.account_mut(address, self.state).code = code;
585+
self.substate.account_mut(address, self.state).state.code = code;
566586
}
567587

568588
fn transfer(&mut self, transfer: Transfer) -> Result<(), ExitError> {
569589
let source = self.substate.account_mut(transfer.source, self.state);
570590

571-
source.balance = match source.balance.checked_sub(transfer.value) {
591+
source.balance = match source.balance.checked_sub(
592+
transfer
593+
.value
594+
.try_into()
595+
.map_err(|_| ExitError::OutOfFund)?,
596+
) {
572597
Some(res) => res,
573-
None => return Err(ExitError::OutOfGas),
598+
None => return Err(ExitError::OutOfFund),
574599
};
575600

576601
let target = self.substate.account_mut(transfer.target, self.state);
577-
target.balance = match target.balance.checked_add(transfer.value) {
602+
target.balance = match target.balance.checked_add(
603+
transfer
604+
.value
605+
.try_into()
606+
.map_err(|_| ExitError::Other("Balance overflow".into()))?,
607+
) {
578608
Some(res) => res,
579609
None => return Err(ExitError::Other("Balance overflow".into())),
580610
};
@@ -609,19 +639,20 @@ pub mod test {
609639
&self.environment
610640
}
611641

612-
fn account(&self, address: Address) -> Option<Account> {
613-
self.accounts.get(&address).cloned()
642+
fn account(&self, address: &Address) -> Option<Account> {
643+
self.accounts.get(address).cloned()
614644
}
615645

616-
fn contains(&self, address: Address) -> bool {
617-
self.accounts.contains(&address)
646+
fn contains(&self, address: &Address) -> bool {
647+
self.accounts.contains(address)
618648
}
619649

620-
fn modify_account<F>(&mut self, address: Address, f: F)
650+
fn modify_account<F>(&mut self, address: Address, f: F) -> Result<(), ExitError>
621651
where
622652
F: FnOnce(Account) -> Option<Account>,
623653
{
624654
self.accounts = self.accounts.clone().modify_account(address, f);
655+
Ok(())
625656
}
626657

627658
fn update_logs(&mut self, block_hash: H256, logs: Vec<Log>) {

0 commit comments

Comments
 (0)