From dec63ce34aeb710736b2dcee5b29245eb4fd680b Mon Sep 17 00:00:00 2001 From: bear Date: Wed, 16 Aug 2023 14:07:40 +0800 Subject: [PATCH 01/15] Add rpc interface --- client/rpc-core/src/eth.rs | 4 ++++ client/rpc/src/eth/block.rs | 4 ++++ client/rpc/src/eth/mod.rs | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/client/rpc-core/src/eth.rs b/client/rpc-core/src/eth.rs index bea3943d01..ca053a1db1 100644 --- a/client/rpc-core/src/eth.rs +++ b/client/rpc-core/src/eth.rs @@ -85,6 +85,10 @@ pub trait EthApi { number: BlockNumber, ) -> RpcResult>; + /// Returns the receipts of a block by number or hash. + #[method(name = "eth_getBlockReceipts")] + async fn block_transaction_receipts(&self, number: BlockNumber) -> RpcResult>; + /// Returns the number of uncles in a block with given hash. #[method(name = "eth_getUncleCountByBlockHash")] fn block_uncles_count_by_hash(&self, hash: H256) -> RpcResult; diff --git a/client/rpc/src/eth/block.rs b/client/rpc/src/eth/block.rs index c9a1f88017..147a86347a 100644 --- a/client/rpc/src/eth/block.rs +++ b/client/rpc/src/eth/block.rs @@ -267,6 +267,10 @@ where } } + pub async fn block_transaction_receipts(&self, number: BlockNumber) -> RpcResult> { + todo!(); + } + pub fn block_uncles_count_by_hash(&self, _: H256) -> RpcResult { Ok(U256::zero()) } diff --git a/client/rpc/src/eth/mod.rs b/client/rpc/src/eth/mod.rs index 646924bb9b..c92c954a84 100644 --- a/client/rpc/src/eth/mod.rs +++ b/client/rpc/src/eth/mod.rs @@ -236,6 +236,10 @@ where self.block_transaction_count_by_number(number).await } + async fn block_transaction_receipts(&self, number: BlockNumber) -> RpcResult> { + self.block_transaction_receipts(number).await + } + fn block_uncles_count_by_hash(&self, hash: H256) -> RpcResult { self.block_uncles_count_by_hash(hash) } From bf8bee7da145b4d2134581c99af0e092cd7b3bbd Mon Sep 17 00:00:00 2001 From: bear Date: Wed, 16 Aug 2023 14:44:55 +0800 Subject: [PATCH 02/15] Impl the rpc --- client/rpc-core/src/eth.rs | 7 +++++-- client/rpc/src/eth/block.rs | 41 ++++++++++++++++++++++++++++++++++--- client/rpc/src/eth/mod.rs | 5 ++++- 3 files changed, 47 insertions(+), 6 deletions(-) diff --git a/client/rpc-core/src/eth.rs b/client/rpc-core/src/eth.rs index ca053a1db1..6d71aba45a 100644 --- a/client/rpc-core/src/eth.rs +++ b/client/rpc-core/src/eth.rs @@ -87,8 +87,11 @@ pub trait EthApi { /// Returns the receipts of a block by number or hash. #[method(name = "eth_getBlockReceipts")] - async fn block_transaction_receipts(&self, number: BlockNumber) -> RpcResult>; - + async fn block_transaction_receipts( + &self, + number: BlockNumber, + ) -> RpcResult>>; + /// Returns the number of uncles in a block with given hash. #[method(name = "eth_getUncleCountByBlockHash")] fn block_uncles_count_by_hash(&self, hash: H256) -> RpcResult; diff --git a/client/rpc/src/eth/block.rs b/client/rpc/src/eth/block.rs index 147a86347a..5c5d7b3a00 100644 --- a/client/rpc/src/eth/block.rs +++ b/client/rpc/src/eth/block.rs @@ -43,7 +43,7 @@ where C: ProvideRuntimeApi, C::Api: EthereumRuntimeRPCApi, C: HeaderBackend + StorageProvider + 'static, - BE: Backend, + BE: Backend + 'static, A: ChainApi + 'static, { pub async fn block_by_hash(&self, hash: H256, full: bool) -> RpcResult> { @@ -267,8 +267,43 @@ where } } - pub async fn block_transaction_receipts(&self, number: BlockNumber) -> RpcResult> { - todo!(); + pub async fn block_transaction_receipts( + &self, + number: BlockNumber, + ) -> RpcResult>> { + let id = match frontier_backend_client::native_block_id::( + self.client.as_ref(), + self.backend.as_ref(), + Some(number), + ) + .await? + { + Some(id) => id, + None => return Ok(vec![]), + }; + + let substrate_hash = self + .client + .expect_block_hash_from_id(&id) + .map_err(|_| internal_err(format!("Expect block number from id: {}", id)))?; + let schema = fc_storage::onchain_storage_schema(self.client.as_ref(), substrate_hash); + let block = self + .overrides + .schemas + .get(&schema) + .unwrap_or(&self.overrides.fallback) + .current_block(substrate_hash); + + let transaction_hashes = match block { + Some(block) => block.transactions.iter().map(|tx| tx.hash()).collect(), + None => vec![], + }; + let mut receipts = Vec::new(); + for hash in transaction_hashes { + receipts.push(self.transaction_receipt(hash).await?); + } + + Ok(receipts) } pub fn block_uncles_count_by_hash(&self, _: H256) -> RpcResult { diff --git a/client/rpc/src/eth/mod.rs b/client/rpc/src/eth/mod.rs index c92c954a84..bed8681375 100644 --- a/client/rpc/src/eth/mod.rs +++ b/client/rpc/src/eth/mod.rs @@ -236,7 +236,10 @@ where self.block_transaction_count_by_number(number).await } - async fn block_transaction_receipts(&self, number: BlockNumber) -> RpcResult> { + async fn block_transaction_receipts( + &self, + number: BlockNumber, + ) -> RpcResult>> { self.block_transaction_receipts(number).await } From 331dc12902e9b06c821ad208ca067f2fd5a9d73c Mon Sep 17 00:00:00 2001 From: bear Date: Wed, 16 Aug 2023 16:23:19 +0800 Subject: [PATCH 03/15] Add tests --- ts-tests/package-lock.json | 2 ++ ts-tests/package.json | 1 + ts-tests/tests/test-block.ts | 62 +++++++++++++++++++++++++++++++++++- ts-tests/truffle-config.js | 2 +- 4 files changed, 65 insertions(+), 2 deletions(-) diff --git a/ts-tests/package-lock.json b/ts-tests/package-lock.json index 1ba811ee34..bed3ac8bcc 100644 --- a/ts-tests/package-lock.json +++ b/ts-tests/package-lock.json @@ -4677,6 +4677,7 @@ "version": "4.0.5", "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.5.tgz", "integrity": "sha512-HTm14iMQKK2FjFLRTM5lAVcyaUzOnqbPtesFIvREgXpJHdQm8bWS+GkQgIkfaBYRHuCnea7w8UVNfwiAQhlr9A==", + "hasInstallScript": true, "optional": true, "dependencies": { "node-gyp-build": "^4.3.0" @@ -5006,6 +5007,7 @@ "version": "5.0.7", "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.7.tgz", "integrity": "sha512-vLt1O5Pp+flcArHGIyKEQq883nBt8nN8tVBcoL0qUXj2XT1n7p70yGIq2VK98I5FdZ1YHc0wk/koOnHjnXWk1Q==", + "hasInstallScript": true, "optional": true, "dependencies": { "node-gyp-build": "^4.3.0" diff --git a/ts-tests/package.json b/ts-tests/package.json index 7ed4d45ac7..37d876dcd4 100644 --- a/ts-tests/package.json +++ b/ts-tests/package.json @@ -8,6 +8,7 @@ "fmt": "prettier ./tests --write", "build": "truffle compile", "test": "mocha -r ts-node/register 'tests/**/*.ts'", + "s": "mocha -r ts-node/register 'tests/**/test-block.ts'", "test-sql": "FRONTIER_BACKEND_TYPE='sql' mocha -r ts-node/register 'tests/**/*.ts'" }, "author": "", diff --git a/ts-tests/tests/test-block.ts b/ts-tests/tests/test-block.ts index 3ec80a545b..2245833666 100644 --- a/ts-tests/tests/test-block.ts +++ b/ts-tests/tests/test-block.ts @@ -177,7 +177,7 @@ describeWithFrontier("Frontier RPC (Pending Block)", (context) => { nonce = nonce + 100; await sendTransaction(); - // do not seal, get pendign block + // do not seal, get pending block let pending_transactions = []; { const pending = (await customRequest(context.web3, "eth_getBlockByNumber", ["pending", false])).result; @@ -195,3 +195,63 @@ describeWithFrontier("Frontier RPC (Pending Block)", (context) => { expect(pending_transactions).to.be.deep.eq(latest_block.transactions); }); }); + +describeWithFrontier("Frontier RPC (BlockReceipts)", (context) => { + const TEST_ACCOUNT = "0x1111111111111111111111111111111111111111"; + const N = 5; + + it("should return empty if block without transaction", async function () { + await createAndFinalizeBlock(context.web3); + expect(await context.web3.eth.getBlockNumber()).to.equal(1); + + let result = await customRequest(context.web3, "eth_getBlockReceipts", [ + await context.web3.eth.getBlockNumber(), + ]); + expect(result.result.length).to.be.eq(0); + }); + + it("should return multiple receipts", async function () { + var nonce = 0; + let sendTransaction = async () => { + const tx = await context.web3.eth.accounts.signTransaction( + { + from: GENESIS_ACCOUNT, + to: TEST_ACCOUNT, + value: "0x200", // Must be higher than ExistentialDeposit + gasPrice: "0x3B9ACA00", + gas: "0x100000", + nonce: nonce, + }, + GENESIS_ACCOUNT_PRIVATE_KEY + ); + nonce = nonce + 1; + return (await customRequest(context.web3, "eth_sendRawTransaction", [tx.rawTransaction])).result; + }; + + // block 1 send 5 transactions + for (var _ of Array(N)) { + await sendTransaction(); + } + await createAndFinalizeBlock(context.web3); + expect(await context.web3.eth.getBlockNumber()).to.equal(2); + + let result = await customRequest(context.web3, "eth_getBlockReceipts", [2]); + expect(result.result.length).to.be.eq(N); + }); + + it("should support block number, tag and hash", async function () { + expect(await context.web3.eth.getBlockNumber()).to.equal(2); + + // block number + expect((await customRequest(context.web3, "eth_getBlockReceipts", [2])).result.length).to.be.eq(N); + // block hash + let block = await context.web3.eth.getBlock(2); + let result = await customRequest(context.web3, "eth_getBlockReceipts", [block.hash, true]); + console.log("result", result); + // expect((await customRequest(context.web3, "eth_getBlockReceipts", [block.hash])).result.length).to.be.eq(N); + // block tags + expect((await customRequest(context.web3, "eth_getBlockReceipts", ["earliest"])).result.length).to.be.eq(0); + expect((await customRequest(context.web3, "eth_getBlockReceipts", ["pending"])).result.length).to.be.eq(0); + expect((await customRequest(context.web3, "eth_getBlockReceipts", ["finalized"])).result.length).to.be.eq(N); + }); +}); diff --git a/ts-tests/truffle-config.js b/ts-tests/truffle-config.js index 3a2b265974..bf767f68e3 100644 --- a/ts-tests/truffle-config.js +++ b/ts-tests/truffle-config.js @@ -86,7 +86,7 @@ module.exports = { compilers: { solc: { version: "0.8.2", // Fetch exact version from solc-bin (default: truffle's version) - docker: true, // Use "0.5.1" you've installed locally with docker (default: false) + docker: false, // Use "0.5.1" you've installed locally with docker (default: false) // settings: { // See the solidity docs for advice about optimization and evmVersion // optimizer: { // enabled: false, From 924a709974e01a468373684e83d4d6507440b614 Mon Sep 17 00:00:00 2001 From: bear Date: Wed, 16 Aug 2023 16:46:15 +0800 Subject: [PATCH 04/15] Update the test --- ts-tests/tests/test-block.ts | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/ts-tests/tests/test-block.ts b/ts-tests/tests/test-block.ts index 2245833666..8bd2d9ad01 100644 --- a/ts-tests/tests/test-block.ts +++ b/ts-tests/tests/test-block.ts @@ -240,18 +240,26 @@ describeWithFrontier("Frontier RPC (BlockReceipts)", (context) => { }); it("should support block number, tag and hash", async function () { - expect(await context.web3.eth.getBlockNumber()).to.equal(2); + let block_number = await context.web3.eth.getBlockNumber(); // block number - expect((await customRequest(context.web3, "eth_getBlockReceipts", [2])).result.length).to.be.eq(N); + expect((await customRequest(context.web3, "eth_getBlockReceipts", [block_number])).result.length).to.be.eq(N); // block hash - let block = await context.web3.eth.getBlock(2); - let result = await customRequest(context.web3, "eth_getBlockReceipts", [block.hash, true]); - console.log("result", result); - // expect((await customRequest(context.web3, "eth_getBlockReceipts", [block.hash])).result.length).to.be.eq(N); + let block = await context.web3.eth.getBlock(block_number); + expect( + ( + await customRequest(context.web3, "eth_getBlockReceipts", [ + { + blockHash: block.hash, + requireCanonical: true, + }, + ]) + ).result.length + ).to.be.eq(N); // block tags expect((await customRequest(context.web3, "eth_getBlockReceipts", ["earliest"])).result.length).to.be.eq(0); expect((await customRequest(context.web3, "eth_getBlockReceipts", ["pending"])).result.length).to.be.eq(0); expect((await customRequest(context.web3, "eth_getBlockReceipts", ["finalized"])).result.length).to.be.eq(N); + expect((await customRequest(context.web3, "eth_getBlockReceipts", ["latest"])).result.length).to.be.eq(N); }); }); From e8af4ab8baff5034f6ef361413397ccbcf57e35d Mon Sep 17 00:00:00 2001 From: bear Date: Wed, 16 Aug 2023 16:57:43 +0800 Subject: [PATCH 05/15] Revert test config in dev process --- ts-tests/package.json | 1 - ts-tests/truffle-config.js | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/ts-tests/package.json b/ts-tests/package.json index 37d876dcd4..7ed4d45ac7 100644 --- a/ts-tests/package.json +++ b/ts-tests/package.json @@ -8,7 +8,6 @@ "fmt": "prettier ./tests --write", "build": "truffle compile", "test": "mocha -r ts-node/register 'tests/**/*.ts'", - "s": "mocha -r ts-node/register 'tests/**/test-block.ts'", "test-sql": "FRONTIER_BACKEND_TYPE='sql' mocha -r ts-node/register 'tests/**/*.ts'" }, "author": "", diff --git a/ts-tests/truffle-config.js b/ts-tests/truffle-config.js index bf767f68e3..3a2b265974 100644 --- a/ts-tests/truffle-config.js +++ b/ts-tests/truffle-config.js @@ -86,7 +86,7 @@ module.exports = { compilers: { solc: { version: "0.8.2", // Fetch exact version from solc-bin (default: truffle's version) - docker: false, // Use "0.5.1" you've installed locally with docker (default: false) + docker: true, // Use "0.5.1" you've installed locally with docker (default: false) // settings: { // See the solidity docs for advice about optimization and evmVersion // optimizer: { // enabled: false, From 4afd01fb0e5a03e92d653b1d0dcd3d20745cea6d Mon Sep 17 00:00:00 2001 From: bear Date: Wed, 16 Aug 2023 16:58:57 +0800 Subject: [PATCH 06/15] Revert lock.json changes --- ts-tests/package-lock.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/ts-tests/package-lock.json b/ts-tests/package-lock.json index bed3ac8bcc..1ba811ee34 100644 --- a/ts-tests/package-lock.json +++ b/ts-tests/package-lock.json @@ -4677,7 +4677,6 @@ "version": "4.0.5", "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.5.tgz", "integrity": "sha512-HTm14iMQKK2FjFLRTM5lAVcyaUzOnqbPtesFIvREgXpJHdQm8bWS+GkQgIkfaBYRHuCnea7w8UVNfwiAQhlr9A==", - "hasInstallScript": true, "optional": true, "dependencies": { "node-gyp-build": "^4.3.0" @@ -5007,7 +5006,6 @@ "version": "5.0.7", "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.7.tgz", "integrity": "sha512-vLt1O5Pp+flcArHGIyKEQq883nBt8nN8tVBcoL0qUXj2XT1n7p70yGIq2VK98I5FdZ1YHc0wk/koOnHjnXWk1Q==", - "hasInstallScript": true, "optional": true, "dependencies": { "node-gyp-build": "^4.3.0" From 432ed187e70aea90fa665d590ad405fcbdbf826d Mon Sep 17 00:00:00 2001 From: bear Date: Thu, 17 Aug 2023 15:33:01 +0800 Subject: [PATCH 07/15] Get BlockInfo in one place --- client/rpc/src/eth/block.rs | 107 +++++---------------------- client/rpc/src/eth/mod.rs | 119 +++++++++++++++++++++++++++++- client/rpc/src/eth/transaction.rs | 24 +++--- 3 files changed, 145 insertions(+), 105 deletions(-) diff --git a/client/rpc/src/eth/block.rs b/client/rpc/src/eth/block.rs index 5c5d7b3a00..bb5ba24df4 100644 --- a/client/rpc/src/eth/block.rs +++ b/client/rpc/src/eth/block.rs @@ -33,7 +33,7 @@ use fc_rpc_core::types::*; use fp_rpc::EthereumRuntimeRPCApi; use crate::{ - eth::{rich_block_build, Eth, EthConfig}, + eth::{rich_block_build, BlockInfo, Eth, EthConfig}, frontier_backend_client, internal_err, }; @@ -47,29 +47,19 @@ where A: ChainApi + 'static, { pub async fn block_by_hash(&self, hash: H256, full: bool) -> RpcResult> { - let client = Arc::clone(&self.client); - let block_data_cache = Arc::clone(&self.block_data_cache); - let backend = Arc::clone(&self.backend); - - let substrate_hash = match frontier_backend_client::load_hash::( - client.as_ref(), - backend.as_ref(), - hash, - ) - .await - .map_err(|err| internal_err(format!("{:?}", err)))? - { - Some(hash) => hash, - _ => return Ok(None), + let BlockInfo { + block, + receipts: _, + statuses, + schema: _, + substrate_hash, + is_eip1559: _, + } = self.block_info_by_eth_hash(hash).await?; + let Some(substrate_hash) = substrate_hash else { + return Ok(None); }; - let schema = fc_storage::onchain_storage_schema(client.as_ref(), substrate_hash); - - let block = block_data_cache.current_block(schema, substrate_hash).await; - let statuses = block_data_cache - .current_transaction_statuses(schema, substrate_hash) - .await; - + let client = Arc::clone(&self.client); let base_fee = client.runtime_api().gas_price(substrate_hash).ok(); match (block, statuses) { @@ -203,26 +193,8 @@ where } pub async fn block_transaction_count_by_hash(&self, hash: H256) -> RpcResult> { - let substrate_hash = match frontier_backend_client::load_hash::( - self.client.as_ref(), - self.backend.as_ref(), - hash, - ) - .await - .map_err(|err| internal_err(format!("{:?}", err)))? - { - Some(hash) => hash, - _ => return Ok(None), - }; - let schema = fc_storage::onchain_storage_schema(self.client.as_ref(), substrate_hash); - let block = self - .overrides - .schemas - .get(&schema) - .unwrap_or(&self.overrides.fallback) - .current_block(substrate_hash); - - match block { + let blockinfo = self.block_info_by_eth_hash(hash).await?; + match blockinfo.block { Some(block) => Ok(Some(U256::from(block.transactions.len()))), None => Ok(None), } @@ -239,29 +211,8 @@ where ))); } - let id = match frontier_backend_client::native_block_id::( - self.client.as_ref(), - self.backend.as_ref(), - Some(number), - ) - .await? - { - Some(id) => id, - None => return Ok(None), - }; - let substrate_hash = self - .client - .expect_block_hash_from_id(&id) - .map_err(|_| internal_err(format!("Expect block number from id: {}", id)))?; - let schema = fc_storage::onchain_storage_schema(self.client.as_ref(), substrate_hash); - let block = self - .overrides - .schemas - .get(&schema) - .unwrap_or(&self.overrides.fallback) - .current_block(substrate_hash); - - match block { + let blockinfo = self.block_info_by_number(number).await?; + match blockinfo.block { Some(block) => Ok(Some(U256::from(block.transactions.len()))), None => Ok(None), } @@ -271,30 +222,8 @@ where &self, number: BlockNumber, ) -> RpcResult>> { - let id = match frontier_backend_client::native_block_id::( - self.client.as_ref(), - self.backend.as_ref(), - Some(number), - ) - .await? - { - Some(id) => id, - None => return Ok(vec![]), - }; - - let substrate_hash = self - .client - .expect_block_hash_from_id(&id) - .map_err(|_| internal_err(format!("Expect block number from id: {}", id)))?; - let schema = fc_storage::onchain_storage_schema(self.client.as_ref(), substrate_hash); - let block = self - .overrides - .schemas - .get(&schema) - .unwrap_or(&self.overrides.fallback) - .current_block(substrate_hash); - - let transaction_hashes = match block { + let blockinfo = self.block_info_by_number(number).await?; + let transaction_hashes = match blockinfo.block { Some(block) => block.transactions.iter().map(|tx| tx.hash()).collect(), None => vec![], }; diff --git a/client/rpc/src/eth/mod.rs b/client/rpc/src/eth/mod.rs index bed8681375..8994524106 100644 --- a/client/rpc/src/eth/mod.rs +++ b/client/rpc/src/eth/mod.rs @@ -32,6 +32,7 @@ use std::{collections::BTreeMap, marker::PhantomData, sync::Arc}; use ethereum::{BlockV2 as EthereumBlock, TransactionV2 as EthereumTransaction}; use ethereum_types::{H160, H256, H512, H64, U256, U64}; +use fp_storage::EthereumStorageSchema; use jsonrpsee::core::{async_trait, RpcResult}; // Substrate use sc_client_api::backend::{Backend, StorageProvider}; @@ -91,7 +92,12 @@ pub struct Eth> { _marker: PhantomData<(B, BE, EC)>, } -impl Eth { +impl> Eth +where + B: BlockT, + C: HeaderBackend + StorageProvider + 'static, + BE: Backend + 'static, +{ pub fn new( client: Arc, pool: Arc

, @@ -126,6 +132,75 @@ impl Eth { _marker: PhantomData, } } + + pub async fn block_info_by_number(&self, number: BlockNumber) -> RpcResult> { + use crate::frontier_backend_client; + + let id = match frontier_backend_client::native_block_id::( + self.client.as_ref(), + self.backend.as_ref(), + Some(number), + ) + .await? + { + Some(id) => id, + None => return Ok(BlockInfo::default()), + }; + + let substrate_hash = self + .client + .expect_block_hash_from_id(&id) + .map_err(|_| internal_err(format!("Expect block number from id: {}", id)))?; + + Ok(self.block_info_by_hash(substrate_hash).await?) + } + + pub async fn block_info_by_eth_hash(&self, ethereum_hash: H256) -> RpcResult> { + use crate::frontier_backend_client; + + let substrate_hash = match frontier_backend_client::load_hash::( + self.client.as_ref(), + self.backend.as_ref(), + ethereum_hash, + ) + .await + .map_err(|err| internal_err(format!("{:?}", err)))? + { + Some(hash) => hash, + _ => return Ok(BlockInfo::default()), + }; + + Ok(self.block_info_by_hash(substrate_hash).await?) + } + + pub async fn block_info_by_hash(&self, substrate_hash: B::Hash) -> RpcResult> { + let schema = fc_storage::onchain_storage_schema(self.client.as_ref(), substrate_hash); + let handler = self + .overrides + .schemas + .get(&schema) + .unwrap_or(&self.overrides.fallback); + + let block = self + .block_data_cache + .current_block(schema, substrate_hash) + .await; + let receipts = handler.current_receipts(substrate_hash); + let statuses = self + .block_data_cache + .current_transaction_statuses(schema, substrate_hash) + .await; + let is_eip1559 = handler.is_eip1559(substrate_hash); + + Ok(BlockInfo::new( + block, + receipts, + statuses, + schema, + Some(substrate_hash), + is_eip1559, + )) + } } impl> Eth { @@ -594,3 +669,45 @@ where ))) } } + +pub struct BlockInfo { + block: Option, + receipts: Option>, + statuses: Option>, + schema: EthereumStorageSchema, + substrate_hash: Option, + is_eip1559: bool, +} + +impl Default for BlockInfo { + fn default() -> Self { + Self { + block: None, + receipts: None, + statuses: None, + schema: EthereumStorageSchema::default(), + substrate_hash: None, + is_eip1559: true, + } + } +} + +impl BlockInfo { + pub fn new( + block: Option, + receipts: Option>, + statuses: Option>, + schema: EthereumStorageSchema, + substrate_hash: Option, + is_eip1559: bool, + ) -> Self { + Self { + block, + receipts, + statuses, + schema, + substrate_hash, + is_eip1559, + } + } +} diff --git a/client/rpc/src/eth/transaction.rs b/client/rpc/src/eth/transaction.rs index f313260046..d1fed6d229 100644 --- a/client/rpc/src/eth/transaction.rs +++ b/client/rpc/src/eth/transaction.rs @@ -269,8 +269,6 @@ where pub async fn transaction_receipt(&self, hash: H256) -> RpcResult> { let client = Arc::clone(&self.client); - let overrides = Arc::clone(&self.overrides); - let block_data_cache = Arc::clone(&self.block_data_cache); let backend = Arc::clone(&self.backend); let (hash, index) = match frontier_backend_client::load_transactions::( @@ -298,19 +296,15 @@ where _ => return Ok(None), }; - let schema = fc_storage::onchain_storage_schema(client.as_ref(), substrate_hash); - let handler = overrides - .schemas - .get(&schema) - .unwrap_or(&overrides.fallback); - - let block = block_data_cache.current_block(schema, substrate_hash).await; - let statuses = block_data_cache - .current_transaction_statuses(schema, substrate_hash) - .await; - - let receipts = handler.current_receipts(substrate_hash); - let is_eip1559 = handler.is_eip1559(substrate_hash); + use crate::eth::BlockInfo; + let BlockInfo { + block, + receipts, + statuses, + schema: _, + substrate_hash: _, + is_eip1559, + } = self.block_info_by_hash(substrate_hash).await?; match (block, statuses, receipts) { (Some(block), Some(statuses), Some(receipts)) => { From 9ab42568a235a876d9a86cbad821f4f36bc1e3fa Mon Sep 17 00:00:00 2001 From: bear Date: Thu, 17 Aug 2023 16:29:07 +0800 Subject: [PATCH 08/15] Move instance code outside --- client/rpc/src/eth/block.rs | 22 ++- client/rpc/src/eth/mod.rs | 59 +++++++- client/rpc/src/eth/transaction.rs | 240 +++++++++++------------------- 3 files changed, 149 insertions(+), 172 deletions(-) diff --git a/client/rpc/src/eth/block.rs b/client/rpc/src/eth/block.rs index bb5ba24df4..74336ca40e 100644 --- a/client/rpc/src/eth/block.rs +++ b/client/rpc/src/eth/block.rs @@ -54,14 +54,12 @@ where schema: _, substrate_hash, is_eip1559: _, - } = self.block_info_by_eth_hash(hash).await?; + base_fee, + } = self.block_info_by_eth_block_hash(hash).await?; let Some(substrate_hash) = substrate_hash else { return Ok(None); }; - let client = Arc::clone(&self.client); - let base_fee = client.runtime_api().gas_price(substrate_hash).ok(); - match (block, statuses) { (Some(block), Some(statuses)) => { let mut rich_block = rich_block_build( @@ -69,7 +67,7 @@ where statuses.into_iter().map(Option::Some).collect(), Some(hash), full, - base_fee, + Some(base_fee), false, ); @@ -193,7 +191,7 @@ where } pub async fn block_transaction_count_by_hash(&self, hash: H256) -> RpcResult> { - let blockinfo = self.block_info_by_eth_hash(hash).await?; + let blockinfo = self.block_info_by_eth_block_hash(hash).await?; match blockinfo.block { Some(block) => Ok(Some(U256::from(block.transactions.len()))), None => Ok(None), @@ -211,8 +209,8 @@ where ))); } - let blockinfo = self.block_info_by_number(number).await?; - match blockinfo.block { + let block_info = self.block_info_by_number(number).await?; + match block_info.block { Some(block) => Ok(Some(U256::from(block.transactions.len()))), None => Ok(None), } @@ -222,14 +220,14 @@ where &self, number: BlockNumber, ) -> RpcResult>> { - let blockinfo = self.block_info_by_number(number).await?; - let transaction_hashes = match blockinfo.block { - Some(block) => block.transactions.iter().map(|tx| tx.hash()).collect(), + let block_info = self.block_info_by_number(number).await?; + let transaction_hashes = match block_info.clone().block { + Some(ref block) => block.transactions.iter().map(|tx| tx.hash()).collect(), None => vec![], }; let mut receipts = Vec::new(); for hash in transaction_hashes { - receipts.push(self.transaction_receipt(hash).await?); + receipts.push(self.transaction_receipt(block_info.clone(), hash).await?); } Ok(receipts) diff --git a/client/rpc/src/eth/mod.rs b/client/rpc/src/eth/mod.rs index 8994524106..dfe8b8583b 100644 --- a/client/rpc/src/eth/mod.rs +++ b/client/rpc/src/eth/mod.rs @@ -33,7 +33,7 @@ use std::{collections::BTreeMap, marker::PhantomData, sync::Arc}; use ethereum::{BlockV2 as EthereumBlock, TransactionV2 as EthereumTransaction}; use ethereum_types::{H160, H256, H512, H64, U256, U64}; use fp_storage::EthereumStorageSchema; -use jsonrpsee::core::{async_trait, RpcResult}; +use jsonrpsee::core::{async_trait, RpcResult, __reexports::serde_json::de}; // Substrate use sc_client_api::backend::{Backend, StorageProvider}; use sc_network_sync::SyncingService; @@ -95,6 +95,8 @@ pub struct Eth> { impl> Eth where B: BlockT, + C: ProvideRuntimeApi, + C::Api: EthereumRuntimeRPCApi, C: HeaderBackend + StorageProvider + 'static, BE: Backend + 'static, { @@ -155,13 +157,50 @@ where Ok(self.block_info_by_hash(substrate_hash).await?) } - pub async fn block_info_by_eth_hash(&self, ethereum_hash: H256) -> RpcResult> { + pub async fn block_info_by_eth_block_hash( + &self, + eth_block_hash: H256, + ) -> RpcResult> { use crate::frontier_backend_client; let substrate_hash = match frontier_backend_client::load_hash::( self.client.as_ref(), self.backend.as_ref(), - ethereum_hash, + eth_block_hash, + ) + .await + .map_err(|err| internal_err(format!("{:?}", err)))? + { + Some(hash) => hash, + _ => return Ok(BlockInfo::default()), + }; + + Ok(self.block_info_by_hash(substrate_hash).await?) + } + + pub async fn block_info_by_eth_transaction_hash( + &self, + ethereum_tx_hash: H256, + ) -> RpcResult> { + use crate::frontier_backend_client; + + let (eth_block_hash, index) = match frontier_backend_client::load_transactions::( + self.client.as_ref(), + self.backend.as_ref(), + ethereum_tx_hash, + true, + ) + .await + .map_err(|err| internal_err(format!("{:?}", err)))? + { + Some((hash, index)) => (hash, index as usize), + None => return Ok(BlockInfo::default()), + }; + + let substrate_hash = match frontier_backend_client::load_hash::( + self.client.as_ref(), + self.backend.as_ref(), + eth_block_hash, ) .await .map_err(|err| internal_err(format!("{:?}", err)))? @@ -191,6 +230,11 @@ where .current_transaction_statuses(schema, substrate_hash) .await; let is_eip1559 = handler.is_eip1559(substrate_hash); + let base_fee = self + .client + .runtime_api() + .gas_price(substrate_hash) + .unwrap_or_default(); Ok(BlockInfo::new( block, @@ -199,6 +243,7 @@ where schema, Some(substrate_hash), is_eip1559, + base_fee, )) } } @@ -368,7 +413,8 @@ where } async fn transaction_receipt(&self, hash: H256) -> RpcResult> { - self.transaction_receipt(hash).await + let block_info = self.block_info_by_eth_transaction_hash(hash).await?; + self.transaction_receipt(block_info, hash).await } // ######################################################################## @@ -670,6 +716,7 @@ where } } +#[derive(Clone)] pub struct BlockInfo { block: Option, receipts: Option>, @@ -677,6 +724,7 @@ pub struct BlockInfo { schema: EthereumStorageSchema, substrate_hash: Option, is_eip1559: bool, + base_fee: U256, } impl Default for BlockInfo { @@ -688,6 +736,7 @@ impl Default for BlockInfo { schema: EthereumStorageSchema::default(), substrate_hash: None, is_eip1559: true, + base_fee: U256::zero(), } } } @@ -700,6 +749,7 @@ impl BlockInfo { schema: EthereumStorageSchema, substrate_hash: Option, is_eip1559: bool, + base_fee: U256, ) -> Self { Self { block, @@ -708,6 +758,7 @@ impl BlockInfo { schema, substrate_hash, is_eip1559, + base_fee, } } } diff --git a/client/rpc/src/eth/transaction.rs b/client/rpc/src/eth/transaction.rs index d1fed6d229..1f57bdd6be 100644 --- a/client/rpc/src/eth/transaction.rs +++ b/client/rpc/src/eth/transaction.rs @@ -34,7 +34,7 @@ use fc_rpc_core::types::*; use fp_rpc::EthereumRuntimeRPCApi; use crate::{ - eth::{transaction_build, Eth, EthConfig}, + eth::{transaction_build, BlockInfo, Eth, EthConfig}, frontier_backend_client, internal_err, }; @@ -49,7 +49,6 @@ where { pub async fn transaction_by_hash(&self, hash: H256) -> RpcResult> { let client = Arc::clone(&self.client); - let block_data_cache = Arc::clone(&self.block_data_cache); let backend = Arc::clone(&self.backend); let graph = Arc::clone(&self.graph); @@ -123,30 +122,12 @@ where } }; - let substrate_hash = match frontier_backend_client::load_hash::( - client.as_ref(), - backend.as_ref(), - hash, - ) - .await - .map_err(|err| internal_err(format!("{:?}", err)))? - { - Some(hash) => hash, - _ => return Ok(None), - }; - - let schema = fc_storage::onchain_storage_schema(client.as_ref(), substrate_hash); - - let block = block_data_cache.current_block(schema, substrate_hash).await; - let statuses = block_data_cache - .current_transaction_statuses(schema, substrate_hash) - .await; - - let base_fee = client - .runtime_api() - .gas_price(substrate_hash) - .unwrap_or_default(); - + let BlockInfo { + block, + statuses, + base_fee, + .. + } = self.block_info_by_eth_block_hash(hash).await?; match (block, statuses) { (Some(block), Some(statuses)) => Ok(Some(transaction_build( block.transactions[index].clone(), @@ -163,35 +144,13 @@ where hash: H256, index: Index, ) -> RpcResult> { - let client = Arc::clone(&self.client); - let block_data_cache = Arc::clone(&self.block_data_cache); - let backend = Arc::clone(&self.backend); - - let substrate_hash = match frontier_backend_client::load_hash::( - client.as_ref(), - backend.as_ref(), - hash, - ) - .await - .map_err(|err| internal_err(format!("{:?}", err)))? - { - Some(hash) => hash, - _ => return Ok(None), - }; - let index = index.value(); - - let schema = fc_storage::onchain_storage_schema(client.as_ref(), substrate_hash); - - let block = block_data_cache.current_block(schema, substrate_hash).await; - let statuses = block_data_cache - .current_transaction_statuses(schema, substrate_hash) - .await; - - let base_fee = client - .runtime_api() - .gas_price(substrate_hash) - .unwrap_or_default(); + let BlockInfo { + block, + statuses, + base_fee, + .. + } = self.block_info_by_eth_block_hash(hash).await?; match (block, statuses) { (Some(block), Some(statuses)) => { @@ -217,36 +176,13 @@ where number: BlockNumber, index: Index, ) -> RpcResult> { - let client = Arc::clone(&self.client); - let block_data_cache = Arc::clone(&self.block_data_cache); - let backend = Arc::clone(&self.backend); - - let id = match frontier_backend_client::native_block_id::( - client.as_ref(), - backend.as_ref(), - Some(number), - ) - .await? - { - Some(id) => id, - None => return Ok(None), - }; - let substrate_hash = client - .expect_block_hash_from_id(&id) - .map_err(|_| internal_err(format!("Expect block number from id: {}", id)))?; - let index = index.value(); - let schema = fc_storage::onchain_storage_schema(client.as_ref(), substrate_hash); - - let block = block_data_cache.current_block(schema, substrate_hash).await; - let statuses = block_data_cache - .current_transaction_statuses(schema, substrate_hash) - .await; - - let base_fee = client - .runtime_api() - .gas_price(substrate_hash) - .unwrap_or_default(); + let BlockInfo { + block, + statuses, + base_fee, + .. + } = self.block_info_by_number(number).await?; match (block, statuses) { (Some(block), Some(statuses)) => { @@ -267,7 +203,11 @@ where } } - pub async fn transaction_receipt(&self, hash: H256) -> RpcResult> { + pub async fn transaction_receipt( + &self, + block_info: BlockInfo, + hash: H256, + ) -> RpcResult> { let client = Arc::clone(&self.client); let backend = Arc::clone(&self.backend); @@ -284,91 +224,79 @@ where None => return Ok(None), }; - let substrate_hash = match frontier_backend_client::load_hash::( - client.as_ref(), - backend.as_ref(), - hash, - ) - .await - .map_err(|err| internal_err(format!("{:?}", err)))? - { - Some(hash) => hash, - _ => return Ok(None), - }; - - use crate::eth::BlockInfo; let BlockInfo { block, receipts, statuses, - schema: _, - substrate_hash: _, - is_eip1559, - } = self.block_info_by_hash(substrate_hash).await?; + .. + } = block_info.clone(); + let Some(substrate_hash) = block_info.substrate_hash else { + return Ok(None); + }; match (block, statuses, receipts) { (Some(block), Some(statuses), Some(receipts)) => { let block_hash = H256::from(keccak_256(&rlp::encode(&block.header))); let receipt = receipts[index].clone(); - let (logs, logs_bloom, status_code, cumulative_gas_used, gas_used) = if !is_eip1559 - { - // Pre-london frontier update stored receipts require cumulative gas calculation. - match receipt { - ethereum::ReceiptV3::Legacy(ref d) => { - let index = core::cmp::min(receipts.len(), index + 1); - let cumulative_gas: u32 = receipts[..index] - .iter() - .map(|r| match r { - ethereum::ReceiptV3::Legacy(d) => Ok(d.used_gas.as_u32()), - _ => Err(internal_err(format!( - "Unknown receipt for request {}", - hash - ))), - }) - .sum::>()?; - ( - d.logs.clone(), - d.logs_bloom, - d.status_code, - U256::from(cumulative_gas), - d.used_gas, - ) - } - _ => { - return Err(internal_err(format!( - "Unknown receipt for request {}", - hash - ))) + let (logs, logs_bloom, status_code, cumulative_gas_used, gas_used) = + if !block_info.is_eip1559 { + // Pre-london frontier update stored receipts require cumulative gas calculation. + match receipt { + ethereum::ReceiptV3::Legacy(ref d) => { + let index = core::cmp::min(receipts.len(), index + 1); + let cumulative_gas: u32 = receipts[..index] + .iter() + .map(|r| match r { + ethereum::ReceiptV3::Legacy(d) => Ok(d.used_gas.as_u32()), + _ => Err(internal_err(format!( + "Unknown receipt for request {}", + hash + ))), + }) + .sum::>()?; + ( + d.logs.clone(), + d.logs_bloom, + d.status_code, + U256::from(cumulative_gas), + d.used_gas, + ) + } + _ => { + return Err(internal_err(format!( + "Unknown receipt for request {}", + hash + ))) + } } - } - } else { - match receipt { - ethereum::ReceiptV3::Legacy(ref d) - | ethereum::ReceiptV3::EIP2930(ref d) - | ethereum::ReceiptV3::EIP1559(ref d) => { - let cumulative_gas = d.used_gas; - let gas_used = if index > 0 { - let previous_receipt = receipts[index - 1].clone(); - let previous_gas_used = match previous_receipt { - ethereum::ReceiptV3::Legacy(d) - | ethereum::ReceiptV3::EIP2930(d) - | ethereum::ReceiptV3::EIP1559(d) => d.used_gas, + } else { + match receipt { + ethereum::ReceiptV3::Legacy(ref d) + | ethereum::ReceiptV3::EIP2930(ref d) + | ethereum::ReceiptV3::EIP1559(ref d) => { + let cumulative_gas = d.used_gas; + let gas_used = if index > 0 { + let previous_receipt = receipts[index - 1].clone(); + let previous_gas_used = match previous_receipt { + ethereum::ReceiptV3::Legacy(d) + | ethereum::ReceiptV3::EIP2930(d) + | ethereum::ReceiptV3::EIP1559(d) => d.used_gas, + }; + cumulative_gas.saturating_sub(previous_gas_used) + } else { + cumulative_gas }; - cumulative_gas.saturating_sub(previous_gas_used) - } else { - cumulative_gas - }; - ( - d.logs.clone(), - d.logs_bloom, - d.status_code, - cumulative_gas, - gas_used, - ) + ( + d.logs.clone(), + d.logs_bloom, + d.status_code, + cumulative_gas, + gas_used, + ) + } } - } - }; + }; let status = statuses[index].clone(); let mut cumulative_receipts = receipts; From 7fe47e31a779e8cbe4a06a2459e73e1391baecce Mon Sep 17 00:00:00 2001 From: bear Date: Thu, 17 Aug 2023 16:45:29 +0800 Subject: [PATCH 09/15] Rename --- client/rpc/src/eth/block.rs | 4 +--- client/rpc/src/eth/mod.rs | 30 +++++++++++------------------- 2 files changed, 12 insertions(+), 22 deletions(-) diff --git a/client/rpc/src/eth/block.rs b/client/rpc/src/eth/block.rs index 74336ca40e..4130ebb510 100644 --- a/client/rpc/src/eth/block.rs +++ b/client/rpc/src/eth/block.rs @@ -49,12 +49,10 @@ where pub async fn block_by_hash(&self, hash: H256, full: bool) -> RpcResult> { let BlockInfo { block, - receipts: _, statuses, - schema: _, substrate_hash, - is_eip1559: _, base_fee, + .. } = self.block_info_by_eth_block_hash(hash).await?; let Some(substrate_hash) = substrate_hash else { return Ok(None); diff --git a/client/rpc/src/eth/mod.rs b/client/rpc/src/eth/mod.rs index dfe8b8583b..cd2bcdc881 100644 --- a/client/rpc/src/eth/mod.rs +++ b/client/rpc/src/eth/mod.rs @@ -32,8 +32,7 @@ use std::{collections::BTreeMap, marker::PhantomData, sync::Arc}; use ethereum::{BlockV2 as EthereumBlock, TransactionV2 as EthereumTransaction}; use ethereum_types::{H160, H256, H512, H64, U256, U64}; -use fp_storage::EthereumStorageSchema; -use jsonrpsee::core::{async_trait, RpcResult, __reexports::serde_json::de}; +use jsonrpsee::core::{async_trait, RpcResult}; // Substrate use sc_client_api::backend::{Backend, StorageProvider}; use sc_network_sync::SyncingService; @@ -52,7 +51,7 @@ use fp_rpc::{ RuntimeStorageOverride, TransactionStatus, }; -use crate::{internal_err, public_key, signer::EthSigner}; +use crate::{frontier_backend_client, internal_err, public_key, signer::EthSigner}; pub use self::{ cache::{EthBlockDataCacheTask, EthTask}, @@ -136,8 +135,6 @@ where } pub async fn block_info_by_number(&self, number: BlockNumber) -> RpcResult> { - use crate::frontier_backend_client; - let id = match frontier_backend_client::native_block_id::( self.client.as_ref(), self.backend.as_ref(), @@ -154,15 +151,13 @@ where .expect_block_hash_from_id(&id) .map_err(|_| internal_err(format!("Expect block number from id: {}", id)))?; - Ok(self.block_info_by_hash(substrate_hash).await?) + Ok(self.block_info_by_substrate_hash(substrate_hash).await?) } pub async fn block_info_by_eth_block_hash( &self, eth_block_hash: H256, ) -> RpcResult> { - use crate::frontier_backend_client; - let substrate_hash = match frontier_backend_client::load_hash::( self.client.as_ref(), self.backend.as_ref(), @@ -175,16 +170,14 @@ where _ => return Ok(BlockInfo::default()), }; - Ok(self.block_info_by_hash(substrate_hash).await?) + Ok(self.block_info_by_substrate_hash(substrate_hash).await?) } pub async fn block_info_by_eth_transaction_hash( &self, ethereum_tx_hash: H256, ) -> RpcResult> { - use crate::frontier_backend_client; - - let (eth_block_hash, index) = match frontier_backend_client::load_transactions::( + let (eth_block_hash, _index) = match frontier_backend_client::load_transactions::( self.client.as_ref(), self.backend.as_ref(), ethereum_tx_hash, @@ -209,10 +202,13 @@ where _ => return Ok(BlockInfo::default()), }; - Ok(self.block_info_by_hash(substrate_hash).await?) + Ok(self.block_info_by_substrate_hash(substrate_hash).await?) } - pub async fn block_info_by_hash(&self, substrate_hash: B::Hash) -> RpcResult> { + pub async fn block_info_by_substrate_hash( + &self, + substrate_hash: B::Hash, + ) -> RpcResult> { let schema = fc_storage::onchain_storage_schema(self.client.as_ref(), substrate_hash); let handler = self .overrides @@ -240,7 +236,6 @@ where block, receipts, statuses, - schema, Some(substrate_hash), is_eip1559, base_fee, @@ -716,12 +711,12 @@ where } } +/// The most commonly used block information in the rpc interfaces. #[derive(Clone)] pub struct BlockInfo { block: Option, receipts: Option>, statuses: Option>, - schema: EthereumStorageSchema, substrate_hash: Option, is_eip1559: bool, base_fee: U256, @@ -733,7 +728,6 @@ impl Default for BlockInfo { block: None, receipts: None, statuses: None, - schema: EthereumStorageSchema::default(), substrate_hash: None, is_eip1559: true, base_fee: U256::zero(), @@ -746,7 +740,6 @@ impl BlockInfo { block: Option, receipts: Option>, statuses: Option>, - schema: EthereumStorageSchema, substrate_hash: Option, is_eip1559: bool, base_fee: U256, @@ -755,7 +748,6 @@ impl BlockInfo { block, receipts, statuses, - schema, substrate_hash, is_eip1559, base_fee, From b5dd524dcd7abbb530e71e943ae20c771f2f8da7 Mon Sep 17 00:00:00 2001 From: bear Date: Thu, 17 Aug 2023 16:47:33 +0800 Subject: [PATCH 10/15] Update `substrate_hash` type --- client/rpc/src/eth/block.rs | 3 --- client/rpc/src/eth/mod.rs | 8 ++++---- client/rpc/src/eth/transaction.rs | 4 +--- template/node/src/rpc/eth.rs | 2 +- ts-tests/package.json | 1 + ts-tests/truffle-config.js | 2 +- 6 files changed, 8 insertions(+), 12 deletions(-) diff --git a/client/rpc/src/eth/block.rs b/client/rpc/src/eth/block.rs index 4130ebb510..5f21f95fbe 100644 --- a/client/rpc/src/eth/block.rs +++ b/client/rpc/src/eth/block.rs @@ -54,9 +54,6 @@ where base_fee, .. } = self.block_info_by_eth_block_hash(hash).await?; - let Some(substrate_hash) = substrate_hash else { - return Ok(None); - }; match (block, statuses) { (Some(block), Some(statuses)) => { diff --git a/client/rpc/src/eth/mod.rs b/client/rpc/src/eth/mod.rs index cd2bcdc881..15a77e1a07 100644 --- a/client/rpc/src/eth/mod.rs +++ b/client/rpc/src/eth/mod.rs @@ -236,7 +236,7 @@ where block, receipts, statuses, - Some(substrate_hash), + substrate_hash, is_eip1559, base_fee, )) @@ -717,7 +717,7 @@ pub struct BlockInfo { block: Option, receipts: Option>, statuses: Option>, - substrate_hash: Option, + substrate_hash: B::Hash, is_eip1559: bool, base_fee: U256, } @@ -728,7 +728,7 @@ impl Default for BlockInfo { block: None, receipts: None, statuses: None, - substrate_hash: None, + substrate_hash: B::Hash::default(), is_eip1559: true, base_fee: U256::zero(), } @@ -740,7 +740,7 @@ impl BlockInfo { block: Option, receipts: Option>, statuses: Option>, - substrate_hash: Option, + substrate_hash: B::Hash, is_eip1559: bool, base_fee: U256, ) -> Self { diff --git a/client/rpc/src/eth/transaction.rs b/client/rpc/src/eth/transaction.rs index 1f57bdd6be..e3ba9ecd9c 100644 --- a/client/rpc/src/eth/transaction.rs +++ b/client/rpc/src/eth/transaction.rs @@ -228,11 +228,9 @@ where block, receipts, statuses, + substrate_hash, .. } = block_info.clone(); - let Some(substrate_hash) = block_info.substrate_hash else { - return Ok(None); - }; match (block, statuses, receipts) { (Some(block), Some(statuses), Some(receipts)) => { diff --git a/template/node/src/rpc/eth.rs b/template/node/src/rpc/eth.rs index 2a117ab5b8..ad94176693 100644 --- a/template/node/src/rpc/eth.rs +++ b/template/node/src/rpc/eth.rs @@ -140,7 +140,7 @@ where } io.merge( - Eth::new( + Eth::::new( client.clone(), pool.clone(), graph.clone(), diff --git a/ts-tests/package.json b/ts-tests/package.json index 7ed4d45ac7..37d876dcd4 100644 --- a/ts-tests/package.json +++ b/ts-tests/package.json @@ -8,6 +8,7 @@ "fmt": "prettier ./tests --write", "build": "truffle compile", "test": "mocha -r ts-node/register 'tests/**/*.ts'", + "s": "mocha -r ts-node/register 'tests/**/test-block.ts'", "test-sql": "FRONTIER_BACKEND_TYPE='sql' mocha -r ts-node/register 'tests/**/*.ts'" }, "author": "", diff --git a/ts-tests/truffle-config.js b/ts-tests/truffle-config.js index 3a2b265974..bf767f68e3 100644 --- a/ts-tests/truffle-config.js +++ b/ts-tests/truffle-config.js @@ -86,7 +86,7 @@ module.exports = { compilers: { solc: { version: "0.8.2", // Fetch exact version from solc-bin (default: truffle's version) - docker: true, // Use "0.5.1" you've installed locally with docker (default: false) + docker: false, // Use "0.5.1" you've installed locally with docker (default: false) // settings: { // See the solidity docs for advice about optimization and evmVersion // optimizer: { // enabled: false, From d997780cbb3eaf6ec7e0e478f5892583b3da7a3c Mon Sep 17 00:00:00 2001 From: bear Date: Thu, 17 Aug 2023 16:48:40 +0800 Subject: [PATCH 11/15] Use reference --- client/rpc/src/eth/block.rs | 2 +- client/rpc/src/eth/mod.rs | 2 +- client/rpc/src/eth/transaction.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/rpc/src/eth/block.rs b/client/rpc/src/eth/block.rs index 5f21f95fbe..c636e7043a 100644 --- a/client/rpc/src/eth/block.rs +++ b/client/rpc/src/eth/block.rs @@ -222,7 +222,7 @@ where }; let mut receipts = Vec::new(); for hash in transaction_hashes { - receipts.push(self.transaction_receipt(block_info.clone(), hash).await?); + receipts.push(self.transaction_receipt(&block_info, hash).await?); } Ok(receipts) diff --git a/client/rpc/src/eth/mod.rs b/client/rpc/src/eth/mod.rs index 15a77e1a07..ece72b640d 100644 --- a/client/rpc/src/eth/mod.rs +++ b/client/rpc/src/eth/mod.rs @@ -409,7 +409,7 @@ where async fn transaction_receipt(&self, hash: H256) -> RpcResult> { let block_info = self.block_info_by_eth_transaction_hash(hash).await?; - self.transaction_receipt(block_info, hash).await + self.transaction_receipt(&block_info, hash).await } // ######################################################################## diff --git a/client/rpc/src/eth/transaction.rs b/client/rpc/src/eth/transaction.rs index e3ba9ecd9c..06cc630793 100644 --- a/client/rpc/src/eth/transaction.rs +++ b/client/rpc/src/eth/transaction.rs @@ -205,7 +205,7 @@ where pub async fn transaction_receipt( &self, - block_info: BlockInfo, + block_info: &BlockInfo, hash: H256, ) -> RpcResult> { let client = Arc::clone(&self.client); From 1be0ab5a9f7b8d89337b82c29bf1652b70a2c99e Mon Sep 17 00:00:00 2001 From: bear Date: Thu, 17 Aug 2023 17:05:37 +0800 Subject: [PATCH 12/15] Self review --- client/rpc/src/eth/mod.rs | 10 ++++++---- client/rpc/src/eth/transaction.rs | 8 +++----- ts-tests/truffle-config.js | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/client/rpc/src/eth/mod.rs b/client/rpc/src/eth/mod.rs index ece72b640d..edd1aeddd6 100644 --- a/client/rpc/src/eth/mod.rs +++ b/client/rpc/src/eth/mod.rs @@ -91,13 +91,15 @@ pub struct Eth> { _marker: PhantomData<(B, BE, EC)>, } -impl> Eth +impl Eth where + A: ChainApi, B: BlockT, C: ProvideRuntimeApi, C::Api: EthereumRuntimeRPCApi, C: HeaderBackend + StorageProvider + 'static, BE: Backend + 'static, + EC: EthConfig, { pub fn new( client: Arc, @@ -151,7 +153,7 @@ where .expect_block_hash_from_id(&id) .map_err(|_| internal_err(format!("Expect block number from id: {}", id)))?; - Ok(self.block_info_by_substrate_hash(substrate_hash).await?) + self.block_info_by_substrate_hash(substrate_hash).await } pub async fn block_info_by_eth_block_hash( @@ -170,7 +172,7 @@ where _ => return Ok(BlockInfo::default()), }; - Ok(self.block_info_by_substrate_hash(substrate_hash).await?) + self.block_info_by_substrate_hash(substrate_hash).await } pub async fn block_info_by_eth_transaction_hash( @@ -202,7 +204,7 @@ where _ => return Ok(BlockInfo::default()), }; - Ok(self.block_info_by_substrate_hash(substrate_hash).await?) + self.block_info_by_substrate_hash(substrate_hash).await } pub async fn block_info_by_substrate_hash( diff --git a/client/rpc/src/eth/transaction.rs b/client/rpc/src/eth/transaction.rs index 06cc630793..12a577373d 100644 --- a/client/rpc/src/eth/transaction.rs +++ b/client/rpc/src/eth/transaction.rs @@ -52,7 +52,7 @@ where let backend = Arc::clone(&self.backend); let graph = Arc::clone(&self.graph); - let (hash, index) = match frontier_backend_client::load_transactions::( + let (eth_block_hash, index) = match frontier_backend_client::load_transactions::( client.as_ref(), backend.as_ref(), hash, @@ -61,7 +61,7 @@ where .await .map_err(|err| internal_err(format!("{:?}", err)))? { - Some((hash, index)) => (hash, index as usize), + Some((eth_block_hash, index)) => (eth_block_hash, index as usize), None => { let api = client.runtime_api(); let best_block = client.info().best_hash; @@ -127,7 +127,7 @@ where statuses, base_fee, .. - } = self.block_info_by_eth_block_hash(hash).await?; + } = self.block_info_by_eth_block_hash(eth_block_hash).await?; match (block, statuses) { (Some(block), Some(statuses)) => Ok(Some(transaction_build( block.transactions[index].clone(), @@ -210,7 +210,6 @@ where ) -> RpcResult> { let client = Arc::clone(&self.client); let backend = Arc::clone(&self.backend); - let (hash, index) = match frontier_backend_client::load_transactions::( client.as_ref(), backend.as_ref(), @@ -231,7 +230,6 @@ where substrate_hash, .. } = block_info.clone(); - match (block, statuses, receipts) { (Some(block), Some(statuses), Some(receipts)) => { let block_hash = H256::from(keccak_256(&rlp::encode(&block.header))); diff --git a/ts-tests/truffle-config.js b/ts-tests/truffle-config.js index bf767f68e3..3a2b265974 100644 --- a/ts-tests/truffle-config.js +++ b/ts-tests/truffle-config.js @@ -86,7 +86,7 @@ module.exports = { compilers: { solc: { version: "0.8.2", // Fetch exact version from solc-bin (default: truffle's version) - docker: false, // Use "0.5.1" you've installed locally with docker (default: false) + docker: true, // Use "0.5.1" you've installed locally with docker (default: false) // settings: { // See the solidity docs for advice about optimization and evmVersion // optimizer: { // enabled: false, From d534fa1179daf3b605ea15af279d9ce4daa8863f Mon Sep 17 00:00:00 2001 From: bear Date: Thu, 17 Aug 2023 17:08:45 +0800 Subject: [PATCH 13/15] Use derive Default --- client/rpc/src/eth/mod.rs | 31 +++++++++---------------------- client/rpc/src/eth/transaction.rs | 2 +- 2 files changed, 10 insertions(+), 23 deletions(-) diff --git a/client/rpc/src/eth/mod.rs b/client/rpc/src/eth/mod.rs index edd1aeddd6..636f06cb12 100644 --- a/client/rpc/src/eth/mod.rs +++ b/client/rpc/src/eth/mod.rs @@ -136,7 +136,7 @@ where } } - pub async fn block_info_by_number(&self, number: BlockNumber) -> RpcResult> { + pub async fn block_info_by_number(&self, number: BlockNumber) -> RpcResult> { let id = match frontier_backend_client::native_block_id::( self.client.as_ref(), self.backend.as_ref(), @@ -159,7 +159,7 @@ where pub async fn block_info_by_eth_block_hash( &self, eth_block_hash: H256, - ) -> RpcResult> { + ) -> RpcResult> { let substrate_hash = match frontier_backend_client::load_hash::( self.client.as_ref(), self.backend.as_ref(), @@ -178,7 +178,7 @@ where pub async fn block_info_by_eth_transaction_hash( &self, ethereum_tx_hash: H256, - ) -> RpcResult> { + ) -> RpcResult> { let (eth_block_hash, _index) = match frontier_backend_client::load_transactions::( self.client.as_ref(), self.backend.as_ref(), @@ -210,7 +210,7 @@ where pub async fn block_info_by_substrate_hash( &self, substrate_hash: B::Hash, - ) -> RpcResult> { + ) -> RpcResult> { let schema = fc_storage::onchain_storage_schema(self.client.as_ref(), substrate_hash); let handler = self .overrides @@ -714,35 +714,22 @@ where } /// The most commonly used block information in the rpc interfaces. -#[derive(Clone)] -pub struct BlockInfo { +#[derive(Clone, Default)] +pub struct BlockInfo { block: Option, receipts: Option>, statuses: Option>, - substrate_hash: B::Hash, + substrate_hash: H, is_eip1559: bool, base_fee: U256, } -impl Default for BlockInfo { - fn default() -> Self { - Self { - block: None, - receipts: None, - statuses: None, - substrate_hash: B::Hash::default(), - is_eip1559: true, - base_fee: U256::zero(), - } - } -} - -impl BlockInfo { +impl BlockInfo { pub fn new( block: Option, receipts: Option>, statuses: Option>, - substrate_hash: B::Hash, + substrate_hash: H, is_eip1559: bool, base_fee: U256, ) -> Self { diff --git a/client/rpc/src/eth/transaction.rs b/client/rpc/src/eth/transaction.rs index 12a577373d..e351a623f7 100644 --- a/client/rpc/src/eth/transaction.rs +++ b/client/rpc/src/eth/transaction.rs @@ -205,7 +205,7 @@ where pub async fn transaction_receipt( &self, - block_info: &BlockInfo, + block_info: &BlockInfo, hash: H256, ) -> RpcResult> { let client = Arc::clone(&self.client); From 0ea508507ba040ce839289cf810048be07714641 Mon Sep 17 00:00:00 2001 From: bear Date: Thu, 17 Aug 2023 17:37:04 +0800 Subject: [PATCH 14/15] Better `transaction_receipt` --- client/rpc/src/eth/block.rs | 14 ++++++++------ client/rpc/src/eth/mod.rs | 17 ++++++++++------- client/rpc/src/eth/transaction.rs | 19 +++---------------- ts-tests/package.json | 1 - 4 files changed, 21 insertions(+), 30 deletions(-) diff --git a/client/rpc/src/eth/block.rs b/client/rpc/src/eth/block.rs index c636e7043a..66553aed85 100644 --- a/client/rpc/src/eth/block.rs +++ b/client/rpc/src/eth/block.rs @@ -216,13 +216,15 @@ where number: BlockNumber, ) -> RpcResult>> { let block_info = self.block_info_by_number(number).await?; - let transaction_hashes = match block_info.clone().block { - Some(ref block) => block.transactions.iter().map(|tx| tx.hash()).collect(), - None => vec![], - }; let mut receipts = Vec::new(); - for hash in transaction_hashes { - receipts.push(self.transaction_receipt(&block_info, hash).await?); + if let Some(statuses) = block_info.clone().statuses { + let transactions: Vec<(H256, usize)> = statuses + .iter() + .map(|tx| (tx.transaction_hash, tx.transaction_index as usize)) + .collect(); + for (hash, index) in transactions { + receipts.push(self.transaction_receipt(&block_info, hash, index).await?); + } } Ok(receipts) diff --git a/client/rpc/src/eth/mod.rs b/client/rpc/src/eth/mod.rs index 636f06cb12..64d1ff53cc 100644 --- a/client/rpc/src/eth/mod.rs +++ b/client/rpc/src/eth/mod.rs @@ -178,8 +178,8 @@ where pub async fn block_info_by_eth_transaction_hash( &self, ethereum_tx_hash: H256, - ) -> RpcResult> { - let (eth_block_hash, _index) = match frontier_backend_client::load_transactions::( + ) -> RpcResult<(BlockInfo, usize)> { + let (eth_block_hash, index) = match frontier_backend_client::load_transactions::( self.client.as_ref(), self.backend.as_ref(), ethereum_tx_hash, @@ -189,7 +189,7 @@ where .map_err(|err| internal_err(format!("{:?}", err)))? { Some((hash, index)) => (hash, index as usize), - None => return Ok(BlockInfo::default()), + None => return Ok((BlockInfo::default(), 0)), }; let substrate_hash = match frontier_backend_client::load_hash::( @@ -201,10 +201,13 @@ where .map_err(|err| internal_err(format!("{:?}", err)))? { Some(hash) => hash, - _ => return Ok(BlockInfo::default()), + _ => return Ok((BlockInfo::default(), 0)), }; - self.block_info_by_substrate_hash(substrate_hash).await + Ok(( + self.block_info_by_substrate_hash(substrate_hash).await?, + index, + )) } pub async fn block_info_by_substrate_hash( @@ -410,8 +413,8 @@ where } async fn transaction_receipt(&self, hash: H256) -> RpcResult> { - let block_info = self.block_info_by_eth_transaction_hash(hash).await?; - self.transaction_receipt(&block_info, hash).await + let (block_info, index) = self.block_info_by_eth_transaction_hash(hash).await?; + self.transaction_receipt(&block_info, hash, index).await } // ######################################################################## diff --git a/client/rpc/src/eth/transaction.rs b/client/rpc/src/eth/transaction.rs index e351a623f7..cfd23c3c51 100644 --- a/client/rpc/src/eth/transaction.rs +++ b/client/rpc/src/eth/transaction.rs @@ -207,22 +207,8 @@ where &self, block_info: &BlockInfo, hash: H256, + index: usize, ) -> RpcResult> { - let client = Arc::clone(&self.client); - let backend = Arc::clone(&self.backend); - let (hash, index) = match frontier_backend_client::load_transactions::( - client.as_ref(), - backend.as_ref(), - hash, - true, - ) - .await - .map_err(|err| internal_err(format!("{:?}", err)))? - { - Some((hash, index)) => (hash, index as usize), - None => return Ok(None), - }; - let BlockInfo { block, receipts, @@ -301,7 +287,8 @@ where let effective_gas_price = match transaction { EthereumTransaction::Legacy(t) => t.gas_price, EthereumTransaction::EIP2930(t) => t.gas_price, - EthereumTransaction::EIP1559(t) => client + EthereumTransaction::EIP1559(t) => self + .client .runtime_api() .gas_price(substrate_hash) .unwrap_or_default() diff --git a/ts-tests/package.json b/ts-tests/package.json index 37d876dcd4..7ed4d45ac7 100644 --- a/ts-tests/package.json +++ b/ts-tests/package.json @@ -8,7 +8,6 @@ "fmt": "prettier ./tests --write", "build": "truffle compile", "test": "mocha -r ts-node/register 'tests/**/*.ts'", - "s": "mocha -r ts-node/register 'tests/**/test-block.ts'", "test-sql": "FRONTIER_BACKEND_TYPE='sql' mocha -r ts-node/register 'tests/**/*.ts'" }, "author": "", From b45e32969f23234c305bd4e6df0c98de59a03269 Mon Sep 17 00:00:00 2001 From: bear Date: Thu, 17 Aug 2023 20:25:12 +0800 Subject: [PATCH 15/15] Fix review --- client/rpc-core/src/eth.rs | 2 +- client/rpc/src/eth/block.rs | 22 +++++++++++++--------- client/rpc/src/eth/mod.rs | 2 +- ts-tests/tests/test-block.ts | 2 +- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/client/rpc-core/src/eth.rs b/client/rpc-core/src/eth.rs index 6d71aba45a..118fda550b 100644 --- a/client/rpc-core/src/eth.rs +++ b/client/rpc-core/src/eth.rs @@ -90,7 +90,7 @@ pub trait EthApi { async fn block_transaction_receipts( &self, number: BlockNumber, - ) -> RpcResult>>; + ) -> RpcResult>>; /// Returns the number of uncles in a block with given hash. #[method(name = "eth_getUncleCountByBlockHash")] diff --git a/client/rpc/src/eth/block.rs b/client/rpc/src/eth/block.rs index 66553aed85..90939bc26c 100644 --- a/client/rpc/src/eth/block.rs +++ b/client/rpc/src/eth/block.rs @@ -214,20 +214,24 @@ where pub async fn block_transaction_receipts( &self, number: BlockNumber, - ) -> RpcResult>> { + ) -> RpcResult>> { let block_info = self.block_info_by_number(number).await?; + let Some(statuses) = block_info.clone().statuses else { + return Ok(None); + }; + let mut receipts = Vec::new(); - if let Some(statuses) = block_info.clone().statuses { - let transactions: Vec<(H256, usize)> = statuses - .iter() - .map(|tx| (tx.transaction_hash, tx.transaction_index as usize)) - .collect(); - for (hash, index) in transactions { - receipts.push(self.transaction_receipt(&block_info, hash, index).await?); + let transactions: Vec<(H256, usize)> = statuses + .iter() + .map(|tx| (tx.transaction_hash, tx.transaction_index as usize)) + .collect(); + for (hash, index) in transactions { + if let Some(receipt) = self.transaction_receipt(&block_info, hash, index).await? { + receipts.push(receipt); } } - Ok(receipts) + Ok(Some(receipts)) } pub fn block_uncles_count_by_hash(&self, _: H256) -> RpcResult { diff --git a/client/rpc/src/eth/mod.rs b/client/rpc/src/eth/mod.rs index 64d1ff53cc..14b2d896e3 100644 --- a/client/rpc/src/eth/mod.rs +++ b/client/rpc/src/eth/mod.rs @@ -359,7 +359,7 @@ where async fn block_transaction_receipts( &self, number: BlockNumber, - ) -> RpcResult>> { + ) -> RpcResult>> { self.block_transaction_receipts(number).await } diff --git a/ts-tests/tests/test-block.ts b/ts-tests/tests/test-block.ts index 8bd2d9ad01..81471a5b5b 100644 --- a/ts-tests/tests/test-block.ts +++ b/ts-tests/tests/test-block.ts @@ -258,7 +258,7 @@ describeWithFrontier("Frontier RPC (BlockReceipts)", (context) => { ).to.be.eq(N); // block tags expect((await customRequest(context.web3, "eth_getBlockReceipts", ["earliest"])).result.length).to.be.eq(0); - expect((await customRequest(context.web3, "eth_getBlockReceipts", ["pending"])).result.length).to.be.eq(0); + expect((await customRequest(context.web3, "eth_getBlockReceipts", ["pending"])).result).to.be.null; expect((await customRequest(context.web3, "eth_getBlockReceipts", ["finalized"])).result.length).to.be.eq(N); expect((await customRequest(context.web3, "eth_getBlockReceipts", ["latest"])).result.length).to.be.eq(N); });