diff --git a/Cargo.lock b/Cargo.lock index 77f248d..7bc7514 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2936,6 +2936,22 @@ dependencies = [ "sp-crypto-hashing", ] +[[package]] +name = "frame-decode" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c470df86cf28818dd3cd2fc4667b80dbefe2236c722c3dc1d09e7c6c82d6dfcd" +dependencies = [ + "frame-metadata", + "parity-scale-codec", + "scale-decode", + "scale-encode", + "scale-info", + "scale-type-resolver", + "sp-crypto-hashing", + "thiserror 2.0.12", +] + [[package]] name = "frame-metadata" version = "23.0.0" @@ -5668,7 +5684,6 @@ version = "0.1.0" dependencies = [ "alloy", "anyhow", - "async-stream", "futures", "revive-common", "revive-dt-common", @@ -5681,6 +5696,7 @@ dependencies = [ "serde_yaml_ng", "sp-core", "sp-runtime", + "subxt 0.44.0", "temp-dir", "tokio", "tower 0.5.2", @@ -7350,11 +7366,48 @@ dependencies = [ "serde", "serde_json", "sp-crypto-hashing", - "subxt-core", - "subxt-lightclient", - "subxt-macro", - "subxt-metadata", - "subxt-rpcs", + "subxt-core 0.43.0", + "subxt-lightclient 0.43.0", + "subxt-macro 0.43.0", + "subxt-metadata 0.43.0", + "subxt-rpcs 0.43.0", + "thiserror 2.0.12", + "tokio", + "tokio-util", + "tracing", + "url", + "wasm-bindgen-futures", + "web-time", +] + +[[package]] +name = "subxt" +version = "0.44.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddbf938ac1d86a361a84709a71cdbae5d87f370770b563651d1ec052eed9d0b4" +dependencies = [ + "async-trait", + "derive-where", + "either", + "frame-metadata", + "futures", + "hex", + "jsonrpsee", + "parity-scale-codec", + "primitive-types 0.13.1", + "scale-bits", + "scale-decode", + "scale-encode", + "scale-info", + "scale-value", + "serde", + "serde_json", + "sp-crypto-hashing", + "subxt-core 0.44.0", + "subxt-lightclient 0.44.0", + "subxt-macro 0.44.0", + "subxt-metadata 0.44.0", + "subxt-rpcs 0.44.0", "thiserror 2.0.12", "tokio", "tokio-util", @@ -7376,7 +7429,24 @@ dependencies = [ "quote", "scale-info", "scale-typegen", - "subxt-metadata", + "subxt-metadata 0.43.0", + "syn 2.0.101", + "thiserror 2.0.12", +] + +[[package]] +name = "subxt-codegen" +version = "0.44.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c250ad8cd102d40ae47977b03295a2ff791375f30ddc7474d399fb56efb793b" +dependencies = [ + "heck", + "parity-scale-codec", + "proc-macro2", + "quote", + "scale-info", + "scale-typegen", + "subxt-metadata 0.44.0", "syn 2.0.101", "thiserror 2.0.12", ] @@ -7390,7 +7460,7 @@ dependencies = [ "base58", "blake2", "derive-where", - "frame-decode", + "frame-decode 0.8.3", "frame-metadata", "hashbrown 0.14.5", "hex", @@ -7406,7 +7476,37 @@ dependencies = [ "serde", "serde_json", "sp-crypto-hashing", - "subxt-metadata", + "subxt-metadata 0.43.0", + "thiserror 2.0.12", + "tracing", +] + +[[package]] +name = "subxt-core" +version = "0.44.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5705c5b420294524e41349bf23c6b11aa474ce731de7317f4153390e1927f702" +dependencies = [ + "base58", + "blake2", + "derive-where", + "frame-decode 0.9.0", + "frame-metadata", + "hashbrown 0.14.5", + "hex", + "impl-serde", + "keccak-hash", + "parity-scale-codec", + "primitive-types 0.13.1", + "scale-bits", + "scale-decode", + "scale-encode", + "scale-info", + "scale-value", + "serde", + "serde_json", + "sp-crypto-hashing", + "subxt-metadata 0.44.0", "thiserror 2.0.12", "tracing", ] @@ -7428,6 +7528,23 @@ dependencies = [ "tracing", ] +[[package]] +name = "subxt-lightclient" +version = "0.44.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64e02732a6c9ae46bc282c1a741b3d3e494021b3e87e7e92cfb3620116d92911" +dependencies = [ + "futures", + "futures-util", + "serde", + "serde_json", + "smoldot-light", + "thiserror 2.0.12", + "tokio", + "tokio-stream", + "tracing", +] + [[package]] name = "subxt-macro" version = "0.43.0" @@ -7439,9 +7556,26 @@ dependencies = [ "proc-macro-error2", "quote", "scale-typegen", - "subxt-codegen", - "subxt-metadata", - "subxt-utils-fetchmetadata", + "subxt-codegen 0.43.0", + "subxt-metadata 0.43.0", + "subxt-utils-fetchmetadata 0.43.0", + "syn 2.0.101", +] + +[[package]] +name = "subxt-macro" +version = "0.44.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "501bf358698f5ab02a6199a1fcd3f1b482e2f5b6eb5d185411e6a74a175ec8e8" +dependencies = [ + "darling 0.20.11", + "parity-scale-codec", + "proc-macro-error2", + "quote", + "scale-typegen", + "subxt-codegen 0.44.0", + "subxt-metadata 0.44.0", + "subxt-utils-fetchmetadata 0.44.0", "syn 2.0.101", ] @@ -7451,7 +7585,22 @@ version = "0.43.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c134068711c0c46906abc0e6e4911204420331530738e18ca903a5469364d9f" dependencies = [ - "frame-decode", + "frame-decode 0.8.3", + "frame-metadata", + "hashbrown 0.14.5", + "parity-scale-codec", + "scale-info", + "sp-crypto-hashing", + "thiserror 2.0.12", +] + +[[package]] +name = "subxt-metadata" +version = "0.44.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01fb7c0bfafad78dda7084c6a2444444744af3bbf7b2502399198b9b4c20eddf" +dependencies = [ + "frame-decode 0.9.0", "frame-metadata", "hashbrown 0.14.5", "parity-scale-codec", @@ -7476,8 +7625,32 @@ dependencies = [ "primitive-types 0.13.1", "serde", "serde_json", - "subxt-core", - "subxt-lightclient", + "subxt-core 0.43.0", + "subxt-lightclient 0.43.0", + "thiserror 2.0.12", + "tokio-util", + "tracing", + "url", +] + +[[package]] +name = "subxt-rpcs" +version = "0.44.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab68a9c20ecedb0cb7d62d64f884e6add91bb70485783bf40aa8eac5c389c6e0" +dependencies = [ + "derive-where", + "frame-metadata", + "futures", + "hex", + "impl-serde", + "jsonrpsee", + "parity-scale-codec", + "primitive-types 0.13.1", + "serde", + "serde_json", + "subxt-core 0.44.0", + "subxt-lightclient 0.44.0", "thiserror 2.0.12", "tokio-util", "tracing", @@ -7507,7 +7680,7 @@ dependencies = [ "serde_json", "sha2 0.10.9", "sp-crypto-hashing", - "subxt-core", + "subxt-core 0.43.0", "thiserror 2.0.12", "zeroize", ] @@ -7523,6 +7696,17 @@ dependencies = [ "thiserror 2.0.12", ] +[[package]] +name = "subxt-utils-fetchmetadata" +version = "0.44.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e450f6812a653c5a3e63a079aa3b60a3f4c362722753c3222286eaa1800f9002" +dependencies = [ + "hex", + "parity-scale-codec", + "thiserror 2.0.12", +] + [[package]] name = "syn" version = "1.0.109" @@ -9316,7 +9500,7 @@ dependencies = [ "serde_json", "sha2 0.10.9", "sp-core", - "subxt", + "subxt 0.43.0", "subxt-signer", "thiserror 1.0.69", "tokio", @@ -9376,7 +9560,7 @@ dependencies = [ "async-trait", "futures", "lazy_static", - "subxt", + "subxt 0.43.0", "subxt-signer", "tokio", "zombienet-configuration", diff --git a/Cargo.toml b/Cargo.toml index d1c48b5..907844a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,6 @@ revive-dt-solc-binaries = { version = "0.1.0", path = "crates/solc-binaries" } ansi_term = "0.12.1" anyhow = "1.0" -async-stream = { version = "0.3.6" } bson = { version = "2.15.0" } cacache = { version = "13.1.0" } clap = { version = "4", features = ["derive"] } @@ -51,6 +50,7 @@ sha2 = { version = "0.10.9" } sp-core = "36.1.0" sp-runtime = "41.1.0" strum = { version = "0.27.2", features = ["derive"] } +subxt = { version = "0.44.0" } temp-dir = { version = "0.1.16" } tempfile = "3.3" thiserror = "2" diff --git a/assets/revive_metadata.scale b/assets/revive_metadata.scale new file mode 100644 index 0000000..68c0a1e Binary files /dev/null and b/assets/revive_metadata.scale differ diff --git a/crates/core/src/differential_benchmarks/watcher.rs b/crates/core/src/differential_benchmarks/watcher.rs index 96f0098..473f134 100644 --- a/crates/core/src/differential_benchmarks/watcher.rs +++ b/crates/core/src/differential_benchmarks/watcher.rs @@ -106,7 +106,9 @@ impl Watcher { // region:TEMPORARY eprintln!("Watcher information for {}", self.platform_identifier); - eprintln!("block_number,block_timestamp,mined_gas,block_gas_limit,tx_count"); + eprintln!( + "block_number,block_timestamp,mined_gas,block_gas_limit,tx_count,ref_time,max_ref_time,proof_size,max_proof_size" + ); // endregion:TEMPORARY while let Some(block) = blocks_information_stream.next().await { // If the block number is equal to or less than the last block before the @@ -141,12 +143,16 @@ impl Watcher { // reporting in place and then it can be removed. This serves as as way of doing // some very simple reporting for the time being. eprintln!( - "\"{}\",\"{}\",\"{}\",\"{}\",\"{}\"", + "\"{}\",\"{}\",\"{}\",\"{}\",\"{}\",\"{}\",\"{}\",\"{}\",\"{}\"", block.block_number, block.block_timestamp, block.mined_gas, block.block_gas_limit, - block.transaction_hashes.len() + block.transaction_hashes.len(), + block.ref_time, + block.max_ref_time, + block.proof_size, + block.max_proof_size, ); // endregion:TEMPORARY diff --git a/crates/node-interaction/src/lib.rs b/crates/node-interaction/src/lib.rs index dbd2bf9..54796a6 100644 --- a/crates/node-interaction/src/lib.rs +++ b/crates/node-interaction/src/lib.rs @@ -3,7 +3,9 @@ use std::pin::Pin; use std::sync::Arc; +use alloy::network::Ethereum; use alloy::primitives::{Address, BlockNumber, BlockTimestamp, StorageKey, TxHash, U256}; +use alloy::providers::DynProvider; use alloy::rpc::types::trace::geth::{DiffMode, GethDebugTracingOptions, GethTrace}; use alloy::rpc::types::{EIP1186AccountProofResponse, TransactionReceipt, TransactionRequest}; use anyhow::Result; @@ -74,6 +76,9 @@ pub trait EthereumNode { + '_, >, >; + + fn provider(&self) + -> Pin>> + '_>>; } #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -92,4 +97,16 @@ pub struct MinedBlockInformation { /// The hashes of the transactions that were mined as part of the block. pub transaction_hashes: Vec, + + /// The ref time for substrate based chains. + pub ref_time: u128, + + /// The max ref time for substrate based chains. + pub max_ref_time: u64, + + /// The proof size for substrate based chains. + pub proof_size: u128, + + /// The max proof size for substrate based chains. + pub max_proof_size: u64, } diff --git a/crates/node/Cargo.toml b/crates/node/Cargo.toml index dfe0827..cffca52 100644 --- a/crates/node/Cargo.toml +++ b/crates/node/Cargo.toml @@ -11,7 +11,6 @@ rust-version.workspace = true [dependencies] anyhow = { workspace = true } alloy = { workspace = true } -async-stream = { workspace = true } futures = { workspace = true } tracing = { workspace = true } tower = { workspace = true } @@ -30,6 +29,7 @@ serde_yaml_ng = { workspace = true } sp-core = { workspace = true } sp-runtime = { workspace = true } +subxt = { workspace = true } zombienet-sdk = { workspace = true } [dev-dependencies] diff --git a/crates/node/src/node_implementations/geth.rs b/crates/node/src/node_implementations/geth.rs index fc31d86..097265d 100644 --- a/crates/node/src/node_implementations/geth.rs +++ b/crates/node/src/node_implementations/geth.rs @@ -32,7 +32,7 @@ use alloy::{ }, }; use anyhow::Context as _; -use futures::{Stream, StreamExt}; +use futures::{FutureExt, Stream, StreamExt}; use revive_common::EVMVersion; use tokio::sync::OnceCell; use tracing::{Instrument, error, instrument}; @@ -535,6 +535,10 @@ impl EthereumNode for GethNode { .as_hashes() .expect("Must be hashes") .to_vec(), + ref_time: 0, + max_ref_time: 0, + proof_size: 0, + max_proof_size: 0, }) }); @@ -542,6 +546,16 @@ impl EthereumNode for GethNode { as Pin>>) }) } + + fn provider( + &self, + ) -> Pin>> + '_>> + { + Box::pin( + self.provider() + .map(|provider| provider.map(|provider| provider.erased())), + ) + } } pub struct GethNodeResolver { diff --git a/crates/node/src/node_implementations/lighthouse_geth.rs b/crates/node/src/node_implementations/lighthouse_geth.rs index f119107..beca317 100644 --- a/crates/node/src/node_implementations/lighthouse_geth.rs +++ b/crates/node/src/node_implementations/lighthouse_geth.rs @@ -43,7 +43,7 @@ use alloy::{ }, }; use anyhow::Context as _; -use futures::{Stream, StreamExt}; +use futures::{FutureExt, Stream, StreamExt}; use revive_common::EVMVersion; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde_with::serde_as; @@ -222,6 +222,7 @@ impl LighthouseGethNode { "--ws.port=8546".to_string(), "--ws.api=eth,net,web3,txpool,engine".to_string(), "--ws.origins=*".to_string(), + "--miner.gaslimit=30000000".to_string(), ], consensus_layer_extra_parameters: vec![ "--disable-quic".to_string(), @@ -247,6 +248,8 @@ impl LighthouseGethNode { .collect::>(); serde_json::to_string(&map).unwrap() }, + gas_limit: 30_000_000, + genesis_gaslimit: 30_000_000, }, wait_for_finalization: false, port_publisher: Some(PortPublisherParameters { @@ -754,6 +757,10 @@ impl EthereumNode for LighthouseGethNode { .as_hashes() .expect("Must be hashes") .to_vec(), + ref_time: 0, + max_ref_time: 0, + proof_size: 0, + max_proof_size: 0, }) }); @@ -761,6 +768,16 @@ impl EthereumNode for LighthouseGethNode { as Pin>>) }) } + + fn provider( + &self, + ) -> Pin>> + '_>> + { + Box::pin( + self.http_provider() + .map(|provider| provider.map(|provider| provider.erased())), + ) + } } pub struct LighthouseGethNodeResolver, P: Provider> { @@ -1035,6 +1052,8 @@ struct NetworkParameters { pub num_validator_keys_per_node: u64, pub genesis_delay: u64, + pub genesis_gaslimit: u64, + pub gas_limit: u64, pub prefunded_accounts: String, } diff --git a/crates/node/src/node_implementations/substrate.rs b/crates/node/src/node_implementations/substrate.rs index ccf1e75..e4fdec4 100644 --- a/crates/node/src/node_implementations/substrate.rs +++ b/crates/node/src/node_implementations/substrate.rs @@ -11,17 +11,10 @@ use std::{ }; use alloy::{ - consensus::{BlockHeader, TxEnvelope}, eips::BlockNumberOrTag, genesis::{Genesis, GenesisAccount}, - network::{ - Ethereum, EthereumWallet, Network, NetworkWallet, TransactionBuilder, - TransactionBuilderError, UnbuiltTransactionError, - }, - primitives::{ - Address, B64, B256, BlockHash, BlockNumber, BlockTimestamp, Bloom, Bytes, StorageKey, - TxHash, U256, - }, + network::{Ethereum, EthereumWallet, NetworkWallet}, + primitives::{Address, BlockHash, BlockNumber, BlockTimestamp, StorageKey, TxHash, U256}, providers::{ Provider, ext::DebugApi, @@ -29,25 +22,23 @@ use alloy::{ }, rpc::types::{ EIP1186AccountProofResponse, TransactionReceipt, TransactionRequest, - eth::{Block, Header, Transaction}, trace::geth::{ DiffMode, GethDebugTracingOptions, GethTrace, PreStateConfig, PreStateFrame, }, }, }; use anyhow::Context as _; -use async_stream::stream; -use futures::Stream; +use futures::{FutureExt, Stream, StreamExt}; use revive_common::EVMVersion; use revive_dt_common::fs::clear_directory; use revive_dt_format::traits::ResolverApi; -use serde::{Deserialize, Serialize}; use serde_json::{Value as JsonValue, json}; use sp_core::crypto::Ss58Codec; use sp_runtime::AccountId32; use revive_dt_config::*; use revive_dt_node_interaction::{EthereumNode, MinedBlockInformation}; +use subxt::{OnlineClient, SubstrateConfig}; use tokio::sync::OnceCell; use tracing::instrument; @@ -80,7 +71,7 @@ pub struct SubstrateNode { eth_proxy_process: Option, wallet: Arc, nonce_manager: CachedNonceManager, - provider: OnceCell>>, + provider: OnceCell>>, consensus: Option, } @@ -353,12 +344,10 @@ impl SubstrateNode { Ok(String::from_utf8_lossy(&output).trim().to_string()) } - async fn provider( - &self, - ) -> anyhow::Result>> { + async fn provider(&self) -> anyhow::Result>> { self.provider .get_or_try_init(|| async move { - construct_concurrency_limited_provider::( + construct_concurrency_limited_provider::( self.rpc_url.as_str(), FallbackGasFiller::new(u64::MAX, 5_000_000_000, 1_000_000_000), ChainIdFiller::new(Some(CHAIN_ID)), @@ -519,53 +508,97 @@ impl EthereumNode for SubstrateNode { + '_, >, > { - fn create_stream( - provider: ConcreteProvider>, - ) -> impl Stream { - stream! { - let mut block_number = provider.get_block_number().await.expect("Failed to get the block number"); - loop { - tokio::time::sleep(Duration::from_secs(1)).await; + #[subxt::subxt(runtime_metadata_path = "../../assets/revive_metadata.scale")] + pub mod revive {} - let Ok(Some(block)) = provider.get_block_by_number(BlockNumberOrTag::Number(block_number)).await - else { - continue; - }; + Box::pin(async move { + let substrate_rpc_port = Self::BASE_SUBSTRATE_RPC_PORT + self.id as u16; + let substrate_rpc_url = format!("ws://127.0.0.1:{substrate_rpc_port}"); + let api = OnlineClient::::from_url(substrate_rpc_url) + .await + .context("Failed to create subxt rpc client")?; + let provider = self.provider().await.context("Failed to create provider")?; - block_number += 1; - yield MinedBlockInformation { - block_number: block.number(), - block_timestamp: block.header.timestamp, - mined_gas: block.header.gas_used as _, - block_gas_limit: block.header.gas_limit, - transaction_hashes: block + let block_stream = api + .blocks() + .subscribe_all() + .await + .context("Failed to subscribe to blocks")?; + + let mined_block_information_stream = block_stream.filter_map(move |block| { + let api = api.clone(); + let provider = provider.clone(); + + async move { + let substrate_block = block.ok()?; + let revive_block = provider + .get_block_by_number( + BlockNumberOrTag::Number(substrate_block.number() as _), + ) + .await + .expect("TODO: Remove") + .expect("TODO: Remove"); + + let used = api + .storage() + .at(substrate_block.reference()) + .fetch_or_default(&revive::storage().system().block_weight()) + .await + .expect("TODO: Remove"); + + let block_ref_time = (used.normal.ref_time as u128) + + (used.operational.ref_time as u128) + + (used.mandatory.ref_time as u128); + let block_proof_size = (used.normal.proof_size as u128) + + (used.operational.proof_size as u128) + + (used.mandatory.proof_size as u128); + + let limits = api + .constants() + .at(&revive::constants().system().block_weights()) + .expect("TODO: Remove"); + + let max_ref_time = limits.max_block.ref_time; + let max_proof_size = limits.max_block.proof_size; + + Some(MinedBlockInformation { + block_number: substrate_block.number() as _, + block_timestamp: revive_block.header.timestamp, + mined_gas: revive_block.header.gas_used as _, + block_gas_limit: revive_block.header.gas_limit as _, + transaction_hashes: revive_block .transactions .into_hashes() .as_hashes() .expect("Must be hashes") .to_vec(), - }; - }; - } - } + ref_time: block_ref_time, + max_ref_time, + proof_size: block_proof_size, + max_proof_size, + }) + } + }); - Box::pin(async move { - let provider = self - .provider() - .await - .context("Failed to create the provider for a block subscription")?; - - let stream = Box::pin(create_stream(provider)) - as Pin>>; - - Ok(stream) + Ok(Box::pin(mined_block_information_stream) + as Pin>>) }) } + + fn provider( + &self, + ) -> Pin>> + '_>> + { + Box::pin( + self.provider() + .map(|provider| provider.map(|provider| provider.erased())), + ) + } } pub struct SubstrateNodeResolver { id: u32, - provider: ConcreteProvider>, + provider: ConcreteProvider>, } impl ResolverApi for SubstrateNodeResolver { @@ -729,430 +762,6 @@ impl Drop for SubstrateNode { } } -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct ReviveNetwork; - -impl Network for ReviveNetwork { - type TxType = ::TxType; - - type TxEnvelope = ::TxEnvelope; - - type UnsignedTx = ::UnsignedTx; - - type ReceiptEnvelope = ::ReceiptEnvelope; - - type Header = ReviveHeader; - - type TransactionRequest = ::TransactionRequest; - - type TransactionResponse = ::TransactionResponse; - - type ReceiptResponse = ::ReceiptResponse; - - type HeaderResponse = Header; - - type BlockResponse = Block, Header>; -} - -impl TransactionBuilder for ::TransactionRequest { - fn chain_id(&self) -> Option { - <::TransactionRequest as TransactionBuilder>::chain_id(self) - } - - fn set_chain_id(&mut self, chain_id: alloy::primitives::ChainId) { - <::TransactionRequest as TransactionBuilder>::set_chain_id( - self, chain_id, - ) - } - - fn nonce(&self) -> Option { - <::TransactionRequest as TransactionBuilder>::nonce(self) - } - - fn set_nonce(&mut self, nonce: u64) { - <::TransactionRequest as TransactionBuilder>::set_nonce( - self, nonce, - ) - } - - fn take_nonce(&mut self) -> Option { - <::TransactionRequest as TransactionBuilder>::take_nonce( - self, - ) - } - - fn input(&self) -> Option<&alloy::primitives::Bytes> { - <::TransactionRequest as TransactionBuilder>::input(self) - } - - fn set_input>(&mut self, input: T) { - <::TransactionRequest as TransactionBuilder>::set_input( - self, input, - ) - } - - fn from(&self) -> Option
{ - <::TransactionRequest as TransactionBuilder>::from(self) - } - - fn set_from(&mut self, from: Address) { - <::TransactionRequest as TransactionBuilder>::set_from( - self, from, - ) - } - - fn kind(&self) -> Option { - <::TransactionRequest as TransactionBuilder>::kind(self) - } - - fn clear_kind(&mut self) { - <::TransactionRequest as TransactionBuilder>::clear_kind( - self, - ) - } - - fn set_kind(&mut self, kind: alloy::primitives::TxKind) { - <::TransactionRequest as TransactionBuilder>::set_kind( - self, kind, - ) - } - - fn value(&self) -> Option { - <::TransactionRequest as TransactionBuilder>::value(self) - } - - fn set_value(&mut self, value: alloy::primitives::U256) { - <::TransactionRequest as TransactionBuilder>::set_value( - self, value, - ) - } - - fn gas_price(&self) -> Option { - <::TransactionRequest as TransactionBuilder>::gas_price(self) - } - - fn set_gas_price(&mut self, gas_price: u128) { - <::TransactionRequest as TransactionBuilder>::set_gas_price( - self, gas_price, - ) - } - - fn max_fee_per_gas(&self) -> Option { - <::TransactionRequest as TransactionBuilder>::max_fee_per_gas( - self, - ) - } - - fn set_max_fee_per_gas(&mut self, max_fee_per_gas: u128) { - <::TransactionRequest as TransactionBuilder>::set_max_fee_per_gas( - self, max_fee_per_gas - ) - } - - fn max_priority_fee_per_gas(&self) -> Option { - <::TransactionRequest as TransactionBuilder>::max_priority_fee_per_gas( - self, - ) - } - - fn set_max_priority_fee_per_gas(&mut self, max_priority_fee_per_gas: u128) { - <::TransactionRequest as TransactionBuilder>::set_max_priority_fee_per_gas( - self, max_priority_fee_per_gas - ) - } - - fn gas_limit(&self) -> Option { - <::TransactionRequest as TransactionBuilder>::gas_limit(self) - } - - fn set_gas_limit(&mut self, gas_limit: u64) { - <::TransactionRequest as TransactionBuilder>::set_gas_limit( - self, gas_limit, - ) - } - - fn access_list(&self) -> Option<&alloy::rpc::types::AccessList> { - <::TransactionRequest as TransactionBuilder>::access_list( - self, - ) - } - - fn set_access_list(&mut self, access_list: alloy::rpc::types::AccessList) { - <::TransactionRequest as TransactionBuilder>::set_access_list( - self, - access_list, - ) - } - - fn complete_type( - &self, - ty: ::TxType, - ) -> Result<(), Vec<&'static str>> { - <::TransactionRequest as TransactionBuilder>::complete_type( - self, ty, - ) - } - - fn can_submit(&self) -> bool { - <::TransactionRequest as TransactionBuilder>::can_submit( - self, - ) - } - - fn can_build(&self) -> bool { - <::TransactionRequest as TransactionBuilder>::can_build(self) - } - - fn output_tx_type(&self) -> ::TxType { - <::TransactionRequest as TransactionBuilder>::output_tx_type( - self, - ) - } - - fn output_tx_type_checked(&self) -> Option<::TxType> { - <::TransactionRequest as TransactionBuilder>::output_tx_type_checked( - self, - ) - } - - fn prep_for_submission(&mut self) { - <::TransactionRequest as TransactionBuilder>::prep_for_submission( - self, - ) - } - - fn build_unsigned( - self, - ) -> alloy::network::BuildResult<::UnsignedTx, ReviveNetwork> { - let result = <::TransactionRequest as TransactionBuilder>::build_unsigned( - self, - ); - match result { - Ok(unsigned_tx) => Ok(unsigned_tx), - Err(UnbuiltTransactionError { request, error }) => { - Err(UnbuiltTransactionError:: { - request, - error: match error { - TransactionBuilderError::InvalidTransactionRequest(tx_type, items) => { - TransactionBuilderError::InvalidTransactionRequest(tx_type, items) - } - TransactionBuilderError::UnsupportedSignatureType => { - TransactionBuilderError::UnsupportedSignatureType - } - TransactionBuilderError::Signer(error) => { - TransactionBuilderError::Signer(error) - } - TransactionBuilderError::Custom(error) => { - TransactionBuilderError::Custom(error) - } - }, - }) - } - } - } - - async fn build>( - self, - wallet: &W, - ) -> Result<::TxEnvelope, TransactionBuilderError> - { - Ok(wallet.sign_request(self).await?) - } -} - -#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct ReviveHeader { - /// The Keccak 256-bit hash of the parent - /// block’s header, in its entirety; formally Hp. - pub parent_hash: B256, - /// The Keccak 256-bit hash of the ommers list portion of this block; formally Ho. - #[serde(rename = "sha3Uncles", alias = "ommersHash")] - pub ommers_hash: B256, - /// The 160-bit address to which all fees collected from the successful mining of this block - /// be transferred; formally Hc. - #[serde(rename = "miner", alias = "beneficiary")] - pub beneficiary: Address, - /// The Keccak 256-bit hash of the root node of the state trie, after all transactions are - /// executed and finalisations applied; formally Hr. - pub state_root: B256, - /// The Keccak 256-bit hash of the root node of the trie structure populated with each - /// transaction in the transactions list portion of the block; formally Ht. - pub transactions_root: B256, - /// The Keccak 256-bit hash of the root node of the trie structure populated with the receipts - /// of each transaction in the transactions list portion of the block; formally He. - pub receipts_root: B256, - /// The Bloom filter composed from indexable information (logger address and log topics) - /// contained in each log entry from the receipt of each transaction in the transactions list; - /// formally Hb. - pub logs_bloom: Bloom, - /// A scalar value corresponding to the difficulty level of this block. This can be calculated - /// from the previous block’s difficulty level and the timestamp; formally Hd. - pub difficulty: U256, - /// A scalar value equal to the number of ancestor blocks. The genesis block has a number of - /// zero; formally Hi. - #[serde(with = "alloy::serde::quantity")] - pub number: BlockNumber, - /// A scalar value equal to the current limit of gas expenditure per block; formally Hl. - // This is the main difference over the Ethereum network implementation. We use u128 here and - // not u64. - #[serde(with = "alloy::serde::quantity")] - pub gas_limit: u128, - /// A scalar value equal to the total gas used in transactions in this block; formally Hg. - #[serde(with = "alloy::serde::quantity")] - pub gas_used: u64, - /// A scalar value equal to the reasonable output of Unix’s time() at this block’s inception; - /// formally Hs. - #[serde(with = "alloy::serde::quantity")] - pub timestamp: u64, - /// An arbitrary byte array containing data relevant to this block. This must be 32 bytes or - /// fewer; formally Hx. - pub extra_data: Bytes, - /// A 256-bit hash which, combined with the - /// nonce, proves that a sufficient amount of computation has been carried out on this block; - /// formally Hm. - pub mix_hash: B256, - /// A 64-bit value which, combined with the mixhash, proves that a sufficient amount of - /// computation has been carried out on this block; formally Hn. - pub nonce: B64, - /// A scalar representing EIP1559 base fee which can move up or down each block according - /// to a formula which is a function of gas used in parent block and gas target - /// (block gas limit divided by elasticity multiplier) of parent block. - /// The algorithm results in the base fee per gas increasing when blocks are - /// above the gas target, and decreasing when blocks are below the gas target. The base fee per - /// gas is burned. - #[serde( - default, - with = "alloy::serde::quantity::opt", - skip_serializing_if = "Option::is_none" - )] - pub base_fee_per_gas: Option, - /// The Keccak 256-bit hash of the withdrawals list portion of this block. - /// - #[serde(default, skip_serializing_if = "Option::is_none")] - pub withdrawals_root: Option, - /// The total amount of blob gas consumed by the transactions within the block, added in - /// EIP-4844. - #[serde( - default, - with = "alloy::serde::quantity::opt", - skip_serializing_if = "Option::is_none" - )] - pub blob_gas_used: Option, - /// A running total of blob gas consumed in excess of the target, prior to the block. Blocks - /// with above-target blob gas consumption increase this value, blocks with below-target blob - /// gas consumption decrease it (bounded at 0). This was added in EIP-4844. - #[serde( - default, - with = "alloy::serde::quantity::opt", - skip_serializing_if = "Option::is_none" - )] - pub excess_blob_gas: Option, - /// The hash of the parent beacon block's root is included in execution blocks, as proposed by - /// EIP-4788. - /// - /// This enables trust-minimized access to consensus state, supporting staking pools, bridges, - /// and more. - /// - /// The beacon roots contract handles root storage, enhancing Ethereum's functionalities. - #[serde(default, skip_serializing_if = "Option::is_none")] - pub parent_beacon_block_root: Option, - /// The Keccak 256-bit hash of the an RLP encoded list with each - /// [EIP-7685] request in the block body. - /// - /// [EIP-7685]: https://eips.ethereum.org/EIPS/eip-7685 - #[serde(default, skip_serializing_if = "Option::is_none")] - pub requests_hash: Option, -} - -impl BlockHeader for ReviveHeader { - fn parent_hash(&self) -> B256 { - self.parent_hash - } - - fn ommers_hash(&self) -> B256 { - self.ommers_hash - } - - fn beneficiary(&self) -> Address { - self.beneficiary - } - - fn state_root(&self) -> B256 { - self.state_root - } - - fn transactions_root(&self) -> B256 { - self.transactions_root - } - - fn receipts_root(&self) -> B256 { - self.receipts_root - } - - fn withdrawals_root(&self) -> Option { - self.withdrawals_root - } - - fn logs_bloom(&self) -> Bloom { - self.logs_bloom - } - - fn difficulty(&self) -> U256 { - self.difficulty - } - - fn number(&self) -> BlockNumber { - self.number - } - - // There's sadly nothing that we can do about this. We're required to implement this trait on - // any type that represents a header and the gas limit type used here is a u64. - fn gas_limit(&self) -> u64 { - self.gas_limit.try_into().unwrap_or(u64::MAX) - } - - fn gas_used(&self) -> u64 { - self.gas_used - } - - fn timestamp(&self) -> u64 { - self.timestamp - } - - fn mix_hash(&self) -> Option { - Some(self.mix_hash) - } - - fn nonce(&self) -> Option { - Some(self.nonce) - } - - fn base_fee_per_gas(&self) -> Option { - self.base_fee_per_gas - } - - fn blob_gas_used(&self) -> Option { - self.blob_gas_used - } - - fn excess_blob_gas(&self) -> Option { - self.excess_blob_gas - } - - fn parent_beacon_block_root(&self) -> Option { - self.parent_beacon_block_root - } - - fn requests_hash(&self) -> Option { - self.requests_hash - } - - fn extra_data(&self) -> &Bytes { - &self.extra_data - } -} - #[cfg(test)] mod tests { use alloy::rpc::types::TransactionRequest; diff --git a/crates/node/src/node_implementations/zombienet.rs b/crates/node/src/node_implementations/zombienet.rs index a5ac8d1..8387685 100644 --- a/crates/node/src/node_implementations/zombienet.rs +++ b/crates/node/src/node_implementations/zombienet.rs @@ -55,8 +55,7 @@ use alloy::{ }; use anyhow::Context as _; -use async_stream::stream; -use futures::Stream; +use futures::{FutureExt, Stream, StreamExt}; use revive_common::EVMVersion; use revive_dt_common::fs::clear_directory; use revive_dt_config::*; @@ -65,6 +64,7 @@ use revive_dt_node_interaction::{EthereumNode, MinedBlockInformation}; use serde_json::{Value as JsonValue, json}; use sp_core::crypto::Ss58Codec; use sp_runtime::AccountId32; +use subxt::{OnlineClient, SubstrateConfig}; use tokio::sync::OnceCell; use tracing::instrument; use zombienet_sdk::{LocalFileSystem, NetworkConfigBuilder, NetworkConfigExt}; @@ -73,7 +73,6 @@ use crate::{ Node, constants::INITIAL_BALANCE, helpers::{Process, ProcessReadinessWaitBehavior}, - node_implementations::substrate::ReviveNetwork, provider_utils::{ ConcreteProvider, FallbackGasFiller, construct_concurrency_limited_provider, execute_transaction, @@ -111,7 +110,7 @@ pub struct ZombienetNode { wallet: Arc, nonce_manager: CachedNonceManager, - provider: OnceCell>>, + provider: OnceCell>>, } impl ZombienetNode { @@ -399,12 +398,10 @@ impl ZombienetNode { Ok(String::from_utf8_lossy(&output).trim().to_string()) } - async fn provider( - &self, - ) -> anyhow::Result>> { + async fn provider(&self) -> anyhow::Result>> { self.provider .get_or_try_init(|| async move { - construct_concurrency_limited_provider::( + construct_concurrency_limited_provider::( self.connection_string.as_str(), FallbackGasFiller::new(u64::MAX, 5_000_000_000, 1_000_000_000), ChainIdFiller::default(), // TODO: use CHAIN_ID constant @@ -567,58 +564,99 @@ impl EthereumNode for ZombienetNode { + '_, >, > { - fn create_stream( - provider: ConcreteProvider>, - ) -> impl Stream { - stream! { - let mut block_number = provider.get_block_number().await.expect("Failed to get the block number"); - loop { - tokio::time::sleep(Duration::from_secs(1)).await; + #[subxt::subxt(runtime_metadata_path = "../../assets/revive_metadata.scale")] + pub mod revive {} - let Ok(Some(block)) = provider.get_block_by_number(BlockNumberOrTag::Number(block_number)).await - else { - continue; - }; + Box::pin(async move { + let substrate_rpc_url = format!("ws://127.0.0.1:{}", self.node_rpc_port.unwrap()); + let api = OnlineClient::::from_url(substrate_rpc_url) + .await + .context("Failed to create subxt rpc client")?; + let provider = self.provider().await.context("Failed to create provider")?; - block_number += 1; - yield MinedBlockInformation { - block_number: block.number(), - block_timestamp: block.header.timestamp, - mined_gas: block.header.gas_used as _, - block_gas_limit: block.header.gas_limit, - transaction_hashes: block + let block_stream = api + .blocks() + .subscribe_all() + .await + .context("Failed to subscribe to blocks")?; + + let mined_block_information_stream = block_stream.filter_map(move |block| { + let api = api.clone(); + let provider = provider.clone(); + + async move { + let substrate_block = block.ok()?; + let revive_block = provider + .get_block_by_number( + BlockNumberOrTag::Number(substrate_block.number() as _), + ) + .await + .expect("TODO: Remove") + .expect("TODO: Remove"); + + let used = api + .storage() + .at(substrate_block.reference()) + .fetch_or_default(&revive::storage().system().block_weight()) + .await + .expect("TODO: Remove"); + + let block_ref_time = (used.normal.ref_time as u128) + + (used.operational.ref_time as u128) + + (used.mandatory.ref_time as u128); + let block_proof_size = (used.normal.proof_size as u128) + + (used.operational.proof_size as u128) + + (used.mandatory.proof_size as u128); + + let limits = api + .constants() + .at(&revive::constants().system().block_weights()) + .expect("TODO: Remove"); + + let max_ref_time = limits.max_block.ref_time; + let max_proof_size = limits.max_block.proof_size; + + Some(MinedBlockInformation { + block_number: substrate_block.number() as _, + block_timestamp: revive_block.header.timestamp, + mined_gas: revive_block.header.gas_used as _, + block_gas_limit: revive_block.header.gas_limit as _, + transaction_hashes: revive_block .transactions .into_hashes() .as_hashes() .expect("Must be hashes") .to_vec(), - }; - }; - } - } + ref_time: block_ref_time, + max_ref_time, + proof_size: block_proof_size, + max_proof_size, + }) + } + }); - Box::pin(async move { - let provider = self - .provider() - .await - .context("Failed to create the provider for a block subscription")?; - - let stream = Box::pin(create_stream(provider)) - as Pin>>; - - Ok(stream) + Ok(Box::pin(mined_block_information_stream) + as Pin>>) }) } + + fn provider( + &self, + ) -> Pin>> + '_>> + { + Box::pin( + self.provider() + .map(|provider| provider.map(|provider| provider.erased())), + ) + } } -pub struct ZombieNodeResolver, P: Provider> { +pub struct ZombieNodeResolver, P: Provider> { id: u32, - provider: FillProvider, + provider: FillProvider, } -impl, P: Provider> ResolverApi - for ZombieNodeResolver -{ +impl, P: Provider> ResolverApi for ZombieNodeResolver { #[instrument(level = "info", skip_all, fields(zombie_node_id = self.id))] fn chain_id( &self, diff --git a/crates/node/src/provider_utils/provider.rs b/crates/node/src/provider_utils/provider.rs index f10b3b6..ba7a2c5 100644 --- a/crates/node/src/provider_utils/provider.rs +++ b/crates/node/src/provider_utils/provider.rs @@ -44,7 +44,7 @@ where // requests at any point of time and no more than that. This is done in an effort to stabilize // the framework from some of the interment issues that we've been seeing related to RPC calls. static GLOBAL_CONCURRENCY_LIMITER_LAYER: LazyLock = - LazyLock::new(|| ConcurrencyLimiterLayer::new(500)); + LazyLock::new(|| ConcurrencyLimiterLayer::new(1000)); let client = ClientBuilder::default() .layer(GLOBAL_CONCURRENCY_LIMITER_LAYER.clone()) diff --git a/run_tests.sh b/run_tests.sh index 37817c6..c0bd229 100755 --- a/run_tests.sh +++ b/run_tests.sh @@ -76,7 +76,7 @@ cat > "$CORPUS_FILE" << EOF { "name": "MatterLabs Solidity Simple, Complex, and Semantic Tests", "paths": [ - "$(realpath "$TEST_REPO_DIR/fixtures/solidity/simple")" + "$(realpath "$TEST_REPO_DIR/fixtures/solidity")" ] } EOF @@ -93,16 +93,17 @@ echo "" # Run the tool cargo build --release; RUST_LOG="info,alloy_pubsub::service=error" ./target/release/retester test \ - --platform geth-evm-solc \ + --platform revive-dev-node-polkavm-resolc \ --corpus "$CORPUS_FILE" \ --working-directory "$WORKDIR" \ --concurrency.number-of-nodes 10 \ --concurrency.number-of-threads 5 \ - --concurrency.ignore-concurrency-limit \ + --concurrency.number-of-concurrent-tasks 500 \ --wallet.additional-keys 100000 \ --kitchensink.path "$SUBSTRATE_NODE_BIN" \ --revive-dev-node.path "$REVIVE_DEV_NODE_BIN" \ --eth-rpc.path "$ETH_RPC_BIN" \ - > logs.log + > logs.log \ + 2> output.log echo -e "${GREEN}=== Test run completed! ===${NC}" \ No newline at end of file