mirror of
https://github.com/pezkuwichain/revive-differential-tests.git
synced 2026-06-13 05:51:01 +00:00
Provide a common node implementation for substrate chains
This commit is contained in:
@@ -20,7 +20,7 @@ use revive_dt_format::traits::ResolverApi;
|
|||||||
use revive_dt_node::{
|
use revive_dt_node::{
|
||||||
Node,
|
Node,
|
||||||
geth::{self, GethNode},
|
geth::{self, GethNode},
|
||||||
kitchensink::KitchensinkNode,
|
substrate::SubstrateNode,
|
||||||
};
|
};
|
||||||
use revive_dt_node_interaction::EthereumNode;
|
use revive_dt_node_interaction::EthereumNode;
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
@@ -54,7 +54,7 @@ impl Platform for Geth {
|
|||||||
pub struct Kitchensink;
|
pub struct Kitchensink;
|
||||||
|
|
||||||
impl Platform for Kitchensink {
|
impl Platform for Kitchensink {
|
||||||
type Blockchain = KitchensinkNode;
|
type Blockchain = SubstrateNode;
|
||||||
type Compiler = revive_resolc::Resolc;
|
type Compiler = revive_resolc::Resolc;
|
||||||
|
|
||||||
fn config_id() -> &'static TestingPlatform {
|
fn config_id() -> &'static TestingPlatform {
|
||||||
|
|||||||
@@ -2,14 +2,13 @@
|
|||||||
|
|
||||||
use alloy::genesis::Genesis;
|
use alloy::genesis::Genesis;
|
||||||
use revive_common::EVMVersion;
|
use revive_common::EVMVersion;
|
||||||
use revive_dt_config::*;
|
|
||||||
use revive_dt_node_interaction::EthereumNode;
|
use revive_dt_node_interaction::EthereumNode;
|
||||||
|
|
||||||
pub mod common;
|
pub mod common;
|
||||||
pub mod constants;
|
pub mod constants;
|
||||||
pub mod geth;
|
pub mod geth;
|
||||||
pub mod kitchensink;
|
|
||||||
pub mod pool;
|
pub mod pool;
|
||||||
|
pub mod substrate;
|
||||||
|
|
||||||
/// An abstract interface for testing nodes.
|
/// An abstract interface for testing nodes.
|
||||||
pub trait Node: EthereumNode {
|
pub trait Node: EthereumNode {
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ use revive_dt_config::{
|
|||||||
KitchensinkConfiguration, ReviveDevNodeConfiguration, WalletConfiguration,
|
KitchensinkConfiguration, ReviveDevNodeConfiguration, WalletConfiguration,
|
||||||
WorkingDirectoryConfiguration,
|
WorkingDirectoryConfiguration,
|
||||||
};
|
};
|
||||||
use tracing::info;
|
|
||||||
|
|
||||||
use crate::Node;
|
use crate::Node;
|
||||||
|
|
||||||
@@ -81,7 +80,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn spawn_node<T: Node + Send>(
|
fn spawn_node<T: Node + Send>(
|
||||||
context: impl AsRef<WorkingDirectoryConfiguration>
|
_: impl AsRef<WorkingDirectoryConfiguration>
|
||||||
+ AsRef<ConcurrencyConfiguration>
|
+ AsRef<ConcurrencyConfiguration>
|
||||||
+ AsRef<GenesisConfiguration>
|
+ AsRef<GenesisConfiguration>
|
||||||
+ AsRef<WalletConfiguration>
|
+ AsRef<WalletConfiguration>
|
||||||
@@ -91,7 +90,7 @@ fn spawn_node<T: Node + Send>(
|
|||||||
+ AsRef<EthRpcConfiguration>
|
+ AsRef<EthRpcConfiguration>
|
||||||
+ Clone
|
+ Clone
|
||||||
+ 'static,
|
+ 'static,
|
||||||
genesis: Genesis,
|
_: Genesis,
|
||||||
) -> anyhow::Result<T> {
|
) -> anyhow::Result<T> {
|
||||||
todo!("Remove");
|
todo!("Remove");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,12 +51,15 @@ use crate::{Node, common::FallbackGasFiller, constants::INITIAL_BALANCE};
|
|||||||
|
|
||||||
static NODE_COUNT: AtomicU32 = AtomicU32::new(0);
|
static NODE_COUNT: AtomicU32 = AtomicU32::new(0);
|
||||||
|
|
||||||
|
/// A node implementation for Substrate based chains. Currently, this supports either kitchensink
|
||||||
|
/// or the revive-dev-node which is done by changing the path and some of the other arguments passed
|
||||||
|
/// to the command.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct KitchensinkNode {
|
pub struct SubstrateNode {
|
||||||
id: u32,
|
id: u32,
|
||||||
substrate_binary: PathBuf,
|
node_binary: PathBuf,
|
||||||
dev_node_binary: PathBuf,
|
|
||||||
eth_proxy_binary: PathBuf,
|
eth_proxy_binary: PathBuf,
|
||||||
|
export_chainspec_command: String,
|
||||||
rpc_url: String,
|
rpc_url: String,
|
||||||
base_directory: PathBuf,
|
base_directory: PathBuf,
|
||||||
logs_directory: PathBuf,
|
logs_directory: PathBuf,
|
||||||
@@ -65,16 +68,11 @@ pub struct KitchensinkNode {
|
|||||||
wallet: Arc<EthereumWallet>,
|
wallet: Arc<EthereumWallet>,
|
||||||
nonce_manager: CachedNonceManager,
|
nonce_manager: CachedNonceManager,
|
||||||
chain_id_filler: ChainIdFiller,
|
chain_id_filler: ChainIdFiller,
|
||||||
use_kitchensink_not_dev_node: bool,
|
|
||||||
/// This vector stores [`File`] objects that we use for logging which we want to flush when the
|
|
||||||
/// node object is dropped. We do not store them in a structured fashion at the moment (in
|
|
||||||
/// separate fields) as the logic that we need to apply to them is all the same regardless of
|
|
||||||
/// what it belongs to, we just want to flush them on [`Drop`] of the node.
|
|
||||||
logs_file_to_flush: Vec<File>,
|
logs_file_to_flush: Vec<File>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl KitchensinkNode {
|
impl SubstrateNode {
|
||||||
const BASE_DIRECTORY: &str = "kitchensink";
|
const BASE_DIRECTORY: &str = "Substrate";
|
||||||
const LOGS_DIRECTORY: &str = "logs";
|
const LOGS_DIRECTORY: &str = "logs";
|
||||||
const DATA_DIRECTORY: &str = "chains";
|
const DATA_DIRECTORY: &str = "chains";
|
||||||
|
|
||||||
@@ -87,44 +85,39 @@ impl KitchensinkNode {
|
|||||||
const SUBSTRATE_LOG_ENV: &str = "error,evm=debug,sc_rpc_server=info,runtime::revive=debug";
|
const SUBSTRATE_LOG_ENV: &str = "error,evm=debug,sc_rpc_server=info,runtime::revive=debug";
|
||||||
const PROXY_LOG_ENV: &str = "info,eth-rpc=debug";
|
const PROXY_LOG_ENV: &str = "info,eth-rpc=debug";
|
||||||
|
|
||||||
const KITCHENSINK_STDOUT_LOG_FILE_NAME: &str = "node_stdout.log";
|
const SUBSTRATE_STDOUT_LOG_FILE_NAME: &str = "node_stdout.log";
|
||||||
const KITCHENSINK_STDERR_LOG_FILE_NAME: &str = "node_stderr.log";
|
const SUBSTRATE_STDERR_LOG_FILE_NAME: &str = "node_stderr.log";
|
||||||
|
|
||||||
const PROXY_STDOUT_LOG_FILE_NAME: &str = "proxy_stdout.log";
|
const PROXY_STDOUT_LOG_FILE_NAME: &str = "proxy_stdout.log";
|
||||||
const PROXY_STDERR_LOG_FILE_NAME: &str = "proxy_stderr.log";
|
const PROXY_STDERR_LOG_FILE_NAME: &str = "proxy_stderr.log";
|
||||||
|
|
||||||
|
pub const KITCHENSINK_EXPORT_CHAINSPEC_COMMAND: &str = "export-chain-spec";
|
||||||
|
pub const REVIVE_DEV_NODE_EXPORT_CHAINSPEC_COMMAND: &str = "build-spec";
|
||||||
|
|
||||||
pub fn new(
|
pub fn new(
|
||||||
|
node_path: PathBuf,
|
||||||
|
export_chainspec_command: &str,
|
||||||
context: impl AsRef<WorkingDirectoryConfiguration>
|
context: impl AsRef<WorkingDirectoryConfiguration>
|
||||||
+ AsRef<ConcurrencyConfiguration>
|
|
||||||
+ AsRef<GenesisConfiguration>
|
|
||||||
+ AsRef<WalletConfiguration>
|
|
||||||
+ AsRef<GethConfiguration>
|
|
||||||
+ AsRef<KitchensinkConfiguration>
|
|
||||||
+ AsRef<ReviveDevNodeConfiguration>
|
|
||||||
+ AsRef<EthRpcConfiguration>
|
+ AsRef<EthRpcConfiguration>
|
||||||
+ Clone,
|
+ AsRef<WalletConfiguration>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let kitchensink_configuration = AsRef::<KitchensinkConfiguration>::as_ref(&context);
|
let working_directory_path =
|
||||||
let dev_node_configuration = AsRef::<ReviveDevNodeConfiguration>::as_ref(&context);
|
AsRef::<WorkingDirectoryConfiguration>::as_ref(&context).as_path();
|
||||||
let eth_rpc_configuration = AsRef::<EthRpcConfiguration>::as_ref(&context);
|
let eth_rpc_path = AsRef::<EthRpcConfiguration>::as_ref(&context)
|
||||||
let working_directory_configuration =
|
.path
|
||||||
AsRef::<WorkingDirectoryConfiguration>::as_ref(&context);
|
.as_path();
|
||||||
let wallet_configuration = AsRef::<WalletConfiguration>::as_ref(&context);
|
let wallet = AsRef::<WalletConfiguration>::as_ref(&context).wallet();
|
||||||
|
|
||||||
let kitchensink_directory = working_directory_configuration
|
let substrate_directory = working_directory_path.join(Self::BASE_DIRECTORY);
|
||||||
.as_path()
|
|
||||||
.join(Self::BASE_DIRECTORY);
|
|
||||||
let id = NODE_COUNT.fetch_add(1, Ordering::SeqCst);
|
let id = NODE_COUNT.fetch_add(1, Ordering::SeqCst);
|
||||||
let base_directory = kitchensink_directory.join(id.to_string());
|
let base_directory = substrate_directory.join(id.to_string());
|
||||||
let logs_directory = base_directory.join(Self::LOGS_DIRECTORY);
|
let logs_directory = base_directory.join(Self::LOGS_DIRECTORY);
|
||||||
|
|
||||||
let wallet = wallet_configuration.wallet();
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
id,
|
id,
|
||||||
substrate_binary: kitchensink_configuration.path.clone(),
|
node_binary: node_path,
|
||||||
dev_node_binary: dev_node_configuration.path.clone(),
|
eth_proxy_binary: eth_rpc_path.to_path_buf(),
|
||||||
eth_proxy_binary: eth_rpc_configuration.path.clone(),
|
export_chainspec_command: export_chainspec_command.to_string(),
|
||||||
rpc_url: String::new(),
|
rpc_url: String::new(),
|
||||||
base_directory,
|
base_directory,
|
||||||
logs_directory,
|
logs_directory,
|
||||||
@@ -133,9 +126,6 @@ impl KitchensinkNode {
|
|||||||
wallet: wallet.clone(),
|
wallet: wallet.clone(),
|
||||||
chain_id_filler: Default::default(),
|
chain_id_filler: Default::default(),
|
||||||
nonce_manager: Default::default(),
|
nonce_manager: Default::default(),
|
||||||
use_kitchensink_not_dev_node: kitchensink_configuration.use_kitchensink,
|
|
||||||
// We know that we only need to be storing 4 files so we can specify that when creating
|
|
||||||
// the vector. It's the stdout and stderr of the substrate-node and the eth-rpc.
|
|
||||||
logs_file_to_flush: Vec::with_capacity(4),
|
logs_file_to_flush: Vec::with_capacity(4),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -153,33 +143,24 @@ impl KitchensinkNode {
|
|||||||
|
|
||||||
// Note: we do not pipe the logs of this process to a separate file since this is just a
|
// Note: we do not pipe the logs of this process to a separate file since this is just a
|
||||||
// once-off export of the default chain spec and not part of the long-running node process.
|
// once-off export of the default chain spec and not part of the long-running node process.
|
||||||
let output = if self.use_kitchensink_not_dev_node {
|
let output = Command::new(&self.node_binary)
|
||||||
Command::new(&self.substrate_binary)
|
.arg(self.export_chainspec_command.as_str())
|
||||||
.arg("export-chain-spec")
|
.arg("--chain")
|
||||||
.arg("--chain")
|
.arg("dev")
|
||||||
.arg("dev")
|
.output()
|
||||||
.output()
|
.context("Failed to export the chain-spec")?;
|
||||||
.context("Failed to export the chain-spec")?
|
|
||||||
} else {
|
|
||||||
Command::new(&self.dev_node_binary)
|
|
||||||
.arg("build-spec")
|
|
||||||
.arg("--chain")
|
|
||||||
.arg("dev")
|
|
||||||
.output()
|
|
||||||
.context("Failed to export the chain-spec")?
|
|
||||||
};
|
|
||||||
|
|
||||||
if !output.status.success() {
|
if !output.status.success() {
|
||||||
anyhow::bail!(
|
anyhow::bail!(
|
||||||
"substrate-node export-chain-spec failed: {}",
|
"Substrate-node export-chain-spec failed: {}",
|
||||||
String::from_utf8_lossy(&output.stderr)
|
String::from_utf8_lossy(&output.stderr)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let content = String::from_utf8(output.stdout)
|
let content = String::from_utf8(output.stdout)
|
||||||
.context("Failed to decode substrate export-chain-spec output as UTF-8")?;
|
.context("Failed to decode Substrate export-chain-spec output as UTF-8")?;
|
||||||
let mut chainspec_json: JsonValue =
|
let mut chainspec_json: JsonValue =
|
||||||
serde_json::from_str(&content).context("Failed to parse substrate chain spec JSON")?;
|
serde_json::from_str(&content).context("Failed to parse Substrate chain spec JSON")?;
|
||||||
|
|
||||||
let existing_chainspec_balances =
|
let existing_chainspec_balances =
|
||||||
chainspec_json["genesis"]["runtimeGenesis"]["patch"]["balances"]["balances"]
|
chainspec_json["genesis"]["runtimeGenesis"]["patch"]["balances"]["balances"]
|
||||||
@@ -250,17 +231,13 @@ impl KitchensinkNode {
|
|||||||
// Start Substrate node
|
// Start Substrate node
|
||||||
let kitchensink_stdout_logs_file = open_options
|
let kitchensink_stdout_logs_file = open_options
|
||||||
.clone()
|
.clone()
|
||||||
.open(self.kitchensink_stdout_log_file_path())
|
.open(self.substrate_stdout_log_file_path())
|
||||||
.context("Failed to open kitchensink stdout logs file")?;
|
.context("Failed to open kitchensink stdout logs file")?;
|
||||||
let kitchensink_stderr_logs_file = open_options
|
let kitchensink_stderr_logs_file = open_options
|
||||||
.clone()
|
.clone()
|
||||||
.open(self.kitchensink_stderr_log_file_path())
|
.open(self.substrate_stderr_log_file_path())
|
||||||
.context("Failed to open kitchensink stderr logs file")?;
|
.context("Failed to open kitchensink stderr logs file")?;
|
||||||
let node_binary_path = if self.use_kitchensink_not_dev_node {
|
let node_binary_path = self.node_binary.as_path();
|
||||||
self.substrate_binary.as_path()
|
|
||||||
} else {
|
|
||||||
self.dev_node_binary.as_path()
|
|
||||||
};
|
|
||||||
self.process_substrate = Command::new(node_binary_path)
|
self.process_substrate = Command::new(node_binary_path)
|
||||||
.arg("--dev")
|
.arg("--dev")
|
||||||
.arg("--chain")
|
.arg("--chain")
|
||||||
@@ -290,17 +267,17 @@ impl KitchensinkNode {
|
|||||||
.context("Failed to clone kitchensink stderr log file handle")?,
|
.context("Failed to clone kitchensink stderr log file handle")?,
|
||||||
)
|
)
|
||||||
.spawn()
|
.spawn()
|
||||||
.context("Failed to spawn substrate node process")?
|
.context("Failed to spawn Substrate node process")?
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
// Give the node a moment to boot
|
// Give the node a moment to boot
|
||||||
if let Err(error) = Self::wait_ready(
|
if let Err(error) = Self::wait_ready(
|
||||||
self.kitchensink_stderr_log_file_path().as_path(),
|
self.substrate_stderr_log_file_path().as_path(),
|
||||||
Self::SUBSTRATE_READY_MARKER,
|
Self::SUBSTRATE_READY_MARKER,
|
||||||
Duration::from_secs(60),
|
Duration::from_secs(60),
|
||||||
) {
|
) {
|
||||||
self.shutdown()
|
self.shutdown()
|
||||||
.context("Failed to gracefully shutdown after substrate start error")?;
|
.context("Failed to gracefully shutdown after Substrate start error")?;
|
||||||
return Err(error);
|
return Err(error);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -414,14 +391,14 @@ impl KitchensinkNode {
|
|||||||
Ok(String::from_utf8_lossy(&output).trim().to_string())
|
Ok(String::from_utf8_lossy(&output).trim().to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn kitchensink_stdout_log_file_path(&self) -> PathBuf {
|
fn substrate_stdout_log_file_path(&self) -> PathBuf {
|
||||||
self.logs_directory
|
self.logs_directory
|
||||||
.join(Self::KITCHENSINK_STDOUT_LOG_FILE_NAME)
|
.join(Self::SUBSTRATE_STDOUT_LOG_FILE_NAME)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn kitchensink_stderr_log_file_path(&self) -> PathBuf {
|
fn substrate_stderr_log_file_path(&self) -> PathBuf {
|
||||||
self.logs_directory
|
self.logs_directory
|
||||||
.join(Self::KITCHENSINK_STDERR_LOG_FILE_NAME)
|
.join(Self::SUBSTRATE_STDERR_LOG_FILE_NAME)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn proxy_stdout_log_file_path(&self) -> PathBuf {
|
fn proxy_stdout_log_file_path(&self) -> PathBuf {
|
||||||
@@ -435,15 +412,11 @@ impl KitchensinkNode {
|
|||||||
async fn provider(
|
async fn provider(
|
||||||
&self,
|
&self,
|
||||||
) -> anyhow::Result<
|
) -> anyhow::Result<
|
||||||
FillProvider<
|
FillProvider<impl TxFiller<ReviveNetwork>, impl Provider<ReviveNetwork>, ReviveNetwork>,
|
||||||
impl TxFiller<KitchensinkNetwork>,
|
|
||||||
impl Provider<KitchensinkNetwork>,
|
|
||||||
KitchensinkNetwork,
|
|
||||||
>,
|
|
||||||
> {
|
> {
|
||||||
ProviderBuilder::new()
|
ProviderBuilder::new()
|
||||||
.disable_recommended_fillers()
|
.disable_recommended_fillers()
|
||||||
.network::<KitchensinkNetwork>()
|
.network::<ReviveNetwork>()
|
||||||
.filler(FallbackGasFiller::new(
|
.filler(FallbackGasFiller::new(
|
||||||
25_000_000,
|
25_000_000,
|
||||||
1_000_000_000,
|
1_000_000_000,
|
||||||
@@ -458,7 +431,7 @@ impl KitchensinkNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EthereumNode for KitchensinkNode {
|
impl EthereumNode for SubstrateNode {
|
||||||
fn execute_transaction(
|
fn execute_transaction(
|
||||||
&self,
|
&self,
|
||||||
transaction: alloy::rpc::types::TransactionRequest,
|
transaction: alloy::rpc::types::TransactionRequest,
|
||||||
@@ -551,19 +524,18 @@ impl EthereumNode for KitchensinkNode {
|
|||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
let id = self.id;
|
let id = self.id;
|
||||||
let provider = self.provider().await?;
|
let provider = self.provider().await?;
|
||||||
Ok(Box::new(KitchensinkNodeResolver { id, provider }) as Box<dyn ResolverApi>)
|
Ok(Box::new(SubstrateNodeResolver { id, provider }) as Box<dyn ResolverApi>)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct KitchensinkNodeResolver<F: TxFiller<KitchensinkNetwork>, P: Provider<KitchensinkNetwork>>
|
pub struct SubstrateNodeResolver<F: TxFiller<ReviveNetwork>, P: Provider<ReviveNetwork>> {
|
||||||
{
|
|
||||||
id: u32,
|
id: u32,
|
||||||
provider: FillProvider<F, P, KitchensinkNetwork>,
|
provider: FillProvider<F, P, ReviveNetwork>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: TxFiller<KitchensinkNetwork>, P: Provider<KitchensinkNetwork>> ResolverApi
|
impl<F: TxFiller<ReviveNetwork>, P: Provider<ReviveNetwork>> ResolverApi
|
||||||
for KitchensinkNodeResolver<F, P>
|
for SubstrateNodeResolver<F, P>
|
||||||
{
|
{
|
||||||
#[instrument(level = "info", skip_all, fields(kitchensink_node_id = self.id))]
|
#[instrument(level = "info", skip_all, fields(kitchensink_node_id = self.id))]
|
||||||
fn chain_id(
|
fn chain_id(
|
||||||
@@ -688,7 +660,7 @@ impl<F: TxFiller<KitchensinkNetwork>, P: Provider<KitchensinkNetwork>> ResolverA
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Remove
|
// TODO: Remove
|
||||||
impl ResolverApi for KitchensinkNode {
|
impl ResolverApi for SubstrateNode {
|
||||||
fn chain_id(
|
fn chain_id(
|
||||||
&self,
|
&self,
|
||||||
) -> Pin<Box<dyn Future<Output = anyhow::Result<alloy::primitives::ChainId>> + '_>> {
|
) -> Pin<Box<dyn Future<Output = anyhow::Result<alloy::primitives::ChainId>> + '_>> {
|
||||||
@@ -830,7 +802,7 @@ impl ResolverApi for KitchensinkNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Node for KitchensinkNode {
|
impl Node for SubstrateNode {
|
||||||
fn id(&self) -> usize {
|
fn id(&self) -> usize {
|
||||||
self.id as _
|
self.id as _
|
||||||
}
|
}
|
||||||
@@ -848,7 +820,7 @@ impl Node for KitchensinkNode {
|
|||||||
}
|
}
|
||||||
if let Some(mut child) = self.process_substrate.take() {
|
if let Some(mut child) = self.process_substrate.take() {
|
||||||
child.kill().map_err(|error| {
|
child.kill().map_err(|error| {
|
||||||
anyhow::anyhow!("Failed to kill the substrate process: {error:?}")
|
anyhow::anyhow!("Failed to kill the Substrate process: {error:?}")
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -870,7 +842,7 @@ impl Node for KitchensinkNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn version(&self) -> anyhow::Result<String> {
|
fn version(&self) -> anyhow::Result<String> {
|
||||||
let output = Command::new(&self.substrate_binary)
|
let output = Command::new(&self.node_binary)
|
||||||
.arg("--version")
|
.arg("--version")
|
||||||
.stdin(Stdio::null())
|
.stdin(Stdio::null())
|
||||||
.stdout(Stdio::piped())
|
.stdout(Stdio::piped())
|
||||||
@@ -895,16 +867,16 @@ impl Node for KitchensinkNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for KitchensinkNode {
|
impl Drop for SubstrateNode {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
self.shutdown().expect("Failed to shutdown")
|
self.shutdown().expect("Failed to shutdown")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct KitchensinkNetwork;
|
pub struct ReviveNetwork;
|
||||||
|
|
||||||
impl Network for KitchensinkNetwork {
|
impl Network for ReviveNetwork {
|
||||||
type TxType = <Ethereum as Network>::TxType;
|
type TxType = <Ethereum as Network>::TxType;
|
||||||
|
|
||||||
type TxEnvelope = <Ethereum as Network>::TxEnvelope;
|
type TxEnvelope = <Ethereum as Network>::TxEnvelope;
|
||||||
@@ -913,7 +885,7 @@ impl Network for KitchensinkNetwork {
|
|||||||
|
|
||||||
type ReceiptEnvelope = <Ethereum as Network>::ReceiptEnvelope;
|
type ReceiptEnvelope = <Ethereum as Network>::ReceiptEnvelope;
|
||||||
|
|
||||||
type Header = KitchensinkHeader;
|
type Header = ReviveHeader;
|
||||||
|
|
||||||
type TransactionRequest = <Ethereum as Network>::TransactionRequest;
|
type TransactionRequest = <Ethereum as Network>::TransactionRequest;
|
||||||
|
|
||||||
@@ -921,12 +893,12 @@ impl Network for KitchensinkNetwork {
|
|||||||
|
|
||||||
type ReceiptResponse = <Ethereum as Network>::ReceiptResponse;
|
type ReceiptResponse = <Ethereum as Network>::ReceiptResponse;
|
||||||
|
|
||||||
type HeaderResponse = Header<KitchensinkHeader>;
|
type HeaderResponse = Header<ReviveHeader>;
|
||||||
|
|
||||||
type BlockResponse = Block<Transaction<TxEnvelope>, Header<KitchensinkHeader>>;
|
type BlockResponse = Block<Transaction<TxEnvelope>, Header<ReviveHeader>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TransactionBuilder<KitchensinkNetwork> for <Ethereum as Network>::TransactionRequest {
|
impl TransactionBuilder<ReviveNetwork> for <Ethereum as Network>::TransactionRequest {
|
||||||
fn chain_id(&self) -> Option<alloy::primitives::ChainId> {
|
fn chain_id(&self) -> Option<alloy::primitives::ChainId> {
|
||||||
<<Ethereum as Network>::TransactionRequest as TransactionBuilder<Ethereum>>::chain_id(self)
|
<<Ethereum as Network>::TransactionRequest as TransactionBuilder<Ethereum>>::chain_id(self)
|
||||||
}
|
}
|
||||||
@@ -1058,7 +1030,7 @@ impl TransactionBuilder<KitchensinkNetwork> for <Ethereum as Network>::Transacti
|
|||||||
|
|
||||||
fn complete_type(
|
fn complete_type(
|
||||||
&self,
|
&self,
|
||||||
ty: <KitchensinkNetwork as Network>::TxType,
|
ty: <ReviveNetwork as Network>::TxType,
|
||||||
) -> Result<(), Vec<&'static str>> {
|
) -> Result<(), Vec<&'static str>> {
|
||||||
<<Ethereum as Network>::TransactionRequest as TransactionBuilder<Ethereum>>::complete_type(
|
<<Ethereum as Network>::TransactionRequest as TransactionBuilder<Ethereum>>::complete_type(
|
||||||
self, ty,
|
self, ty,
|
||||||
@@ -1075,13 +1047,13 @@ impl TransactionBuilder<KitchensinkNetwork> for <Ethereum as Network>::Transacti
|
|||||||
<<Ethereum as Network>::TransactionRequest as TransactionBuilder<Ethereum>>::can_build(self)
|
<<Ethereum as Network>::TransactionRequest as TransactionBuilder<Ethereum>>::can_build(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn output_tx_type(&self) -> <KitchensinkNetwork as Network>::TxType {
|
fn output_tx_type(&self) -> <ReviveNetwork as Network>::TxType {
|
||||||
<<Ethereum as Network>::TransactionRequest as TransactionBuilder<Ethereum>>::output_tx_type(
|
<<Ethereum as Network>::TransactionRequest as TransactionBuilder<Ethereum>>::output_tx_type(
|
||||||
self,
|
self,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn output_tx_type_checked(&self) -> Option<<KitchensinkNetwork as Network>::TxType> {
|
fn output_tx_type_checked(&self) -> Option<<ReviveNetwork as Network>::TxType> {
|
||||||
<<Ethereum as Network>::TransactionRequest as TransactionBuilder<Ethereum>>::output_tx_type_checked(
|
<<Ethereum as Network>::TransactionRequest as TransactionBuilder<Ethereum>>::output_tx_type_checked(
|
||||||
self,
|
self,
|
||||||
)
|
)
|
||||||
@@ -1095,15 +1067,14 @@ impl TransactionBuilder<KitchensinkNetwork> for <Ethereum as Network>::Transacti
|
|||||||
|
|
||||||
fn build_unsigned(
|
fn build_unsigned(
|
||||||
self,
|
self,
|
||||||
) -> alloy::network::BuildResult<<KitchensinkNetwork as Network>::UnsignedTx, KitchensinkNetwork>
|
) -> alloy::network::BuildResult<<ReviveNetwork as Network>::UnsignedTx, ReviveNetwork> {
|
||||||
{
|
|
||||||
let result = <<Ethereum as Network>::TransactionRequest as TransactionBuilder<Ethereum>>::build_unsigned(
|
let result = <<Ethereum as Network>::TransactionRequest as TransactionBuilder<Ethereum>>::build_unsigned(
|
||||||
self,
|
self,
|
||||||
);
|
);
|
||||||
match result {
|
match result {
|
||||||
Ok(unsigned_tx) => Ok(unsigned_tx),
|
Ok(unsigned_tx) => Ok(unsigned_tx),
|
||||||
Err(UnbuiltTransactionError { request, error }) => {
|
Err(UnbuiltTransactionError { request, error }) => {
|
||||||
Err(UnbuiltTransactionError::<KitchensinkNetwork> {
|
Err(UnbuiltTransactionError::<ReviveNetwork> {
|
||||||
request,
|
request,
|
||||||
error: match error {
|
error: match error {
|
||||||
TransactionBuilderError::InvalidTransactionRequest(tx_type, items) => {
|
TransactionBuilderError::InvalidTransactionRequest(tx_type, items) => {
|
||||||
@@ -1124,20 +1095,18 @@ impl TransactionBuilder<KitchensinkNetwork> for <Ethereum as Network>::Transacti
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn build<W: alloy::network::NetworkWallet<KitchensinkNetwork>>(
|
async fn build<W: alloy::network::NetworkWallet<ReviveNetwork>>(
|
||||||
self,
|
self,
|
||||||
wallet: &W,
|
wallet: &W,
|
||||||
) -> Result<
|
) -> Result<<ReviveNetwork as Network>::TxEnvelope, TransactionBuilderError<ReviveNetwork>>
|
||||||
<KitchensinkNetwork as Network>::TxEnvelope,
|
{
|
||||||
TransactionBuilderError<KitchensinkNetwork>,
|
|
||||||
> {
|
|
||||||
Ok(wallet.sign_request(self).await?)
|
Ok(wallet.sign_request(self).await?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct KitchensinkHeader {
|
pub struct ReviveHeader {
|
||||||
/// The Keccak 256-bit hash of the parent
|
/// The Keccak 256-bit hash of the parent
|
||||||
/// block’s header, in its entirety; formally Hp.
|
/// block’s header, in its entirety; formally Hp.
|
||||||
pub parent_hash: B256,
|
pub parent_hash: B256,
|
||||||
@@ -1240,7 +1209,7 @@ pub struct KitchensinkHeader {
|
|||||||
pub requests_hash: Option<B256>,
|
pub requests_hash: Option<B256>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BlockHeader for KitchensinkHeader {
|
impl BlockHeader for ReviveHeader {
|
||||||
fn parent_hash(&self) -> B256 {
|
fn parent_hash(&self) -> B256 {
|
||||||
self.parent_hash
|
self.parent_hash
|
||||||
}
|
}
|
||||||
@@ -1344,7 +1313,7 @@ mod tests {
|
|||||||
context
|
context
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_node() -> (ExecutionContext, KitchensinkNode) {
|
fn new_node() -> (ExecutionContext, SubstrateNode) {
|
||||||
// Note: When we run the tests in the CI we found that if they're all
|
// Note: When we run the tests in the CI we found that if they're all
|
||||||
// run in parallel then the CI is unable to start all of the nodes in
|
// run in parallel then the CI is unable to start all of the nodes in
|
||||||
// time and their start up times-out. Therefore, we want all of the
|
// time and their start up times-out. Therefore, we want all of the
|
||||||
@@ -1364,7 +1333,11 @@ mod tests {
|
|||||||
let _guard = NODE_START_MUTEX.lock().unwrap();
|
let _guard = NODE_START_MUTEX.lock().unwrap();
|
||||||
|
|
||||||
let context = test_config();
|
let context = test_config();
|
||||||
let mut node = KitchensinkNode::new(&context);
|
let mut node = SubstrateNode::new(
|
||||||
|
context.kitchensink_configuration.path.clone(),
|
||||||
|
SubstrateNode::KITCHENSINK_EXPORT_CHAINSPEC_COMMAND,
|
||||||
|
&context,
|
||||||
|
);
|
||||||
node.init(context.genesis_configuration.genesis().unwrap().clone())
|
node.init(context.genesis_configuration.genesis().unwrap().clone())
|
||||||
.expect("Failed to initialize the node")
|
.expect("Failed to initialize the node")
|
||||||
.spawn_process()
|
.spawn_process()
|
||||||
@@ -1373,8 +1346,8 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A shared node that multiple tests can use. It starts up once.
|
/// A shared node that multiple tests can use. It starts up once.
|
||||||
fn shared_node() -> &'static KitchensinkNode {
|
fn shared_node() -> &'static SubstrateNode {
|
||||||
static NODE: LazyLock<(ExecutionContext, KitchensinkNode)> = LazyLock::new(|| {
|
static NODE: LazyLock<(ExecutionContext, SubstrateNode)> = LazyLock::new(|| {
|
||||||
let (context, node) = new_node();
|
let (context, node) = new_node();
|
||||||
(context, node)
|
(context, node)
|
||||||
});
|
});
|
||||||
@@ -1423,7 +1396,12 @@ mod tests {
|
|||||||
}
|
}
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
let mut dummy_node = KitchensinkNode::new(&test_config());
|
let context = test_config();
|
||||||
|
let mut dummy_node = SubstrateNode::new(
|
||||||
|
context.kitchensink_configuration.path.clone(),
|
||||||
|
SubstrateNode::KITCHENSINK_EXPORT_CHAINSPEC_COMMAND,
|
||||||
|
&context,
|
||||||
|
);
|
||||||
|
|
||||||
// Call `init()`
|
// Call `init()`
|
||||||
dummy_node
|
dummy_node
|
||||||
@@ -1433,16 +1411,16 @@ mod tests {
|
|||||||
// Check that the patched chainspec file was generated
|
// Check that the patched chainspec file was generated
|
||||||
let final_chainspec_path = dummy_node
|
let final_chainspec_path = dummy_node
|
||||||
.base_directory
|
.base_directory
|
||||||
.join(KitchensinkNode::CHAIN_SPEC_JSON_FILE);
|
.join(SubstrateNode::CHAIN_SPEC_JSON_FILE);
|
||||||
assert!(final_chainspec_path.exists(), "Chainspec file should exist");
|
assert!(final_chainspec_path.exists(), "Chainspec file should exist");
|
||||||
|
|
||||||
let contents = fs::read_to_string(&final_chainspec_path).expect("Failed to read chainspec");
|
let contents = fs::read_to_string(&final_chainspec_path).expect("Failed to read chainspec");
|
||||||
|
|
||||||
// Validate that the Substrate addresses derived from the Ethereum addresses are in the file
|
// Validate that the Substrate addresses derived from the Ethereum addresses are in the file
|
||||||
let first_eth_addr = KitchensinkNode::eth_to_substrate_address(
|
let first_eth_addr = SubstrateNode::eth_to_substrate_address(
|
||||||
&"90F8bf6A479f320ead074411a4B0e7944Ea8c9C1".parse().unwrap(),
|
&"90F8bf6A479f320ead074411a4B0e7944Ea8c9C1".parse().unwrap(),
|
||||||
);
|
);
|
||||||
let second_eth_addr = KitchensinkNode::eth_to_substrate_address(
|
let second_eth_addr = SubstrateNode::eth_to_substrate_address(
|
||||||
&"Ab8483F64d9C6d1EcF9b849Ae677dD3315835cb2".parse().unwrap(),
|
&"Ab8483F64d9C6d1EcF9b849Ae677dD3315835cb2".parse().unwrap(),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -1469,7 +1447,12 @@ mod tests {
|
|||||||
}
|
}
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
let node = KitchensinkNode::new(&test_config());
|
let context = test_config();
|
||||||
|
let node = SubstrateNode::new(
|
||||||
|
context.kitchensink_configuration.path.clone(),
|
||||||
|
SubstrateNode::KITCHENSINK_EXPORT_CHAINSPEC_COMMAND,
|
||||||
|
&context,
|
||||||
|
);
|
||||||
|
|
||||||
let result = node
|
let result = node
|
||||||
.extract_balance_from_genesis_file(&serde_json::from_str(genesis_json).unwrap())
|
.extract_balance_from_genesis_file(&serde_json::from_str(genesis_json).unwrap())
|
||||||
@@ -1502,7 +1485,7 @@ mod tests {
|
|||||||
];
|
];
|
||||||
|
|
||||||
for eth_addr in eth_addresses {
|
for eth_addr in eth_addresses {
|
||||||
let ss58 = KitchensinkNode::eth_to_substrate_address(ð_addr.parse().unwrap());
|
let ss58 = SubstrateNode::eth_to_substrate_address(ð_addr.parse().unwrap());
|
||||||
|
|
||||||
println!("Ethereum: {eth_addr} -> Substrate SS58: {ss58}");
|
println!("Ethereum: {eth_addr} -> Substrate SS58: {ss58}");
|
||||||
}
|
}
|
||||||
@@ -1530,7 +1513,7 @@ mod tests {
|
|||||||
];
|
];
|
||||||
|
|
||||||
for (eth_addr, expected_ss58) in cases {
|
for (eth_addr, expected_ss58) in cases {
|
||||||
let result = KitchensinkNode::eth_to_substrate_address(ð_addr.parse().unwrap());
|
let result = SubstrateNode::eth_to_substrate_address(ð_addr.parse().unwrap());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
result, expected_ss58,
|
result, expected_ss58,
|
||||||
"Mismatch for Ethereum address {eth_addr}"
|
"Mismatch for Ethereum address {eth_addr}"
|
||||||
@@ -1545,8 +1528,8 @@ mod tests {
|
|||||||
let version = node.version().unwrap();
|
let version = node.version().unwrap();
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
version.starts_with("substrate-node"),
|
version.starts_with("Substrate-node"),
|
||||||
"Expected substrate-node version string, got: {version}"
|
"Expected Substrate-node version string, got: {version}"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user