Skip to content

Commit

Permalink
feat: implement EthGetBlockReceiptsLimited RPC method (#5018)
Browse files Browse the repository at this point in the history
Co-authored-by: hanabi1224 <harlowmoo@gmail.com>
  • Loading branch information
virajbhartiya and hanabi1224 authored Nov 29, 2024
1 parent 3d6ea59 commit bcc13b0
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 31 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ for more details.
- [#4839](https://github.com/ChainSafe/forest/issues/4839) Add support for the
`Filecoin.EthGetBlockReceipts` RPC method.

- [#5017](https://github.com/ChainSafe/forest/issues/5017) Add support for the
`Filecoin.EthGetBlockReceiptsLimited` RPC method.

- [#4943](https://github.com/ChainSafe/forest/pull/4943) Add generation of
method aliases for `forest-tool shed openrpc` subcommand and sort all methods
in lexicographic order.
Expand Down
94 changes: 63 additions & 31 deletions src/rpc/methods/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1280,6 +1280,51 @@ impl RpcMethod<2> for EthGetBlockByNumber {
}
}

async fn get_block_receipts<DB: Blockstore + Send + Sync + 'static>(
ctx: &Ctx<DB>,
block_hash: EthHash,
limit: Option<usize>,
) -> Result<Vec<EthTxReceipt>, ServerError> {
let ts = get_tipset_from_hash(ctx.chain_store(), &block_hash)?;
let ts_ref = Arc::new(ts);
let ts_key = ts_ref.key();
let (state_root, msgs_and_receipts) = execute_tipset(ctx, &ts_ref).await?;

let msgs_and_receipts = if let Some(limit) = limit {
msgs_and_receipts.into_iter().take(limit).collect()
} else {
msgs_and_receipts
};

let mut receipts = Vec::with_capacity(msgs_and_receipts.len());
let state = StateTree::new_from_root(ctx.store_owned(), &state_root)?;

for (i, (msg, receipt)) in msgs_and_receipts.into_iter().enumerate() {
let return_dec = receipt.return_data().deserialize().unwrap_or(Ipld::Null);

let message_lookup = MessageLookup {
receipt,
tipset: ts_key.clone(),
height: ts_ref.epoch(),
message: msg.cid(),
return_dec,
};

let tx = new_eth_tx(
ctx,
&state,
ts_ref.epoch(),
&ts_key.cid()?,
&msg.cid(),
i as u64,
)?;

let tx_receipt = new_eth_tx_receipt(ctx, &tx, &message_lookup).await?;
receipts.push(tx_receipt);
}
Ok(receipts)
}

pub enum EthGetBlockReceipts {}
impl RpcMethod<1> for EthGetBlockReceipts {
const NAME: &'static str = "Filecoin.EthGetBlockReceipts";
Expand All @@ -1294,38 +1339,25 @@ impl RpcMethod<1> for EthGetBlockReceipts {
ctx: Ctx<impl Blockstore + Send + Sync + 'static>,
(block_hash,): Self::Params,
) -> Result<Self::Ok, ServerError> {
let ts = get_tipset_from_hash(ctx.chain_store(), &block_hash)?;
let ts_ref = Arc::new(ts);
let ts_key = ts_ref.key();
let (state_root, msgs_and_receipts) = execute_tipset(&ctx, &ts_ref).await?;
let mut receipts = Vec::with_capacity(msgs_and_receipts.len());

let state = StateTree::new_from_root(ctx.store_owned(), &state_root)?;

for (i, (msg, receipt)) in msgs_and_receipts.into_iter().enumerate() {
let return_dec = receipt.return_data().deserialize().unwrap_or(Ipld::Null);

let message_lookup = MessageLookup {
receipt,
tipset: ts_key.clone(),
height: ts_ref.epoch(),
message: msg.cid(),
return_dec,
};
get_block_receipts(&ctx, block_hash, None).await
}
}

let tx = new_eth_tx(
&ctx,
&state,
ts_ref.epoch(),
&ts_key.cid()?,
&msg.cid(),
i as u64,
)?;

let tx_receipt = new_eth_tx_receipt(&ctx, &tx, &message_lookup).await?;
receipts.push(tx_receipt);
}
Ok(receipts)
pub enum EthGetBlockReceiptsLimited {}
impl RpcMethod<2> for EthGetBlockReceiptsLimited {
const NAME: &'static str = "Filecoin.EthGetBlockReceiptsLimited";
const NAME_ALIAS: Option<&'static str> = Some("eth_getBlockReceiptsLimited");
const PARAM_NAMES: [&'static str; 2] = ["block_hash", "limit"];
const API_PATHS: ApiPaths = ApiPaths::V1;
const PERMISSION: Permission = Permission::Read;
type Params = (EthHash, EthUint64);
type Ok = Vec<EthTxReceipt>;

async fn handle(
ctx: Ctx<impl Blockstore + Send + Sync + 'static>,
(block_hash, EthUint64(limit)): Self::Params,
) -> Result<Self::Ok, ServerError> {
get_block_receipts(&ctx, block_hash, Some(limit as usize)).await
}
}

Expand Down
1 change: 1 addition & 0 deletions src/rpc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ macro_rules! for_each_method {
$callback!(crate::rpc::eth::EthGetBlockByHash);
$callback!(crate::rpc::eth::EthGetBlockByNumber);
$callback!(crate::rpc::eth::EthGetBlockReceipts);
$callback!(crate::rpc::eth::EthGetBlockReceiptsLimited);
$callback!(crate::rpc::eth::EthGetBlockTransactionCountByHash);
$callback!(crate::rpc::eth::EthGetBlockTransactionCountByNumber);
$callback!(crate::rpc::eth::EthGetCode);
Expand Down
3 changes: 3 additions & 0 deletions src/tool/subcommands/api_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1443,6 +1443,9 @@ fn eth_tests_with_tipset<DB: Blockstore>(store: &Arc<DB>, shared_tipset: &Tipset
RpcTest::identity(
EthGetBlockTransactionCountByHash::request((block_hash.clone(),)).unwrap(),
),
RpcTest::identity(
EthGetBlockReceiptsLimited::request((block_hash.clone(), EthUint64(800))).unwrap(),
),
RpcTest::identity(
EthGetBlockTransactionCountByNumber::request((EthInt64(shared_tipset.epoch()),))
.unwrap(),
Expand Down

0 comments on commit bcc13b0

Please sign in to comment.