Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
a2c6faa
add transfrom_evm_to_jor function
Mr-Leshiy Apr 1, 2022
ccace08
update evm ledger interface, norrow the scope
Mr-Leshiy Apr 1, 2022
3ac119a
add new evm_move_state function
Mr-Leshiy Apr 1, 2022
7f39eb6
fix clippy
Mr-Leshiy Apr 1, 2022
241d75b
fix evm_move_state function
Mr-Leshiy Apr 1, 2022
c803f5b
update transfrom_evm_to_jor
Mr-Leshiy Apr 4, 2022
a81ae59
Merge branch 'master' into ca-accounts-mapping
Mr-Leshiy Apr 4, 2022
4ab495b
add account ledger tests
Mr-Leshiy Apr 4, 2022
39293bb
fix clippy
Mr-Leshiy Apr 4, 2022
f5fb2e7
small refactor
Mr-Leshiy Apr 5, 2022
717bc5d
fix clippy
Mr-Leshiy Apr 5, 2022
a3f11c7
add two basic test cases
Mr-Leshiy Apr 5, 2022
1ebedd5
add one test case
Mr-Leshiy Apr 5, 2022
ce63451
add additional error tests
Mr-Leshiy Apr 6, 2022
516a698
Merge branch 'master' into ca-accounts-mapping
Mr-Leshiy Apr 7, 2022
a19d8e0
fix clippy
Mr-Leshiy Apr 7, 2022
ae45f8f
fix typos
Mr-Leshiy Apr 7, 2022
d59b033
add run_transaction_call_test_1
Mr-Leshiy Apr 7, 2022
3204dff
add run_transaction_call_test_2 test
Mr-Leshiy Apr 7, 2022
c9de4f3
fix run_transaction_call_test_2, add new run_transaction_call_test_er…
Mr-Leshiy Apr 8, 2022
7a0ac76
add run_transaction_call_test_error_2 test
Mr-Leshiy Apr 8, 2022
87df6c3
add contract address generation helper functions,
Mr-Leshiy Apr 8, 2022
81f7045
update
Mr-Leshiy Apr 9, 2022
55e16c5
update run_transaction_create_test_1
Mr-Leshiy Apr 11, 2022
72714c7
add few more tests
Mr-Leshiy Apr 11, 2022
0fd907c
add error tests
Mr-Leshiy Apr 11, 2022
9db2165
Merge branch 'master' into ca-accounts-mapping
Mr-Leshiy Apr 12, 2022
6b642fe
fix clippy
Mr-Leshiy Apr 12, 2022
1766581
fix typo
Mr-Leshiy Apr 12, 2022
3f5c065
remove unneeded code
Mr-Leshiy Apr 12, 2022
e0c0075
add desctiption for the transform_evm_to_jor function
Mr-Leshiy Apr 13, 2022
d991ac5
Merge branch 'master' into ca-accounts-mapping
Mr-Leshiy Apr 28, 2022
72c4366
Merge branch 'master' into ca-accounts-mapping
Mr-Leshiy May 5, 2022
7f41922
fix build
Mr-Leshiy May 5, 2022
5b6e43b
Merge branch 'master' into ca-accounts-mapping
Mr-Leshiy May 12, 2022
0d3f14e
update comments
Mr-Leshiy May 12, 2022
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
41 changes: 34 additions & 7 deletions chain-evm/src/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ use ethereum_types::{H160, H256, U256};
use evm::{
backend::{Backend, Basic},
executor::stack::{Accessed, StackExecutor, StackState, StackSubstateMetadata},
Context, ExitFatal, ExitReason, ExitRevert, Transfer,
Context, CreateScheme, ExitFatal, ExitReason, ExitRevert, Transfer,
};
use ripemd::Digest;
use sha3::Keccak256;
use std::collections::{BTreeMap, BTreeSet};
use thiserror::Error;

Expand Down Expand Up @@ -220,6 +222,36 @@ impl<'a, T> VirtualMachine<'a, T> {
}
}

pub fn generate_address_create<State: EvmState>(
vm: VirtualMachine<State>,
caller: Address,
) -> Address {
let precompiles = Precompiles::new();
let config = vm.config;
let executor = StackExecutor::new_with_precompiles(vm, config, &precompiles);

executor.create_address(CreateScheme::Legacy { caller })
}

pub fn generate_address_create2<State: EvmState>(
vm: VirtualMachine<State>,
caller: Address,
init_code: ByteCode,
salt: H256,
) -> Address {
let precompiles = Precompiles::new();
let config = vm.config;
let executor = StackExecutor::new_with_precompiles(vm, config, &precompiles);

let code_hash = H256::from_slice(Keccak256::digest(&init_code).as_slice());

executor.create_address(CreateScheme::Create2 {
caller,
code_hash,
salt,
})
}

/// Top-level abstraction for the EVM with the
/// necessary types used to get the runtime going.
fn execute_transaction<State: EvmState, F, T>(vm: VirtualMachine<State>, f: F) -> Result<T, Error>
Expand All @@ -232,7 +264,6 @@ where
let config = vm.config;
let gas_price = vm.gas_price();

// let memory_stack_state = MemoryStackState::new(vm.substate.metadata.clone(), &vm);
let mut executor = StackExecutor::new_with_precompiles(vm, config, &precompiles);

let (exit_reason, val) = f(&mut executor);
Expand Down Expand Up @@ -284,8 +315,6 @@ fn convert_access_list_to_tuples_vec(access_list: AccessList) -> Vec<(Address, V
}

/// Execute a CREATE transaction
#[allow(clippy::too_many_arguments)]
#[allow(clippy::boxed_local)]
pub fn transact_create<State: EvmState>(
vm: VirtualMachine<State>,
value: U256,
Expand All @@ -296,12 +325,11 @@ pub fn transact_create<State: EvmState>(
let gas_limit = vm.gas_limit;
let access_list = convert_access_list_to_tuples_vec(access_list);
execute_transaction(vm, |executor| {
executor.transact_create(caller, value, init_code.to_vec(), gas_limit, access_list)
executor.transact_create(caller, value, init_code.into(), gas_limit, access_list)
})
}

/// Execute a CREATE2 transaction
#[allow(clippy::too_many_arguments)]
pub fn transact_create2<State: EvmState>(
vm: VirtualMachine<State>,
value: U256,
Expand All @@ -325,7 +353,6 @@ pub fn transact_create2<State: EvmState>(
}

/// Execute a CALL transaction
#[allow(clippy::too_many_arguments)]
pub fn transact_call<State: EvmState>(
vm: VirtualMachine<State>,
address: Address,
Expand Down
43 changes: 13 additions & 30 deletions chain-evm/src/precompiles/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,38 +73,21 @@ pub struct Precompiles(pub prelude::BTreeMap<prelude::Address, PrecompileFn>);

impl Precompiles {
pub fn new() -> Self {
let addresses = prelude::vec![
ECRecover::ADDRESS,
SHA256::ADDRESS,
RIPEMD160::ADDRESS,
Identity::ADDRESS,
ModExp::ADDRESS,
Bn128Add::ADDRESS,
Bn128Mul::ADDRESS,
Bn128Pair::ADDRESS,
Blake2F::ADDRESS,
ExitToNear::ADDRESS,
ExitToEthereum::ADDRESS,
let fun: Vec<(prelude::Address, PrecompileFn)> = vec![
(ECRecover::ADDRESS, ECRecover::run),
(SHA256::ADDRESS, SHA256::run),
(RIPEMD160::ADDRESS, RIPEMD160::run),
(Identity::ADDRESS, Identity::run),
(ModExp::ADDRESS, ModExp::run),
(Bn128Add::ADDRESS, Bn128Add::run),
(Bn128Mul::ADDRESS, Bn128Mul::run),
(Bn128Pair::ADDRESS, Bn128Pair::run),
(Blake2F::ADDRESS, Blake2F::run),
(ExitToNear::ADDRESS, ExitToNear::run),
(ExitToEthereum::ADDRESS, ExitToEthereum::run),
];
let fun: prelude::Vec<PrecompileFn> = prelude::vec![
ECRecover::run,
SHA256::run,
RIPEMD160::run,
Identity::run,
ModExp::run,
Bn128Add::run,
Bn128Mul::run,
Bn128Pair::run,
Blake2F::run,
ExitToNear::run,
ExitToEthereum::run,
];
let mut map = prelude::BTreeMap::new();
for (address, fun) in addresses.into_iter().zip(fun) {
map.insert(address, fun);
}

Precompiles(map)
Precompiles(fun.into_iter().collect())
}
}

Expand Down
29 changes: 23 additions & 6 deletions chain-evm/src/state/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,13 @@ pub struct AccountState {

impl Account {
pub fn is_empty(&self) -> bool {
self.state.nonce.is_zero()
&& self.balance == Balance::zero()
&& self.state.storage.is_empty()
self.balance == Balance::zero() && self.state.is_empty()
}
}

impl AccountState {
pub fn is_empty(&self) -> bool {
self.nonce.is_zero() && self.code.is_empty() && self.storage.is_empty()
}
}

Expand Down Expand Up @@ -115,11 +119,20 @@ impl AccountTrie {
}
}

#[cfg(test)]
#[cfg(any(test, feature = "property-test-api"))]
mod test {
use super::*;

const MAX_SIZE: u64 = u64::MAX;
use quickcheck::{Arbitrary, Gen};

impl Arbitrary for AccountState {
fn arbitrary<G: Gen>(g: &mut G) -> Self {
Self {
storage: Storage::new(),
code: Box::new([Arbitrary::arbitrary(g); 32]),
nonce: u64::arbitrary(g).into(),
}
}
}

#[test]
fn account_balance_u256_zero() {
Expand All @@ -128,6 +141,8 @@ mod test {

#[test]
fn account_balance_u256_checked_add() {
const MAX_SIZE: u64 = u64::MAX;

let val = 100u64;
assert_eq!(
Balance::from(val).checked_add(U256::from(0u64).try_into().unwrap()),
Expand All @@ -154,6 +169,8 @@ mod test {

#[test]
fn account_balance_u256_can_never_use_more_than_64_bits() {
const MAX_SIZE: u64 = u64::MAX;

// convert from u64
assert_eq!(Balance::from(MAX_SIZE), Balance(MAX_SIZE));
// try to convert from U256
Expand Down
2 changes: 1 addition & 1 deletion chain-evm/src/state/logs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use super::Trie;
/// In-memory representation of all logs.
pub type BlockLogsTrie = Trie<BlockHash, Vec<Log>>;

#[derive(Default, Clone, PartialEq, Eq)]
#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct LogsState {
block_logs: BlockLogsTrie,
}
Expand Down
127 changes: 124 additions & 3 deletions chain-impl-mockchain/src/accounting/account/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,17 +208,48 @@ impl<ID: Clone + Eq + Hash, Extra: Clone> Ledger<ID, Extra> {
.map_err(|e| e.into())
}

#[cfg(feature = "evm")]
pub fn evm_move_state(
mut self,
new_identifier: ID,
old_identifier: &ID,
) -> Result<Self, LedgerError> {
// get old state
match self.get_state(old_identifier).cloned() {
Ok(state) => {
// remove old state
self.0 = self.0.update(old_identifier, |_| Ok(None))?;
// move state
self.0
.insert_or_update(new_identifier, state.clone(), |st| {
if !st.evm_state.is_empty() {
return Err(LedgerError::AlreadyExists);
}
Ok(Some(AccountState {
value: st.value.checked_add(state.value)?,
evm_state: state.evm_state,
..st.clone()
}))
})
.map(Ledger)
}
// if does not exist do nothing
Err(LedgerError::NonExistent) => Ok(self),
Err(e) => Err(e),
}
}

#[cfg(feature = "evm")]
pub fn evm_insert_or_update(
&self,
identifier: &ID,
identifier: ID,
value: Value,
evm_state: chain_evm::state::AccountState,
extra: Extra,
) -> Result<Self, LedgerError> {
self.0
.insert_or_update(
identifier.clone(),
identifier,
AccountState::new_evm(evm_state.clone(), value, extra),
|st| {
Ok(Some(AccountState {
Expand Down Expand Up @@ -326,8 +357,98 @@ mod tests {
}
}

#[cfg(feature = "evm")]
#[quickcheck]
#[allow(clippy::too_many_arguments)]
fn evm_functions_test(
account_id1: Identifier,
account_id2: Identifier,
account_id3: Identifier,
value1: Value,
value2: Value,
value3: Value,
evm_state1: chain_evm::state::AccountState,
evm_state2: chain_evm::state::AccountState,
) -> bool {
let mut ledger = Ledger::new();

ledger = ledger
.evm_insert_or_update(account_id1.clone(), value1, evm_state1.clone(), ())
.unwrap();

assert_eq!(
ledger.get_state(&account_id1),
Ok(&AccountState::new_evm(evm_state1, value1, ()))
);

ledger = ledger
.evm_insert_or_update(account_id1.clone(), value2, evm_state2.clone(), ())
.unwrap();

assert_eq!(
ledger.get_state(&account_id1),
Ok(&AccountState::new_evm(evm_state2.clone(), value2, ()))
);

ledger = ledger
.evm_move_state(account_id2.clone(), &account_id1)
.unwrap();

if account_id1 != account_id2 {
assert_eq!(
ledger.get_state(&account_id1),
Err(LedgerError::NonExistent)
);
}

assert_eq!(
ledger.get_state(&account_id2),
Ok(&AccountState::new_evm(evm_state2.clone(), value2, ()))
);

ledger = ledger
.evm_insert_or_update(
account_id3.clone(),
value3,
chain_evm::state::AccountState::default(),
(),
)
.unwrap();

assert_eq!(
ledger.get_state(&account_id3),
Ok(&AccountState::new_evm(
chain_evm::state::AccountState::default(),
value3,
()
))
);

ledger = ledger
.evm_move_state(account_id3.clone(), &account_id2)
.unwrap();

if account_id2 != account_id3 {
assert_eq!(
ledger.get_state(&account_id2),
Err(LedgerError::NonExistent)
);

assert_eq!(
ledger.get_state(&account_id3),
Ok(&AccountState::new_evm(
evm_state2,
value3.saturating_add(value2),
()
))
);
}

true
}

#[quickcheck]
pub fn account_ledger_test(
fn account_ledger_test(
mut ledger: Ledger,
account_id: Identifier,
value: Value,
Expand Down
Loading