Skip to content

Commit

Permalink
most vm tests working
Browse files Browse the repository at this point in the history
  • Loading branch information
max-wickham committed Oct 30, 2024
1 parent 93ad837 commit ccc32d8
Show file tree
Hide file tree
Showing 9 changed files with 182 additions and 125 deletions.
121 changes: 63 additions & 58 deletions src/configs/gas_costs.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use std::ops::Div;

use primitive_types::{H256, U256};
use static_costs::{G_COLD_ACCOUNT_ACCESS, G_NEW_ACCOUNT, G_SELF_DESTRUCT};
use primitive_types::{ H256, U256 };
use static_costs::{ G_COLD_ACCOUNT_ACCESS, G_NEW_ACCOUNT, G_SELF_DESTRUCT };

use crate::evm_logic::util::{ZERO, ZERO_H256};
use crate::evm_logic::util::{ ZERO, ZERO_H256 };

pub mod static_costs {
pub const G_ZERO: u64 = 0;
Expand Down Expand Up @@ -113,7 +113,8 @@ pub enum DynamicCosts {
SelfDestruct {
address_exists: bool,
is_cold: bool,
}
positive_balance: bool,
},
}

impl DynamicCosts {
Expand Down Expand Up @@ -142,92 +143,98 @@ impl DynamicCosts {
static_costs::G_WARM_ACCESS
}
}
DynamicCosts::Call {
value,
empty_account,
target_is_cold,
is_delegate,
is_code,
} => {
println!("empty_account: {}", empty_account);
println!("target_is_cold {}", target_is_cold);
DynamicCosts::Call { value, empty_account, target_is_cold, is_delegate, is_code } => {
// println!("empty_account: {}", empty_account);
// println!("target_is_cold {}", target_is_cold);

0 + if *target_is_cold {
static_costs::G_COLD_ACCOUNT_ACCESS
} else {
static_costs::G_WARM_ACCESS
} +
if !value.eq(&ZERO) & !is_delegate {
static_costs::G_CALL_VALUE - static_costs::G_CALL_STIPEND
} else {0} +
if !value.eq(&ZERO) & *empty_account & !is_delegate &!is_code {
static_costs::G_NEW_ACCOUNT
} else {0}
0 +
(if *target_is_cold {
static_costs::G_COLD_ACCOUNT_ACCESS
} else {
static_costs::G_WARM_ACCESS
}) +
(if !value.eq(&ZERO) & !is_delegate {
static_costs::G_CALL_VALUE - static_costs::G_CALL_STIPEND
} else {
0
}) +
(if !value.eq(&ZERO) & *empty_account & !is_delegate & !is_code {
static_costs::G_NEW_ACCOUNT
} else {
0
})
}
DynamicCosts::Keccak256 { len } => {
println!("Len in Keccak256: {}", len);
static_costs::G_KECCAK256 + (len.div_ceil(32)) * static_costs::G_KECCAK256_WORD
// println!("Len in Keccak256: {}", len);
let x =
static_costs::G_KECCAK256 + len.div_ceil(32) * static_costs::G_KECCAK256_WORD;
// println!("Cost in Keccak256: {}", x);
x
}
DynamicCosts::Log { topic_length, size } => {
static_costs::G_LOG
+ static_costs::G_LOG_TOPIC * (*topic_length as u64)
+ static_costs::G_LOG_DATA * (*size as u64)
static_costs::G_LOG +
static_costs::G_LOG_TOPIC * (*topic_length as u64) +
static_costs::G_LOG_DATA * (*size as u64)
}

DynamicCosts::Exp { power } => {
// bytes_for_u256
let bytes = (power.bits() + 7) / 8;
static_costs::G_EXP + static_costs::G_EXP_BYTE * bytes as u64
static_costs::G_EXP + static_costs::G_EXP_BYTE * (bytes as u64)
}

DynamicCosts::Copy { size_bytes } => {
println!("size_bytes: {}", size_bytes);
println!("size_bytes.div_ceil(32): {}", size_bytes.div_ceil(32) as u64);
static_costs::G_VERY_LOW + static_costs::G_COPY * (size_bytes.div_ceil(32) as u64)
// println!("size_bytes: {}", size_bytes);
// println!("size_bytes.div_ceil(32): {}", size_bytes.div_ceil(32) as u64);
static_costs::G_VERY_LOW + static_costs::G_COPY * (size_bytes.div_ceil(32) as u64)
}

DynamicCosts::ExtCodeCopy { target_is_cold, size_bytes } => {
println!("size_bytes: {}", size_bytes);
println!("size_bytes.div_ceil(32): {}", size_bytes.div_ceil(32) as u64);
// println!("size_bytes: {}", size_bytes);
// println!("size_bytes.div_ceil(32): {}", size_bytes.div_ceil(32) as u64);
static_costs::G_COPY * (size_bytes.div_ceil(32) as u64) +
if *target_is_cold {
static_costs::G_COLD_ACCOUNT_ACCESS
} else {
static_costs::G_WARM_ACCESS
}
(if *target_is_cold {
static_costs::G_COLD_ACCOUNT_ACCESS
} else {
static_costs::G_WARM_ACCESS
})
}
DynamicCosts::Create {deployed_code_size} => {

println!("Code Size {}",deployed_code_size);
static_costs::G_CREATE + static_costs::G_KECCAK256_WORD * (*deployed_code_size as u64).div_ceil(32)
DynamicCosts::Create { deployed_code_size } => {
// println!("Code Size {}",deployed_code_size);
static_costs::G_CREATE +
static_costs::G_KECCAK256_WORD * (*deployed_code_size as u64).div_ceil(32)
}
DynamicCosts::SLoad { target_is_cold } => {
println!("Is cold: {}", target_is_cold);
// println!("Is cold: {}", target_is_cold);
if *target_is_cold {
static_costs::G_COLDS_LOAD
} else {
static_costs::G_WARM_ACCESS
}
}
DynamicCosts::SStore { original, current, new, target_is_cold } => {
let mut gas_cost = if *target_is_cold { static_costs::G_COLDS_LOAD } else { 0};
gas_cost += if current.eq(&new) | !original.eq(&current) {
println!("Warm access");
let mut gas_cost = if *target_is_cold { static_costs::G_COLDS_LOAD } else { 0 };
gas_cost += if current.eq(&new) | !original.eq(&current) {
// println!("Warm access");
static_costs::G_WARM_ACCESS
} else if original.eq(&ZERO_H256) {
static_costs::G_SSET
} else {
static_costs::G_SRESET
};
gas_cost

}
DynamicCosts::SelfDestruct { address_exists, is_cold} => {
G_SELF_DESTRUCT + if !*address_exists {
G_NEW_ACCOUNT
} else {
if *is_cold { G_COLD_ACCOUNT_ACCESS } else { 0 }
}
DynamicCosts::SelfDestruct { address_exists, is_cold, positive_balance } => {
G_SELF_DESTRUCT +
(if !*address_exists {
if *positive_balance {
G_NEW_ACCOUNT
} else{
0
}
} else {
if *is_cold { G_COLD_ACCOUNT_ACCESS } else { 0 }
})
}
_ => 0,
}
Expand All @@ -241,9 +248,7 @@ impl DynamicCosts {
0
}
}
DynamicCosts::SelfDestruct { address_exists, is_cold } => {
24000
}
DynamicCosts::SelfDestruct { .. } => { 24000 }
_ => 0,
}
}
Expand Down
27 changes: 24 additions & 3 deletions src/evm_logic/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,13 @@ impl EVMContext {
#[inline]
fn execute_program(&mut self, runtime: &mut impl Runtime, debug: bool) -> ExecutionResult {
runtime.add_context();

// let num_none_zero_calldata = self.message.data.iter().filter(|x| **x != 0).count() as u64;
// let num_zero_calldata = self.message.data.len() as u64 - num_none_zero_calldata as u64;

// let calldata_cost = static_costs::G_ZERO + static_costs::G_TX_DATA_NON_ZERO * num_none_zero_calldata + static_costs::G_TX_DATA_ZERO * num_zero_calldata;
// self.gas_recorder.record_gas_usage(calldata_cost as u64);

let mut result;
let jump_dests = decoder::calculate_jump_dests(self);
if self.program.len() != 0 {
Expand All @@ -97,6 +104,7 @@ impl EVMContext {
} else {
result = ExecutionResult::Error(ExecutionError::InvalidMemSize);
}

// TODO move this into gas_recorder
self.gas_recorder.gas_usage = if self.gas_recorder.gas_usage > self.gas_input as usize {
self.gas_input as u64
Expand Down Expand Up @@ -165,7 +173,10 @@ pub fn execute_transaction(
origin: origin,
gas_price: gas_price,
};
runtime.mark_hot(contract_address);

println!("Origin: {:x}", origin);
println!("Contract Address: {:x}", contract_address);
let mut evm = EVMContext::create_sub_context(
contract_address,
message,
Expand All @@ -184,19 +195,29 @@ pub fn execute_transaction(
if debug {
println!("Call Data Gas Cost: {:x}", evm.gas_recorder.gas_usage);
}

println!("Value: {:x}", value);
// TODO checks here on balance
runtime.deposit(contract_address, value);
// withdraw the value from the sender
runtime.withdrawal(origin, value);
let result = evm.execute_program(runtime, debug);
let gas_usage = evm.gas_recorder.usage_with_refunds();

// Increase Nonce and deposit the value
runtime.increase_nonce(origin);

match result {
ExecutionResult::Success(_) => {
runtime.deposit(contract_address, value);
}
_ => {
// Undo the value send, TODO fix this up
runtime.deposit(origin, value);
// withdraw the value from the sender
runtime.withdrawal(origin, value);
runtime.withdrawal(contract_address, value);
}
_ => {}
}

// Withdraw the gas from the wallet
let eth_usage = (gas_usage) * gas_price.as_usize();
runtime.withdrawal(origin, U256::from(eth_usage as u64));
Expand Down
53 changes: 33 additions & 20 deletions src/evm_logic/evm/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ pub fn call(evm: &mut EVMContext, runtime: &mut impl Runtime, debug: bool) -> Ex
}
.cost(),
);
println!("Gas reamining {:x}", evm.gas_input - evm.gas_recorder.gas_usage as u64);
// if evm.gas_recorder.gas_input > evm.gas_recorder.gas_usage {
// println!(
// "Gas usage {:x}",
Expand Down Expand Up @@ -101,7 +100,7 @@ pub fn call_code(evm: &mut EVMContext, runtime: &mut impl Runtime, debug: bool)
// evm.gas_recorder.record_gas_usage(evm.gas_recorder.gas_input as u64);
// return ExecutionResult::Error(ExecutionError::InvalidAddress);
// }
let call_args = CallArgs {
let mut call_args = CallArgs {
gas: gas,
code_address: address,
contract_address: evm.contract_address,
Expand All @@ -112,6 +111,7 @@ pub fn call_code(evm: &mut EVMContext, runtime: &mut impl Runtime, debug: bool)
ret_offset: ret_offset,
ret_size: ret_size,
};

evm.gas_recorder.record_gas_usage(
DynamicCosts::Call {
value: value,
Expand All @@ -125,6 +125,10 @@ pub fn call_code(evm: &mut EVMContext, runtime: &mut impl Runtime, debug: bool)
}
.cost(),
);

if call_args.value != ZERO {
call_args.gas += G_CALL_STIPEND;
}
return_if_gas_too_high!(evm.gas_recorder);
match make_call(evm, runtime, debug, call_args, false) {
ExecutionResult::Error(_) => {
Expand Down Expand Up @@ -270,7 +274,7 @@ pub fn make_call(
args: CallArgs,
is_static: bool,
) -> ExecutionResult {
println!("Making call");
// println!("Making call");
let code = match runtime.exists(args.code_address) {
true => runtime.code(args.code_address),
false => {
Expand All @@ -281,32 +285,36 @@ pub fn make_call(
if !runtime.exists(args.code_address) {
return ExecutionResult::Success(ExecutionSuccess::RevertedTransaction);
}
println!("Code found");
println!("gas: {:x}", args.gas);
// println!("Gas reamining {:x}", evm.gas_input - evm.gas_recorder.gas_usage as u64);
if args.args_offset + args.args_size > evm.memory.len() {
return_if_error!(evm.memory.expand(args.args_offset + args.args_size, Some(&mut evm.gas_recorder)));
}
if args.ret_offset + args.ret_size > evm.memory.len() {
return_if_error!(evm.memory.expand(args.ret_offset + args.ret_size, Some(&mut evm.gas_recorder)));
}
// println!("Gas reamining {:x}", evm.gas_input - evm.gas_recorder.gas_usage as u64);

// println!("Code found");
// println!("gas: {:x}", args.gas);

// let code: Vec<u8> = runtime.code(args.code_address);
let mut gas = args
.gas
.min(((evm.gas_input - evm.gas_recorder.gas_usage.clone() as u64) * 63).div_ceil(64));
if args.value != ZERO {
gas += G_CALL_STIPEND;
}
println!("args.offset: {:x}", args.args_offset);
println!("args.size: {:x}", args.args_size);
println!("args.ret: {:x}", args.ret_offset);
println!("args.ret size: {:x}", args.ret_size);
println!("value: {:x}", args.value);
println!("gas: {:x}", gas);

// println!("args.offset: {:x}", args.args_offset);
// println!("args.size: {:x}", args.args_size);
// println!("args.ret: {:x}", args.ret_offset);
// println!("args.ret size: {:x}", args.ret_size);
// println!("value: {:x}", args.value);
// println!("gas: {:x}", gas);
if args.args_offset.checked_add(args.args_size).is_none()
{
evm.gas_recorder
.record_gas_usage(evm.gas_recorder.gas_input as u64);
println!("Invalid args size");
// println!("Invalid args size");
return ExecutionResult::Error(ExecutionError::InvalidMemSize);
}
if args.args_offset + args.args_size > evm.memory.len() {
return_if_error!(evm.memory.expand(args.args_offset + args.args_size, Some(&mut evm.gas_recorder)));
}
let mut sub_evm = EVMContext::create_sub_context(
args.contract_address,
Message {
Expand All @@ -322,15 +330,20 @@ pub fn make_call(
is_static,
);
if runtime.balance(evm.contract_address) < args.value {
// TODO should this be here ????
// println!("Insufficient balance");
// println!("Balance: {:x}", runtime.balance(evm.contract_address));
// println!("Value: {:x}", args.value);
evm.gas_recorder.record_gas_usage(evm.gas_recorder.gas_input as u64);
return ExecutionResult::Error(ExecutionError::InsufficientBalance);
}
runtime.add_context();
runtime.withdrawal(evm.contract_address, args.value);
runtime.deposit(sub_evm.contract_address, args.value);
println!("Executing");
// println!("Executing");
let execution_result = sub_evm.execute_program(runtime, debug);
println!("Execution result: {:?}", execution_result);
println!("run");
// println!("Execution result: {:?}", execution_result);
match &execution_result {
ExecutionResult::Error(error) => {
runtime.revert_context();
Expand Down
Loading

0 comments on commit ccc32d8

Please sign in to comment.