diff --git a/src/cli/subcommands/chain_cmd.rs b/src/cli/subcommands/chain_cmd.rs index cb781119028a..c15bab97725c 100644 --- a/src/cli/subcommands/chain_cmd.rs +++ b/src/cli/subcommands/chain_cmd.rs @@ -7,6 +7,7 @@ use list::ChainListCommand; mod prune; use prune::ChainPruneCommands; +use super::print_pretty_lotus_json; use crate::blocks::{Tipset, TipsetKey}; use crate::lotus_json::HasLotusJson; use crate::message::ChainMessage; @@ -15,8 +16,7 @@ use anyhow::{bail, ensure}; use cid::Cid; use clap::Subcommand; use nunny::Vec as NonEmpty; - -use super::print_pretty_lotus_json; +use std::sync::Arc; #[derive(Debug, Clone, clap::ValueEnum)] pub enum Format { @@ -143,7 +143,7 @@ impl ChainCommands { async fn tipset_by_epoch_or_offset( client: &rpc::Client, epoch_or_offset: i64, -) -> Result { +) -> Result, jsonrpsee::core::ClientError> { let current_head = ChainHead::call(client, ()).await?; let target_epoch = match epoch_or_offset.is_negative() { diff --git a/src/cli/subcommands/f3_cmd.rs b/src/cli/subcommands/f3_cmd.rs index 2f2b29e04843..a788202adc95 100644 --- a/src/cli/subcommands/f3_cmd.rs +++ b/src/cli/subcommands/f3_cmd.rs @@ -6,7 +6,7 @@ mod tests; use std::{ borrow::Cow, - sync::LazyLock, + sync::{Arc, LazyLock}, time::{Duration, Instant}, }; @@ -151,7 +151,7 @@ impl F3Commands { async fn get_heads( client: &rpc::Client, - ) -> anyhow::Result<(Tipset, FinalityCertificate)> { + ) -> anyhow::Result<(Arc, FinalityCertificate)> { let cert_head = client.call(F3GetLatestCertificate::request(())?).await?; let chain_head = client.call(ChainHead::request(())?).await?; Ok((chain_head, cert_head)) diff --git a/src/lotus_json/arc.rs b/src/lotus_json/arc.rs new file mode 100644 index 000000000000..0c4fc7cf497d --- /dev/null +++ b/src/lotus_json/arc.rs @@ -0,0 +1,25 @@ +// Copyright 2019-2025 ChainSafe Systems +// SPDX-License-Identifier: Apache-2.0, MIT + +use super::*; +use std::sync::Arc; + +impl HasLotusJson for Arc { + type LotusJson = T::LotusJson; + + #[cfg(test)] + fn snapshots() -> Vec<(serde_json::Value, Self)> { + T::snapshots() + .into_iter() + .map(|(k, v)| (k, Arc::new(v))) + .collect() + } + + fn into_lotus_json(self) -> Self::LotusJson { + (*self).clone().into_lotus_json() + } + + fn from_lotus_json(lotus_json: Self::LotusJson) -> Self { + Arc::new(T::from_lotus_json(lotus_json)) + } +} diff --git a/src/lotus_json/mod.rs b/src/lotus_json/mod.rs index a20be0692645..6735a6e653f0 100644 --- a/src/lotus_json/mod.rs +++ b/src/lotus_json/mod.rs @@ -220,6 +220,7 @@ decl_and_test!( // but you MUST document any tech debt - the reason WHY it cannot be tested above. mod actors; mod allocation; +mod arc; mod beneficiary_term; // fil_actor_miner_state::v12::BeneficiaryTerm: !quickcheck::Arbitrary mod bit_field; // fil_actors_shared::fvm_ipld_bitfield::BitField: !quickcheck::Arbitrary mod bytecode_hash; diff --git a/src/rpc/methods/chain.rs b/src/rpc/methods/chain.rs index 108426bf82f5..d24a8b1573de 100644 --- a/src/rpc/methods/chain.rs +++ b/src/rpc/methods/chain.rs @@ -141,7 +141,7 @@ impl RpcMethod<0> for ChainGetFinalizedTipset { ); type Params = (); - type Ok = Tipset; + type Ok = Arc; async fn handle( ctx: Ctx, @@ -154,7 +154,7 @@ impl RpcMethod<0> for ChainGetFinalizedTipset { match get_f3_finality_tipset(&ctx, ec_finality_epoch).await { Ok(f3_tipset) => { tracing::debug!("Using F3 finalized tipset at epoch {}", f3_tipset.epoch()); - Ok((*f3_tipset).clone()) + Ok(f3_tipset) } Err(_) => { // fallback to ec finality @@ -164,7 +164,7 @@ impl RpcMethod<0> for ChainGetFinalizedTipset { head, ResolveNullTipset::TakeOlder, )?; - Ok((*ec_tipset).clone()) + Ok(ec_tipset) } } } @@ -867,7 +867,7 @@ impl RpcMethod<2> for ChainGetTipSetByHeight { const DESCRIPTION: Option<&'static str> = Some("Returns the tipset at the specified height."); type Params = (ChainEpoch, ApiTipsetKey); - type Ok = Tipset; + type Ok = Arc; async fn handle( ctx: Ctx, @@ -879,7 +879,7 @@ impl RpcMethod<2> for ChainGetTipSetByHeight { let tss = ctx .chain_index() .tipset_by_height(height, ts, ResolveNullTipset::TakeOlder)?; - Ok((*tss).clone()) + Ok(tss) } } @@ -896,7 +896,7 @@ impl RpcMethod<2> for ChainGetTipSetAfterHeight { ); type Params = (ChainEpoch, ApiTipsetKey); - type Ok = Tipset; + type Ok = Arc; async fn handle( ctx: Ctx, @@ -908,7 +908,7 @@ impl RpcMethod<2> for ChainGetTipSetAfterHeight { let tss = ctx .chain_index() .tipset_by_height(height, ts, ResolveNullTipset::TakeNewer)?; - Ok((*tss).clone()) + Ok(tss) } } @@ -937,11 +937,11 @@ impl RpcMethod<0> for ChainHead { const DESCRIPTION: Option<&'static str> = Some("Returns the chain head (heaviest tipset)."); type Params = (); - type Ok = Tipset; + type Ok = Arc; async fn handle(ctx: Ctx, (): Self::Params) -> Result { let heaviest = ctx.chain_store().heaviest_tipset(); - Ok((*heaviest).clone()) + Ok(heaviest) } } @@ -974,7 +974,7 @@ impl RpcMethod<1> for ChainGetTipSet { const DESCRIPTION: Option<&'static str> = Some("Returns the tipset with the specified CID."); type Params = (ApiTipsetKey,); - type Ok = Tipset; + type Ok = Arc; async fn handle( ctx: Ctx, @@ -983,7 +983,7 @@ impl RpcMethod<1> for ChainGetTipSet { let ts = ctx .chain_store() .load_required_tipset_or_heaviest(&tipset_key)?; - Ok((*ts).clone()) + Ok(ts) } } @@ -996,7 +996,7 @@ impl RpcMethod<1> for ChainGetTipSetV2 { const DESCRIPTION: Option<&'static str> = Some("Returns the tipset with the specified CID."); type Params = (ApiTipsetKey,); - type Ok = Tipset; + type Ok = Arc; async fn handle(_: Ctx, _: Self::Params) -> Result { Err(ServerError::unsupported_method()) @@ -1098,10 +1098,7 @@ pub(crate) fn chain_notify( let current = data.chain_store().heaviest_tipset(); let (change, tipset) = ("current".into(), current); sender - .send(vec![ApiHeadChange { - change, - tipset: tipset.as_ref().clone(), - }]) + .send(vec![ApiHeadChange { change, tipset }]) .expect("receiver is not dropped"); let mut subscriber = data.chain_store().publisher().subscribe(); @@ -1115,13 +1112,7 @@ pub(crate) fn chain_notify( HeadChange::Apply(ts) => ("apply".into(), ts), }; - if sender - .send(vec![ApiHeadChange { - change, - tipset: tipset.as_ref().clone(), - }]) - .is_err() - { + if sender.send(vec![ApiHeadChange { change, tipset }]).is_err() { break; } } @@ -1254,7 +1245,7 @@ pub struct ApiHeadChange { pub change: String, #[serde(rename = "Val", with = "crate::lotus_json")] #[schemars(with = "LotusJson")] - pub tipset: Tipset, + pub tipset: Arc, } lotus_json_with_self!(ApiHeadChange);