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] rpc - gas used fixes #7482

Merged
merged 14 commits into from
Feb 7, 2025
7 changes: 7 additions & 0 deletions prdoc/pr_7482.prdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
title: '[pallet-revive] rpc - gas used fixes '
doc:
- audience: Runtime Dev
description: '#7463 follow up with RPC fixes'
crates:
- name: pallet-revive-eth-rpc
bump: minor
40 changes: 22 additions & 18 deletions substrate/frame/revive/rpc/examples/rust/deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,8 @@ use pallet_revive::{
create1,
evm::{Account, BlockTag, ReceiptInfo, U256},
};
use pallet_revive_eth_rpc::{
example::{wait_for_receipt, TransactionBuilder},
EthRpcClient,
};
use pallet_revive_eth_rpc::{example::TransactionBuilder, EthRpcClient};
use std::sync::Arc;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
Expand All @@ -36,43 +34,49 @@ async fn main() -> anyhow::Result<()> {
println!("Account:");
println!("- address: {:?}", account.address());
println!("- substrate: {}", account.substrate_account());
let client = HttpClientBuilder::default().build("http://localhost:8545")?;
let client = Arc::new(HttpClientBuilder::default().build("http://localhost:8545")?);

println!("\n\n=== Deploying contract ===\n\n");

let nonce = client.get_transaction_count(account.address(), BlockTag::Latest.into()).await?;
let hash = TransactionBuilder::default()
let tx = TransactionBuilder::new(&client)
.value(5_000_000_000_000u128.into())
.input(input)
.send(&client)
.send()
.await?;

println!("Deploy Tx hash: {hash:?}");
println!("Deploy Tx hash: {:?}", tx.hash());
let ReceiptInfo { block_number, gas_used, contract_address, .. } =
wait_for_receipt(&client, hash).await?;
tx.wait_for_receipt().await?;

let contract_address = contract_address.unwrap();
assert_eq!(contract_address, create1(&account.address(), nonce.try_into().unwrap()));

println!("Receipt:");
println!("- Block number: {block_number}");
println!("- Gas used: {gas_used}");
println!("- Block number: {block_number}");
println!("- Gas estimated: {}", tx.gas());
println!("- Gas used: {gas_used}");
println!("- Contract address: {contract_address:?}");
let balance = client.get_balance(contract_address, BlockTag::Latest.into()).await?;
println!("- Contract balance: {balance:?}");

if std::env::var("SKIP_CALL").is_ok() {
return Ok(());
}

println!("\n\n=== Calling contract ===\n\n");
let hash = TransactionBuilder::default()
let tx = TransactionBuilder::new(&client)
.value(U256::from(1_000_000u32))
.to(contract_address)
.send(&client)
.send()
.await?;

println!("Contract call tx hash: {hash:?}");
let ReceiptInfo { block_number, gas_used, to, .. } = wait_for_receipt(&client, hash).await?;
println!("Contract call tx hash: {:?}", tx.hash());
let ReceiptInfo { block_number, gas_used, to, .. } = tx.wait_for_receipt().await?;
println!("Receipt:");
println!("- Block number: {block_number}");
println!("- Gas used: {gas_used}");
println!("- To: {to:?}");
println!("- Block number: {block_number}");
println!("- Gas used: {gas_used}");
println!("- Gas estimated: {}", tx.gas());
println!("- To: {to:?}");
Ok(())
}
3 changes: 2 additions & 1 deletion substrate/frame/revive/rpc/examples/rust/rpc-playground.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@
use jsonrpsee::http_client::HttpClientBuilder;
use pallet_revive::evm::{Account, BlockTag};
use pallet_revive_eth_rpc::EthRpcClient;
use std::sync::Arc;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
let account = Account::default();
println!("Account address: {:?}", account.address());

let client = HttpClientBuilder::default().build("http://localhost:8545")?;
let client = Arc::new(HttpClientBuilder::default().build("http://localhost:8545")?);

let block = client.get_block_by_number(BlockTag::Latest.into(), false).await?;
println!("Latest block: {block:#?}");
Expand Down
17 changes: 7 additions & 10 deletions substrate/frame/revive/rpc/examples/rust/transfer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,12 @@
// limitations under the License.
use jsonrpsee::http_client::HttpClientBuilder;
use pallet_revive::evm::{Account, BlockTag, ReceiptInfo};
use pallet_revive_eth_rpc::{
example::{wait_for_receipt, TransactionBuilder},
EthRpcClient,
};
use pallet_revive_eth_rpc::{example::TransactionBuilder, EthRpcClient};
use std::sync::Arc;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
let client = HttpClientBuilder::default().build("http://localhost:8545")?;
let client = Arc::new(HttpClientBuilder::default().build("http://localhost:8545")?);

let alith = Account::default();
let alith_address = alith.address();
Expand All @@ -41,16 +39,15 @@ async fn main() -> anyhow::Result<()> {
print_balance().await?;
println!("\n\n=== Transferring ===\n\n");

let hash = TransactionBuilder::default()
let tx = TransactionBuilder::new(&client)
.signer(alith)
.value(value)
.to(ethan.address())
.send(&client)
.send()
.await?;
println!("Transaction hash: {hash:?}");
println!("Transaction hash: {:?}", tx.hash());

let ReceiptInfo { block_number, gas_used, status, .. } =
wait_for_receipt(&client, hash).await?;
let ReceiptInfo { block_number, gas_used, status, .. } = tx.wait_for_receipt().await?;
println!("Receipt: ");
println!("- Block number: {block_number}");
println!("- Gas used: {gas_used}");
Expand Down
Binary file modified substrate/frame/revive/rpc/revive_chain.metadata
Binary file not shown.
18 changes: 14 additions & 4 deletions substrate/frame/revive/rpc/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
// limitations under the License.
//! The Ethereum JSON-RPC server.
use crate::{
client::{connect, Client},
client::{connect, native_to_eth_ratio, Client},
BlockInfoProvider, BlockInfoProviderImpl, CacheReceiptProvider, DBReceiptProvider,
EthRpcServer, EthRpcServerImpl, ReceiptProvider, SystemHealthRpcServer,
EthRpcServer, EthRpcServerImpl, ReceiptExtractor, ReceiptProvider, SystemHealthRpcServer,
SystemHealthRpcServerImpl, LOG_TARGET,
};
use clap::Parser;
Expand Down Expand Up @@ -146,6 +146,8 @@ pub fn run(cmd: CliCommand) -> anyhow::Result<()> {
let (api, rpc_client, rpc) = connect(&node_rpc_url).await?;
let block_provider: Arc<dyn BlockInfoProvider> =
Arc::new(BlockInfoProviderImpl::new(cache_size, api.clone(), rpc.clone()));

let receipt_extractor = ReceiptExtractor::new(native_to_eth_ratio(&api).await?);
let receipt_provider: Arc<dyn ReceiptProvider> =
if let Some(database_url) = database_url.as_ref() {
log::info!(target: LOG_TARGET, "🔗 Connecting to provided database");
Expand All @@ -155,6 +157,7 @@ pub fn run(cmd: CliCommand) -> anyhow::Result<()> {
database_url,
database_read_only,
block_provider.clone(),
receipt_extractor.clone(),
)
.await?,
))
Expand All @@ -163,8 +166,15 @@ pub fn run(cmd: CliCommand) -> anyhow::Result<()> {
Arc::new(CacheReceiptProvider::default())
};

let client =
Client::new(api, rpc_client, rpc, block_provider, receipt_provider).await?;
let client = Client::new(
api,
rpc_client,
rpc,
block_provider,
receipt_provider,
receipt_extractor,
)
.await?;
client.subscribe_and_cache_blocks(&essential_spawn_handle);
Ok::<_, crate::ClientError>(client)
}
Expand Down
29 changes: 19 additions & 10 deletions substrate/frame/revive/rpc/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,10 @@
//! The client connects to the source substrate chain
//! and is used by the rpc server to query and send transactions to the substrate chain.
use crate::{
extract_receipts_from_block,
subxt_client::{
revive::calls::types::EthTransact, runtime_types::pallet_revive::storage::ContractInfo,
},
BlockInfoProvider, ReceiptProvider, TransactionInfo, LOG_TARGET,
BlockInfoProvider, ReceiptExtractor, ReceiptProvider, TransactionInfo, LOG_TARGET,
};
use jsonrpsee::types::{error::CALL_EXECUTION_FAILED_CODE, ErrorObjectOwned};
use pallet_revive::{
Expand Down Expand Up @@ -170,6 +169,7 @@ pub struct Client {
rpc: LegacyRpcMethods<SrcChainConfig>,
receipt_provider: Arc<dyn ReceiptProvider>,
block_provider: Arc<dyn BlockInfoProvider>,
receipt_extractor: ReceiptExtractor,
chain_id: u64,
max_block_weight: Weight,
}
Expand All @@ -180,6 +180,12 @@ async fn chain_id(api: &OnlineClient<SrcChainConfig>) -> Result<u64, ClientError
api.constants().at(&query).map_err(|err| err.into())
}

/// Fetch the native_to_eth_ratio
pub async fn native_to_eth_ratio(api: &OnlineClient<SrcChainConfig>) -> Result<u32, ClientError> {
let query = subxt_client::constants().revive().native_to_eth_ratio();
api.constants().at(&query).map_err(|err| err.into())
}

/// Fetch the max block weight from the substrate chain.
async fn max_block_weight(api: &OnlineClient<SrcChainConfig>) -> Result<Weight, ClientError> {
let query = subxt_client::constants().system().block_weights();
Expand Down Expand Up @@ -226,6 +232,7 @@ impl Client {
rpc: LegacyRpcMethods<SrcChainConfig>,
block_provider: Arc<dyn BlockInfoProvider>,
receipt_provider: Arc<dyn ReceiptProvider>,
receipt_extractor: ReceiptExtractor,
) -> Result<Self, ClientError> {
let (chain_id, max_block_weight) =
tokio::try_join!(chain_id(&api), max_block_weight(&api))?;
Expand All @@ -236,6 +243,7 @@ impl Client {
rpc,
receipt_provider,
block_provider,
receipt_extractor,
chain_id,
max_block_weight,
})
Expand Down Expand Up @@ -320,7 +328,7 @@ impl Client {
},
};

log::debug!(target: LOG_TARGET, "Pushing block: {}", block.number());
log::trace!(target: LOG_TARGET, "Pushing block: {}", block.number());
if let Err(err) = callback(block).await {
log::error!(target: LOG_TARGET, "Failed to process block: {err:?}");
}
Expand All @@ -336,7 +344,7 @@ impl Client {
spawn_handle.spawn("subscribe-blocks", None, async move {
let res = client
.subscribe_new_blocks(SubscriptionType::BestBlocks, |block| async {
let receipts = extract_receipts_from_block(&block).await?;
let receipts = client.receipt_extractor.extract_from_block(&block).await?;

client.receipt_provider.insert(&block.hash(), &receipts).await;
if let Some(pruned) = client.block_provider.cache_block(block).await {
Expand All @@ -360,17 +368,18 @@ impl Client {
) -> Result<(), ClientError> {
let new_blocks_fut =
self.subscribe_new_blocks(SubscriptionType::FinalizedBlocks, |block| async move {
let receipts = extract_receipts_from_block(&block).await.inspect_err(|err| {
log::error!(target: LOG_TARGET, "Failed to extract receipts from block: {err:?}");
})?;
let receipts =
self.receipt_extractor.extract_from_block(&block).await.inspect_err(|err| {
log::error!(target: LOG_TARGET, "Failed to extract receipts from block: {err:?}");
})?;
self.receipt_provider.insert(&block.hash(), &receipts).await;
Ok(())
});

let Some(oldest_block) = oldest_block else { return new_blocks_fut.await };

let old_blocks_fut = self.subscribe_past_blocks(|block| async move {
let receipts = extract_receipts_from_block(&block).await?;
let receipts = self.receipt_extractor.extract_from_block(&block).await?;
self.receipt_provider.insert(&block.hash(), &receipts).await;
if block.number() == oldest_block {
Ok(ControlFlow::Break(()))
Expand Down Expand Up @@ -481,7 +490,7 @@ impl Client {
pub async fn receipt_by_hash_and_index(
&self,
block_hash: &H256,
transaction_index: &U256,
transaction_index: usize,
) -> Option<ReceiptInfo> {
self.receipt_provider
.receipt_by_block_hash_and_index(block_hash, transaction_index)
Expand Down Expand Up @@ -665,7 +674,7 @@ impl Client {
let state_root = header.state_root.0.into();
let extrinsics_root = header.extrinsics_root.0.into();

let receipts = extract_receipts_from_block(&block).await.unwrap_or_default();
let receipts = self.receipt_extractor.extract_from_block(&block).await.unwrap_or_default();
let gas_used =
receipts.iter().fold(U256::zero(), |acc, (_, receipt)| acc + receipt.gas_used);
let transactions = if hydrated_transactions {
Expand Down
20 changes: 15 additions & 5 deletions substrate/frame/revive/rpc/src/eth-indexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
//! The Ethereum JSON-RPC server.
use clap::Parser;
use pallet_revive_eth_rpc::{
client::{connect, Client, SubstrateBlockNumber},
BlockInfoProvider, BlockInfoProviderImpl, DBReceiptProvider, ReceiptProvider,
client::{connect, native_to_eth_ratio, Client, SubstrateBlockNumber},
BlockInfoProvider, BlockInfoProviderImpl, DBReceiptProvider, ReceiptExtractor, ReceiptProvider,
};
use sc_cli::SharedParams;
use std::sync::Arc;
Expand Down Expand Up @@ -78,10 +78,20 @@ pub async fn main() -> anyhow::Result<()> {
let (api, rpc_client, rpc) = connect(&node_rpc_url).await?;
let block_provider: Arc<dyn BlockInfoProvider> =
Arc::new(BlockInfoProviderImpl::new(0, api.clone(), rpc.clone()));
let receipt_provider: Arc<dyn ReceiptProvider> =
Arc::new(DBReceiptProvider::new(&database_url, false, block_provider.clone()).await?);
let receipt_extractor = ReceiptExtractor::new(native_to_eth_ratio(&api).await?);
let receipt_provider: Arc<dyn ReceiptProvider> = Arc::new(
DBReceiptProvider::new(
&database_url,
false,
block_provider.clone(),
receipt_extractor.clone(),
)
.await?,
);

let client = Client::new(api, rpc_client, rpc, block_provider, receipt_provider).await?;
let client =
Client::new(api, rpc_client, rpc, block_provider, receipt_provider, receipt_extractor)
.await?;
client.subscribe_and_cache_receipts(oldest_block).await?;

Ok(())
Expand Down
24 changes: 11 additions & 13 deletions substrate/frame/revive/rpc/src/eth-rpc-tester.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,8 @@
use clap::Parser;
use jsonrpsee::http_client::HttpClientBuilder;
use pallet_revive::evm::{Account, BlockTag, ReceiptInfo};
use pallet_revive_eth_rpc::{
example::{wait_for_receipt, TransactionBuilder},
EthRpcClient,
};
use pallet_revive_eth_rpc::{example::TransactionBuilder, EthRpcClient};
use std::sync::Arc;
use tokio::{
io::{AsyncBufReadExt, BufReader},
process::{Child, ChildStderr, Command},
Expand Down Expand Up @@ -119,37 +117,37 @@ async fn test_eth_rpc(stderr: ChildStderr) -> anyhow::Result<()> {

println!("Account:");
println!("- address: {:?}", account.address());
let client = HttpClientBuilder::default().build("http://localhost:8545")?;
let client = Arc::new(HttpClientBuilder::default().build("http://localhost:8545")?);

let nonce = client.get_transaction_count(account.address(), BlockTag::Latest.into()).await?;
let balance = client.get_balance(account.address(), BlockTag::Latest.into()).await?;
println!("- nonce: {nonce:?}");
println!("- balance: {balance:?}");

println!("\n\n=== Deploying dummy contract ===\n\n");
let hash = TransactionBuilder::default().input(input).send(&client).await?;
let tx = TransactionBuilder::new(&client).input(input).send().await?;

println!("Hash: {hash:?}");
println!("Hash: {:?}", tx.hash());
println!("Waiting for receipt...");
let ReceiptInfo { block_number, gas_used, contract_address, .. } =
wait_for_receipt(&client, hash).await?;
tx.wait_for_receipt().await?;

let contract_address = contract_address.unwrap();
println!("\nReceipt:");
println!("Block explorer: https://westend-asset-hub-eth-explorer.parity.io/{hash:?}");
println!("Block explorer: https://westend-asset-hub-eth-explorer.parity.io/{:?}", tx.hash());
println!("- Block number: {block_number}");
println!("- Gas used: {gas_used}");
println!("- Address: {contract_address:?}");

println!("\n\n=== Calling dummy contract ===\n\n");
let hash = TransactionBuilder::default().to(contract_address).send(&client).await?;
let tx = TransactionBuilder::new(&client).to(contract_address).send().await?;

println!("Hash: {hash:?}");
println!("Hash: {:?}", tx.hash());
println!("Waiting for receipt...");

let ReceiptInfo { block_number, gas_used, to, .. } = wait_for_receipt(&client, hash).await?;
let ReceiptInfo { block_number, gas_used, to, .. } = tx.wait_for_receipt().await?;
println!("\nReceipt:");
println!("Block explorer: https://westend-asset-hub-eth-explorer.parity.io/{hash:?}");
println!("Block explorer: https://westend-asset-hub-eth-explorer.parity.io/{:?}", tx.hash());
println!("- Block number: {block_number}");
println!("- Gas used: {gas_used}");
println!("- To: {to:?}");
Expand Down
Loading
Loading