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

refactor: pass tracing config to provider #738

Merged
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
6 changes: 3 additions & 3 deletions crates/edr_napi/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -645,7 +645,7 @@ export declare class EdrContext {
/** A JSON-RPC provider for Ethereum. */
export declare class Provider {
/**Constructs a new provider with the provided configuration. */
static withConfig(context: EdrContext, config: ProviderConfig, loggerConfig: LoggerConfig, subscriberCallback: (event: SubscriptionEvent) => void): Promise<Provider>
static withConfig(context: EdrContext, config: ProviderConfig, loggerConfig: LoggerConfig, tracingConfig: any, subscriberCallback: (event: SubscriptionEvent) => void): Promise<Provider>
/**Handles a JSON-RPC request and returns a JSON-RPC response. */
handleRequest(jsonRequest: string): Promise<Response>
setCallOverrideCallback(callOverrideCallback: (contract_address: Buffer, data: Buffer) => Promise<CallOverrideResult | undefined>): void
Expand All @@ -661,8 +661,8 @@ export declare class Response {
/** Returns the response data as a JSON string or a JSON object. */
get data(): string | any
get solidityTrace(): RawTrace | null
/**Compute the error stack trace. Return undefined if there was no error, returns the stack trace if it can be computed or returns the error message if available as fallback. */
stackTrace(config: any): SolidityStackTrace | string | null
/**Compute the error stack trace. Return undefined if there was no error, returns the stack trace if it can be computed or returns the error message if available as a fallback. */
stackTrace(): SolidityStackTrace | string | null
get traces(): Array<RawTrace>
}
/**
Expand Down
23 changes: 14 additions & 9 deletions crates/edr_napi/src/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use crate::{
pub struct Provider {
provider: Arc<edr_provider::Provider<LoggerError>>,
runtime: runtime::Handle,
tracing_config: Arc<edr_solidity::vm_trace_decoder::TracingConfig>,
#[cfg(feature = "scenarios")]
scenario_file: Option<napi::tokio::sync::Mutex<napi::tokio::fs::File>>,
}
Expand All @@ -36,6 +37,8 @@ impl Provider {
_context: &EdrContext,
config: ProviderConfig,
logger_config: LoggerConfig,
// TODO avoid opaque type
tracing_config: serde_json::Value,
#[napi(ts_arg_type = "(event: SubscriptionEvent) => void")] subscriber_callback: JsFunction,
) -> napi::Result<JsObject> {
let config = edr_provider::ProviderConfig::try_from(config)?;
Expand All @@ -45,6 +48,10 @@ impl Provider {
let subscriber_callback = SubscriberCallback::new(&env, subscriber_callback)?;
let subscriber_callback = Box::new(move |event| subscriber_callback.call(event));

// TODO get actual type as argument
let tracing_config: edr_solidity::vm_trace_decoder::TracingConfig =
serde_json::from_value(tracing_config)?;

let (deferred, promise) = env.create_deferred()?;
runtime.clone().spawn_blocking(move || {
#[cfg(feature = "scenarios")]
Expand All @@ -67,6 +74,7 @@ impl Provider {
Ok(Provider {
provider: Arc::new(provider),
runtime,
tracing_config: Arc::new(tracing_config),
#[cfg(feature = "scenarios")]
scenario_file,
})
Expand Down Expand Up @@ -125,6 +133,7 @@ impl Provider {
solidity_trace: None,
data: Either::A(json),
traces: Vec::new(),
tracing_config: Arc::clone(&self.tracing_config),
});
}
};
Expand Down Expand Up @@ -189,6 +198,7 @@ impl Provider {
solidity_trace,
data,
traces: traces.into_iter().map(Arc::new).collect(),
tracing_config: Arc::clone(&self.tracing_config),
})
}

Expand Down Expand Up @@ -234,6 +244,7 @@ pub struct Response {
solidity_trace: Option<Arc<edr_evm::trace::Trace>>,
/// This may contain zero or more traces, depending on the (batch) request
traces: Vec<Arc<edr_evm::trace::Trace>>,
tracing_config: Arc<edr_solidity::vm_trace_decoder::TracingConfig>,
}

#[napi]
Expand All @@ -252,12 +263,9 @@ impl Response {
}

// Rust port of https://github.com/NomicFoundation/hardhat/blob/c20bf195a6efdc2d74e778b7a4a7799aac224841/packages/hardhat-core/src/internal/hardhat-network/provider/provider.ts#L590
#[doc = "Compute the error stack trace. Return undefined if there was no error, returns the stack trace if it can be computed or returns the error message if available as fallback."]
#[doc = "Compute the error stack trace. Return undefined if there was no error, returns the stack trace if it can be computed or returns the error message if available as a fallback."]
#[napi]
pub fn stack_trace(
&self,
config: serde_json::Value,
) -> napi::Result<Option<Either<SolidityStackTrace, String>>> {
pub fn stack_trace(&self) -> napi::Result<Option<Either<SolidityStackTrace, String>>> {
let Some(trace) = &self.solidity_trace else {
return Ok(None);
};
Expand All @@ -267,13 +275,10 @@ impl Response {
let mut vm_trace = vm_tracer.get_last_top_level_message_trace();
let vm_tracer_error = vm_tracer.get_last_error();

// TODO get actual type as argument
let tracing_config: edr_solidity::vm_trace_decoder::TracingConfig =
serde_json::from_value(config)?;
let mut vm_trace_decoder = edr_solidity::vm_trace_decoder::VmTraceDecoder::new();
edr_solidity::vm_trace_decoder::initialize_vm_trace_decoder(
&mut vm_trace_decoder,
tracing_config,
&self.tracing_config,
)?;

vm_trace = vm_trace.map(|trace| vm_trace_decoder.try_to_decode_message_trace(trace));
Expand Down
6 changes: 3 additions & 3 deletions crates/edr_solidity/src/vm_trace_decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,13 +183,13 @@ pub struct ContractAndFunctionName {

pub fn initialize_vm_trace_decoder(
vm_trace_decoder: &mut VmTraceDecoder,
config: TracingConfig,
config: &TracingConfig,
) -> anyhow::Result<()> {
let Some(build_infos) = config.build_infos else {
let Some(build_infos) = &config.build_infos else {
return Ok(());
};

for build_info in &build_infos {
for build_info in build_infos {
let bytecodes = create_models_and_decode_bytecodes(
build_info.solc_version.clone(),
&build_info.input,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
toBytes,
} from "@nomicfoundation/ethereumjs-util";

import { MessageTrace } from "hardhat/internal/hardhat-network/stack-traces/message-trace";

Check failure on line 8 in hardhat-tests/test/internal/hardhat-network/stack-traces/execution.ts

View workflow job for this annotation

GitHub Actions / Lint Hardhat tests

'MessageTrace' is defined but never used. Allowed unused vars must match /^_/u
import { defaultHardhatNetworkParams } from "hardhat/internal/core/config/default-config";
import {
MempoolOrder,
TracingConfig,
} from "hardhat/internal/hardhat-network/provider/node-types";
import { EdrProviderWrapper } from "hardhat/internal/hardhat-network/provider/provider";
import { VMTracer } from "hardhat/internal/hardhat-network/stack-traces/vm-tracer";

Check failure on line 15 in hardhat-tests/test/internal/hardhat-network/stack-traces/execution.ts

View workflow job for this annotation

GitHub Actions / Lint Hardhat tests

'VMTracer' is defined but never used. Allowed unused vars must match /^_/u
import { LoggerConfig } from "hardhat/internal/hardhat-network/provider/modules/logger";
import { SolidityStackTrace } from "hardhat/internal/hardhat-network/stack-traces/solidity-stack-trace";
import { Response } from "@nomicfoundation/edr";
Expand Down Expand Up @@ -106,8 +106,7 @@

export async function traceTransaction(
provider: EdrProviderWrapper,
txData: TxData,
tracingConfig: TracingConfig
txData: TxData
): Promise<SolidityStackTrace | string | undefined> {
const stringifiedArgs = JSON.stringify({
method: "eth_sendTransaction",
Expand All @@ -125,7 +124,7 @@
});

if (txData.to !== undefined) {
const code = await provider.request({

Check failure on line 127 in hardhat-tests/test/internal/hardhat-network/stack-traces/execution.ts

View workflow job for this annotation

GitHub Actions / Lint Hardhat tests

'code' is assigned a value but never used. Allowed unused vars must match /^_/u
method: "eth_getCode",
params: [bytesToHex(txData.to), "latest"],
});
Expand All @@ -136,7 +135,7 @@
}

const responseObject: Response =
await provider["_provider"].handleRequest(stringifiedArgs);

Check failure on line 138 in hardhat-tests/test/internal/hardhat-network/stack-traces/execution.ts

View workflow job for this annotation

GitHub Actions / Lint Hardhat tests

["_provider"] is better written in dot notation

let response;
if (typeof responseObject.data === "string") {
Expand All @@ -150,7 +149,7 @@
params: [response.result ?? response.error.data.transactionHash],
});

const stackTrace = responseObject.stackTrace(tracingConfig);
const stackTrace = responseObject.stackTrace();

const contractAddress = receipt.contractAddress?.slice(2);

Expand Down
27 changes: 14 additions & 13 deletions hardhat-tests/test/internal/hardhat-network/stack-traces/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@
ConsoleLogger,
} from "hardhat/internal/hardhat-network/stack-traces/consoleLogger";
import {
printMessageTrace,

Check failure on line 13 in hardhat-tests/test/internal/hardhat-network/stack-traces/test.ts

View workflow job for this annotation

GitHub Actions / Lint Hardhat tests

'printMessageTrace' is defined but never used. Allowed unused vars must match /^_/u
printStackTrace,
} from "hardhat/internal/hardhat-network/stack-traces/debug";
import { linkHexStringBytecode } from "hardhat/internal/hardhat-network/stack-traces/library-utils";
import {
CallMessageTrace,

Check failure on line 18 in hardhat-tests/test/internal/hardhat-network/stack-traces/test.ts

View workflow job for this annotation

GitHub Actions / Lint Hardhat tests

'CallMessageTrace' is defined but never used. Allowed unused vars must match /^_/u
CreateMessageTrace,

Check failure on line 19 in hardhat-tests/test/internal/hardhat-network/stack-traces/test.ts

View workflow job for this annotation

GitHub Actions / Lint Hardhat tests

'CreateMessageTrace' is defined but never used. Allowed unused vars must match /^_/u
MessageTrace,

Check failure on line 20 in hardhat-tests/test/internal/hardhat-network/stack-traces/test.ts

View workflow job for this annotation

GitHub Actions / Lint Hardhat tests

'MessageTrace' is defined but never used. Allowed unused vars must match /^_/u
} from "hardhat/internal/hardhat-network/stack-traces/message-trace";
import {
SolidityStackTrace,
Expand All @@ -25,7 +25,7 @@
StackTraceEntryType,
} from "hardhat/internal/hardhat-network/stack-traces/solidity-stack-trace";
import { SolidityTracer } from "hardhat/internal/hardhat-network/stack-traces/solidityTracer";
import { VmTraceDecoderT } from "hardhat/internal/hardhat-network/stack-traces/vm-trace-decoder";

Check failure on line 28 in hardhat-tests/test/internal/hardhat-network/stack-traces/test.ts

View workflow job for this annotation

GitHub Actions / Lint Hardhat tests

'VmTraceDecoderT' is defined but never used. Allowed unused vars must match /^_/u
import { SUPPORTED_SOLIDITY_VERSION_RANGE } from "hardhat/internal/hardhat-network/stack-traces/constants";
import {
BuildInfo,
Expand Down Expand Up @@ -480,7 +480,7 @@
};

const logger = new FakeModulesLogger();
const solidityTracer = new SolidityTracer();

Check failure on line 483 in hardhat-tests/test/internal/hardhat-network/stack-traces/test.ts

View workflow job for this annotation

GitHub Actions / Lint Hardhat tests

'solidityTracer' is assigned a value but never used. Allowed unused vars must match /^_/u
const provider = await instantiateProvider(
{
enabled: false,
Expand All @@ -501,8 +501,7 @@
tx,
provider,
compilerOutput,
txIndexToContract,
tracingConfig,
txIndexToContract
);

if (typeof stackTraceOrContractAddress === "string") {
Expand All @@ -525,21 +524,22 @@
tx,
provider,
compilerOutput,
contract!,
tracingConfig,
contract!
);
}

try {
if (tx.stackTrace === undefined) {
assert.isTrue(
stackTraceOrContractAddress === undefined || typeof stackTraceOrContractAddress === "string",
stackTraceOrContractAddress === undefined ||
typeof stackTraceOrContractAddress === "string",
// FVTODO
`Transaction ${txIndex} shouldn't have failed`
);
} else {
assert.isFalse(
stackTraceOrContractAddress === undefined || typeof stackTraceOrContractAddress === "string",
stackTraceOrContractAddress === undefined ||
typeof stackTraceOrContractAddress === "string",
`Transaction ${txIndex} should have failed`
);
}
Expand All @@ -549,7 +549,10 @@
throw error;
}

if (stackTraceOrContractAddress !== undefined && typeof stackTraceOrContractAddress !== "string") {
if (
stackTraceOrContractAddress !== undefined &&
typeof stackTraceOrContractAddress !== "string"
) {
try {
compareStackTraces(
txIndex,
Expand Down Expand Up @@ -630,8 +633,7 @@
tx: DeploymentTransaction,
provider: EdrProviderWrapper,
compilerOutput: CompilerOutput,
txIndexToContract: Map<number, DeployedContract>,
tracingConfig: TracingConfig,
txIndexToContract: Map<number, DeployedContract>
): Promise<SolidityStackTrace | string | undefined> {
const file = compilerOutput.contracts[tx.file];

Expand Down Expand Up @@ -665,7 +667,7 @@
value: tx.value !== undefined ? BigInt(tx.value) : undefined,
data,
gas: tx.gas !== undefined ? BigInt(tx.gas) : undefined,
}, tracingConfig);
});

return trace;
}
Expand All @@ -675,8 +677,7 @@
tx: CallTransaction,
provider: EdrProviderWrapper,
compilerOutput: CompilerOutput,
contract: DeployedContract,
tracingConfig: TracingConfig,
contract: DeployedContract
): Promise<SolidityStackTrace | string | undefined> {
const compilerContract =
compilerOutput.contracts[contract.file][contract.name];
Expand All @@ -700,7 +701,7 @@
value: tx.value !== undefined ? BigInt(tx.value) : undefined,
data,
gas: tx.gas !== undefined ? BigInt(tx.gas) : undefined,
}, tracingConfig);
});

return trace;
}
Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
"pnpm": {
"overrides": {
"hardhat>@nomicfoundation/edr": "workspace:*"
},
"patchedDependencies": {
"[email protected]": "patches/[email protected]"
}
},
"private": true,
Expand Down
13 changes: 13 additions & 0 deletions patches/[email protected]
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
diff --git a/internal/hardhat-network/provider/provider.js b/internal/hardhat-network/provider/provider.js
index a4b921c8a37b7d5967955d0449df3d05dbe725a8..7ff9eac18cb9a587aa6bd13ff69904cb4b610611 100644
--- a/internal/hardhat-network/provider/provider.js
+++ b/internal/hardhat-network/provider/provider.js
@@ -196,7 +196,7 @@ class EdrProviderWrapper extends events_1.EventEmitter {
printLineFn(message);
}
},
- }, (event) => {
+ }, tracingConfig ?? {}, (event) => {
eventAdapter.emit("ethEvent", event);
});
const minimalEthereumJsNode = {
27 changes: 16 additions & 11 deletions pnpm-lock.yaml

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

Loading