Skip to content

Commit 6df01a9

Browse files
authored
feat: add eth-rpc binary to pop up contract (#705)
1 parent 726b77b commit 6df01a9

File tree

14 files changed

+344
-170
lines changed

14 files changed

+344
-170
lines changed

Cargo.lock

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ cumulus-client-cli = { version = "0.26.0", default-features = false }
7979
# benchmarking
8080
cumulus-primitives-proof-size-hostfunction = "0.15.0"
8181
frame-benchmarking-cli = { version = "51.0.0", default-features = false }
82-
frame-storage-access-test-runtime = { version = "0.4.0", default-features = false }
8382
sc-chain-spec = { version = "46.0.0", default-features = false }
8483
sp-runtime = { version = "44.0.0", default-features = false }
8584
sp-statement-store = "23.0.0"

crates/pop-chains/src/up/mod.rs

Lines changed: 47 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -895,7 +895,7 @@ mod tests {
895895

896896
mod zombienet {
897897
use super::*;
898-
use pop_common::Status;
898+
use pop_common::{Status, helpers::with_current_dir_async};
899899

900900
pub(crate) struct Output;
901901
impl Status for Output {
@@ -1478,48 +1478,52 @@ name = "collator"
14781478
command = "substrate-contracts-node"
14791479
"#
14801480
)?;
1481-
// Expecting failure since no custom path is provided and binaries don't exist in the
1482-
// default build directory.
1483-
assert!(matches!(
1484-
Zombienet::new(&cache, config.path().try_into()?, None, None, None, None, None).await,
1485-
Err(Error::MissingBinary(command))
1486-
if command == "parachain-template-node"
1487-
));
1488-
// Create the binaries in the default build directory.
1489-
let parachain_template = PathBuf::from("target/release/parachain-template-node");
1490-
create_dir_all(parachain_template.parent().unwrap())?;
1491-
File::create(&parachain_template)?;
1492-
// Ensure the the binary is detected in the debug profile too.
1493-
let parachain_contracts_template =
1494-
PathBuf::from("target/debug/substrate-contracts-node");
1495-
create_dir_all(parachain_contracts_template.parent().unwrap())?;
1496-
File::create(&parachain_contracts_template)?;
1497-
1498-
let zombienet =
1499-
Zombienet::new(&cache, config.path().try_into()?, None, None, None, None, None)
1500-
.await?;
1501-
// Remove the binaries created above after Zombienet initialization, as they are no
1502-
// longer needed.
1503-
remove_file(&parachain_template)?;
1504-
remove_file(&parachain_contracts_template)?;
1505-
remove_dir(parachain_template.parent().unwrap())?;
1506-
remove_dir(parachain_contracts_template.parent().unwrap())?;
1507-
1508-
assert_eq!(zombienet.parachains.len(), 2);
1509-
let parachain = &zombienet.parachains.get(&1000).unwrap().binary;
1510-
assert_eq!(parachain.name(), "parachain-template-node");
1511-
assert_eq!(parachain.path(), Path::new("./target/release/parachain-template-node"));
1512-
assert_eq!(parachain.version(), None);
1513-
assert!(matches!(parachain, Binary::Local { .. }));
1514-
let contract_parachain = &zombienet.parachains.get(&2000).unwrap().binary;
1515-
assert_eq!(contract_parachain.name(), "substrate-contracts-node");
1516-
assert_eq!(
1517-
contract_parachain.path(),
1518-
Path::new("./target/debug/substrate-contracts-node")
1519-
);
1520-
assert_eq!(contract_parachain.version(), None);
1521-
assert!(matches!(contract_parachain, Binary::Local { .. }));
1522-
Ok(())
1481+
let temp_workspace = tempdir()?;
1482+
with_current_dir_async(temp_workspace.path(), async || {
1483+
// Expecting failure since no custom path is provided and binaries don't exist in
1484+
// the default build directory.
1485+
assert!(matches!(
1486+
Zombienet::new(&cache, config.path().try_into()?, None, None, None, None, None).await,
1487+
Err(Error::MissingBinary(command))
1488+
if command == "parachain-template-node"
1489+
));
1490+
// Create the binaries in the default build directory.
1491+
let parachain_template = PathBuf::from("target/release/parachain-template-node");
1492+
create_dir_all(parachain_template.parent().unwrap())?;
1493+
File::create(&parachain_template)?;
1494+
// Ensure the the binary is detected in the debug profile too.
1495+
let parachain_contracts_template =
1496+
PathBuf::from("target/debug/substrate-contracts-node");
1497+
create_dir_all(parachain_contracts_template.parent().unwrap())?;
1498+
File::create(&parachain_contracts_template)?;
1499+
1500+
let zombienet =
1501+
Zombienet::new(&cache, config.path().try_into()?, None, None, None, None, None)
1502+
.await?;
1503+
// Remove the binaries created above after Zombienet initialization, as they are no
1504+
// longer needed.
1505+
remove_file(&parachain_template)?;
1506+
remove_file(&parachain_contracts_template)?;
1507+
remove_dir(parachain_template.parent().unwrap())?;
1508+
remove_dir(parachain_contracts_template.parent().unwrap())?;
1509+
1510+
assert_eq!(zombienet.parachains.len(), 2);
1511+
let parachain = &zombienet.parachains.get(&1000).unwrap().binary;
1512+
assert_eq!(parachain.name(), "parachain-template-node");
1513+
assert_eq!(parachain.path(), Path::new("./target/release/parachain-template-node"));
1514+
assert_eq!(parachain.version(), None);
1515+
assert!(matches!(parachain, Binary::Local { .. }));
1516+
let contract_parachain = &zombienet.parachains.get(&2000).unwrap().binary;
1517+
assert_eq!(contract_parachain.name(), "substrate-contracts-node");
1518+
assert_eq!(
1519+
contract_parachain.path(),
1520+
Path::new("./target/debug/substrate-contracts-node")
1521+
);
1522+
assert_eq!(contract_parachain.version(), None);
1523+
assert!(matches!(contract_parachain, Binary::Local { .. }));
1524+
Ok(())
1525+
})
1526+
.await
15231527
}
15241528

15251529
#[tokio::test]

crates/pop-cli/src/commands/bench/pallet.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1320,12 +1320,11 @@ mod tests {
13201320
cli::MockCli,
13211321
common::{
13221322
bench::source_omni_bencher_binary,
1323-
helpers::with_current_dir,
13241323
runtime::{Feature::Benchmark, get_mock_runtime},
13251324
},
13261325
};
13271326
use anyhow::Ok;
1328-
use pop_common::Profile;
1327+
use pop_common::{Profile, helpers::with_current_dir};
13291328
use std::fs::{self, File};
13301329
use strum::EnumMessage;
13311330
use tempfile::tempdir;

crates/pop-cli/src/commands/call/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ impl Display for Command {
7171
#[cfg(test)]
7272
mod tests {
7373
use super::*;
74-
use crate::common::helpers::with_current_dir;
74+
use pop_common::helpers::with_current_dir;
7575
use std::{env::set_current_dir, fs};
7676
use tempfile::tempdir;
7777

crates/pop-cli/src/commands/test/contract.rs

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::{
44
cli,
55
common::{
66
TestFeature::{self, *},
7-
contracts::check_contracts_node_and_prompt,
7+
contracts::check_ink_node_and_prompt,
88
},
99
};
1010
use clap::Args;
@@ -44,22 +44,18 @@ impl TestContractCommand {
4444
if self.e2e {
4545
cli.intro("Starting end-to-end tests")?;
4646
let spinner = spinner();
47-
self.node = match check_contracts_node_and_prompt(
48-
cli,
49-
&spinner,
50-
&crate::cache()?,
51-
self.skip_confirm,
52-
)
53-
.await
54-
{
55-
Ok(binary_path) => Some(binary_path),
56-
Err(_) => {
57-
cli.warning(
58-
"🚫 substrate-contracts-node is necessary to run e2e tests. Will try to run tests anyway...",
59-
)?;
60-
Some(PathBuf::new())
61-
},
62-
};
47+
self.node =
48+
match check_ink_node_and_prompt(cli, &spinner, &crate::cache()?, self.skip_confirm)
49+
.await
50+
{
51+
Ok((binary_path, _)) => Some(binary_path),
52+
Err(_) => {
53+
cli.warning(
54+
"🚫 ink-node is necessary to run e2e tests. Will try to run tests anyway...",
55+
)?;
56+
Some(PathBuf::new())
57+
},
58+
};
6359

6460
spinner.clear();
6561
test_e2e_smart_contract(&self.path, self.node.as_deref(), self.test)?;

crates/pop-cli/src/commands/up/contract.rs

Lines changed: 45 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ use crate::{
88
commands::call::contract::CallContractCommand,
99
common::{
1010
contracts::{
11-
check_contracts_node_and_prompt, has_contract_been_built, map_account,
12-
normalize_call_args, request_contract_function_args, terminate_node,
11+
check_ink_node_and_prompt, has_contract_been_built, map_account, normalize_call_args,
12+
request_contract_function_args, terminate_nodes,
1313
},
1414
rpc::prompt_to_select_chain_rpc,
1515
urls,
@@ -19,12 +19,12 @@ use crate::{
1919
};
2020
use clap::Args;
2121
use cliclack::{ProgressBar, spinner};
22-
use console::{Emoji, Style};
22+
use console::Emoji;
2323
use pop_contracts::{
2424
Bytes, FunctionType, UpOpts, Verbosity, Weight, build_smart_contract,
2525
dry_run_gas_estimate_instantiate, dry_run_upload, extract_function, get_contract_code,
2626
get_instantiate_payload, get_upload_payload, instantiate_contract_signed,
27-
instantiate_smart_contract, is_chain_alive, parse_hex_bytes, run_contracts_node,
27+
instantiate_smart_contract, is_chain_alive, parse_hex_bytes, run_eth_rpc_node, run_ink_node,
2828
set_up_deployment, set_up_upload, upload_contract_signed, upload_smart_contract,
2929
};
3030
use sp_core::bytes::to_hex;
@@ -34,6 +34,8 @@ use url::Url;
3434

3535
const COMPLETE: &str = "🚀 Deployment complete";
3636
const DEFAULT_PORT: u16 = 9944;
37+
const DEFAULT_ETH_RPC_PORT: u16 = 8545;
38+
const DEFAULT_INK_NODE_URL: &str = "ws://127.0.0.1:9944";
3739
const FAILED: &str = "🚫 Deployment failed.";
3840
const HELP_HEADER: &str = "Smart contract deployment options";
3941

@@ -127,7 +129,7 @@ impl UpContractCommand {
127129
}
128130

129131
// Check if specified chain is accessible
130-
let process = if !is_chain_alive(self.url.clone()).await? {
132+
let processes = if !is_chain_alive(self.url.clone()).await? {
131133
let local_url = Url::parse(urls::LOCAL).expect("default url is valid");
132134
let start_local_node = if !self.skip_confirm {
133135
let msg = if self.url.as_str() == urls::LOCAL {
@@ -166,11 +168,12 @@ impl UpContractCommand {
166168
// Update url to that of the launched node
167169
self.url = local_url;
168170

169-
let log = NamedTempFile::new()?;
171+
let log_ink_node = NamedTempFile::new()?;
172+
let log_eth_rpc = NamedTempFile::new()?;
170173
let spinner = spinner();
171174

172175
// uses the cache location
173-
let binary_path = match check_contracts_node_and_prompt(
176+
let (ink_node_binary_path, eth_rpc_binary_path) = match check_ink_node_and_prompt(
174177
&mut Cli,
175178
&spinner,
176179
&crate::cache()?,
@@ -189,25 +192,40 @@ impl UpContractCommand {
189192

190193
spinner.start("Starting local node...");
191194

192-
let process =
193-
run_contracts_node(binary_path, Some(log.as_file()), DEFAULT_PORT).await?;
194-
let bar = Style::new().magenta().dim().apply_to(Emoji("│", "|"));
195-
spinner.stop(format!(
195+
let ink_node_process =
196+
run_ink_node(&ink_node_binary_path, Some(log_ink_node.as_file()), DEFAULT_PORT)
197+
.await?;
198+
let eth_rpc_node_process = run_eth_rpc_node(
199+
&eth_rpc_binary_path,
200+
Some(log_eth_rpc.as_file()),
201+
DEFAULT_INK_NODE_URL,
202+
DEFAULT_ETH_RPC_PORT,
203+
)
204+
.await?;
205+
spinner.clear();
206+
Cli.info(format!(
196207
"Local node started successfully:{}",
197208
style(format!(
198-
"
199-
{bar} {}
200-
{bar} {}",
209+
"\n{}\n{}",
201210
style(format!(
202211
"portal: https://polkadot.js.org/apps/?rpc={}#/explorer",
203212
self.url
204213
))
205214
.dim(),
206-
style(format!("logs: tail -f {}", log.path().display())).dim(),
215+
style(format!("logs: tail -f {}", log_ink_node.path().display())).dim(),
216+
))
217+
.dim()
218+
))?;
219+
Cli.info(format!(
220+
"Ethereum RPC node started successfully:{}",
221+
style(format!(
222+
"\n{}\n{}",
223+
style(format!("url: ws://localhost:{}", DEFAULT_ETH_RPC_PORT)).dim(),
224+
style(format!("logs: tail -f {}", log_eth_rpc.path().display())).dim(),
207225
))
208226
.dim()
209-
));
210-
Some((process, log))
227+
))?;
228+
Some(((ink_node_process, log_ink_node), (eth_rpc_node_process, log_eth_rpc)))
211229
} else {
212230
None
213231
}
@@ -221,7 +239,7 @@ impl UpContractCommand {
221239
Ok(data) => data,
222240
Err(e) => {
223241
Cli.error(format!("An error occurred getting the call data: {e}"))?;
224-
terminate_node(&mut Cli, process).await?;
242+
terminate_nodes(&mut Cli, processes).await?;
225243
Cli.outro_cancel(FAILED)?;
226244
return Ok(());
227245
},
@@ -242,7 +260,7 @@ impl UpContractCommand {
242260
Err(e) => {
243261
spinner
244262
.error(format!("An error occurred uploading your contract: {e}"));
245-
terminate_node(&mut Cli, process).await?;
263+
terminate_nodes(&mut Cli, processes).await?;
246264
Cli.outro_cancel(FAILED)?;
247265
return Ok(());
248266
},
@@ -261,7 +279,7 @@ impl UpContractCommand {
261279
Cli.error(format!(
262280
"An error occurred instantiating the contract: {e}"
263281
))?;
264-
terminate_node(&mut Cli, process).await?;
282+
terminate_nodes(&mut Cli, processes).await?;
265283
Cli.outro_cancel(FAILED)?;
266284
return Ok(());
267285
},
@@ -279,7 +297,7 @@ impl UpContractCommand {
279297
Err(e) => {
280298
spinner
281299
.error(format!("An error occurred uploading your contract: {e}"));
282-
terminate_node(&mut Cli, process).await?;
300+
terminate_nodes(&mut Cli, processes).await?;
283301
Cli.outro_cancel(FAILED)?;
284302
return Ok(());
285303
},
@@ -299,19 +317,19 @@ impl UpContractCommand {
299317
}
300318
} else {
301319
Cli.outro_cancel("Signed payload doesn't exist.")?;
302-
terminate_node(&mut Cli, process).await?;
320+
terminate_nodes(&mut Cli, processes).await?;
303321
return Ok(());
304322
}
305323

306324
Cli.outro(COMPLETE)?;
307-
terminate_node(&mut Cli, process).await?;
325+
terminate_nodes(&mut Cli, processes).await?;
308326
return Ok(());
309327
}
310328

311329
// Check for upload only.
312330
if self.upload_only {
313331
let result = self.upload_contract().await;
314-
terminate_node(&mut Cli, process).await?;
332+
terminate_nodes(&mut Cli, processes).await?;
315333
match result {
316334
Ok(_) => {
317335
Cli.outro(COMPLETE)?;
@@ -334,7 +352,7 @@ impl UpContractCommand {
334352
Ok(i) => i,
335353
Err(e) => {
336354
Cli.error(format!("An error occurred instantiating the contract: {e}"))?;
337-
terminate_node(&mut Cli, process).await?;
355+
terminate_nodes(&mut Cli, processes).await?;
338356
Cli.outro_cancel(FAILED)?;
339357
return Ok(());
340358
},
@@ -354,7 +372,7 @@ impl UpContractCommand {
354372
},
355373
Err(e) => {
356374
spinner.error(format!("{e}"));
357-
terminate_node(&mut Cli, process).await?;
375+
terminate_nodes(&mut Cli, processes).await?;
358376
Cli.outro_cancel(FAILED)?;
359377
return Ok(());
360378
},
@@ -371,7 +389,7 @@ impl UpContractCommand {
371389

372390
Cli.success(COMPLETE)?;
373391
self.keep_interacting_with_node(&mut Cli, contract_address).await?;
374-
terminate_node(&mut Cli, process).await?;
392+
terminate_nodes(&mut Cli, processes).await?;
375393
}
376394

377395
Ok(())

0 commit comments

Comments
 (0)