Skip to content

Commit

Permalink
evm tracing (#2716)
Browse files Browse the repository at this point in the history
  • Loading branch information
ermalkaleci authored Mar 26, 2024
1 parent 432100c commit d3134db
Show file tree
Hide file tree
Showing 19 changed files with 1,208 additions and 59 deletions.
3 changes: 1 addition & 2 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ concurrency:
cancel-in-progress: true

env:
TARPAULIN_VERSION: 0.27.2
# LIBCLANG_PATH: "/usr/lib/llvm-11/lib" # default `llvm-config --prefix`
TARPAULIN_VERSION: 0.27.3
CARGO_INCREMENTAL: 0
jobs:
test:
Expand Down
55 changes: 55 additions & 0 deletions .github/workflows/tracing-runtime.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: Build and publish evm tracing runtime
on:
release:
types: [published]
# Allow manual trigger for old releases
workflow_dispatch:
inputs:
# Branch with old release + tracing feature
branch:
description: Branch to build tracing runtime
required: true
type: string
# Set the tag to publish the tracing runtime
tag:
description: Existing tag to publish tracing runtime. i.e. 1.0.0
required: true
type: string

jobs:
build-runtime:
name: "Build evm tracing runtime ${{ matrix.network }}"
permissions:
contents: write
runs-on: [self-hosted, linux]
strategy:
matrix:
network: [karura, acala]
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.inputs.branch || github.ref }}
submodules: recursive
- name: Install toolchain
uses: dtolnay/rust-toolchain@nightly
- name: Setup cmake
uses: jwlawson/actions-setup-cmake@v1.13
- name: Install subwasm ${{ env.SUBWASM_VERSION }}
run: |
wget https://github.com/chevdor/subwasm/releases/download/v${{ env.SUBWASM_VERSION }}/subwasm_linux_amd64_v${{ env.SUBWASM_VERSION }}.deb
sudo dpkg -i subwasm_linux_amd64_v${{ env.SUBWASM_VERSION }}.deb
subwasm --version
- name: Build
run: make build-wasm-${{ matrix.network }}-tracing
- name: Find spec version
run: |
SPEC_VERSION=`subwasm version -j target/production/wbuild/${{ matrix.network }}-runtime/${{ matrix.network }}_runtime.compact.compressed.wasm | jq .specVersion`
cp target/production/wbuild/${{ matrix.network }}-runtime/${{ matrix.network }}_runtime.compact.compressed.wasm > ${{ matrix.network }}_runtime_tracing_$SPEC_VERSION.compact.compressed.wasm
echo "SPEC_VERSION=$SPEC_VERSION" >> $GITHUB_ENV
- name: Upload tracing runtime
uses: softprops/action-gh-release@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
tag_name: ${{ github.event.inputs.tag }}
files: ${{ matrix.network }}_runtime_tracing_${{ env.SPEC_VERSION }}.compact.compressed.wasm

1 change: 1 addition & 0 deletions Cargo.lock

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

9 changes: 9 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ test-eth: githooks test-evm

.PHONY: test-evm
test-evm: githooks
SKIP_WASM_BUILD= ${cargo_test} -p module-evm --features tracing
SKIP_WASM_BUILD= ${cargo_test} --release -p evm-jsontests --features evm-tests

.PHONY: test-runtimes
Expand Down Expand Up @@ -236,6 +237,14 @@ srtool-build-wasm-karura:
srtool-build-wasm-acala:
PACKAGE=acala-runtime PROFILE=production BUILD_OPTS="--features on-chain-release-build,no-metadata-docs" ./scripts/srtool-build.sh

.PHONY: build-wasm-karura-tracing
build-wasm-karura-tracing:
./scripts/build-only-wasm.sh --profile production -p karura-runtime --features=on-chain-release-build,tracing

.PHONY: build-wasm-acala-tracing
build-wasm-acala-tracing:
./scripts/build-only-wasm.sh --profile production -p acala-runtime --features=on-chain-release-build,tracing

.PHONY: generate-tokens
generate-tokens:
./scripts/generate-tokens-and-predeploy-contracts.sh
Expand Down
4 changes: 2 additions & 2 deletions modules/evm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ serde_json = { workspace = true, features = ["alloc"], optional = true }
hex = { workspace = true, features = ["alloc"], optional = true }
num = { workspace = true, features = ["alloc"] }
bn = { workspace = true }
environmental = { version = "1.1.4", default-features = false, optional = true }

frame-support = { workspace = true }
frame-system = { workspace = true }
Expand Down Expand Up @@ -60,7 +61,6 @@ pallet-utility = { workspace = true, features = ["std"] }
default = ["std"]
std = [
"serde/std",

"parity-scale-codec/std",
"frame-support/std",
"frame-system/std",
Expand Down Expand Up @@ -100,7 +100,7 @@ try-runtime = [
"pallet-balances/try-runtime",
"pallet-timestamp/try-runtime",
]
tracing = ["module-evm-utility/tracing"]
tracing = ["environmental", "primitives/tracing", "module-evm-utility/tracing"]
wasm-bench = [
"wasm-bencher/wasm-bench",
"hex",
Expand Down
1 change: 1 addition & 0 deletions modules/evm/rpc/runtime-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ std = [
"sp-core/std",
"primitives/std",
]
tracing = ["primitives/tracing"]
27 changes: 27 additions & 0 deletions modules/evm/rpc/runtime-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,30 @@ sp_api::decl_runtime_apis! {
) -> Result<CreateInfo, sp_runtime::DispatchError>;
}
}

#[cfg(feature = "tracing")]
sp_api::decl_runtime_apis! {
pub trait EVMTraceApi<Balance> where
Balance: Codec + MaybeDisplay + MaybeFromStr,
{
fn trace_call(
from: H160,
to: H160,
data: Vec<u8>,
value: Balance,
gas_limit: u64,
storage_limit: u32,
access_list: Option<Vec<AccessListItem>>,
) -> Result<Vec<primitives::evm::tracing::CallTrace>, sp_runtime::DispatchError>;

fn trace_vm(
from: H160,
to: H160,
data: Vec<u8>,
value: Balance,
gas_limit: u64,
storage_limit: u32,
access_list: Option<Vec<AccessListItem>>,
) -> Result<primitives::evm::tracing::VMTrace, sp_runtime::DispatchError>;
}
}
3 changes: 3 additions & 0 deletions modules/evm/src/runner/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ pub mod state;
pub mod storage_meter;
pub mod tagged_runtime;

#[cfg(feature = "tracing")]
pub mod tracing;

use crate::{BalanceOf, CallInfo, Config, CreateInfo};
use module_evm_utility::evm;
pub use primitives::evm::{EvmAddress, Vicinity};
Expand Down
96 changes: 41 additions & 55 deletions modules/evm/src/runner/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,38 +46,17 @@ use sp_runtime::traits::Zero;
use sp_std::{collections::btree_set::BTreeSet, rc::Rc, vec::Vec};

macro_rules! event {
($x:expr) => {};
}

#[cfg(feature = "tracing")]
mod tracing {
pub struct Tracer;
impl module_evm_utility::evm::tracing::EventListener for Tracer {
fn event(&mut self, event: module_evm_utility::evm::tracing::Event) {
frame_support::log::debug!(
target: "evm", "evm tracing: {:?}", event
);
}
}
impl module_evm_utility::evm_runtime::tracing::EventListener for Tracer {
fn event(&mut self, event: module_evm_utility::evm_runtime::tracing::Event) {
frame_support::log::debug!(
target: "evm", "evm_runtime tracing: {:?}", event
);
}
}
impl module_evm_utility::evm_gasometer::tracing::EventListener for Tracer {
fn event(&mut self, event: module_evm_utility::evm_gasometer::tracing::Event) {
frame_support::log::debug!(
target: "evm", "evm_gasometer tracing: {:?}", event
);
($event:expr) => {{
#[cfg(feature = "tracing")]
{
use crate::runner::tracing::{self, Event::*, EventListener};
tracing::with(|tracer| {
EventListener::event(tracer, $event);
});
}
}
}};
}

#[cfg(feature = "tracing")]
use tracing::*;

macro_rules! emit_exit {
($reason:expr) => {{
let reason = $reason;
Expand Down Expand Up @@ -212,6 +191,12 @@ impl<'config> StackSubstateMetadata<'config> {
}

pub fn spit_child(&self, gas_limit: u64, is_static: bool) -> Self {
event!(Enter {
depth: match self.depth {
None => 0,
Some(n) => n + 1,
} as u32
});
Self {
gasometer: Gasometer::new(gas_limit, self.gasometer.config()),
storage_meter: StorageMeter::new(self.storage_meter.available_storage()),
Expand Down Expand Up @@ -560,7 +545,7 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet> StackExecu
value,
init_code: &init_code,
gas_limit,
address: self.create_address(CreateScheme::Legacy { caller }),
address: self.create_address(CreateScheme::Legacy { caller }).unwrap_or_default(),
});

if let Some(limit) = self.config.max_initcode_size {
Expand Down Expand Up @@ -603,27 +588,28 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet> StackExecu
gas_limit: u64,
access_list: Vec<(H160, Vec<H256>)>, // See EIP-2930
) -> (ExitReason, Vec<u8>) {
if let Some(limit) = self.config.max_initcode_size {
if init_code.len() > limit {
self.state.metadata_mut().gasometer.fail();
return emit_exit!(ExitError::CreateContractLimit.into(), Vec::new());
}
}

let code_hash = H256::from_slice(Keccak256::digest(&init_code).as_slice());
event!(TransactCreate2 {
caller,
value,
init_code: &init_code,
salt,
gas_limit,
address: self.create_address(CreateScheme::Create2 {
caller,
code_hash,
salt,
}),
address: self
.create_address(CreateScheme::Create2 {
caller,
code_hash: H256::from_slice(Keccak256::digest(&init_code).as_slice()),
salt,
})
.unwrap_or_default(),
});

if let Some(limit) = self.config.max_initcode_size {
if init_code.len() > limit {
self.state.metadata_mut().gasometer.fail();
return emit_exit!(ExitError::CreateContractLimit.into(), Vec::new());
}
}

if let Err(e) = self.record_create_transaction_cost(&init_code, &access_list) {
return emit_exit!(e.into(), Vec::new());
}
Expand All @@ -633,7 +619,7 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet> StackExecu
caller,
CreateScheme::Create2 {
caller,
code_hash,
code_hash: H256::from_slice(Keccak256::digest(&init_code).as_slice()),
salt,
},
value,
Expand Down Expand Up @@ -661,13 +647,6 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet> StackExecu
gas_limit: u64,
access_list: Vec<(H160, Vec<H256>)>,
) -> (ExitReason, Vec<u8>) {
if let Some(limit) = self.config.max_initcode_size {
if init_code.len() > limit {
self.state.metadata_mut().gasometer.fail();
return emit_exit!(ExitError::CreateContractLimit.into(), Vec::new());
}
}

event!(TransactCreate {
caller,
value,
Expand All @@ -676,6 +655,13 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet> StackExecu
address,
});

if let Some(limit) = self.config.max_initcode_size {
if init_code.len() > limit {
self.state.metadata_mut().gasometer.fail();
return emit_exit!(ExitError::CreateContractLimit.into(), Vec::new());
}
}

if let Err(e) = self.record_create_transaction_cost(&init_code, &access_list) {
return emit_exit!(e.into(), Vec::new());
}
Expand Down Expand Up @@ -714,10 +700,6 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet> StackExecu
gas_limit: u64,
access_list: Vec<(H160, Vec<H256>)>,
) -> (ExitReason, Vec<u8>) {
if let Err(e) = self.state.inc_nonce(caller) {
return (e.into(), Vec::new());
}

event!(TransactCall {
caller,
address,
Expand All @@ -726,6 +708,10 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet> StackExecu
gas_limit,
});

if let Err(e) = self.state.inc_nonce(caller) {
return emit_exit!(e.into(), Vec::new());
}

let transaction_cost = gasometer::call_transaction_cost(&data, &access_list);
let gasometer = &mut self.state.metadata_mut().gasometer;
match gasometer.record_transaction(transaction_cost) {
Expand Down
Loading

0 comments on commit d3134db

Please sign in to comment.