@nomicfoundation/edr 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.toml +5 -11
- package/index.d.ts +31 -2
- package/package.json +8 -8
- package/src/account.rs +22 -4
- package/src/block.rs +8 -0
- package/src/provider.rs +67 -4
- package/src/result.rs +4 -0
- package/src/scenarios.rs +3 -3
package/Cargo.toml
CHANGED
|
@@ -7,34 +7,28 @@ edition = "2021"
|
|
|
7
7
|
crate-type = ["cdylib"]
|
|
8
8
|
|
|
9
9
|
[dependencies]
|
|
10
|
-
alloy-dyn-abi = { version = "0.7.6", default-features = false }
|
|
11
|
-
alloy-json-abi = { version = "0.7.4", default-features = false }
|
|
12
10
|
alloy-sol-types = { version = "0.5.1", default-features = false, features = ["std"] }
|
|
13
11
|
ansi_term = { version = "0.12.1", default-features = false }
|
|
14
|
-
crossbeam-channel = { version = "0.5.6", default-features = false }
|
|
15
12
|
itertools = { version = "0.12.0", default-features = false }
|
|
16
|
-
indexmap = { version = "2" }
|
|
17
13
|
k256 = { version = "0.13.1", default-features = false, features = ["arithmetic", "ecdsa", "pkcs8", "precomputed-tables", "std"] }
|
|
18
|
-
log = { version = "0.4.20", default-features = false }
|
|
19
14
|
# The `async` feature ensures that a tokio runtime is available
|
|
20
15
|
napi = { version = "2.16.11", default-features = false, features = ["async", "error_anyhow", "napi8", "serde-json"] }
|
|
21
16
|
napi-derive = "2.16.11"
|
|
22
17
|
edr_defaults = { version = "0.3.5", path = "../edr_defaults" }
|
|
23
|
-
edr_evm = { version = "0.3.5", path = "../edr_evm", features = ["tracing"]}
|
|
18
|
+
edr_evm = { version = "0.3.5", path = "../edr_evm", features = ["tracing"] }
|
|
24
19
|
edr_eth = { version = "0.3.5", path = "../edr_eth" }
|
|
25
20
|
edr_provider = { version = "0.3.5", path = "../edr_provider" }
|
|
26
21
|
edr_rpc_eth = { version = "0.3.5", path = "../edr_rpc_eth" }
|
|
27
|
-
edr_solidity ={ version = "0.3.5", path = "../edr_solidity" }
|
|
22
|
+
edr_solidity = { version = "0.3.5", path = "../edr_solidity" }
|
|
23
|
+
edr_scenarios = { version = "0.3.5", path = "../edr_scenarios", optional = true }
|
|
28
24
|
serde_json = { version = "1.0.85", default-features = false, features = ["alloc"] }
|
|
29
25
|
thiserror = { version = "1.0.37", default-features = false }
|
|
30
26
|
tracing = { version = "0.1.37", default-features = false, features = ["std"] }
|
|
31
27
|
tracing-flame = { version = "0.2.0", default-features = false, features = ["smallvec"] }
|
|
32
28
|
tracing-subscriber = { version = "0.3.18", default-features = false, features = ["ansi", "env-filter", "fmt", "parking_lot", "smallvec", "std"] }
|
|
33
|
-
parking_lot = { version = "0.12.1", default-features = false }
|
|
34
|
-
lazy_static = { version = "1.4.0", features = [] }
|
|
35
29
|
rand = { version = "0.8.4", optional = true }
|
|
36
|
-
semver = "1.0.22"
|
|
37
30
|
serde = { version = "1.0.189", features = ["derive"] }
|
|
31
|
+
static_assertions = "1.1.0"
|
|
38
32
|
strum = { version = "0.26.0", features = ["derive"] }
|
|
39
33
|
mimalloc = { version = "0.1.39", default-features = false, features = ["local_dynamic_tls"] }
|
|
40
34
|
|
|
@@ -55,7 +49,7 @@ napi-build = "2.0.1"
|
|
|
55
49
|
|
|
56
50
|
[features]
|
|
57
51
|
tracing = ["edr_evm/tracing", "edr_provider/tracing"]
|
|
58
|
-
scenarios = ["rand"]
|
|
52
|
+
scenarios = ["rand", "edr_scenarios"]
|
|
59
53
|
|
|
60
54
|
[profile.release]
|
|
61
55
|
lto = true
|
package/index.d.ts
CHANGED
|
@@ -42,6 +42,12 @@ export interface BlockOptions {
|
|
|
42
42
|
* block (EIP-4788).
|
|
43
43
|
*/
|
|
44
44
|
parentBeaconBlockRoot?: Buffer
|
|
45
|
+
/**
|
|
46
|
+
* The commitment hash calculated for a list of [EIP-7685] data requests.
|
|
47
|
+
*
|
|
48
|
+
* [EIP-7685]: https://eips.ethereum.org/EIPS/eip-7685
|
|
49
|
+
*/
|
|
50
|
+
requestsHash?: Buffer
|
|
45
51
|
}
|
|
46
52
|
/** Information about the blob gas used in a block. */
|
|
47
53
|
export interface BlobGas {
|
|
@@ -254,6 +260,27 @@ export interface ProviderConfig {
|
|
|
254
260
|
/** The network ID of the blockchain */
|
|
255
261
|
networkId: bigint
|
|
256
262
|
}
|
|
263
|
+
/** Tracing config for Solidity stack trace generation. */
|
|
264
|
+
export interface TracingConfigWithBuffers {
|
|
265
|
+
/**
|
|
266
|
+
* Build information to use for decoding contracts. Either a Hardhat v2
|
|
267
|
+
* build info file that contains both input and output or a Hardhat v3
|
|
268
|
+
* build info file that doesn't contain output and a separate output file.
|
|
269
|
+
*/
|
|
270
|
+
buildInfos?: Array<Uint8Array> | Array<BuildInfoAndOutput>
|
|
271
|
+
/** Whether to ignore contracts whose name starts with "Ignored". */
|
|
272
|
+
ignoreContracts?: boolean
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Hardhat V3 build info where the compiler output is not part of the build
|
|
276
|
+
* info file.
|
|
277
|
+
*/
|
|
278
|
+
export interface BuildInfoAndOutput {
|
|
279
|
+
/** The build info input file */
|
|
280
|
+
buildInfo: Uint8Array
|
|
281
|
+
/** The build info output file */
|
|
282
|
+
output: Uint8Array
|
|
283
|
+
}
|
|
257
284
|
/** The possible reasons for successful termination of the EVM. */
|
|
258
285
|
export const enum SuccessReason {
|
|
259
286
|
/** The opcode `STOP` was called */
|
|
@@ -321,7 +348,9 @@ export const enum ExceptionalHalt {
|
|
|
321
348
|
/** Aud data is smaller then already present data size. */
|
|
322
349
|
EofAuxDataTooSmall = 15,
|
|
323
350
|
/** EOF Subroutine stack overflow */
|
|
324
|
-
EOFFunctionStackOverflow = 16
|
|
351
|
+
EOFFunctionStackOverflow = 16,
|
|
352
|
+
/** Check for target address validity is only done inside subcall. */
|
|
353
|
+
InvalidEXTCALLTarget = 17
|
|
325
354
|
}
|
|
326
355
|
/** The result when the EVM terminates due to an exceptional halt. */
|
|
327
356
|
export interface HaltResult {
|
|
@@ -595,7 +624,7 @@ export declare class EdrContext {
|
|
|
595
624
|
/** A JSON-RPC provider for Ethereum. */
|
|
596
625
|
export declare class Provider {
|
|
597
626
|
/**Constructs a new provider with the provided configuration. */
|
|
598
|
-
static withConfig(context: EdrContext, config: ProviderConfig, loggerConfig: LoggerConfig, tracingConfig:
|
|
627
|
+
static withConfig(context: EdrContext, config: ProviderConfig, loggerConfig: LoggerConfig, tracingConfig: TracingConfigWithBuffers, subscriberCallback: (event: SubscriptionEvent) => void): Promise<Provider>
|
|
599
628
|
/**Handles a JSON-RPC request and returns a JSON-RPC response. */
|
|
600
629
|
handleRequest(jsonRequest: string): Promise<Response>
|
|
601
630
|
setCallOverrideCallback(callOverrideCallback: (contract_address: Buffer, data: Buffer) => Promise<CallOverrideResult | undefined>): void
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nomicfoundation/edr",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"devDependencies": {
|
|
5
5
|
"@napi-rs/cli": "^2.18.4",
|
|
6
6
|
"@types/chai": "^4.2.0",
|
|
@@ -52,13 +52,13 @@
|
|
|
52
52
|
"repository": "NomicFoundation/edr.git",
|
|
53
53
|
"types": "index.d.ts",
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@nomicfoundation/edr-darwin-arm64": "0.
|
|
56
|
-
"@nomicfoundation/edr-darwin-x64": "0.
|
|
57
|
-
"@nomicfoundation/edr-linux-arm64-gnu": "0.
|
|
58
|
-
"@nomicfoundation/edr-linux-arm64-musl": "0.
|
|
59
|
-
"@nomicfoundation/edr-linux-x64-gnu": "0.
|
|
60
|
-
"@nomicfoundation/edr-linux-x64-musl": "0.
|
|
61
|
-
"@nomicfoundation/edr-win32-x64-msvc": "0.
|
|
55
|
+
"@nomicfoundation/edr-darwin-arm64": "0.9.0",
|
|
56
|
+
"@nomicfoundation/edr-darwin-x64": "0.9.0",
|
|
57
|
+
"@nomicfoundation/edr-linux-arm64-gnu": "0.9.0",
|
|
58
|
+
"@nomicfoundation/edr-linux-arm64-musl": "0.9.0",
|
|
59
|
+
"@nomicfoundation/edr-linux-x64-gnu": "0.9.0",
|
|
60
|
+
"@nomicfoundation/edr-linux-x64-musl": "0.9.0",
|
|
61
|
+
"@nomicfoundation/edr-win32-x64-msvc": "0.9.0"
|
|
62
62
|
},
|
|
63
63
|
"scripts": {
|
|
64
64
|
"artifacts": "napi artifacts",
|
package/src/account.rs
CHANGED
|
@@ -1,14 +1,22 @@
|
|
|
1
|
-
use
|
|
2
|
-
|
|
1
|
+
use std::fmt::{Debug, Display};
|
|
2
|
+
|
|
3
|
+
#[allow(deprecated)]
|
|
4
|
+
// This is the only source file in production code where it's allowed to create
|
|
5
|
+
// `DangerousSecretKeyStr`.
|
|
6
|
+
use edr_eth::signature::{secret_key_from_str, DangerousSecretKeyStr};
|
|
7
|
+
use napi::{bindgen_prelude::BigInt, JsString, Status};
|
|
3
8
|
use napi_derive::napi;
|
|
9
|
+
use serde::Serialize;
|
|
4
10
|
|
|
5
11
|
use crate::cast::TryCast;
|
|
6
12
|
|
|
7
13
|
/// An account that needs to be created during the genesis block.
|
|
8
14
|
#[napi(object)]
|
|
9
15
|
pub struct GenesisAccount {
|
|
16
|
+
// Using JsString here as it doesn't have `Debug`, `Display` and `Serialize` implementation
|
|
17
|
+
// which prevents accidentally leaking the secret keys to error messages and logs.
|
|
10
18
|
/// Account secret key
|
|
11
|
-
pub secret_key:
|
|
19
|
+
pub secret_key: JsString,
|
|
12
20
|
/// Account balance
|
|
13
21
|
pub balance: BigInt,
|
|
14
22
|
}
|
|
@@ -17,7 +25,17 @@ impl TryFrom<GenesisAccount> for edr_provider::AccountConfig {
|
|
|
17
25
|
type Error = napi::Error;
|
|
18
26
|
|
|
19
27
|
fn try_from(value: GenesisAccount) -> Result<Self, Self::Error> {
|
|
20
|
-
|
|
28
|
+
static_assertions::assert_not_impl_all!(JsString: Debug, Display, Serialize);
|
|
29
|
+
// `k256::SecretKey` has `Debug` implementation, but it's opaque (only shows the
|
|
30
|
+
// type name)
|
|
31
|
+
static_assertions::assert_not_impl_any!(k256::SecretKey: Display, Serialize);
|
|
32
|
+
|
|
33
|
+
let secret_key = value.secret_key.into_utf8()?;
|
|
34
|
+
// This is the only place in production code where it's allowed to use
|
|
35
|
+
// `DangerousSecretKeyStr`.
|
|
36
|
+
#[allow(deprecated)]
|
|
37
|
+
let secret_key_str = DangerousSecretKeyStr(secret_key.as_str()?);
|
|
38
|
+
let secret_key: k256::SecretKey = secret_key_from_str(secret_key_str)
|
|
21
39
|
.map_err(|e| napi::Error::new(Status::InvalidArg, e.to_string()))?;
|
|
22
40
|
|
|
23
41
|
Ok(Self {
|
package/src/block.rs
CHANGED
|
@@ -35,6 +35,10 @@ pub struct BlockOptions {
|
|
|
35
35
|
/// The hash tree root of the parent beacon block for the given execution
|
|
36
36
|
/// block (EIP-4788).
|
|
37
37
|
pub parent_beacon_block_root: Option<Buffer>,
|
|
38
|
+
/// The commitment hash calculated for a list of [EIP-7685] data requests.
|
|
39
|
+
///
|
|
40
|
+
/// [EIP-7685]: https://eips.ethereum.org/EIPS/eip-7685
|
|
41
|
+
pub requests_hash: Option<Buffer>,
|
|
38
42
|
}
|
|
39
43
|
|
|
40
44
|
impl TryFrom<BlockOptions> for edr_eth::block::BlockOptions {
|
|
@@ -92,6 +96,10 @@ impl TryFrom<BlockOptions> for edr_eth::block::BlockOptions {
|
|
|
92
96
|
.parent_beacon_block_root
|
|
93
97
|
.map(TryCast::<B256>::try_cast)
|
|
94
98
|
.transpose()?,
|
|
99
|
+
requests_hash: value
|
|
100
|
+
.requests_hash
|
|
101
|
+
.map(TryCast::<B256>::try_cast)
|
|
102
|
+
.transpose()?,
|
|
95
103
|
})
|
|
96
104
|
}
|
|
97
105
|
}
|
package/src/provider.rs
CHANGED
|
@@ -5,7 +5,9 @@ use std::sync::Arc;
|
|
|
5
5
|
use edr_provider::{time::CurrentTime, InvalidRequestReason};
|
|
6
6
|
use edr_rpc_eth::jsonrpc;
|
|
7
7
|
use edr_solidity::contract_decoder::ContractDecoder;
|
|
8
|
-
use napi::{
|
|
8
|
+
use napi::{
|
|
9
|
+
bindgen_prelude::Uint8Array, tokio::runtime, Either, Env, JsFunction, JsObject, Status,
|
|
10
|
+
};
|
|
9
11
|
use napi_derive::napi;
|
|
10
12
|
|
|
11
13
|
use self::config::ProviderConfig;
|
|
@@ -37,7 +39,7 @@ impl Provider {
|
|
|
37
39
|
_context: &EdrContext,
|
|
38
40
|
config: ProviderConfig,
|
|
39
41
|
logger_config: LoggerConfig,
|
|
40
|
-
tracing_config:
|
|
42
|
+
tracing_config: TracingConfigWithBuffers,
|
|
41
43
|
#[napi(ts_arg_type = "(event: SubscriptionEvent) => void")] subscriber_callback: JsFunction,
|
|
42
44
|
) -> napi::Result<JsObject> {
|
|
43
45
|
let runtime = runtime::Handle::current();
|
|
@@ -45,8 +47,9 @@ impl Provider {
|
|
|
45
47
|
let config = edr_provider::ProviderConfig::try_from(config)?;
|
|
46
48
|
|
|
47
49
|
// TODO https://github.com/NomicFoundation/edr/issues/760
|
|
48
|
-
let build_info_config
|
|
49
|
-
|
|
50
|
+
let build_info_config =
|
|
51
|
+
edr_solidity::artifacts::BuildInfoConfig::parse_from_buffers((&tracing_config).into())
|
|
52
|
+
.map_err(|err| napi::Error::from_reason(err.to_string()))?;
|
|
50
53
|
let contract_decoder = ContractDecoder::new(&build_info_config)
|
|
51
54
|
.map_err(|error| napi::Error::from_reason(error.to_string()))?;
|
|
52
55
|
let contract_decoder = Arc::new(contract_decoder);
|
|
@@ -245,6 +248,66 @@ impl Provider {
|
|
|
245
248
|
}
|
|
246
249
|
}
|
|
247
250
|
|
|
251
|
+
/// Tracing config for Solidity stack trace generation.
|
|
252
|
+
#[napi(object)]
|
|
253
|
+
pub struct TracingConfigWithBuffers {
|
|
254
|
+
/// Build information to use for decoding contracts. Either a Hardhat v2
|
|
255
|
+
/// build info file that contains both input and output or a Hardhat v3
|
|
256
|
+
/// build info file that doesn't contain output and a separate output file.
|
|
257
|
+
pub build_infos: Option<Either<Vec<Uint8Array>, Vec<BuildInfoAndOutput>>>,
|
|
258
|
+
/// Whether to ignore contracts whose name starts with "Ignored".
|
|
259
|
+
pub ignore_contracts: Option<bool>,
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/// Hardhat V3 build info where the compiler output is not part of the build
|
|
263
|
+
/// info file.
|
|
264
|
+
#[napi(object)]
|
|
265
|
+
pub struct BuildInfoAndOutput {
|
|
266
|
+
/// The build info input file
|
|
267
|
+
pub build_info: Uint8Array,
|
|
268
|
+
/// The build info output file
|
|
269
|
+
pub output: Uint8Array,
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
impl<'a> From<&'a BuildInfoAndOutput>
|
|
273
|
+
for edr_solidity::artifacts::BuildInfoBufferSeparateOutput<'a>
|
|
274
|
+
{
|
|
275
|
+
fn from(value: &'a BuildInfoAndOutput) -> Self {
|
|
276
|
+
Self {
|
|
277
|
+
build_info: value.build_info.as_ref(),
|
|
278
|
+
output: value.output.as_ref(),
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
impl<'a> From<&'a TracingConfigWithBuffers>
|
|
284
|
+
for edr_solidity::artifacts::BuildInfoConfigWithBuffers<'a>
|
|
285
|
+
{
|
|
286
|
+
fn from(value: &'a TracingConfigWithBuffers) -> Self {
|
|
287
|
+
use edr_solidity::artifacts::{BuildInfoBufferSeparateOutput, BuildInfoBuffers};
|
|
288
|
+
|
|
289
|
+
let build_infos = value.build_infos.as_ref().map(|infos| match infos {
|
|
290
|
+
Either::A(with_output) => BuildInfoBuffers::WithOutput(
|
|
291
|
+
with_output
|
|
292
|
+
.iter()
|
|
293
|
+
.map(std::convert::AsRef::as_ref)
|
|
294
|
+
.collect(),
|
|
295
|
+
),
|
|
296
|
+
Either::B(separate_output) => BuildInfoBuffers::SeparateInputOutput(
|
|
297
|
+
separate_output
|
|
298
|
+
.iter()
|
|
299
|
+
.map(BuildInfoBufferSeparateOutput::from)
|
|
300
|
+
.collect(),
|
|
301
|
+
),
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
Self {
|
|
305
|
+
build_infos,
|
|
306
|
+
ignore_contracts: value.ignore_contracts,
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
248
311
|
#[derive(Debug)]
|
|
249
312
|
struct SolidityTraceData {
|
|
250
313
|
trace: Arc<edr_evm::trace::Trace>,
|
package/src/result.rs
CHANGED
|
@@ -106,6 +106,8 @@ pub enum ExceptionalHalt {
|
|
|
106
106
|
EofAuxDataTooSmall,
|
|
107
107
|
/// EOF Subroutine stack overflow
|
|
108
108
|
EOFFunctionStackOverflow,
|
|
109
|
+
/// Check for target address validity is only done inside subcall.
|
|
110
|
+
InvalidEXTCALLTarget,
|
|
109
111
|
}
|
|
110
112
|
|
|
111
113
|
impl From<edr_evm::HaltReason> for ExceptionalHalt {
|
|
@@ -136,6 +138,7 @@ impl From<edr_evm::HaltReason> for ExceptionalHalt {
|
|
|
136
138
|
edr_evm::HaltReason::EOFFunctionStackOverflow => {
|
|
137
139
|
ExceptionalHalt::EOFFunctionStackOverflow
|
|
138
140
|
}
|
|
141
|
+
edr_evm::HaltReason::InvalidEXTCALLTarget => ExceptionalHalt::InvalidEXTCALLTarget,
|
|
139
142
|
edr_evm::HaltReason::OverflowPayment
|
|
140
143
|
| edr_evm::HaltReason::StateChangeDuringStaticCall
|
|
141
144
|
| edr_evm::HaltReason::CallNotAllowedInsideStatic
|
|
@@ -167,6 +170,7 @@ impl From<ExceptionalHalt> for edr_evm::HaltReason {
|
|
|
167
170
|
ExceptionalHalt::EofAuxDataOverflow => Self::EofAuxDataOverflow,
|
|
168
171
|
ExceptionalHalt::EofAuxDataTooSmall => Self::EofAuxDataTooSmall,
|
|
169
172
|
ExceptionalHalt::EOFFunctionStackOverflow => Self::EOFFunctionStackOverflow,
|
|
173
|
+
ExceptionalHalt::InvalidEXTCALLTarget => Self::InvalidEXTCALLTarget,
|
|
170
174
|
}
|
|
171
175
|
}
|
|
172
176
|
}
|
package/src/scenarios.rs
CHANGED
|
@@ -8,8 +8,8 @@ use serde::Serialize;
|
|
|
8
8
|
const SCENARIO_FILE_PREFIX: &str = "EDR_SCENARIO_PREFIX";
|
|
9
9
|
|
|
10
10
|
#[derive(Clone, Debug, Serialize)]
|
|
11
|
-
struct ScenarioConfig
|
|
12
|
-
provider_config:
|
|
11
|
+
struct ScenarioConfig {
|
|
12
|
+
provider_config: edr_scenarios::ScenarioProviderConfig,
|
|
13
13
|
logger_enabled: bool,
|
|
14
14
|
}
|
|
15
15
|
|
|
@@ -32,7 +32,7 @@ pub(crate) async fn scenario_file(
|
|
|
32
32
|
File::create(format!("{scenario_prefix}_{timestamp}_{suffix}.json")).await?;
|
|
33
33
|
|
|
34
34
|
let config = ScenarioConfig {
|
|
35
|
-
provider_config,
|
|
35
|
+
provider_config: provider_config.clone().into(),
|
|
36
36
|
logger_enabled,
|
|
37
37
|
};
|
|
38
38
|
let mut line = serde_json::to_string(&config)?;
|