Skip to content

Commit

Permalink
Add txpool RPC and impl new_pending_transaction_filter (#1073)
Browse files Browse the repository at this point in the history
* Add new filter type

* Add txpool client side

* Fix node compile

* Fix rpc

* Dev filter_changes

* Add feature and format

* Use sp_core::hashing

* Fix clippy

* Format code

* Add pending transaction polling ts tests

* Add txpool ts-test

* Fix clippy CI

* Fix review

* Remove `TxPoolRuntimeApi`

* Clean trait bound

* Clean trait bound

* Remove feature `txpool`
  • Loading branch information
boundless-forest authored Jun 25, 2023
1 parent 433d8f7 commit 406c6c7
Show file tree
Hide file tree
Showing 15 changed files with 565 additions and 31 deletions.
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.

2 changes: 2 additions & 0 deletions client/rpc-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@ pub mod types;
mod eth;
mod eth_pubsub;
mod net;
mod txpool;
mod web3;

pub use self::{
eth::{EthApiServer, EthFilterApiServer},
eth_pubsub::EthPubSubApiServer,
net::NetApiServer,
txpool::TxPoolApiServer,
web3::Web3ApiServer,
};
37 changes: 37 additions & 0 deletions client/rpc-core/src/txpool.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
// This file is part of Frontier.
//
// Copyright (c) 2015-2022 Parity Technologies (UK) Ltd.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

//! tx pool rpc interface

use ethereum_types::U256;
use jsonrpsee::{core::RpcResult, proc_macros::rpc};
// Frontier
use crate::types::*;

/// TxPool rpc interface
#[rpc(server)]
pub trait TxPoolApi {
#[method(name = "txpool_content")]
fn content(&self) -> RpcResult<TxPoolResult<TransactionMap<TxPoolTransaction>>>;

#[method(name = "txpool_inspect")]
fn inspect(&self) -> RpcResult<TxPoolResult<TransactionMap<Summary>>>;

#[method(name = "txpool_status")]
fn status(&self) -> RpcResult<TxPoolResult<U256>>;
}
3 changes: 2 additions & 1 deletion client/rpc-core/src/types/filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use std::{
collections::BTreeMap,
collections::{BTreeMap, HashSet},
sync::{Arc, Mutex},
};

Expand Down Expand Up @@ -460,6 +460,7 @@ pub struct FilterPoolItem {
pub last_poll: BlockNumber,
pub filter_type: FilterType,
pub at_block: u64,
pub pending_transaction_hashes: HashSet<H256>,
}

/// On-memory stored filters created through the `eth_newFilter` RPC.
Expand Down
2 changes: 2 additions & 0 deletions client/rpc-core/src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ mod receipt;
mod sync;
mod transaction;
mod transaction_request;
mod txpool;
mod work;

pub mod pubsub;
Expand All @@ -55,5 +56,6 @@ pub use self::{
},
transaction::{LocalTransactionStatus, RichRawTransaction, Transaction},
transaction_request::{TransactionMessage, TransactionRequest},
txpool::{Get, Summary, TransactionMap, TxPoolResult, TxPoolTransaction},
work::Work,
};
170 changes: 170 additions & 0 deletions client/rpc-core/src/types/txpool.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
// This file is part of Frontier.
//
// Copyright (c) 2015-2022 Parity Technologies (UK) Ltd.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use std::collections::HashMap;

use ethereum::{TransactionAction, TransactionV2 as EthereumTransaction};
use ethereum_types::{H160, H256, U256};
use serde::{Serialize, Serializer};
// Frontier
use crate::types::Bytes;

pub type TransactionMap<T> = HashMap<H160, HashMap<U256, T>>;

pub trait Get {
fn get(hash: H256, from_address: H160, txn: &EthereumTransaction) -> Self;
}

#[derive(Debug, Serialize)]
pub struct TxPoolResult<T: Serialize> {
pub pending: T,
pub queued: T,
}

#[derive(Clone, Debug)]
pub struct Summary {
pub to: Option<H160>,
pub value: U256,
pub gas: U256,
pub gas_price: U256,
}

impl Serialize for Summary {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let res = format!(
"0x{:x}: {} wei + {} gas x {} wei",
self.to.unwrap_or_default(),
self.value,
self.gas,
self.gas_price
);
serializer.serialize_str(&res)
}
}

impl Get for Summary {
fn get(_hash: H256, _from_address: H160, txn: &EthereumTransaction) -> Self {
let (action, value, gas_price, gas_limit) = match txn {
EthereumTransaction::Legacy(t) => (t.action, t.value, t.gas_price, t.gas_limit),
EthereumTransaction::EIP2930(t) => (t.action, t.value, t.gas_price, t.gas_limit),
EthereumTransaction::EIP1559(t) => (t.action, t.value, t.max_fee_per_gas, t.gas_limit),
};
Self {
to: match action {
TransactionAction::Call(to) => Some(to),
_ => None,
},
value,
gas_price,
gas: gas_limit,
}
}
}

#[derive(Debug, Default, Clone, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct TxPoolTransaction {
/// Hash
pub hash: H256,
/// Nonce
pub nonce: U256,
/// Block hash
#[serde(serialize_with = "block_hash_serialize")]
pub block_hash: Option<H256>,
/// Block number
pub block_number: Option<U256>,
/// Sender
pub from: H160,
/// Recipient
#[serde(serialize_with = "to_serialize")]
pub to: Option<H160>,
/// Transfered value
pub value: U256,
/// Gas Price
pub gas_price: U256,
/// Gas
pub gas: U256,
/// Data
pub input: Bytes,
/// Transaction Index
pub transaction_index: Option<U256>,
}

fn block_hash_serialize<S>(hash: &Option<H256>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&format!("0x{:x}", hash.unwrap_or_default()))
}

fn to_serialize<S>(hash: &Option<H160>, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&format!("0x{:x}", hash.unwrap_or_default()))
}

impl Get for TxPoolTransaction {
fn get(hash: H256, from_address: H160, txn: &EthereumTransaction) -> Self {
let (nonce, action, value, gas_price, gas_limit, input) = match txn {
EthereumTransaction::Legacy(t) => (
t.nonce,
t.action,
t.value,
t.gas_price,
t.gas_limit,
t.input.clone(),
),
EthereumTransaction::EIP2930(t) => (
t.nonce,
t.action,
t.value,
t.gas_price,
t.gas_limit,
t.input.clone(),
),
EthereumTransaction::EIP1559(t) => (
t.nonce,
t.action,
t.value,
t.max_fee_per_gas,
t.gas_limit,
t.input.clone(),
),
};
Self {
hash,
nonce,
block_hash: None,
block_number: None,
from: from_address,
to: match action {
TransactionAction::Call(to) => Some(to),
_ => None,
},
value,
gas_price,
gas: gas_limit,
input: Bytes(input),
transaction_index: None,
}
}
}
1 change: 1 addition & 0 deletions client/rpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ prometheus = { version = "0.13.1", default-features = false }
rand = "0.8"
rlp = { workspace = true }
scale-codec = { package = "parity-scale-codec", workspace = true }
serde = { workspace = true }
tokio = { version = "1.24", features = ["sync"] }

# Substrate
Expand Down
Loading

0 comments on commit 406c6c7

Please sign in to comment.