Compare commits

...

4 Commits

Author SHA1 Message Date
Omar Abdulla 1d5d4d14bf Edit how CLI reporter prints 2025-08-25 20:18:48 +03:00
Omar Abdulla f94faa2de2 Fix the logic for finding the ABI in resolc 2025-08-25 19:55:57 +03:00
Omar Abdulla 59f439b5f8 Update the kitchensink tests 2025-08-25 18:12:01 +03:00
Omar Abdulla 8d1523fd77 Configure kitchensink to use devnode by default 2025-08-25 17:43:52 +03:00
4 changed files with 87 additions and 29 deletions
+32 -14
View File
@@ -181,23 +181,41 @@ impl SolidityCompiler for Resolc {
.evm .evm
.and_then(|evm| evm.bytecode.clone()) .and_then(|evm| evm.bytecode.clone())
.context("Unexpected - Contract compiled with resolc has no bytecode")?; .context("Unexpected - Contract compiled with resolc has no bytecode")?;
let abi = contract_information let abi = {
let metadata = contract_information
.metadata .metadata
.as_ref() .as_ref()
.and_then(|metadata| metadata.as_object()) .context("No metadata found for the contract")?;
.and_then(|metadata| metadata.get("solc_metadata")) let solc_metadata_str = match metadata {
.and_then(|solc_metadata| solc_metadata.as_str()) serde_json::Value::String(solc_metadata_str) => solc_metadata_str.as_str(),
.and_then(|metadata| serde_json::from_str::<serde_json::Value>(metadata).ok()) serde_json::Value::Object(metadata_object) => {
.and_then(|metadata| { let solc_metadata_value = metadata_object
metadata.get("output").and_then(|output| { .get("solc_metadata")
output .context("Contract doesn't have a 'solc_metadata' field")?;
.get("abi") solc_metadata_value
.and_then(|abi| serde_json::from_value::<JsonAbi>(abi.clone()).ok()) .as_str()
}) .context("The 'solc_metadata' field is not a string")?
}) }
.context( serde_json::Value::Null
"Unexpected - Failed to get the ABI for a contract compiled with resolc", | serde_json::Value::Bool(_)
| serde_json::Value::Number(_)
| serde_json::Value::Array(_) => {
anyhow::bail!("Unsupported type of metadata {metadata:?}")
}
};
let solc_metadata =
serde_json::from_str::<serde_json::Value>(solc_metadata_str).context(
"Failed to deserialize the solc_metadata as a serde_json generic value",
)?; )?;
let output_value = solc_metadata
.get("output")
.context("solc_metadata doesn't have an output field")?;
let abi_value = output_value
.get("abi")
.context("solc_metadata output doesn't contain an abi field")?;
serde_json::from_value::<JsonAbi>(abi_value.clone())
.context("ABI found in solc_metadata output is not valid ABI")?
};
map.insert(contract_name, (bytecode.object, abi)); map.insert(contract_name, (bytecode.object, abi));
} }
} }
+12
View File
@@ -115,6 +115,18 @@ pub struct Arguments {
#[arg(short, long = "kitchensink", default_value = "substrate-node")] #[arg(short, long = "kitchensink", default_value = "substrate-node")]
pub kitchensink: PathBuf, pub kitchensink: PathBuf,
/// The path to the `revive-dev-node` executable.
///
/// By default it uses `revive-dev-node` binary found in `$PATH`.
#[arg(long = "revive-dev-node", default_value = "revive-dev-node")]
pub revive_dev_node: PathBuf,
/// By default the tool uses the revive-dev-node when it's running differential tests against
/// PolkaVM since the dev-node is much faster than kitchensink. This flag allows the caller to
/// configure the tool to use kitchensink rather than the dev-node.
#[arg(long)]
pub use_kitchensink_not_dev_node: bool,
/// The path to the `eth_proxy` executable. /// The path to the `eth_proxy` executable.
/// ///
/// By default it uses `eth-rpc` binary found in `$PATH`. /// By default it uses `eth-rpc` binary found in `$PATH`.
+14 -6
View File
@@ -546,22 +546,30 @@ async fn start_cli_reporting_task(reporter: Reporter) {
number_of_successes += 1; number_of_successes += 1;
writeln!( writeln!(
buf, buf,
"{}{}Case Succeeded{}{} - Steps Executed: {}", "{}{}Case Succeeded{} - Steps Executed: {}{}",
GREEN, BOLD, BOLD_RESET, COLOR_RESET, steps_executed GREEN, BOLD, BOLD_RESET, steps_executed, COLOR_RESET
) )
} }
TestCaseStatus::Failed { reason } => { TestCaseStatus::Failed { reason } => {
number_of_failures += 1; number_of_failures += 1;
writeln!( writeln!(
buf, buf,
"{}{}Case Failed{}{} - Reason: {}", "{}{}Case Failed{} - Reason: {}{}",
RED, BOLD, BOLD_RESET, COLOR_RESET, reason RED,
BOLD,
BOLD_RESET,
reason.trim(),
COLOR_RESET,
) )
} }
TestCaseStatus::Ignored { reason, .. } => writeln!( TestCaseStatus::Ignored { reason, .. } => writeln!(
buf, buf,
"{}{}Case Ignored{}{} - Reason: {}", "{}{}Case Ignored{} - Reason: {}{}",
GREY, BOLD, BOLD_RESET, COLOR_RESET, reason GREY,
BOLD,
BOLD_RESET,
reason.trim(),
COLOR_RESET,
), ),
}; };
} }
+23 -3
View File
@@ -54,6 +54,7 @@ static NODE_COUNT: AtomicU32 = AtomicU32::new(0);
pub struct KitchensinkNode { pub struct KitchensinkNode {
id: u32, id: u32,
substrate_binary: PathBuf, substrate_binary: PathBuf,
dev_node_binary: PathBuf,
eth_proxy_binary: PathBuf, eth_proxy_binary: PathBuf,
rpc_url: String, rpc_url: String,
base_directory: PathBuf, base_directory: PathBuf,
@@ -63,6 +64,7 @@ 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 /// 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 /// 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 /// separate fields) as the logic that we need to apply to them is all the same regardless of
@@ -101,11 +103,21 @@ 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 = Command::new(&self.substrate_binary) let output = if self.use_kitchensink_not_dev_node {
Command::new(&self.substrate_binary)
.arg("export-chain-spec") .arg("export-chain-spec")
.arg("--chain") .arg("--chain")
.arg("dev") .arg("dev")
.output()?; .output()
.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!(
@@ -188,7 +200,12 @@ impl KitchensinkNode {
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.kitchensink_stderr_log_file_path())?;
self.process_substrate = Command::new(&self.substrate_binary) let node_binary_path = if self.use_kitchensink_not_dev_node {
self.substrate_binary.as_path()
} else {
self.dev_node_binary.as_path()
};
self.process_substrate = Command::new(node_binary_path)
.arg("--dev") .arg("--dev")
.arg("--chain") .arg("--chain")
.arg(chainspec_path) .arg(chainspec_path)
@@ -533,6 +550,7 @@ impl Node for KitchensinkNode {
Self { Self {
id, id,
substrate_binary: config.kitchensink.clone(), substrate_binary: config.kitchensink.clone(),
dev_node_binary: config.revive_dev_node.clone(),
eth_proxy_binary: config.eth_proxy.clone(), eth_proxy_binary: config.eth_proxy.clone(),
rpc_url: String::new(), rpc_url: String::new(),
base_directory, base_directory,
@@ -542,6 +560,7 @@ impl Node for KitchensinkNode {
wallet: Arc::new(wallet), wallet: Arc::new(wallet),
chain_id_filler: Default::default(), chain_id_filler: Default::default(),
nonce_manager: Default::default(), nonce_manager: Default::default(),
use_kitchensink_not_dev_node: config.use_kitchensink_not_dev_node,
// We know that we only need to be storing 4 files so we can specify that when creating // 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. // 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),
@@ -1059,6 +1078,7 @@ mod tests {
Arguments { Arguments {
kitchensink: PathBuf::from("substrate-node"), kitchensink: PathBuf::from("substrate-node"),
eth_proxy: PathBuf::from("eth-rpc"), eth_proxy: PathBuf::from("eth-rpc"),
use_kitchensink_not_dev_node: true,
..Default::default() ..Default::default()
} }
} }