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

feat(rpc): add impls for gasprice and max priority fee #2471

Merged
merged 1 commit into from
Apr 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions crates/primitives/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,12 @@ impl SealedBlock {
}
}

impl From<SealedBlock> for Block {
fn from(block: SealedBlock) -> Self {
block.unseal()
}
}

impl Deref for SealedBlock {
type Target = SealedHeader;
fn deref(&self) -> &Self::Target {
Expand Down
8 changes: 4 additions & 4 deletions crates/rpc/rpc-api/src/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,10 @@ pub trait EthApi {
#[method(name = "eth_gasPrice")]
async fn gas_price(&self) -> Result<U256>;

/// Introduced in EIP-1159, returns suggestion for the priority for dynamic fee transactions.
#[method(name = "eth_maxPriorityFeePerGas")]
async fn max_priority_fee_per_gas(&self) -> Result<U256>;

/// Returns the Transaction fee history
///
/// Introduced in EIP-1159 for getting information on the appropriate priority fee to use.
Expand All @@ -191,10 +195,6 @@ pub trait EthApi {
reward_percentiles: Option<Vec<f64>>,
) -> Result<FeeHistory>;

/// Returns the current maxPriorityFeePerGas per gas in wei.
#[method(name = "eth_maxPriorityFeePerGas")]
async fn max_priority_fee_per_gas(&self) -> Result<U256>;

/// Returns whether the client is actively mining new blocks.
#[method(name = "eth_mining")]
async fn is_mining(&self) -> Result<bool>;
Expand Down
4 changes: 2 additions & 2 deletions crates/rpc/rpc-builder/tests/it/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,14 +97,14 @@ where
EthApiClient::send_transaction(client, transaction_request).await.unwrap_err();
EthApiClient::hashrate(client).await.unwrap();
EthApiClient::submit_hashrate(client, U256::default(), H256::default()).await.unwrap();
EthApiClient::gas_price(client).await.unwrap();
EthApiClient::max_priority_fee_per_gas(client).await.unwrap();

// Unimplemented
assert!(is_unimplemented(
EthApiClient::get_proof(client, address, vec![], None).await.err().unwrap()
));
assert!(is_unimplemented(EthApiClient::author(client).await.err().unwrap()));
assert!(is_unimplemented(EthApiClient::gas_price(client).await.err().unwrap()));
assert!(is_unimplemented(EthApiClient::max_priority_fee_per_gas(client).await.err().unwrap()));
assert!(is_unimplemented(EthApiClient::is_mining(client).await.err().unwrap()));
assert!(is_unimplemented(EthApiClient::get_work(client).await.err().unwrap()));
assert!(is_unimplemented(
Expand Down
35 changes: 26 additions & 9 deletions crates/rpc/rpc/src/eth/api/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,30 +56,47 @@ where
Ok(self.cache().get_block_transactions(block_hash).await?.map(|txs| txs.len()))
}

/// Returns the rpc block object for the given block id.
///
/// If `full` is true, the block object will contain all transaction objects, otherwise it will
/// only contain the transaction hashes.
/// Returns the block header for the given block id.
pub(crate) async fn header(
&self,
block_id: impl Into<BlockId>,
) -> EthResult<Option<reth_primitives::SealedHeader>> {
Ok(self.block(block_id).await?.map(|block| block.header))
}

/// Returns the block object for the given block id.
pub(crate) async fn block(
&self,
block_id: impl Into<BlockId>,
full: bool,
) -> EthResult<Option<RichBlock>> {
) -> EthResult<Option<reth_primitives::SealedBlock>> {
let block_id = block_id.into();
// TODO support pending block
let block_hash = match self.client().block_hash_for_id(block_id)? {
Some(block_hash) => block_hash,
None => return Ok(None),
};

let block = match self.cache().get_block(block_hash).await? {
Ok(self.cache().get_block(block_hash).await?.map(|block| block.seal(block_hash)))
}

/// Returns the populated rpc block object for the given block id.
///
/// If `full` is true, the block object will contain all transaction objects, otherwise it will
/// only contain the transaction hashes.
pub(crate) async fn rpc_block(
&self,
block_id: impl Into<BlockId>,
full: bool,
) -> EthResult<Option<RichBlock>> {
let block = match self.block(block_id).await? {
Some(block) => block,
None => return Ok(None),
};

let block_hash = block.hash;
let total_difficulty =
self.client().header_td(&block_hash)?.ok_or(EthApiError::UnknownBlockNumber)?;
let block = Block::from_block(block, total_difficulty, full.into(), Some(block_hash))?;
let block =
Block::from_block(block.into(), total_difficulty, full.into(), Some(block_hash))?;
Ok(Some(block.into()))
}
}
19 changes: 18 additions & 1 deletion crates/rpc/rpc/src/eth/api/fees.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{
EthApi,
};
use reth_network_api::NetworkInfo;
use reth_primitives::{BlockId, U256};
use reth_primitives::{BlockId, BlockNumberOrTag, U256};
use reth_provider::{BlockProvider, EvmEnvProvider, StateProviderFactory};
use reth_rpc_types::{FeeHistory, FeeHistoryCacheItem, TxGasAndReward};
use reth_transaction_pool::TransactionPool;
Expand All @@ -17,6 +17,23 @@ where
Client: BlockProvider + StateProviderFactory + EvmEnvProvider + 'static,
Network: NetworkInfo + Send + Sync + 'static,
{
/// Returns a suggestion for a gas price for legacy transactions.
///
/// See also: <https://github.com/ethereum/pm/issues/328#issuecomment-853234014>
pub(crate) async fn gas_price(&self) -> EthResult<U256> {
let header = self.block(BlockNumberOrTag::Latest);
let suggested_tip = self.suggested_priority_fee();
let (header, suggested_tip) = futures::try_join!(header, suggested_tip)?;
let base_fee = header.and_then(|h| h.base_fee_per_gas).unwrap_or_default();
Ok(suggested_tip + U256::from(base_fee))
}

/// Returns a suggestion for the priority fee (the tip)
pub(crate) async fn suggested_priority_fee(&self) -> EthResult<U256> {
// TODO: properly implement sampling https://github.com/ethereum/pm/issues/328#issuecomment-853234014
Ok(U256::from(1e9 as u64))
}

/// Reports the fee history, for the given amount of blocks, up until the newest block
/// provided.
pub(crate) async fn fee_history(
Expand Down
18 changes: 10 additions & 8 deletions crates/rpc/rpc/src/eth/api/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ where
/// Handler for: `eth_getBlockByHash`
async fn block_by_hash(&self, hash: H256, full: bool) -> Result<Option<RichBlock>> {
trace!(target: "rpc::eth", ?hash, ?full, "Serving eth_getBlockByHash");
Ok(EthApi::block(self, hash, full).await?)
Ok(EthApi::rpc_block(self, hash, full).await?)
}

/// Handler for: `eth_getBlockByNumber`
Expand All @@ -83,7 +83,7 @@ where
full: bool,
) -> Result<Option<RichBlock>> {
trace!(target: "rpc::eth", ?number, ?full, "Serving eth_getBlockByNumber");
Ok(EthApi::block(self, number, full).await?)
Ok(EthApi::rpc_block(self, number, full).await?)
}

/// Handler for: `eth_getBlockTransactionCountByHash`
Expand Down Expand Up @@ -248,7 +248,14 @@ where

/// Handler for: `eth_gasPrice`
async fn gas_price(&self) -> Result<U256> {
Err(internal_rpc_err("unimplemented"))
trace!(target: "rpc::eth", "Serving eth_gasPrice");
return Ok(EthApi::gas_price(self).await?)
}

/// Handler for: `eth_maxPriorityFeePerGas`
async fn max_priority_fee_per_gas(&self) -> Result<U256> {
trace!(target: "rpc::eth", "Serving eth_maxPriorityFeePerGas");
return Ok(EthApi::suggested_priority_fee(self).await?)
}

// FeeHistory is calculated based on lazy evaluation of fees for historical blocks, and further
Expand All @@ -271,11 +278,6 @@ where
.await?)
}

/// Handler for: `eth_maxPriorityFeePerGas`
async fn max_priority_fee_per_gas(&self) -> Result<U256> {
Err(internal_rpc_err("unimplemented"))
}

/// Handler for: `eth_mining`
async fn is_mining(&self) -> Result<bool> {
Err(internal_rpc_err("unimplemented"))
Expand Down