Skip to content

Commit

Permalink
Add nonce field for the EvmTransaction (#810)
Browse files Browse the repository at this point in the history
* update EvmTransaction struct

* update

* add validate_transaction_nonce() function

* add tests

* fix clippy

* fix ui_test

* fixed suggestions
  • Loading branch information
Mr-Leshiy authored May 27, 2022
1 parent 0ba454f commit c9fba3e
Show file tree
Hide file tree
Showing 8 changed files with 352 additions and 253 deletions.
6 changes: 3 additions & 3 deletions chain-evm/src/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -415,14 +415,14 @@ impl<'a, State: EvmState> Backend for VirtualMachine<'a, State> {
.known_account(&address)
.map(|account| Basic {
balance: account.balance.into(),
nonce: account.state.nonce,
nonce: account.state.nonce.into(),
})
.unwrap_or_else(|| {
self.state
.account(&address)
.map(|account| Basic {
balance: account.balance.into(),
nonce: account.state.nonce,
nonce: account.state.nonce.into(),
})
.unwrap_or_default()
})
Expand Down Expand Up @@ -592,7 +592,7 @@ impl<'a, State: EvmState> StackState<'a> for VirtualMachine<'a, State> {
}

fn inc_nonce(&mut self, address: H160) {
self.substate.account_mut(address, self.state).state.nonce += U256::one();
self.substate.account_mut(address, self.state).state.nonce += 1;
}

fn set_storage(&mut self, address: H160, key: H256, value: H256) {
Expand Down
8 changes: 3 additions & 5 deletions chain-evm/src/state/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ use crate::{
};
use ethereum_types::U256;

pub type Nonce = U256;

/// Ethereum account balance which uses the least 64 significant bits of the `U256` type.
#[derive(Clone, Copy, Default, Debug, PartialEq, Eq, PartialOrd)]
pub struct Balance(u64);
Expand Down Expand Up @@ -79,7 +77,7 @@ pub struct AccountState {
/// EVM bytecode of this account.
pub code: ByteCode,
/// Account nonce. A number of value transfers from this account.
pub nonce: Nonce,
pub nonce: u64,
}

impl Account {
Expand All @@ -90,7 +88,7 @@ impl Account {

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

Expand Down Expand Up @@ -129,7 +127,7 @@ mod test {
Self {
storage: Storage::new(),
code: Box::new([Arbitrary::arbitrary(g); 32]),
nonce: u64::arbitrary(g).into(),
nonce: u64::arbitrary(g),
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion chain-evm/src/state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ mod logs;
mod storage;
mod trie;

pub use account::{Account, AccountState, AccountTrie, Balance, ByteCode, Nonce};
pub use account::{Account, AccountState, AccountTrie, Balance, ByteCode};
use evm::ExitError;
pub use logs::LogsState;
use std::borrow::Cow;
Expand Down
2 changes: 1 addition & 1 deletion chain-evm/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ impl TryFrom<AccountState> for Account {
.try_into()
.map_err(|_| "can not convert balance")?,
state: crate::state::AccountState {
nonce: val.nonce,
nonce: val.nonce.as_u64(),
storage: val.storage.into_iter().collect(),
code: val.code.into(),
},
Expand Down
252 changes: 111 additions & 141 deletions chain-impl-mockchain/src/evm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,55 +13,37 @@ use chain_evm::{
state::ByteCode,
};

/// Variants of supported EVM transactions
/// Variants of supported EVM action types
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum EvmTransaction {
pub enum EvmActionType {
#[cfg(feature = "evm")]
Create {
caller: Address,
value: u64,
init_code: ByteCode,
gas_limit: u64,
access_list: AccessList,
},
Create { init_code: ByteCode },
#[cfg(feature = "evm")]
Create2 {
caller: Address,
value: u64,
init_code: ByteCode,
salt: H256,
gas_limit: u64,
access_list: AccessList,
},
Create2 { init_code: ByteCode, salt: H256 },
#[cfg(feature = "evm")]
Call {
caller: Address,
address: Address,
value: u64,
data: ByteCode,
gas_limit: u64,
access_list: AccessList,
},
Call { address: Address, data: ByteCode },
}

#[cfg(feature = "evm")]
impl Default for EvmTransaction {
fn default() -> Self {
Self::Call {
caller: Default::default(),
address: Default::default(),
value: Default::default(),
data: Default::default(),
gas_limit: Default::default(),
access_list: Default::default(),
}
}
/// Variants of supported EVM transactions
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct EvmTransaction {
#[cfg(feature = "evm")]
pub caller: Address,
#[cfg(feature = "evm")]
pub value: u64,
#[cfg(feature = "evm")]
pub nonce: u64,
#[cfg(feature = "evm")]
pub gas_limit: u64,
#[cfg(feature = "evm")]
pub access_list: AccessList,
pub action_type: EvmActionType,
}

#[cfg(feature = "evm")]
impl From<&EvmTransaction> for u8 {
fn from(other: &EvmTransaction) -> Self {
use EvmTransaction::*;
impl From<&EvmActionType> for u8 {
fn from(other: &EvmActionType) -> Self {
use EvmActionType::*;
match other {
Create { .. } => 0,
Create2 { .. } => 1,
Expand All @@ -73,98 +55,84 @@ impl From<&EvmTransaction> for u8 {
#[cfg(feature = "evm")]
impl Decodable for EvmTransaction {
fn decode(rlp: &Rlp<'_>) -> Result<Self, DecoderError> {
fn decode_tx_create(rlp: &Rlp<'_>) -> Result<EvmTransaction, DecoderError> {
Ok(EvmTransaction::Create {
caller: rlp.val_at(1)?,
value: rlp.val_at(2)?,
init_code: rlp.list_at(3)?.into_boxed_slice(),
gas_limit: rlp.val_at(4)?,
access_list: rlp.list_at(5)?,
})
}
fn decode_tx_create2(rlp: &Rlp<'_>) -> Result<EvmTransaction, DecoderError> {
Ok(EvmTransaction::Create2 {
caller: rlp.val_at(1)?,
value: rlp.val_at(2)?,
init_code: rlp.list_at(3)?.into_boxed_slice(),
salt: rlp.val_at(4)?,
gas_limit: rlp.val_at(5)?,
access_list: rlp.list_at(6)?,
})
}
fn decode_tx_call(rlp: &Rlp<'_>) -> Result<EvmTransaction, DecoderError> {
Ok(EvmTransaction::Call {
caller: rlp.val_at(1)?,
address: rlp.val_at(2)?,
value: rlp.val_at(3)?,
data: rlp.list_at(4)?.into_boxed_slice(),
gas_limit: rlp.val_at(5)?,
access_list: rlp.list_at(6)?,
})
}

let caller = rlp.val_at(1)?;
let value = rlp.val_at(2)?;
let nonce = rlp.val_at(3)?;
let gas_limit = rlp.val_at(4)?;
let access_list = rlp.list_at(5)?;
match rlp.val_at(0)? {
0u8 => decode_tx_create(rlp),
1u8 => decode_tx_create2(rlp),
2u8 => decode_tx_call(rlp),
_ => Err(DecoderError::Custom("invalid evm transaction")),
}
}
}

#[cfg(feature = "evm")]
impl Encodable for EvmTransaction {
fn rlp_append(&self, s: &mut RlpStream) {
use EvmTransaction::*;
match self {
Create {
0u8 => Ok(EvmTransaction {
caller,
value,
init_code,
nonce,
gas_limit,
access_list,
} => {
s.begin_list(6);
s.append(&u8::from(self));
s.append(caller);
s.append(value);
s.append_list(init_code);
s.append(gas_limit);
s.append_list(access_list);
}
Create2 {
action_type: EvmActionType::Create {
init_code: rlp.list_at(6)?.into_boxed_slice(),
},
}),
1u8 => Ok(EvmTransaction {
caller,
value,
init_code,
salt,
nonce,
gas_limit,
access_list,
} => {
s.begin_list(7);
s.append(&u8::from(self));
s.append(caller);
s.append(value);
s.append_list(init_code);
s.append(salt);
s.append(gas_limit);
s.append_list(access_list);
}
Call {
action_type: EvmActionType::Create2 {
init_code: rlp.list_at(6)?.into_boxed_slice(),
salt: rlp.val_at(7)?,
},
}),
2u8 => Ok(EvmTransaction {
caller,
address,
value,
data,
nonce,
gas_limit,
access_list,
} => {
action_type: EvmActionType::Call {
address: rlp.val_at(6)?,
data: rlp.list_at(7)?.into_boxed_slice(),
},
}),
_ => Err(DecoderError::Custom("invalid evm transaction")),
}
}
}

#[cfg(feature = "evm")]
impl Encodable for EvmTransaction {
fn rlp_append(&self, s: &mut RlpStream) {
match &self.action_type {
EvmActionType::Create { init_code } => {
s.begin_list(7);
s.append(&u8::from(self));
s.append(caller);
s.append(&u8::from(&self.action_type));
s.append(&self.caller);
s.append(&self.value);
s.append(&self.nonce);
s.append(&self.gas_limit);
s.append_list(&self.access_list);
s.append_list(init_code);
}
EvmActionType::Create2 { init_code, salt } => {
s.begin_list(8);
s.append(&u8::from(&self.action_type));
s.append(&self.caller);
s.append(&self.value);
s.append(&self.nonce);
s.append(&self.gas_limit);
s.append_list(&self.access_list);
s.append_list(init_code);
s.append(salt);
}
EvmActionType::Call { address, data } => {
s.begin_list(8);
s.append(&u8::from(&self.action_type));
s.append(&self.caller);
s.append(&self.value);
s.append(&self.nonce);
s.append(&self.gas_limit);
s.append_list(&self.access_list);
s.append(address);
s.append(value);
s.append_list(data);
s.append(gas_limit);
s.append_list(access_list);
}
}
}
Expand Down Expand Up @@ -212,10 +180,30 @@ mod test {
};
use quickcheck::Arbitrary;

impl Arbitrary for EvmActionType {
fn arbitrary<G: quickcheck::Gen>(g: &mut G) -> Self {
match u8::arbitrary(g) % 3 {
0 => Self::Create {
init_code: Box::new([Arbitrary::arbitrary(g); 32]),
},
1 => Self::Create2 {
init_code: Box::new([Arbitrary::arbitrary(g); 32]),
salt: [u8::arbitrary(g); H256::len_bytes()].into(),
},
2 => Self::Call {
address: [u8::arbitrary(g); H160::len_bytes()].into(),
data: Box::new([Arbitrary::arbitrary(g); 32]),
},
_ => unreachable!(),
}
}
}

impl Arbitrary for EvmTransaction {
fn arbitrary<G: quickcheck::Gen>(g: &mut G) -> Self {
let caller = [u8::arbitrary(g); H160::len_bytes()].into();
let value = u64::arbitrary(g);
let nonce = u64::arbitrary(g);
let gas_limit = Arbitrary::arbitrary(g);
let access_list: AccessList = match u8::arbitrary(g) % 2 {
0 => vec![],
Expand Down Expand Up @@ -243,31 +231,13 @@ mod test {
},
],
};
match u8::arbitrary(g) % 3 {
0 => Self::Create {
caller,
value,
init_code: Box::new([Arbitrary::arbitrary(g); 32]),
gas_limit,
access_list,
},
1 => Self::Create2 {
caller,
value,
init_code: Box::new([Arbitrary::arbitrary(g); 32]),
salt: [u8::arbitrary(g); H256::len_bytes()].into(),
gas_limit,
access_list,
},
2 => Self::Call {
caller,
address: [u8::arbitrary(g); H160::len_bytes()].into(),
value,
data: Box::new([Arbitrary::arbitrary(g); 32]),
gas_limit,
access_list,
},
_ => unreachable!(),
Self {
caller,
value,
nonce,
gas_limit,
access_list,
action_type: Arbitrary::arbitrary(g),
}
}
}
Expand Down
Loading

0 comments on commit c9fba3e

Please sign in to comment.