Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[pallet-revive] eth-rpc fixes #6453

Merged
merged 6 commits into from
Nov 12, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .config/nextest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,9 @@ serial-integration = { max-threads = 1 }
[[profile.default.overrides]]
filter = 'test(/(^ui$|_ui|ui_)/)'
test-group = 'serial-integration'

# Running eth-rpc tests sequentially
# As they rely on a shared resource (the RPC and Node) and could run into race conditions with the nonces
[[profile.default.overrides]]
filter = 'package(pallet-revive-eth-rpc) and test(/^tests::/)'
test-group = 'serial-integration'
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions prdoc/pr_6453.prdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
title: '[pallet-revive] breakdown integration tests'
doc:
- audience: Runtime Dev
description: null
pgherveou marked this conversation as resolved.
Show resolved Hide resolved
crates:
- name: pallet-revive-eth-rpc
bump: minor
1 change: 1 addition & 0 deletions substrate/frame/revive/rpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ ethabi = { version = "18.0.0" }
example = ["hex-literal", "rlp", "secp256k1", "subxt-signer"]

[dev-dependencies]
static_init = { workspace = true }
hex-literal = { workspace = true }
pallet-revive-fixtures = { workspace = true }
substrate-cli-test-utils = { workspace = true }
Expand Down
139 changes: 101 additions & 38 deletions substrate/frame/revive/rpc/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use pallet_revive::{
create1,
evm::{Account, BlockTag, U256},
};
use static_init::dynamic;
use std::thread;
use substrate_cli_test_utils::*;

Expand Down Expand Up @@ -60,6 +61,52 @@ fn get_contract(name: &str) -> anyhow::Result<(Vec<u8>, ethabi::Contract)> {
Ok((bytecode, contract))
}

struct SharedResources {
_node_handle: std::thread::JoinHandle<()>,
_rpc_handle: std::thread::JoinHandle<()>,
}

impl SharedResources {
fn start() -> Self {
// Start the node.
let _node_handle = thread::spawn(move || {
if let Err(e) = start_node_inline(vec![
"--dev",
"--rpc-port=45789",
"--no-telemetry",
"--no-prometheus",
"-lerror,evm=debug,sc_rpc_server=info,runtime::revive=trace",
]) {
panic!("Node exited with error: {e:?}");
}
});

// Start the rpc server.
let args = CliCommand::parse_from([
"--dev",
"--rpc-port=45788",
"--node-rpc-url=ws://localhost:45789",
"--no-prometheus",
"-linfo,eth-rpc=debug",
]);

let _rpc_handle = thread::spawn(move || {
if let Err(e) = cli::run(args) {
panic!("eth-rpc exited with error: {e:?}");
}
});

Self { _node_handle, _rpc_handle }
}

async fn client() -> WsClient {
ws_client_with_retry("ws://localhost:45788").await
}
}

#[dynamic(lazy)]
static mut SHARED_RESOURCES: SharedResources = SharedResources::start();

macro_rules! unwrap_call_err(
($err:expr) => {
match $err.downcast_ref::<jsonrpsee::core::client::Error>().unwrap() {
Expand All @@ -70,41 +117,42 @@ macro_rules! unwrap_call_err(
);

#[tokio::test]
async fn test_jsonrpsee_server() -> anyhow::Result<()> {
// Start the node.
let _ = thread::spawn(move || {
if let Err(e) = start_node_inline(vec![
"--dev",
"--rpc-port=45789",
"--no-telemetry",
"--no-prometheus",
"-lerror,evm=debug,sc_rpc_server=info,runtime::revive=trace",
]) {
panic!("Node exited with error: {e:?}");
}
});

// Start the rpc server.
let args = CliCommand::parse_from([
"--dev",
"--rpc-port=45788",
"--node-rpc-url=ws://localhost:45789",
"--no-prometheus",
"-linfo,eth-rpc=debug",
]);
let _ = thread::spawn(move || {
if let Err(e) = cli::run(args) {
panic!("eth-rpc exited with error: {e:?}");
}
});
async fn transfer() -> anyhow::Result<()> {
let _lock = SHARED_RESOURCES.write();
let client = SharedResources::client().await;

let client = ws_client_with_retry("ws://localhost:45788").await;
let ethan = Account::from(subxt_signer::eth::dev::ethan());
let initial_balance = client.get_balance(ethan.address(), BlockTag::Latest.into()).await?;

let value = 1_000_000_000_000_000_000_000u128.into();
let hash = TransactionBuilder::default()
.value(value)
.to(ethan.address())
.send(&client)
.await?;

let receipt = wait_for_successful_receipt(&client, hash).await?;
assert_eq!(
Some(ethan.address()),
receipt.to,
"Receipt should have the correct contract address."
);

let increase =
client.get_balance(ethan.address(), BlockTag::Latest.into()).await? - initial_balance;
assert_eq!(value, increase);
Ok(())
}

#[tokio::test]
async fn deploy_and_call() -> anyhow::Result<()> {
let _lock = SHARED_RESOURCES.write();
let client = SharedResources::client().await;
let account = Account::default();

// Balance transfer
let ethan = Account::from(subxt_signer::eth::dev::ethan());
let ethan_balance = client.get_balance(ethan.address(), BlockTag::Latest.into()).await?;
assert_eq!(U256::zero(), ethan_balance);
let initial_balance = client.get_balance(ethan.address(), BlockTag::Latest.into()).await?;

let value = 1_000_000_000_000_000_000_000u128.into();
let hash = TransactionBuilder::default()
Expand All @@ -120,8 +168,8 @@ async fn test_jsonrpsee_server() -> anyhow::Result<()> {
"Receipt should have the correct contract address."
);

let ethan_balance = client.get_balance(ethan.address(), BlockTag::Latest.into()).await?;
assert_eq!(value, ethan_balance, "ethan's balance should be the same as the value sent.");
let updated_balance = client.get_balance(ethan.address(), BlockTag::Latest.into()).await?;
assert_eq!(value, updated_balance - initial_balance);

// Deploy contract
let data = b"hello world".to_vec();
Expand Down Expand Up @@ -169,15 +217,19 @@ async fn test_jsonrpsee_server() -> anyhow::Result<()> {
wait_for_successful_receipt(&client, hash).await?;
let increase = client.get_balance(contract_address, BlockTag::Latest.into()).await? - balance;
assert_eq!(value, increase, "contract's balance should have increased by the value sent.");
Ok(())
}

// Deploy revert
#[tokio::test]
async fn revert_call() -> anyhow::Result<()> {
let _lock = SHARED_RESOURCES.write();
let client = SharedResources::client().await;
let (bytecode, contract) = get_contract("revert")?;
let receipt = TransactionBuilder::default()
.input(contract.constructor.clone().unwrap().encode_input(bytecode, &[]).unwrap())
.send_and_wait_for_receipt(&client)
.await?;

// Call doRevert
let err = TransactionBuilder::default()
.to(receipt.contract_address.unwrap())
.input(contract.function("doRevert")?.encode_input(&[])?.to_vec())
Expand All @@ -187,25 +239,36 @@ async fn test_jsonrpsee_server() -> anyhow::Result<()> {

let call_err = unwrap_call_err!(err.source().unwrap());
assert_eq!(call_err.message(), "Execution reverted: revert message");
Ok(())
}

// Deploy event
#[tokio::test]
async fn event_logs() -> anyhow::Result<()> {
let _lock = SHARED_RESOURCES.write();
let client = SharedResources::client().await;
let (bytecode, contract) = get_contract("event")?;
let receipt = TransactionBuilder::default()
.input(bytecode)
.send_and_wait_for_receipt(&client)
.await?;

// Call triggerEvent
let receipt = TransactionBuilder::default()
.to(receipt.contract_address.unwrap())
.input(contract.function("triggerEvent")?.encode_input(&[])?.to_vec())
.send_and_wait_for_receipt(&client)
.await?;
assert_eq!(receipt.logs.len(), 1, "There should be one log.");
Ok(())
}

#[tokio::test]
async fn invalid_transaction() -> anyhow::Result<()> {
let _lock = SHARED_RESOURCES.write();
let client = SharedResources::client().await;
let ethan = Account::from(subxt_signer::eth::dev::ethan());

// Invalid transaction
let err = TransactionBuilder::default()
.value(value)
.value(U256::from(1_000_000_000_000u128))
.to(ethan.address())
.mutate(|tx| tx.chain_id = Some(42u32.into()))
.send(&client)
Expand Down
Loading