feat: add tx length rpc methods (#142)

* adding documentation for rpc.md

* adding rpc methods in table for rpc.md

* adjusting readme to link to rpc.md

* fixing grammar

* grammar

* adding RPC Methods according to documentation and listing column as Client Function

* adding more description space

* undoing description spacing

* adding get block transaction count by hash to node.rs and rpc.rs

* functioning getblocktransactioncountbyhash function

* removing documentation

* adding second rpc method and simplifying logic

* adjusting example and node.rs

* formatting

* fixing clippy errors

* adding to client and to rpc.md

* formatting

* integrating into client

* u64 return types, rpc.md updated to get_nonce, get_transaction_count -> get_nonce revert

* cargo fmt
This commit is contained in:
Giovanni Vignone 2022-12-13 19:19:36 -05:00 committed by GitHub
parent 94bf458d94
commit c26e393b7d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 72 additions and 15 deletions

View File

@ -340,6 +340,20 @@ impl<DB: Database> Client<DB> {
self.node.read().await.get_nonce(address, block).await
}
pub async fn get_block_transaction_count_by_hash(&self, hash: &Vec<u8>) -> Result<u64> {
self.node
.read()
.await
.get_block_transaction_count_by_hash(hash)
}
pub async fn get_block_transaction_count_by_number(&self, block: BlockTag) -> Result<u64> {
self.node
.read()
.await
.get_block_transaction_count_by_number(block)
}
pub async fn get_code(&self, address: &Address, block: BlockTag) -> Result<Vec<u8>> {
self.node.read().await.get_code(address, block).await
}

View File

@ -155,6 +155,20 @@ impl Node {
Ok(account.nonce)
}
pub fn get_block_transaction_count_by_hash(&self, hash: &Vec<u8>) -> Result<u64> {
let payload = self.get_payload_by_hash(hash)?;
let transaction_count = payload.1.transactions.len();
Ok(transaction_count as u64)
}
pub fn get_block_transaction_count_by_number(&self, block: BlockTag) -> Result<u64> {
let payload = self.get_payload(block)?;
let transaction_count = payload.transactions.len();
Ok(transaction_count as u64)
}
pub async fn get_code(&self, address: &Address, block: BlockTag) -> Result<Vec<u8>> {
self.check_blocktag_age(&block)?;
@ -248,19 +262,11 @@ impl Node {
hash: &Vec<u8>,
full_tx: bool,
) -> Result<Option<ExecutionBlock>> {
let payloads = self
.payloads
.iter()
.filter(|entry| &entry.1.block_hash.to_vec() == hash)
.collect::<Vec<(&u64, &ExecutionPayload)>>();
let payload = self.get_payload_by_hash(hash);
if let Some(payload_entry) = payloads.get(0) {
self.execution
.get_block(payload_entry.1, full_tx)
.await
.map(Some)
} else {
Ok(None)
match payload {
Ok(payload) => self.execution.get_block(payload.1, full_tx).await.map(Some),
Err(_) => Ok(None),
}
}
@ -296,6 +302,19 @@ impl Node {
}
}
fn get_payload_by_hash(&self, hash: &Vec<u8>) -> Result<(&u64, &ExecutionPayload)> {
let payloads = self
.payloads
.iter()
.filter(|entry| &entry.1.block_hash.to_vec() == hash)
.collect::<Vec<(&u64, &ExecutionPayload)>>();
payloads
.get(0)
.cloned()
.ok_or(eyre!("Block not found by hash"))
}
fn check_head_age(&self) -> Result<(), NodeError> {
let synced_slot = self.consensus.get_header().slot;
let expected_slot = self.consensus.expected_current_slot();

View File

@ -57,6 +57,11 @@ trait EthRpc {
async fn get_balance(&self, address: &str, block: BlockTag) -> Result<String, Error>;
#[method(name = "getTransactionCount")]
async fn get_transaction_count(&self, address: &str, block: BlockTag) -> Result<String, Error>;
#[method(name = "getBlockTransactionCountByHash")]
async fn get_block_transaction_count_by_hash(&self, hash: &str) -> Result<String, Error>;
#[method(name = "getBlockTransactionCountByNumber")]
async fn get_block_transaction_count_by_number(&self, block: BlockTag)
-> Result<String, Error>;
#[method(name = "getCode")]
async fn get_code(&self, address: &str, block: BlockTag) -> Result<String, Error>;
#[method(name = "call")]
@ -133,6 +138,23 @@ impl EthRpcServer for RpcInner {
Ok(format!("0x{nonce:x}"))
}
async fn get_block_transaction_count_by_hash(&self, hash: &str) -> Result<String, Error> {
let hash = convert_err(hex_str_to_bytes(hash))?;
let node = self.node.read().await;
let transaction_count = convert_err(node.get_block_transaction_count_by_hash(&hash))?;
Ok(u64_to_hex_string(transaction_count))
}
async fn get_block_transaction_count_by_number(
&self,
block: BlockTag,
) -> Result<String, Error> {
let node = self.node.read().await;
let transaction_count = convert_err(node.get_block_transaction_count_by_number(block))?;
Ok(u64_to_hex_string(transaction_count))
}
async fn get_code(&self, address: &str, block: BlockTag) -> Result<String, Error> {
let address = convert_err(Address::from_str(address))?;
let node = self.node.read().await;

View File

@ -9,7 +9,7 @@ use helios::{client::ClientBuilder, config::networks::Network, types::BlockTag};
async fn main() -> Result<()> {
env_logger::Builder::from_env(Env::default().default_filter_or("info")).init();
let untrusted_rpc_url = "https://mainnet.infura.io/v3/<YOUR_API_KEY>";
let untrusted_rpc_url = "https://eth-mainnet.g.alchemy.com/v2/<YOUR_API_KEY>";
log::info!("Using untrusted RPC URL [REDACTED]");
let consensus_rpc = "https://www.lightclientdata.org";

6
rpc.md
View File

@ -7,7 +7,7 @@ Helios provides a variety of RPC methods for interacting with the Ethereum netwo
| RPC Method | Client Function | Description | Example |
| ---------- | --------------- | ----------- | ------- |
| `eth_getBalance` | `get_balance` | Returns the balance of the account given an address. | `client.get_balance(&self, address: &str, block: BlockTag)` |
| `eth_getTransactionCount` | `get_transaction_count` | Returns the number of transactions sent from the given address. | `client.get_transaction_count(&self, address: &str, block: BlockTag)` |
| `eth_getTransactionCount` | `get_nonce` | Returns the number of transactions sent from the given address. | `client.get_nonce(&self, address: &str, block: BlockTag)` |
| `eth_getCode` | `get_code` | Returns the code at a given address. | `client.get_code(&self, address: &str, block: BlockTag)` |
| `eth_call` | `call` | Executes a new message call immediately without creating a transaction on the blockchain. | `client.call(&self, opts: CallOpts, block: BlockTag)` |
| `eth_estimateGas` | `estimate_gas` | Generates and returns an estimate of how much gas is necessary to allow the transaction to complete. | `client.estimate_gas(&self, opts: CallOpts)` |
@ -20,4 +20,6 @@ Helios provides a variety of RPC methods for interacting with the Ethereum netwo
| `eth_sendRawTransaction` | `send_raw_transaction` | Submits a raw transaction to the network. | `client.send_raw_transaction(&self, bytes: &str)` |
| `eth_getTransactionReceipt` | `get_transaction_receipt` | Returns the receipt of a transaction by transaction hash. | `client.get_transaction_receipt(&self, hash: &str)` |
| `eth_getLogs` | `get_logs` | Returns an array of logs matching the filter. | `client.get_logs(&self, filter: Filter)` |
| `eth_getStorageAt` | `get_storage_at` | Returns the value from a storage position at a given address. | `client.get_storage_at(&self, address: &str, slot: H256, block: BlockTag)` |
| `eth_getStorageAt` | `get_storage_at` | Returns the value from a storage position at a given address. | `client.get_storage_at(&self, address: &str, slot: H256, block: BlockTag)` |
| `eth_getBlockTransactionCountByHash` | `get_block_transaction_count_by_hash` | Returns the number of transactions in a block from a block matching the transaction hash. | `client.get_block_transaction_count_by_hash(&self, hash: &str)` |
| `eth_getBlockTransactionCountByNumber` | `get_block_transaction_count_by_number` | Returns the number of transactions in a block from a block matching the block number. | `client.get_block_transaction_count_by_number(&self, block: BlockTag)` |