diff --git a/CHANGELOG.md b/CHANGELOG.md index f8404b43a57..cd6fd75e1c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,8 @@ ### Changed +- [#6897](https://github.com/ChainSafe/forest/pull/6897): Integrated EC finality into Eth RPC methods. + - [#6821](https://github.com/ChainSafe/forest/pull/6821): Added message receipt size and event size to `forest-tool archive info` output. - [#6830](https://github.com/ChainSafe/forest/pull/6830): Make base fee FIP-0115 activation configurable via `FOREST_FEES_FIP0115HEIGHT` environment variable. The FIP will NOT be automatically activated on the next network upgrade with this change, for now. diff --git a/src/rpc/methods/chain.rs b/src/rpc/methods/chain.rs index cfb86e22ed7..91e35470ae9 100644 --- a/src/rpc/methods/chain.rs +++ b/src/rpc/methods/chain.rs @@ -1070,26 +1070,9 @@ impl ChainGetTipSetV2 { pub async fn get_latest_finalized_tipset( ctx: &Ctx, ) -> anyhow::Result { - let Some(f3_finalized_head) = ctx.chain_store().f3_finalized_tipset() else { - return Self::get_ec_finalized_tipset(ctx); - }; - let head = ctx.chain_store().heaviest_tipset(); - // Latest F3 finalized tipset is older than EC finality, falling back to EC finality - if head.epoch() > f3_finalized_head.epoch() + ctx.chain_config().policy.chain_finality { - Self::get_ec_finalized_tipset(ctx) - } else { - Ok(f3_finalized_head) - } - } - - pub fn get_ec_finalized_tipset(ctx: &Ctx) -> anyhow::Result { - let head = ctx.chain_store().heaviest_tipset(); - let ec_finality_epoch = (head.epoch() - ctx.chain_config().policy.chain_finality).max(0); - Ok(ctx.chain_index().tipset_by_height( - ec_finality_epoch, - head, - ResolveNullTipset::TakeOlder, - )?) + ChainGetTipSetFinalityStatus::get_finality_status(ctx) + .finalized_tip_set + .context("failed to resolve finalized tipset") } pub async fn get_tipset( @@ -1146,7 +1129,7 @@ impl ChainGetTipSetFinalityStatus { pub fn get_finality_status(ctx: &Ctx) -> ChainFinalityStatus { let head = ctx.chain_store().heaviest_tipset(); let (ec_finality_threshold_depth, ec_finalized_tip_set) = - Self::get_ec_finality_threshold_depth_and_tipset_with_cache(ctx, head.clone()); + Self::get_ec_finality_threshold_depth_and_tipset_with_cache(ctx, head.shallow_clone()); let f3_finalized_tip_set = ctx.chain_store().f3_finalized_tipset(); let finalized_tip_set = match (&ec_finalized_tip_set, &f3_finalized_tip_set) { (Some(ec), Some(f3)) => { @@ -1169,7 +1152,7 @@ impl ChainGetTipSetFinalityStatus { } } - fn get_ec_finality_threshold_depth_and_tipset_with_cache( + pub fn get_ec_finality_threshold_depth_and_tipset_with_cache( ctx: &Ctx, head: Tipset, ) -> (i64, Option) { @@ -1208,7 +1191,7 @@ impl ChainGetTipSetFinalityStatus { let finality = ctx.chain_config().policy.chain_finality; let chain_len = finality as usize + FINALITY_CHAIN_EXTRA_EPOCHS; let mut chain = Vec::with_capacity(chain_len); - let mut ts = head.clone(); + let mut ts = head.shallow_clone(); while chain.len() < chain_len { chain.push(ts.len() as i64); if let Ok(parent) = ctx.chain_index().load_required_tipset(ts.parents()) { @@ -1245,12 +1228,16 @@ impl ChainGetTipSetFinalityStatus { let finalized = if depth >= 0 && let Ok(ts) = ctx.chain_index().tipset_by_height( (head.epoch() - depth).max(0), - head, + head.shallow_clone(), ResolveNullTipset::TakeOlder, ) { - Some(ts.shallow_clone()) + Some(ts) } else { - None + let ec_finality_epoch = + (head.epoch() - ctx.chain_config().policy.chain_finality).max(0); + ctx.chain_index() + .tipset_by_height(ec_finality_epoch, head, ResolveNullTipset::TakeOlder) + .ok() }; (depth, finalized) } diff --git a/src/rpc/methods/eth.rs b/src/rpc/methods/eth.rs index 00c7899668e..3966c8e5b7b 100644 --- a/src/rpc/methods/eth.rs +++ b/src/rpc/methods/eth.rs @@ -6,7 +6,7 @@ mod eth_tx; pub mod filter; pub mod pubsub; pub(crate) mod pubsub_trait; -mod tipset_resolver; +pub mod tipset_resolver; pub(crate) mod trace; pub mod types; mod utils; diff --git a/src/rpc/methods/eth/tipset_resolver.rs b/src/rpc/methods/eth/tipset_resolver.rs index 8ac6158ff04..acdbd595934 100644 --- a/src/rpc/methods/eth/tipset_resolver.rs +++ b/src/rpc/methods/eth/tipset_resolver.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0, MIT use super::*; -use crate::rpc::chain::SAFE_HEIGHT_DISTANCE; +use crate::rpc::chain::{ChainGetTipSetFinalityStatus, SAFE_HEIGHT_DISTANCE}; pub struct TipsetResolver<'a, DB> where @@ -167,17 +167,14 @@ where )?) } - /// Returns the tipset considered finalized by expected-consensus finality. - /// - /// The finalized epoch is computed as head.epoch() minus the chain's `policy.chain_finality`, clamped to zero. The tipset at that epoch is returned; when the exact height is unavailable, an older tipset is selected. + /// Returns the tipset considered finalized by the expected-consensus finality calculator(`FRC-0089`). pub fn get_ec_finalized_tipset(&self) -> anyhow::Result { let head = self.ctx.chain_store().heaviest_tipset(); - let ec_finality_epoch = - (head.epoch() - self.ctx.chain_config().policy.chain_finality).max(0); - Ok(self.ctx.chain_index().tipset_by_height( - ec_finality_epoch, - head, - ResolveNullTipset::TakeOlder, - )?) + let (_, ec_finalized_tipset) = + ChainGetTipSetFinalityStatus::get_ec_finality_threshold_depth_and_tipset_with_cache( + self.ctx, + head.clone(), + ); + ec_finalized_tipset.context("failed to resolve EC finalized tipset") } } diff --git a/src/tool/subcommands/api_cmd/api_compare_tests.rs b/src/tool/subcommands/api_cmd/api_compare_tests.rs index da5a70f63fe..6255e1451e3 100644 --- a/src/tool/subcommands/api_cmd/api_compare_tests.rs +++ b/src/tool/subcommands/api_cmd/api_compare_tests.rs @@ -490,6 +490,7 @@ fn chain_tests(offline: bool) -> Vec { } else { RpcTest::identity(ChainGetTipSetFinalityStatus::request(()).unwrap()) }, + RpcTest::basic(ChainGetFinalizedTipset::request(()).unwrap()), ] } @@ -567,7 +568,6 @@ fn chain_tests_with_tipset( .clone() .into(),))?), RpcTest::identity(ChainTipSetWeight::request((tipset.key().into(),))?), - RpcTest::basic(ChainGetFinalizedTipset::request(())?), ]; if !offline { diff --git a/src/tool/subcommands/api_cmd/test_snapshots.txt b/src/tool/subcommands/api_cmd/test_snapshots.txt index a1ae73b00ce..bf6f1c03665 100644 --- a/src/tool/subcommands/api_cmd/test_snapshots.txt +++ b/src/tool/subcommands/api_cmd/test_snapshots.txt @@ -5,7 +5,7 @@ filecoin_chaingetevents_1764864316078100.rpcsnap.json.zst filecoin_chaingetevents_1765289237680041.rpcsnap.json.zst filecoin_chaingetevents_1765289237680294.rpcsnap.json.zst filecoin_chaingetevents_1765289237681455.rpcsnap.json.zst -filecoin_chaingetfinalizedtipset_1759828121342574.rpcsnap.json.zst +filecoin_chaingetfinalizedtipset_1776082510830037.rpcsnap.json.zst filecoin_chaingetgenesis_1736937286915866.rpcsnap.json.zst filecoin_chaingetmessage_1758734340836824.rpcsnap.json.zst filecoin_chaingetmessagesintipset_1758734696116136.rpcsnap.json.zst @@ -108,7 +108,7 @@ filecoin_ethgettransactionbyhash_1741272955520821.rpcsnap.json.zst filecoin_ethgettransactionbyhashlimited_1741272955509708.rpcsnap.json.zst filecoin_ethgettransactioncount_1740132538183426.rpcsnap.json.zst filecoin_ethgettransactioncount_v1_unknown_addr_1770288294132251.rpcsnap.json.zst -filecoin_ethgettransactioncount_v2_1767847407595348.rpcsnap.json.zst +filecoin_ethgettransactioncount_v2_1776080971678636.rpcsnap.json.zst filecoin_ethgettransactioncount_v2_unknown_addr_1770288294132366.rpcsnap.json.zst filecoin_ethgettransactionhashbycid_1737446676698540.rpcsnap.json.zst filecoin_ethgettransactionreceipt_1741272955712904.rpcsnap.json.zst