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: Use checked operations #2579

Merged
merged 8 commits into from
Oct 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
26 changes: 15 additions & 11 deletions lib/ain-evm/src/backend.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::{error::Error, sync::Arc};

use anyhow::format_err;
use ethereum::{Account, Log};
use ethereum_types::{H160, H256, U256};
use evm::backend::{Apply, ApplyBackend, Backend, Basic};
Expand Down Expand Up @@ -410,7 +411,10 @@ impl EVMBackend {
let basic = self.basic(address);

let new_basic = Basic {
balance: basic.balance + amount,
balance: basic
.balance
.checked_add(amount)
.ok_or_else(|| format_err!("Balance overflow"))?,
..basic
};

Expand All @@ -424,21 +428,21 @@ impl EVMBackend {
.ok_or(BackendError::NoSuchAccount(address))?;

if account.balance < amount {
Err(BackendError::InsufficientBalance(InsufficientBalance {
return Err(BackendError::InsufficientBalance(InsufficientBalance {
address,
account_balance: account.balance,
amount,
})
.into())
} else {
let new_basic = Basic {
balance: account.balance - amount,
nonce: account.nonce,
};

self.apply(address, Some(new_basic), None, Vec::new(), false)?;
Ok(())
.into());
}

let new_basic = Basic {
balance: account.balance - amount, // sub is safe due to check above
nonce: account.nonce,
};

self.apply(address, Some(new_basic), None, Vec::new(), false)?;
Ok(())
}
}

Expand Down
42 changes: 25 additions & 17 deletions lib/ain-evm/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ pub struct FeeHistoryData {
}

pub const INITIAL_BASE_FEE: U256 = U256([10_000_000_000, 0, 0, 0]); // wei
pub const MAX_BASE_FEE: U256 = crate::weiamount::MAX_MONEY_SATS;

impl BlockService {
pub fn new(storage: Arc<Storage>) -> Result<Self> {
Expand Down Expand Up @@ -76,34 +77,33 @@ impl BlockService {
parent_base_fee: U256,
base_fee_max_change_denominator: U256,
initial_base_fee: U256,
max_base_fee: U256,
) -> Result<U256> {
match parent_gas_used.cmp(&parent_gas_target) {
Ordering::Equal => Ok(parent_base_fee),
Ordering::Greater => {
let gas_used_delta = parent_gas_used - parent_gas_target;
let gas_used_delta = parent_gas_used - parent_gas_target; // sub is safe due to cmp
let base_fee_per_gas_delta = self.get_base_fee_per_gas_delta(
gas_used_delta,
parent_gas_target,
parent_base_fee,
base_fee_max_change_denominator,
)?;
Ok(max(
parent_base_fee + base_fee_per_gas_delta,
initial_base_fee,
))
Ok(parent_base_fee
.saturating_add(base_fee_per_gas_delta)
.min(max_base_fee))
}
Ordering::Less => {
let gas_used_delta = parent_gas_target - parent_gas_used;
let gas_used_delta = parent_gas_target - parent_gas_used; // sub is safe due to cmp
let base_fee_per_gas_delta = self.get_base_fee_per_gas_delta(
gas_used_delta,
parent_gas_target,
parent_base_fee,
base_fee_max_change_denominator,
)?;
Ok(max(
parent_base_fee - base_fee_per_gas_delta,
initial_base_fee,
))
Ok(parent_base_fee
.saturating_sub(base_fee_per_gas_delta)
.max(initial_base_fee))
}
}
}
Expand Down Expand Up @@ -134,13 +134,15 @@ impl BlockService {
parent_base_fee: U256,
base_fee_max_change_denominator: U256,
initial_base_fee: U256,
max_base_fee: U256,
) -> Result<U256> {
self.base_fee_calculation(
parent_gas_used,
parent_gas_target,
parent_base_fee,
base_fee_max_change_denominator,
initial_base_fee,
max_base_fee,
)
}

Expand Down Expand Up @@ -171,6 +173,7 @@ impl BlockService {
parent_base_fee,
base_fee_max_change_denominator,
INITIAL_BASE_FEE,
MAX_BASE_FEE,
)
}

Expand Down Expand Up @@ -201,7 +204,9 @@ impl BlockService {

blocks.push(block);

block_number -= U256::one();
block_number = block_number
.checked_sub(U256::one())
.ok_or_else(|| format_err!("block_number underflow"))?;
}

let oldest_block = blocks.last().unwrap().header.number;
Expand All @@ -216,7 +221,7 @@ impl BlockService {
f64::default() // empty block
} else {
u64::try_from(block.header.gas_used)? as f64
/ u64::try_from(block.header.gas_limit)? as f64
/ u64::try_from(block.header.gas_limit)? as f64 // safe due to check
};

base_fee_per_gas.push(base_fee);
Expand Down Expand Up @@ -281,10 +286,11 @@ impl BlockService {
};

// add another entry for baseFeePerGas
let next_block_base_fee = match self
.storage
.get_block_by_number(&(first_block + U256::one()))?
{
let next_block_base_fee = match self.storage.get_block_by_number(
&(first_block
.checked_add(U256::one())
.ok_or_else(|| format_err!("Block number overflow"))?),
)? {
None => {
// get one block earlier (this should exist)
let block = self
Expand Down Expand Up @@ -368,7 +374,9 @@ impl BlockService {
.header
.base_fee;

Ok(base_fee + priority_fee)
Ok(base_fee
.checked_add(priority_fee)
.ok_or_else(|| format_err!("Legacy fee overflow"))?)
}
}

Expand Down
2 changes: 1 addition & 1 deletion lib/ain-evm/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ pub fn get_abi_encoded_string(input: &str) -> H256 {
let length = input.len();

let mut storage_value = H256::default();
storage_value.0[31] = (length * 2) as u8;
storage_value.0[31] = (length * 2) as u8; // safe due to character limits on token name/symbol on DVM
storage_value.0[..length].copy_from_slice(input.as_bytes());

storage_value
Expand Down
10 changes: 8 additions & 2 deletions lib/ain-evm/src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -945,13 +945,19 @@ impl EVMCoreService {

let mut nonce = state_root_nonce;
for elem in nonce_set.range(state_root_nonce..) {
if (elem - nonce) > U256::from(1) {
if elem
.checked_sub(nonce)
.ok_or_else(|| format_err!("elem underflow"))?
> U256::one()
{
break;
} else {
nonce = *elem;
}
}
nonce += U256::from(1);
nonce = nonce
.checked_add(U256::one())
.ok_or_else(|| format_err!("nonce overflow"))?;
Ok(nonce)
}
}
Expand Down
20 changes: 16 additions & 4 deletions lib/ain-evm/src/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,13 @@ impl EVMServices {
.ok_or_else(|| format_err!("calculate total gas fees failed from overflow"))?;
}

let total_burnt_fees = template.total_gas_used * base_fee;
let total_priority_fees = total_gas_fees - total_burnt_fees;
let total_burnt_fees = template
.total_gas_used
.checked_mul(base_fee)
.ok_or_else(|| format_err!("total_burnt_fees overflow"))?;
let total_priority_fees = total_gas_fees
.checked_sub(total_burnt_fees)
.ok_or_else(|| format_err!("total_priority_fees underflow"))?;
debug!(
"[construct_block] Total burnt fees : {:#?}",
total_burnt_fees
Expand Down Expand Up @@ -227,7 +232,7 @@ impl EVMServices {
block.header.hash(),
block.header.number,
base_fee,
);
)?;
template.block_data = Some(BlockData { block, receipts });

Ok(FinalizedBlockInfo {
Expand Down Expand Up @@ -513,7 +518,14 @@ impl EVMServices {
) -> Result<u64> {
let (target_block, initial_state_root) = match self.storage.get_latest_block()? {
None => (U256::zero(), GENESIS_STATE_ROOT), // Genesis block
Some(block) => (block.header.number + 1, block.header.state_root),
Some(block) => (
block
.header
.number
.checked_add(U256::one())
.ok_or_else(|| format_err!("Block number overflow"))?,
block.header.state_root,
),
};

let block_difficulty = U256::from(difficulty);
Expand Down
7 changes: 6 additions & 1 deletion lib/ain-evm/src/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,12 @@ impl<'backend> AinExecutor<'backend> {
let used_gas = if system_tx { 0u64 } else { executor.used_gas() };
let total_gas_used = self.backend.vicinity.total_gas_used;
let block_gas_limit = self.backend.vicinity.block_gas_limit;
if !system_tx && total_gas_used + U256::from(used_gas) > block_gas_limit {
if !system_tx
&& total_gas_used
.checked_add(U256::from(used_gas))
.ok_or_else(|| format_err!("total_gas_used overflow"))?
> block_gas_limit
{
return Err(format_err!(
"[exec] block size limit exceeded, tx cannot make it into the block"
)
Expand Down
4 changes: 2 additions & 2 deletions lib/ain-evm/src/fee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ pub fn calculate_current_prepay_gas_fee(signed_tx: &SignedTx, base_fee: U256) ->
let gas_limit = signed_tx.gas_limit();

gas_limit
.checked_mul(signed_tx.effective_gas_price(base_fee))
.checked_mul(signed_tx.effective_gas_price(base_fee)?)
.ok_or_else(|| format_err!("calculate current prepay fee failed from overflow").into())
}

Expand All @@ -61,6 +61,6 @@ pub fn calculate_max_prepay_gas_fee(signed_tx: &SignedTx) -> Result<U256> {
// Gas prices are denoted in wei
pub fn calculate_gas_fee(signed_tx: &SignedTx, used_gas: U256, base_fee: U256) -> Result<U256> {
used_gas
.checked_mul(signed_tx.effective_gas_price(base_fee))
.checked_mul(signed_tx.effective_gas_price(base_fee)?)
.ok_or_else(|| format_err!("calculate gas fee failed from overflow").into())
}
6 changes: 3 additions & 3 deletions lib/ain-evm/src/filters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ impl FilterService {
to_block: U256,
) -> usize {
let mut filter_id = self.filter_id.write().unwrap();
*filter_id += 1;
*filter_id = filter_id.wrapping_add(1);

let mut filters = self.filters.write().unwrap();
filters.insert(
Expand All @@ -103,7 +103,7 @@ impl FilterService {
pub fn create_block_filter(&self) -> usize {
let mut filters = self.filters.write().unwrap();
let mut filter_id = self.filter_id.write().unwrap();
*filter_id += 1;
*filter_id = filter_id.wrapping_add(1);

let filter = Filter::NewBlock(BlockFilter {
id: *filter_id,
Expand All @@ -118,7 +118,7 @@ impl FilterService {
pub fn create_transaction_filter(&self) -> usize {
let mut filters = self.filters.write().unwrap();
let mut filter_id = self.filter_id.write().unwrap();
*filter_id += 1;
*filter_id = filter_id.wrapping_add(1);

let filter = Filter::NewPendingTransactions(PendingTransactionFilter {
id: *filter_id,
Expand Down
11 changes: 8 additions & 3 deletions lib/ain-evm/src/log.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use anyhow::format_err;
use std::{collections::HashMap, sync::Arc};

use ethereum::ReceiptV3;
Expand Down Expand Up @@ -50,7 +51,7 @@ impl LogService {
block_number: U256,
) -> Result<()> {
let mut logs_map: HashMap<H160, Vec<LogIndex>> = HashMap::new();
let mut log_index = 0; // log index is a block level index
let mut log_index = 0_usize; // log index is a block level index
for receipt in receipts {
let logs = match &receipt.receipt {
ReceiptV3::Legacy(r) | ReceiptV3::EIP2930(r) | ReceiptV3::EIP1559(r) => &r.logs,
Expand All @@ -71,7 +72,9 @@ impl LogService {
transaction_index: U256::from(receipt.tx_index),
});

log_index += 1;
log_index = log_index
.checked_add(1)
.ok_or_else(|| format_err!("log_index overflow"))?;
}
}

Expand Down Expand Up @@ -142,7 +145,9 @@ impl LogService {
while from_block_number <= filter.to_block {
debug!("Will query block {from_block_number}");
block_numbers.push(from_block_number);
from_block_number += U256::one();
from_block_number = from_block_number
.checked_add(U256::one())
.ok_or_else(|| format_err!("from_block_number overflow"))?;
}

let logs = block_numbers
Expand Down
27 changes: 18 additions & 9 deletions lib/ain-evm/src/receipt.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use anyhow::format_err;
use std::sync::Arc;

use ethereum::{util::ordered_trie_root, EnvelopedEncodable, ReceiptV3};
Expand Down Expand Up @@ -61,8 +62,8 @@ impl ReceiptService {
block_hash: H256,
block_number: U256,
base_fee: U256,
) -> Vec<Receipt> {
let mut logs_size = 0;
) -> Result<Vec<Receipt>> {
let mut logs_size = 0_usize;
let mut cumulative_gas = U256::zero();

transactions
Expand All @@ -76,10 +77,14 @@ impl ReceiptService {
| ReceiptV3::EIP1559(data) => data,
};
let logs_len = receipt_data.logs.len();
logs_size += logs_len;
cumulative_gas += receipt_data.used_gas;

Receipt {
logs_size = logs_size
.checked_add(logs_len)
.ok_or_else(|| format_err!("logs_size overflow"))?;
cumulative_gas = cumulative_gas
.checked_add(receipt_data.used_gas)
.ok_or_else(|| format_err!("cumulative_gas overflow"))?;

let receipt = Receipt {
receipt,
block_hash,
block_number,
Expand All @@ -93,10 +98,14 @@ impl ReceiptService {
get_contract_address(&signed_tx.sender, &signed_tx.nonce())
})
}),
logs_index: logs_size - logs_len,
logs_index: logs_size
.checked_sub(logs_len)
.ok_or_else(|| format_err!("logs_size underflow"))?,
cumulative_gas,
effective_gas_price: signed_tx.effective_gas_price(base_fee),
}
effective_gas_price: signed_tx.effective_gas_price(base_fee)?,
};

Ok(receipt)
})
.collect()
}
Expand Down
Loading