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
Changes from 2 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
8 changes: 6 additions & 2 deletions lib/ain-evm/src/backend.rs
Original file line number Diff line number Diff line change
@@ -410,7 +410,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
};

@@ -432,7 +435,7 @@ impl EVMBackend {
.into())
} else {
let new_basic = Basic {
balance: account.balance - amount,
balance: account.balance - amount, // sub is safe due to check above
nonce: account.nonce,
};

@@ -460,6 +463,7 @@ pub enum BackendError {
RefundUnusedGasFailed(String),
}

use anyhow::format_err;
use std::fmt;

impl fmt::Display for BackendError {
37 changes: 21 additions & 16 deletions lib/ain-evm/src/block.rs
Original file line number Diff line number Diff line change
@@ -80,30 +80,30 @@ impl BlockService {
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(match parent_base_fee.checked_add(base_fee_per_gas_delta) {
prasannavl marked this conversation as resolved.
Show resolved Hide resolved
None => U256::MAX, // overflow case
Some(sum) => max(sum, initial_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(match parent_base_fee.checked_sub(base_fee_per_gas_delta) {
prasannavl marked this conversation as resolved.
Show resolved Hide resolved
None => initial_base_fee, // underflow case
Some(sub) => max(sub, initial_base_fee),
})
}
}
}
@@ -201,7 +201,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;
@@ -281,10 +283,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
@@ -368,7 +371,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"))?)
}
}

10 changes: 8 additions & 2 deletions lib/ain-evm/src/core.rs
Original file line number Diff line number Diff line change
@@ -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::from(1)
{
break;
} else {
nonce = *elem;
}
}
nonce += U256::from(1);
nonce = nonce
.checked_add(U256::one())
.ok_or_else(|| format_err!("Nonce overflow"))?;
Ok(nonce)
}
}
20 changes: 16 additions & 4 deletions lib/ain-evm/src/evm.rs
Original file line number Diff line number Diff line change
@@ -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
@@ -227,7 +232,7 @@ impl EVMServices {
block.header.hash(),
block.header.number,
base_fee,
);
)?;
template.block_data = Some(BlockData { block, receipts });

Ok(FinalizedBlockInfo {
@@ -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);
7 changes: 6 additions & 1 deletion lib/ain-evm/src/executor.rs
Original file line number Diff line number Diff line change
@@ -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"
)
6 changes: 3 additions & 3 deletions lib/ain-evm/src/filters.rs
Original file line number Diff line number Diff line change
@@ -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(
@@ -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,
@@ -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,
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;
@@ -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,
@@ -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"))?;
}
}

@@ -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
25 changes: 17 additions & 8 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};
@@ -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
@@ -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,
@@ -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),
}
};

Ok(receipt)
})
.collect()
}
11 changes: 8 additions & 3 deletions lib/ain-grpc/src/rpc/debug.rs
Original file line number Diff line number Diff line change
@@ -187,7 +187,7 @@ impl MetachainDebugRPCServer for MetachainDebugRPCModule {
else {
return Err(Error::Custom("Cannot get EIP1559 TX fee estimate without max_fee_per_gas and max_priority_fee_per_gas".to_string()));
};
let gas_fee = cmp::min(max_fee_per_gas, max_priority_fee_per_gas + base_fee);
let gas_fee = cmp::min(max_fee_per_gas, max_priority_fee_per_gas.checked_add(base_fee).ok_or_else(|| Error::Custom("max_priority_fee_per_gas overflow".to_string()))?);
used_gas.checked_mul(gas_fee)
}
_ => {
@@ -199,8 +199,13 @@ impl MetachainDebugRPCServer for MetachainDebugRPCModule {
"Cannot get fee estimate, fee value overflow".to_string()
))?;

let burnt_fee = used_gas * base_fee;
let priority_fee = gas_fee - burnt_fee;
let burnt_fee = used_gas
.checked_mul(base_fee)
.ok_or_else(|| Error::Custom("burnt_fee overflow".to_string()))?;
let priority_fee = gas_fee
.checked_sub(burnt_fee)
.ok_or_else(|| Error::Custom("priority_fee underflow".to_string()))?;

Ok(FeeEstimate {
used_gas,
gas_fee,
6 changes: 4 additions & 2 deletions lib/ain-grpc/src/rpc/eth.rs
Original file line number Diff line number Diff line change
@@ -924,7 +924,7 @@ impl MetachainRPCServer for MetachainRPCModule {

let starting_block = self.handler.block.get_starting_block_number();

let highest_block = current_block + (highest_native_block - current_native_height);
let highest_block = current_block + (highest_native_block - current_native_height); // safe since current height cannot be higher than seen height
debug!("Highest native: {highest_native_block}\nCurrent native: {current_native_height}\nCurrent ETH: {current_block}\nHighest ETH: {highest_block}");

Ok(SyncState::Syncing(SyncInfo {
@@ -976,7 +976,9 @@ impl MetachainRPCServer for MetachainRPCModule {

while block_number <= to_block_number {
block_numbers.push(block_number);
block_number += U256::one();
block_number = block_number
.checked_add(U256::one())
.ok_or_else(|| Error::Custom("block_number overflow".to_string()))?;
}

Ok::<Vec<U256>, Error>(block_numbers)