mirror of
https://github.com/pezkuwichain/revive-differential-tests.git
synced 2026-04-26 00:27:59 +00:00
Allow for genesis to be exported by the tool
This commit is contained in:
@@ -130,7 +130,7 @@ impl GethNode {
|
||||
|
||||
/// Create the node directory and call `geth init` to configure the genesis.
|
||||
#[instrument(level = "info", skip_all, fields(geth_node_id = self.id))]
|
||||
fn init(&mut self, mut genesis: Genesis) -> anyhow::Result<&mut Self> {
|
||||
fn init(&mut self, genesis: Genesis) -> anyhow::Result<&mut Self> {
|
||||
let _ = clear_directory(&self.base_directory);
|
||||
let _ = clear_directory(&self.logs_directory);
|
||||
|
||||
@@ -139,16 +139,7 @@ impl GethNode {
|
||||
create_dir_all(&self.logs_directory)
|
||||
.context("Failed to create logs directory for geth node")?;
|
||||
|
||||
for signer_address in
|
||||
<EthereumWallet as NetworkWallet<Ethereum>>::signer_addresses(&self.wallet)
|
||||
{
|
||||
// Note, the use of the entry API here means that we only modify the entries for any
|
||||
// account that is not in the `alloc` field of the genesis state.
|
||||
genesis
|
||||
.alloc
|
||||
.entry(signer_address)
|
||||
.or_insert(GenesisAccount::default().with_balance(U256::from(INITIAL_BALANCE)));
|
||||
}
|
||||
let genesis = Self::node_genesis(genesis, self.wallet.as_ref());
|
||||
let genesis_path = self.base_directory.join(Self::GENESIS_JSON_FILE);
|
||||
serde_json::to_writer(
|
||||
File::create(&genesis_path).context("Failed to create geth genesis file")?,
|
||||
@@ -265,6 +256,16 @@ impl GethNode {
|
||||
.await
|
||||
.cloned()
|
||||
}
|
||||
|
||||
pub fn node_genesis(mut genesis: Genesis, wallet: &EthereumWallet) -> Genesis {
|
||||
for signer_address in NetworkWallet::<Ethereum>::signer_addresses(&wallet) {
|
||||
genesis
|
||||
.alloc
|
||||
.entry(signer_address)
|
||||
.or_insert(GenesisAccount::default().with_balance(U256::from(INITIAL_BALANCE)));
|
||||
}
|
||||
genesis
|
||||
}
|
||||
}
|
||||
|
||||
impl EthereumNode for GethNode {
|
||||
|
||||
@@ -541,6 +541,16 @@ impl LighthouseGethNode {
|
||||
.await
|
||||
})
|
||||
}
|
||||
|
||||
pub fn node_genesis(mut genesis: Genesis, wallet: &EthereumWallet) -> Genesis {
|
||||
for signer_address in NetworkWallet::<Ethereum>::signer_addresses(&wallet) {
|
||||
genesis
|
||||
.alloc
|
||||
.entry(signer_address)
|
||||
.or_insert(GenesisAccount::default().with_balance(U256::from(INITIAL_BALANCE)));
|
||||
}
|
||||
genesis
|
||||
}
|
||||
}
|
||||
|
||||
impl EthereumNode for LighthouseGethNode {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::{
|
||||
fs::{create_dir_all, remove_dir_all},
|
||||
path::PathBuf,
|
||||
path::{Path, PathBuf},
|
||||
pin::Pin,
|
||||
process::{Command, Stdio},
|
||||
sync::{
|
||||
@@ -12,7 +12,7 @@ use std::{
|
||||
|
||||
use alloy::{
|
||||
eips::BlockNumberOrTag,
|
||||
genesis::{Genesis, GenesisAccount},
|
||||
genesis::Genesis,
|
||||
network::{Ethereum, EthereumWallet, NetworkWallet},
|
||||
primitives::{Address, BlockHash, BlockNumber, BlockTimestamp, StorageKey, TxHash, U256},
|
||||
providers::{
|
||||
@@ -32,7 +32,7 @@ use futures::{FutureExt, Stream, StreamExt};
|
||||
use revive_common::EVMVersion;
|
||||
use revive_dt_common::fs::clear_directory;
|
||||
use revive_dt_format::traits::ResolverApi;
|
||||
use serde_json::{Value as JsonValue, json};
|
||||
use serde_json::json;
|
||||
use sp_core::crypto::Ss58Codec;
|
||||
use sp_runtime::AccountId32;
|
||||
|
||||
@@ -129,7 +129,7 @@ impl SubstrateNode {
|
||||
}
|
||||
}
|
||||
|
||||
fn init(&mut self, mut genesis: Genesis) -> anyhow::Result<&mut Self> {
|
||||
fn init(&mut self, _: Genesis) -> anyhow::Result<&mut Self> {
|
||||
let _ = remove_dir_all(self.base_directory.as_path());
|
||||
let _ = clear_directory(&self.base_directory);
|
||||
let _ = clear_directory(&self.logs_directory);
|
||||
@@ -141,65 +141,12 @@ impl SubstrateNode {
|
||||
|
||||
let template_chainspec_path = self.base_directory.join(Self::CHAIN_SPEC_JSON_FILE);
|
||||
|
||||
// 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.
|
||||
let output = Command::new(&self.node_binary)
|
||||
.arg(self.export_chainspec_command.as_str())
|
||||
.arg("--chain")
|
||||
.arg("dev")
|
||||
.env_remove("RUST_LOG")
|
||||
.output()
|
||||
.context("Failed to export the chain-spec")?;
|
||||
|
||||
if !output.status.success() {
|
||||
anyhow::bail!(
|
||||
"Substrate-node export-chain-spec failed: {}",
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
);
|
||||
}
|
||||
|
||||
let content = String::from_utf8(output.stdout)
|
||||
.context("Failed to decode Substrate export-chain-spec output as UTF-8")?;
|
||||
let mut chainspec_json: JsonValue =
|
||||
serde_json::from_str(&content).context("Failed to parse Substrate chain spec JSON")?;
|
||||
|
||||
let existing_chainspec_balances =
|
||||
chainspec_json["genesis"]["runtimeGenesis"]["patch"]["balances"]["balances"]
|
||||
.as_array()
|
||||
.cloned()
|
||||
.unwrap_or_default();
|
||||
|
||||
let mut merged_balances: Vec<(String, u128)> = existing_chainspec_balances
|
||||
.into_iter()
|
||||
.filter_map(|val| {
|
||||
if let Some(arr) = val.as_array() {
|
||||
if arr.len() == 2 {
|
||||
let account = arr[0].as_str()?.to_string();
|
||||
let balance = arr[1].as_f64()? as u128;
|
||||
return Some((account, balance));
|
||||
}
|
||||
}
|
||||
None
|
||||
})
|
||||
.collect();
|
||||
let mut eth_balances = {
|
||||
for signer_address in
|
||||
<EthereumWallet as NetworkWallet<Ethereum>>::signer_addresses(&self.wallet)
|
||||
{
|
||||
// Note, the use of the entry API here means that we only modify the entries for any
|
||||
// account that is not in the `alloc` field of the genesis state.
|
||||
genesis
|
||||
.alloc
|
||||
.entry(signer_address)
|
||||
.or_insert(GenesisAccount::default().with_balance(U256::from(INITIAL_BALANCE)));
|
||||
}
|
||||
self.extract_balance_from_genesis_file(&genesis)
|
||||
.context("Failed to extract balances from EVM genesis JSON")?
|
||||
};
|
||||
merged_balances.append(&mut eth_balances);
|
||||
|
||||
chainspec_json["genesis"]["runtimeGenesis"]["patch"]["balances"]["balances"] =
|
||||
json!(merged_balances);
|
||||
let chainspec_json = Self::node_genesis(
|
||||
&self.node_binary,
|
||||
&self.export_chainspec_command,
|
||||
&self.wallet,
|
||||
)
|
||||
.context("Failed to prepare the chainspec command")?;
|
||||
|
||||
serde_json::to_writer_pretty(
|
||||
std::fs::File::create(&template_chainspec_path)
|
||||
@@ -307,21 +254,6 @@ impl SubstrateNode {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn extract_balance_from_genesis_file(
|
||||
&self,
|
||||
genesis: &Genesis,
|
||||
) -> anyhow::Result<Vec<(String, u128)>> {
|
||||
genesis
|
||||
.alloc
|
||||
.iter()
|
||||
.try_fold(Vec::new(), |mut vec, (address, acc)| {
|
||||
let substrate_address = Self::eth_to_substrate_address(address);
|
||||
let balance = acc.balance.try_into()?;
|
||||
vec.push((substrate_address, balance));
|
||||
Ok(vec)
|
||||
})
|
||||
}
|
||||
|
||||
fn eth_to_substrate_address(address: &Address) -> String {
|
||||
let eth_bytes = address.0.0;
|
||||
|
||||
@@ -360,6 +292,45 @@ impl SubstrateNode {
|
||||
.await
|
||||
.cloned()
|
||||
}
|
||||
|
||||
pub fn node_genesis(
|
||||
node_path: &Path,
|
||||
export_chainspec_command: &str,
|
||||
wallet: &EthereumWallet,
|
||||
) -> anyhow::Result<serde_json::Value> {
|
||||
let output = Command::new(node_path)
|
||||
.arg(export_chainspec_command)
|
||||
.arg("--chain")
|
||||
.arg("dev")
|
||||
.env_remove("RUST_LOG")
|
||||
.output()
|
||||
.context("Failed to export the chain-spec")?;
|
||||
|
||||
if !output.status.success() {
|
||||
anyhow::bail!(
|
||||
"Substrate-node export-chain-spec failed: {}",
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
);
|
||||
}
|
||||
|
||||
let content = String::from_utf8(output.stdout)
|
||||
.context("Failed to decode Substrate export-chain-spec output as UTF-8")?;
|
||||
let mut chainspec_json = serde_json::from_str::<serde_json::Value>(&content)
|
||||
.context("Failed to parse Substrate chain spec JSON")?;
|
||||
|
||||
let existing_chainspec_balances =
|
||||
chainspec_json["genesis"]["runtimeGenesis"]["patch"]["balances"]["balances"]
|
||||
.as_array_mut()
|
||||
.expect("Can't fail");
|
||||
|
||||
for address in NetworkWallet::<Ethereum>::signer_addresses(wallet) {
|
||||
let substrate_address = Self::eth_to_substrate_address(&address);
|
||||
let balance = INITIAL_BALANCE;
|
||||
existing_chainspec_balances.push(json!((substrate_address, balance)));
|
||||
}
|
||||
|
||||
Ok(chainspec_json)
|
||||
}
|
||||
}
|
||||
|
||||
impl EthereumNode for SubstrateNode {
|
||||
@@ -900,50 +871,6 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "Ignored since they take a long time to run"]
|
||||
fn test_parse_genesis_alloc() {
|
||||
// Create test genesis file
|
||||
let genesis_json = r#"
|
||||
{
|
||||
"alloc": {
|
||||
"0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1": { "balance": "1000000000000000000" },
|
||||
"0x0000000000000000000000000000000000000000": { "balance": "0xDE0B6B3A7640000" },
|
||||
"0xffffffffffffffffffffffffffffffffffffffff": { "balance": "123456789" }
|
||||
}
|
||||
}
|
||||
"#;
|
||||
|
||||
let context = test_config();
|
||||
let node = SubstrateNode::new(
|
||||
context.kitchensink_configuration.path.clone(),
|
||||
SubstrateNode::KITCHENSINK_EXPORT_CHAINSPEC_COMMAND,
|
||||
None,
|
||||
&context,
|
||||
);
|
||||
|
||||
let result = node
|
||||
.extract_balance_from_genesis_file(&serde_json::from_str(genesis_json).unwrap())
|
||||
.unwrap();
|
||||
|
||||
let result_map: std::collections::HashMap<_, _> = result.into_iter().collect();
|
||||
|
||||
assert_eq!(
|
||||
result_map.get("5FLneRcWAfk3X3tg6PuGyLNGAquPAZez5gpqvyuf3yUK8VaV"),
|
||||
Some(&1_000_000_000_000_000_000u128)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
result_map.get("5C4hrfjw9DjXZTzV3MwzrrAr9P1MLDHajjSidz9bR544LEq1"),
|
||||
Some(&1_000_000_000_000_000_000u128)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
result_map.get("5HrN7fHLXWcFiXPwwtq2EkSGns9eMmoUQnbVKweNz3VVr6N4"),
|
||||
Some(&123_456_789u128)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "Ignored since they take a long time to run"]
|
||||
fn print_eth_to_substrate_mappings() {
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
use std::{
|
||||
fs::{create_dir_all, remove_dir_all},
|
||||
path::PathBuf,
|
||||
path::{Path, PathBuf},
|
||||
pin::Pin,
|
||||
process::{Command, Stdio},
|
||||
sync::{
|
||||
@@ -40,7 +40,7 @@ use std::{
|
||||
|
||||
use alloy::{
|
||||
eips::BlockNumberOrTag,
|
||||
genesis::{Genesis, GenesisAccount},
|
||||
genesis::Genesis,
|
||||
network::{Ethereum, EthereumWallet, NetworkWallet},
|
||||
primitives::{Address, BlockHash, BlockNumber, BlockTimestamp, StorageKey, TxHash, U256},
|
||||
providers::{
|
||||
@@ -61,7 +61,7 @@ use revive_dt_common::fs::clear_directory;
|
||||
use revive_dt_config::*;
|
||||
use revive_dt_format::traits::ResolverApi;
|
||||
use revive_dt_node_interaction::{EthereumNode, MinedBlockInformation};
|
||||
use serde_json::{Value as JsonValue, json};
|
||||
use serde_json::json;
|
||||
use sp_core::crypto::Ss58Codec;
|
||||
use sp_runtime::AccountId32;
|
||||
use subxt::{OnlineClient, SubstrateConfig};
|
||||
@@ -164,7 +164,7 @@ impl ZombienetNode {
|
||||
}
|
||||
}
|
||||
|
||||
fn init(&mut self, genesis: Genesis) -> anyhow::Result<&mut Self> {
|
||||
fn init(&mut self, _: Genesis) -> anyhow::Result<&mut Self> {
|
||||
let _ = clear_directory(&self.base_directory);
|
||||
let _ = clear_directory(&self.logs_directory);
|
||||
|
||||
@@ -174,7 +174,7 @@ impl ZombienetNode {
|
||||
.context("Failed to create logs directory for zombie node")?;
|
||||
|
||||
let template_chainspec_path = self.base_directory.join(Self::CHAIN_SPEC_JSON_FILE);
|
||||
self.prepare_chainspec(template_chainspec_path.clone(), genesis)?;
|
||||
self.prepare_chainspec(template_chainspec_path.clone())?;
|
||||
let polkadot_parachain_path = self
|
||||
.polkadot_parachain_path
|
||||
.to_str()
|
||||
@@ -286,71 +286,9 @@ impl ZombienetNode {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn prepare_chainspec(
|
||||
&mut self,
|
||||
template_chainspec_path: PathBuf,
|
||||
mut genesis: Genesis,
|
||||
) -> anyhow::Result<()> {
|
||||
let output = Command::new(self.polkadot_parachain_path.as_path())
|
||||
.arg(Self::EXPORT_CHAINSPEC_COMMAND)
|
||||
.arg("--chain")
|
||||
.arg("asset-hub-westend-local")
|
||||
.env_remove("RUST_LOG")
|
||||
.output()
|
||||
.context("Failed to export the chainspec of the chain")?;
|
||||
|
||||
if !output.status.success() {
|
||||
anyhow::bail!(
|
||||
"Build chain-spec failed: {}",
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
);
|
||||
}
|
||||
|
||||
let content = String::from_utf8(output.stdout)
|
||||
.context("Failed to decode collators chain-spec output as UTF-8")?;
|
||||
let mut chainspec_json: JsonValue =
|
||||
serde_json::from_str(&content).context("Failed to parse collators chain spec JSON")?;
|
||||
|
||||
let existing_chainspec_balances =
|
||||
chainspec_json["genesis"]["runtimeGenesis"]["patch"]["balances"]["balances"]
|
||||
.as_array()
|
||||
.cloned()
|
||||
.unwrap_or_default();
|
||||
|
||||
let mut merged_balances: Vec<(String, u128)> = existing_chainspec_balances
|
||||
.into_iter()
|
||||
.filter_map(|val| {
|
||||
if let Some(arr) = val.as_array() {
|
||||
if arr.len() == 2 {
|
||||
let account = arr[0].as_str()?.to_string();
|
||||
let balance = arr[1].as_f64()? as u128;
|
||||
return Some((account, balance));
|
||||
}
|
||||
}
|
||||
None
|
||||
})
|
||||
.collect();
|
||||
|
||||
let mut eth_balances = {
|
||||
for signer_address in
|
||||
<EthereumWallet as NetworkWallet<Ethereum>>::signer_addresses(&self.wallet)
|
||||
{
|
||||
// Note, the use of the entry API here means that we only modify the entries for any
|
||||
// account that is not in the `alloc` field of the genesis state.
|
||||
genesis
|
||||
.alloc
|
||||
.entry(signer_address)
|
||||
.or_insert(GenesisAccount::default().with_balance(U256::from(INITIAL_BALANCE)));
|
||||
}
|
||||
self.extract_balance_from_genesis_file(&genesis)
|
||||
.context("Failed to extract balances from EVM genesis JSON")?
|
||||
};
|
||||
|
||||
merged_balances.append(&mut eth_balances);
|
||||
|
||||
chainspec_json["genesis"]["runtimeGenesis"]["patch"]["balances"]["balances"] =
|
||||
json!(merged_balances);
|
||||
|
||||
fn prepare_chainspec(&mut self, template_chainspec_path: PathBuf) -> anyhow::Result<()> {
|
||||
let chainspec_json = Self::node_genesis(&self.polkadot_parachain_path, &self.wallet)
|
||||
.context("Failed to prepare the zombienet chainspec file")?;
|
||||
let writer = std::fs::File::create(&template_chainspec_path)
|
||||
.context("Failed to create template chainspec file")?;
|
||||
|
||||
@@ -360,21 +298,6 @@ impl ZombienetNode {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn extract_balance_from_genesis_file(
|
||||
&self,
|
||||
genesis: &Genesis,
|
||||
) -> anyhow::Result<Vec<(String, u128)>> {
|
||||
genesis
|
||||
.alloc
|
||||
.iter()
|
||||
.try_fold(Vec::new(), |mut vec, (address, acc)| {
|
||||
let polkadot_address = Self::eth_to_polkadot_address(address);
|
||||
let balance = acc.balance.try_into()?;
|
||||
vec.push((polkadot_address, balance));
|
||||
Ok(vec)
|
||||
})
|
||||
}
|
||||
|
||||
fn eth_to_polkadot_address(address: &Address) -> String {
|
||||
let eth_bytes = address.0.0;
|
||||
|
||||
@@ -414,6 +337,44 @@ impl ZombienetNode {
|
||||
.await
|
||||
.cloned()
|
||||
}
|
||||
|
||||
pub fn node_genesis(
|
||||
node_path: &Path,
|
||||
wallet: &EthereumWallet,
|
||||
) -> anyhow::Result<serde_json::Value> {
|
||||
let output = Command::new(node_path)
|
||||
.arg(Self::EXPORT_CHAINSPEC_COMMAND)
|
||||
.arg("--chain")
|
||||
.arg("asset-hub-westend-local")
|
||||
.env_remove("RUST_LOG")
|
||||
.output()
|
||||
.context("Failed to export the chainspec of the chain")?;
|
||||
|
||||
if !output.status.success() {
|
||||
anyhow::bail!(
|
||||
"Substrate-node export-chain-spec failed: {}",
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
);
|
||||
}
|
||||
|
||||
let content = String::from_utf8(output.stdout)
|
||||
.context("Failed to decode Substrate export-chain-spec output as UTF-8")?;
|
||||
let mut chainspec_json = serde_json::from_str::<serde_json::Value>(&content)
|
||||
.context("Failed to parse Substrate chain spec JSON")?;
|
||||
|
||||
let existing_chainspec_balances =
|
||||
chainspec_json["genesis"]["runtimeGenesis"]["patch"]["balances"]["balances"]
|
||||
.as_array_mut()
|
||||
.expect("Can't fail");
|
||||
|
||||
for address in NetworkWallet::<Ethereum>::signer_addresses(wallet) {
|
||||
let substrate_address = Self::eth_to_polkadot_address(&address);
|
||||
let balance = INITIAL_BALANCE;
|
||||
existing_chainspec_balances.push(json!((substrate_address, balance)));
|
||||
}
|
||||
|
||||
Ok(chainspec_json)
|
||||
}
|
||||
}
|
||||
|
||||
impl EthereumNode for ZombienetNode {
|
||||
@@ -956,47 +917,6 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_parse_genesis_alloc() {
|
||||
// Create test genesis file
|
||||
let genesis_json = r#"
|
||||
{
|
||||
"alloc": {
|
||||
"0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1": { "balance": "1000000000000000000" },
|
||||
"0x0000000000000000000000000000000000000000": { "balance": "0xDE0B6B3A7640000" },
|
||||
"0xffffffffffffffffffffffffffffffffffffffff": { "balance": "123456789" }
|
||||
}
|
||||
}
|
||||
"#;
|
||||
|
||||
let context = test_config();
|
||||
let node = ZombienetNode::new(
|
||||
context.polkadot_parachain_configuration.path.clone(),
|
||||
&context,
|
||||
);
|
||||
|
||||
let result = node
|
||||
.extract_balance_from_genesis_file(&serde_json::from_str(genesis_json).unwrap())
|
||||
.unwrap();
|
||||
|
||||
let result_map: std::collections::HashMap<_, _> = result.into_iter().collect();
|
||||
|
||||
assert_eq!(
|
||||
result_map.get("5FLneRcWAfk3X3tg6PuGyLNGAquPAZez5gpqvyuf3yUK8VaV"),
|
||||
Some(&1_000_000_000_000_000_000u128)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
result_map.get("5C4hrfjw9DjXZTzV3MwzrrAr9P1MLDHajjSidz9bR544LEq1"),
|
||||
Some(&1_000_000_000_000_000_000u128)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
result_map.get("5HrN7fHLXWcFiXPwwtq2EkSGns9eMmoUQnbVKweNz3VVr6N4"),
|
||||
Some(&123_456_789u128)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn print_eth_to_polkadot_mappings() {
|
||||
let eth_addresses = vec![
|
||||
|
||||
Reference in New Issue
Block a user