Skip to content

Commit

Permalink
record external cost ref: rust-ethereum/evm#170
Browse files Browse the repository at this point in the history
  • Loading branch information
zjb0807 committed Jan 18, 2024
1 parent 298a300 commit 8a5dbb9
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 16 deletions.
16 changes: 8 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions modules/evm-utility/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ sha3 = { workspace = true }

sp-std = { workspace = true }

evm = { git = "https://github.com/rust-blockchain/evm", rev = "adfa174ca6e021e9b0f530bd87e20989eaab31ca", default-features = false, features = ["with-codec"] }
evm-gasometer = { git = "https://github.com/rust-blockchain/evm", rev = "adfa174ca6e021e9b0f530bd87e20989eaab31ca", default-features = false }
evm-runtime = { git = "https://github.com/rust-blockchain/evm", rev = "adfa174ca6e021e9b0f530bd87e20989eaab31ca", default-features = false }
evm = { git = "https://github.com/rust-blockchain/evm", rev = "e85c34f96e3237c09955193b41154030b78119c5", default-features = false, features = ["with-codec"] }
evm-gasometer = { git = "https://github.com/rust-blockchain/evm", rev = "e85c34f96e3237c09955193b41154030b78119c5", default-features = false }
evm-runtime = { git = "https://github.com/rust-blockchain/evm", rev = "e85c34f96e3237c09955193b41154030b78119c5", default-features = false }
#evm = { version = "0.41.1", default-features = false, features = ["with-codec"] }
#evm-gasometer = { version = "0.41.0", default-features = false }
#evm-runtime = { version = "0.41.0", default-features = false }
Expand Down
2 changes: 1 addition & 1 deletion modules/evm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ pub use module_evm_utility::{
evm::{
self,
executor::stack::{IsPrecompileResult, PrecompileFailure, PrecompileHandle, PrecompileOutput, PrecompileSet},
Config as EvmConfig, Context, ExitError, ExitFatal, ExitReason, ExitRevert, ExitSucceed,
Config as EvmConfig, Context, ExitError, ExitFatal, ExitReason, ExitRevert, ExitSucceed, ExternalOperation,
},
Account,
};
Expand Down
8 changes: 8 additions & 0 deletions modules/evm/src/precompiles/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,14 @@ pub mod tests {
}
}

fn record_external_cost(&mut self, _ref_time: Option<u64>, _proof_size: Option<u64>) -> Result<(), ExitError> {
unimplemented!()
}

fn refund_external_cost(&mut self, _ref_time: Option<u64>, _proof_size: Option<u64>) {
unimplemented!()
}

fn remaining_gas(&self) -> u64 {
unimplemented!()
}
Expand Down
71 changes: 67 additions & 4 deletions modules/evm/src/runner/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,21 @@ pub trait StackState<'config>: Backend {
fn code_hash(&self, address: H160) -> H256 {
H256::from_slice(Keccak256::digest(self.code(address)).as_slice())
}

fn record_external_dynamic_opcode_cost(
&mut self,
_opcode: Opcode,
_gas_cost: gasometer::GasCost,
_target: StorageTarget,
) -> Result<(), ExitError> {
Ok(())
}

fn record_external_cost(&mut self, _ref_time: Option<u64>, _proof_size: Option<u64>) -> Result<(), ExitError> {
Ok(())
}

fn refund_external_cost(&mut self, _ref_time: Option<u64>, _proof_size: Option<u64>) {}
}

/// A precompile result.
Expand Down Expand Up @@ -725,6 +740,10 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet> StackExecu
self.initialize_with_access_list(access_list);
}

if let Err(e) = self.record_external_operation(crate::ExternalOperation::AccountBasicRead) {
return (e.into(), Vec::new());
}

let context = Context {
caller,
address,
Expand Down Expand Up @@ -876,6 +895,10 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet> StackExecu
return Capture::Exit((ExitError::OutOfFund.into(), None, Vec::new()));
}

if let Err(e) = self.record_external_operation(crate::ExternalOperation::AccountBasicRead) {
return Capture::Exit((ExitReason::Error(e), None, Vec::new()));
}

if let Err(e) = self.state.inc_nonce(caller) {
return Capture::Exit((e.into(), None, Vec::new()));
}
Expand All @@ -901,7 +924,12 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet> StackExecu
self.enter_substate(gas_limit, false);

{
if self.code_size(address) != U256::zero() {
if let Err(e) = self.record_external_operation(crate::ExternalOperation::AddressCodeRead(address)) {
let _ = self.exit_substate(StackExitKind::Failed);
return Capture::Exit((ExitReason::Error(e), None, Vec::new()));
}
let code_size = self.code_size(address);
if code_size != U256::zero() {
let _ = self.exit_substate(StackExitKind::Failed);
return Capture::Exit((ExitError::CreateCollision.into(), None, Vec::new()));
}
Expand Down Expand Up @@ -935,6 +963,10 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet> StackExecu
}

if self.config.create_increase_nonce {
if let Err(e) = self.record_external_operation(crate::ExternalOperation::AccountBasicRead) {
let _ = self.exit_substate(StackExitKind::Failed);
return Capture::Exit((ExitReason::Error(e), None, Vec::new()));
}
if let Err(e) = self.state.inc_nonce(address) {
return Capture::Exit((e.into(), None, Vec::new()));
}
Expand Down Expand Up @@ -1015,11 +1047,15 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet> StackExecu
}
}

let code = self.code(code_address);

self.enter_substate(gas_limit, is_static);
self.state.touch(context.address);

if let Err(e) = self.record_external_operation(crate::ExternalOperation::AddressCodeRead(code_address)) {
let _ = self.exit_substate(StackExitKind::Failed);
return Capture::Exit((ExitReason::Error(e), Vec::new()));
}
let code = self.code(code_address);

if let Some(depth) = self.state.metadata().depth {
if depth > self.config.call_stack_limit {
let _ = self.exit_substate(StackExitKind::Reverted);
Expand All @@ -1028,6 +1064,10 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet> StackExecu
}

if let Some(transfer) = transfer {
if let Err(e) = self.record_external_operation(crate::ExternalOperation::AccountBasicRead) {
let _ = self.exit_substate(StackExitKind::Failed);
return Capture::Exit((ExitReason::Error(e), Vec::new()));
}
match self.state.transfer(transfer) {
Ok(()) => (),
Err(e) => {
Expand Down Expand Up @@ -1125,6 +1165,9 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet> StackExecu
Ok(()) => {
self.state.set_code(address, out);
let exit_result = self.exit_substate(StackExitKind::Succeeded);
if let Err(e) = self.record_external_operation(crate::ExternalOperation::Write) {
return (e.into(), None, Vec::new());
}
if let Err(e) = exit_result {
return (e.into(), None, Vec::new());
}
Expand Down Expand Up @@ -1438,6 +1481,10 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet> Handler
let gasometer = &mut self.state.metadata_mut().gasometer;

gasometer.record_dynamic_cost(gas_cost, memory_cost)?;

self.state
.record_external_dynamic_opcode_cost(opcode, gas_cost, target)?;

match target {
StorageTarget::Address(address) => self.state.metadata_mut().access_address(address),
StorageTarget::Slot(address, key) => self.state.metadata_mut().access_storage(address, key),
Expand All @@ -1447,6 +1494,10 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet> Handler

Ok(())
}

fn record_external_operation(&mut self, op: crate::ExternalOperation) -> Result<(), ExitError> {
self.state.record_external_operation(op)
}
}

struct StackExecutorHandle<'inner, 'config, 'precompiles, S, P> {
Expand Down Expand Up @@ -1481,11 +1532,13 @@ impl<'inner, 'config, 'precompiles, S: StackState<'config>, P: PrecompileSet> Pr
Err(err) => return (ExitReason::Error(err), Vec::new()),
};

let target_exists = self.executor.exists(code_address);

let gas_cost = gasometer::GasCost::Call {
value: transfer.clone().map(|x| x.value).unwrap_or_else(U256::zero),
gas: U256::from(gas_limit.unwrap_or(u64::MAX)),
target_is_cold,
target_exists: self.executor.exists(code_address),
target_exists,
};

// We record the length of the input.
Expand Down Expand Up @@ -1543,6 +1596,16 @@ impl<'inner, 'config, 'precompiles, S: StackState<'config>, P: PrecompileSet> Pr
self.executor.state.metadata_mut().gasometer.record_cost(cost)
}

/// Record Substrate specific cost.
fn record_external_cost(&mut self, ref_time: Option<u64>, proof_size: Option<u64>) -> Result<(), ExitError> {
self.executor.state.record_external_cost(ref_time, proof_size)
}

/// Refund Substrate specific cost.
fn refund_external_cost(&mut self, ref_time: Option<u64>, proof_size: Option<u64>) {
self.executor.state.refund_external_cost(ref_time, proof_size);
}

/// Retreive the remaining gas.
fn remaining_gas(&self) -> u64 {
self.executor.state.metadata().gasometer.gas()
Expand Down

0 comments on commit 8a5dbb9

Please sign in to comment.