From f496aedca61c9b57141159d990fd40ee20cdbfa7 Mon Sep 17 00:00:00 2001 From: hanabi1224 Date: Wed, 11 Dec 2024 20:45:14 +0800 Subject: [PATCH] feat(tool): forest-tool api generate-test-snapshot --- src/chain/store/index.rs | 13 +- src/rpc/mod.rs | 393 +++++++++--------- src/rpc/reflect/mod.rs | 26 +- src/tool/subcommands/api_cmd.rs | 29 ++ .../api_cmd/generate_test_snapshot.rs | 125 ++++++ 5 files changed, 375 insertions(+), 211 deletions(-) create mode 100644 src/tool/subcommands/api_cmd/generate_test_snapshot.rs diff --git a/src/chain/store/index.rs b/src/chain/store/index.rs index a9383e396e32..17d59dceceb5 100644 --- a/src/chain/store/index.rs +++ b/src/chain/store/index.rs @@ -7,6 +7,7 @@ use crate::beacon::{BeaconEntry, IGNORE_DRAND_VAR}; use crate::blocks::{Tipset, TipsetKey}; use crate::metrics; use crate::shim::clock::ChainEpoch; +use crate::utils::misc::env::is_env_truthy; use fvm_ipld_blockstore::Blockstore; use itertools::Itertools; use lru::LruCache; @@ -47,11 +48,13 @@ impl ChainIndex { /// Loads a tipset from memory given the tipset keys and cache. Semantically /// identical to [`Tipset::load`] but the result is cached. pub fn load_tipset(&self, tsk: &TipsetKey) -> Result>, Error> { - if let Some(ts) = self.ts_cache.lock().get(tsk) { - metrics::LRU_CACHE_HIT - .get_or_create(&metrics::values::TIPSET) - .inc(); - return Ok(Some(ts.clone())); + if !is_env_truthy("FOREST_TIPSET_CACHE_DISABLED") { + if let Some(ts) = self.ts_cache.lock().get(tsk) { + metrics::LRU_CACHE_HIT + .get_or_create(&metrics::values::TIPSET) + .inc(); + return Ok(Some(ts.clone())); + } } let ts_opt = Tipset::load(&self.db, tsk)?.map(Arc::new); diff --git a/src/rpc/mod.rs b/src/rpc/mod.rs index cb1c9856f0e9..f5244f081bb3 100644 --- a/src/rpc/mod.rs +++ b/src/rpc/mod.rs @@ -31,237 +31,238 @@ pub use jsonrpsee::core::ClientError; /// trait. /// /// All methods should be entered here. +#[macro_export] macro_rules! for_each_method { ($callback:path) => { // auth vertical - $callback!(crate::rpc::auth::AuthNew); - $callback!(crate::rpc::auth::AuthVerify); + $callback!($crate::rpc::auth::AuthNew); + $callback!($crate::rpc::auth::AuthVerify); // beacon vertical - $callback!(crate::rpc::beacon::BeaconGetEntry); + $callback!($crate::rpc::beacon::BeaconGetEntry); // chain vertical - $callback!(crate::rpc::chain::ChainExport); - $callback!(crate::rpc::chain::ChainGetBlock); - $callback!(crate::rpc::chain::ChainGetBlockMessages); - $callback!(crate::rpc::chain::ChainGetEvents); - $callback!(crate::rpc::chain::ChainGetGenesis); - $callback!(crate::rpc::chain::ChainGetMessage); - $callback!(crate::rpc::chain::ChainGetMessagesInTipset); - $callback!(crate::rpc::chain::ChainGetMinBaseFee); - $callback!(crate::rpc::chain::ChainGetParentMessages); - $callback!(crate::rpc::chain::ChainGetParentReceipts); - $callback!(crate::rpc::chain::ChainGetPath); - $callback!(crate::rpc::chain::ChainGetTipSet); - $callback!(crate::rpc::chain::ChainGetTipSetAfterHeight); - $callback!(crate::rpc::chain::ChainGetTipSetByHeight); - $callback!(crate::rpc::chain::ChainHasObj); - $callback!(crate::rpc::chain::ChainHead); - $callback!(crate::rpc::chain::ChainReadObj); - $callback!(crate::rpc::chain::ChainSetHead); - $callback!(crate::rpc::chain::ChainStatObj); - $callback!(crate::rpc::chain::ChainTipSetWeight); + $callback!($crate::rpc::chain::ChainExport); + $callback!($crate::rpc::chain::ChainGetBlock); + $callback!($crate::rpc::chain::ChainGetBlockMessages); + $callback!($crate::rpc::chain::ChainGetEvents); + $callback!($crate::rpc::chain::ChainGetGenesis); + $callback!($crate::rpc::chain::ChainGetMessage); + $callback!($crate::rpc::chain::ChainGetMessagesInTipset); + $callback!($crate::rpc::chain::ChainGetMinBaseFee); + $callback!($crate::rpc::chain::ChainGetParentMessages); + $callback!($crate::rpc::chain::ChainGetParentReceipts); + $callback!($crate::rpc::chain::ChainGetPath); + $callback!($crate::rpc::chain::ChainGetTipSet); + $callback!($crate::rpc::chain::ChainGetTipSetAfterHeight); + $callback!($crate::rpc::chain::ChainGetTipSetByHeight); + $callback!($crate::rpc::chain::ChainHasObj); + $callback!($crate::rpc::chain::ChainHead); + $callback!($crate::rpc::chain::ChainReadObj); + $callback!($crate::rpc::chain::ChainSetHead); + $callback!($crate::rpc::chain::ChainStatObj); + $callback!($crate::rpc::chain::ChainTipSetWeight); // common vertical - $callback!(crate::rpc::common::Session); - $callback!(crate::rpc::common::Shutdown); - $callback!(crate::rpc::common::StartTime); - $callback!(crate::rpc::common::Version); + $callback!($crate::rpc::common::Session); + $callback!($crate::rpc::common::Shutdown); + $callback!($crate::rpc::common::StartTime); + $callback!($crate::rpc::common::Version); // eth vertical - $callback!(crate::rpc::eth::EthAccounts); - $callback!(crate::rpc::eth::EthAddressToFilecoinAddress); - $callback!(crate::rpc::eth::EthBlockNumber); - $callback!(crate::rpc::eth::EthCall); - $callback!(crate::rpc::eth::EthChainId); - $callback!(crate::rpc::eth::EthEstimateGas); - $callback!(crate::rpc::eth::EthFeeHistory); - $callback!(crate::rpc::eth::EthGasPrice); - $callback!(crate::rpc::eth::EthGetBalance); - $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); - $callback!(crate::rpc::eth::EthGetLogs); - $callback!(crate::rpc::eth::EthGetMessageCidByTransactionHash); - $callback!(crate::rpc::eth::EthGetStorageAt); - $callback!(crate::rpc::eth::EthGetTransactionByHash); - $callback!(crate::rpc::eth::EthGetTransactionByHashLimited); - $callback!(crate::rpc::eth::EthGetTransactionCount); - $callback!(crate::rpc::eth::EthGetTransactionHashByCid); - $callback!(crate::rpc::eth::EthGetTransactionByBlockNumberAndIndex); - $callback!(crate::rpc::eth::EthGetTransactionByBlockHashAndIndex); - $callback!(crate::rpc::eth::EthMaxPriorityFeePerGas); - $callback!(crate::rpc::eth::EthProtocolVersion); - $callback!(crate::rpc::eth::EthGetTransactionReceipt); - $callback!(crate::rpc::eth::EthGetTransactionReceiptLimited); - $callback!(crate::rpc::eth::EthNewFilter); - $callback!(crate::rpc::eth::EthNewPendingTransactionFilter); - $callback!(crate::rpc::eth::EthNewBlockFilter); - $callback!(crate::rpc::eth::EthUninstallFilter); - $callback!(crate::rpc::eth::EthSyncing); - $callback!(crate::rpc::eth::Web3ClientVersion); - $callback!(crate::rpc::eth::EthSendRawTransaction); + $callback!($crate::rpc::eth::EthAccounts); + $callback!($crate::rpc::eth::EthAddressToFilecoinAddress); + $callback!($crate::rpc::eth::EthBlockNumber); + $callback!($crate::rpc::eth::EthCall); + $callback!($crate::rpc::eth::EthChainId); + $callback!($crate::rpc::eth::EthEstimateGas); + $callback!($crate::rpc::eth::EthFeeHistory); + $callback!($crate::rpc::eth::EthGasPrice); + $callback!($crate::rpc::eth::EthGetBalance); + $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); + $callback!($crate::rpc::eth::EthGetLogs); + $callback!($crate::rpc::eth::EthGetMessageCidByTransactionHash); + $callback!($crate::rpc::eth::EthGetStorageAt); + $callback!($crate::rpc::eth::EthGetTransactionByHash); + $callback!($crate::rpc::eth::EthGetTransactionByHashLimited); + $callback!($crate::rpc::eth::EthGetTransactionCount); + $callback!($crate::rpc::eth::EthGetTransactionHashByCid); + $callback!($crate::rpc::eth::EthGetTransactionByBlockNumberAndIndex); + $callback!($crate::rpc::eth::EthGetTransactionByBlockHashAndIndex); + $callback!($crate::rpc::eth::EthMaxPriorityFeePerGas); + $callback!($crate::rpc::eth::EthProtocolVersion); + $callback!($crate::rpc::eth::EthGetTransactionReceipt); + $callback!($crate::rpc::eth::EthGetTransactionReceiptLimited); + $callback!($crate::rpc::eth::EthNewFilter); + $callback!($crate::rpc::eth::EthNewPendingTransactionFilter); + $callback!($crate::rpc::eth::EthNewBlockFilter); + $callback!($crate::rpc::eth::EthUninstallFilter); + $callback!($crate::rpc::eth::EthSyncing); + $callback!($crate::rpc::eth::Web3ClientVersion); + $callback!($crate::rpc::eth::EthSendRawTransaction); // gas vertical - $callback!(crate::rpc::gas::GasEstimateFeeCap); - $callback!(crate::rpc::gas::GasEstimateGasLimit); - $callback!(crate::rpc::gas::GasEstimateGasPremium); - $callback!(crate::rpc::gas::GasEstimateMessageGas); + $callback!($crate::rpc::gas::GasEstimateFeeCap); + $callback!($crate::rpc::gas::GasEstimateGasLimit); + $callback!($crate::rpc::gas::GasEstimateGasPremium); + $callback!($crate::rpc::gas::GasEstimateMessageGas); // market vertical - $callback!(crate::rpc::market::MarketAddBalance); + $callback!($crate::rpc::market::MarketAddBalance); // miner vertical - $callback!(crate::rpc::miner::MinerCreateBlock); - $callback!(crate::rpc::miner::MinerGetBaseInfo); + $callback!($crate::rpc::miner::MinerCreateBlock); + $callback!($crate::rpc::miner::MinerGetBaseInfo); // mpool vertical - $callback!(crate::rpc::mpool::MpoolBatchPush); - $callback!(crate::rpc::mpool::MpoolBatchPushUntrusted); - $callback!(crate::rpc::mpool::MpoolGetNonce); - $callback!(crate::rpc::mpool::MpoolPending); - $callback!(crate::rpc::mpool::MpoolPush); - $callback!(crate::rpc::mpool::MpoolPushMessage); - $callback!(crate::rpc::mpool::MpoolPushUntrusted); - $callback!(crate::rpc::mpool::MpoolSelect); + $callback!($crate::rpc::mpool::MpoolBatchPush); + $callback!($crate::rpc::mpool::MpoolBatchPushUntrusted); + $callback!($crate::rpc::mpool::MpoolGetNonce); + $callback!($crate::rpc::mpool::MpoolPending); + $callback!($crate::rpc::mpool::MpoolPush); + $callback!($crate::rpc::mpool::MpoolPushMessage); + $callback!($crate::rpc::mpool::MpoolPushUntrusted); + $callback!($crate::rpc::mpool::MpoolSelect); // msig vertical - $callback!(crate::rpc::msig::MsigGetAvailableBalance); - $callback!(crate::rpc::msig::MsigGetPending); - $callback!(crate::rpc::msig::MsigGetVested); - $callback!(crate::rpc::msig::MsigGetVestingSchedule); + $callback!($crate::rpc::msig::MsigGetAvailableBalance); + $callback!($crate::rpc::msig::MsigGetPending); + $callback!($crate::rpc::msig::MsigGetVested); + $callback!($crate::rpc::msig::MsigGetVestingSchedule); // net vertical - $callback!(crate::rpc::net::NetAddrsListen); - $callback!(crate::rpc::net::NetAgentVersion); - $callback!(crate::rpc::net::NetAutoNatStatus); - $callback!(crate::rpc::net::NetConnect); - $callback!(crate::rpc::net::NetDisconnect); - $callback!(crate::rpc::net::NetFindPeer); - $callback!(crate::rpc::net::NetInfo); - $callback!(crate::rpc::net::NetListening); - $callback!(crate::rpc::net::NetPeers); - $callback!(crate::rpc::net::NetProtectAdd); - $callback!(crate::rpc::net::NetProtectList); - $callback!(crate::rpc::net::NetProtectRemove); - $callback!(crate::rpc::net::NetVersion); + $callback!($crate::rpc::net::NetAddrsListen); + $callback!($crate::rpc::net::NetAgentVersion); + $callback!($crate::rpc::net::NetAutoNatStatus); + $callback!($crate::rpc::net::NetConnect); + $callback!($crate::rpc::net::NetDisconnect); + $callback!($crate::rpc::net::NetFindPeer); + $callback!($crate::rpc::net::NetInfo); + $callback!($crate::rpc::net::NetListening); + $callback!($crate::rpc::net::NetPeers); + $callback!($crate::rpc::net::NetProtectAdd); + $callback!($crate::rpc::net::NetProtectList); + $callback!($crate::rpc::net::NetProtectRemove); + $callback!($crate::rpc::net::NetVersion); // node vertical - $callback!(crate::rpc::node::NodeStatus); + $callback!($crate::rpc::node::NodeStatus); // state vertical - $callback!(crate::rpc::state::StateAccountKey); - $callback!(crate::rpc::state::StateCall); - $callback!(crate::rpc::state::StateCirculatingSupply); - $callback!(crate::rpc::state::StateCompute); - $callback!(crate::rpc::state::StateDealProviderCollateralBounds); - $callback!(crate::rpc::state::StateFetchRoot); - $callback!(crate::rpc::state::StateGetActor); - $callback!(crate::rpc::state::StateGetAllAllocations); - $callback!(crate::rpc::state::StateGetAllClaims); - $callback!(crate::rpc::state::StateGetAllocation); - $callback!(crate::rpc::state::StateGetAllocationForPendingDeal); - $callback!(crate::rpc::state::StateGetAllocationIdForPendingDeal); - $callback!(crate::rpc::state::StateGetAllocations); - $callback!(crate::rpc::state::StateGetBeaconEntry); - $callback!(crate::rpc::state::StateGetClaim); - $callback!(crate::rpc::state::StateGetClaims); - $callback!(crate::rpc::state::StateGetNetworkParams); - $callback!(crate::rpc::state::StateGetRandomnessDigestFromBeacon); - $callback!(crate::rpc::state::StateGetRandomnessDigestFromTickets); - $callback!(crate::rpc::state::StateGetRandomnessFromBeacon); - $callback!(crate::rpc::state::StateGetRandomnessFromTickets); - $callback!(crate::rpc::state::StateGetReceipt); - $callback!(crate::rpc::state::StateListActors); - $callback!(crate::rpc::state::StateListMessages); - $callback!(crate::rpc::state::StateListMiners); - $callback!(crate::rpc::state::StateLookupID); - $callback!(crate::rpc::state::StateLookupRobustAddress); - $callback!(crate::rpc::state::StateMarketBalance); - $callback!(crate::rpc::state::StateMarketDeals); - $callback!(crate::rpc::state::StateMarketParticipants); - $callback!(crate::rpc::state::StateMarketStorageDeal); - $callback!(crate::rpc::state::StateMinerActiveSectors); - $callback!(crate::rpc::state::StateMinerAllocated); - $callback!(crate::rpc::state::StateMinerAvailableBalance); - $callback!(crate::rpc::state::StateMinerDeadlines); - $callback!(crate::rpc::state::StateMinerFaults); - $callback!(crate::rpc::state::StateMinerInfo); - $callback!(crate::rpc::state::StateMinerInitialPledgeCollateral); - $callback!(crate::rpc::state::StateMinerPartitions); - $callback!(crate::rpc::state::StateMinerPower); - $callback!(crate::rpc::state::StateMinerPreCommitDepositForPower); - $callback!(crate::rpc::state::StateMinerProvingDeadline); - $callback!(crate::rpc::state::StateMinerRecoveries); - $callback!(crate::rpc::state::StateMinerSectorAllocated); - $callback!(crate::rpc::state::StateMinerSectorCount); - $callback!(crate::rpc::state::StateMinerSectors); - $callback!(crate::rpc::state::StateNetworkName); - $callback!(crate::rpc::state::StateNetworkVersion); - $callback!(crate::rpc::state::StateReadState); - $callback!(crate::rpc::state::StateReplay); - $callback!(crate::rpc::state::StateSearchMsg); - $callback!(crate::rpc::state::StateSearchMsgLimited); - $callback!(crate::rpc::state::StateSectorExpiration); - $callback!(crate::rpc::state::StateSectorGetInfo); - $callback!(crate::rpc::state::StateSectorPartition); - $callback!(crate::rpc::state::StateSectorPreCommitInfo); - $callback!(crate::rpc::state::StateSectorPreCommitInfoV0); - $callback!(crate::rpc::state::StateVerifiedClientStatus); - $callback!(crate::rpc::state::StateVerifiedRegistryRootKey); - $callback!(crate::rpc::state::StateVerifierStatus); - $callback!(crate::rpc::state::StateVMCirculatingSupplyInternal); - $callback!(crate::rpc::state::StateWaitMsg); - $callback!(crate::rpc::state::StateWaitMsgV0); + $callback!($crate::rpc::state::StateAccountKey); + $callback!($crate::rpc::state::StateCall); + $callback!($crate::rpc::state::StateCirculatingSupply); + $callback!($crate::rpc::state::StateCompute); + $callback!($crate::rpc::state::StateDealProviderCollateralBounds); + $callback!($crate::rpc::state::StateFetchRoot); + $callback!($crate::rpc::state::StateGetActor); + $callback!($crate::rpc::state::StateGetAllAllocations); + $callback!($crate::rpc::state::StateGetAllClaims); + $callback!($crate::rpc::state::StateGetAllocation); + $callback!($crate::rpc::state::StateGetAllocationForPendingDeal); + $callback!($crate::rpc::state::StateGetAllocationIdForPendingDeal); + $callback!($crate::rpc::state::StateGetAllocations); + $callback!($crate::rpc::state::StateGetBeaconEntry); + $callback!($crate::rpc::state::StateGetClaim); + $callback!($crate::rpc::state::StateGetClaims); + $callback!($crate::rpc::state::StateGetNetworkParams); + $callback!($crate::rpc::state::StateGetRandomnessDigestFromBeacon); + $callback!($crate::rpc::state::StateGetRandomnessDigestFromTickets); + $callback!($crate::rpc::state::StateGetRandomnessFromBeacon); + $callback!($crate::rpc::state::StateGetRandomnessFromTickets); + $callback!($crate::rpc::state::StateGetReceipt); + $callback!($crate::rpc::state::StateListActors); + $callback!($crate::rpc::state::StateListMessages); + $callback!($crate::rpc::state::StateListMiners); + $callback!($crate::rpc::state::StateLookupID); + $callback!($crate::rpc::state::StateLookupRobustAddress); + $callback!($crate::rpc::state::StateMarketBalance); + $callback!($crate::rpc::state::StateMarketDeals); + $callback!($crate::rpc::state::StateMarketParticipants); + $callback!($crate::rpc::state::StateMarketStorageDeal); + $callback!($crate::rpc::state::StateMinerActiveSectors); + $callback!($crate::rpc::state::StateMinerAllocated); + $callback!($crate::rpc::state::StateMinerAvailableBalance); + $callback!($crate::rpc::state::StateMinerDeadlines); + $callback!($crate::rpc::state::StateMinerFaults); + $callback!($crate::rpc::state::StateMinerInfo); + $callback!($crate::rpc::state::StateMinerInitialPledgeCollateral); + $callback!($crate::rpc::state::StateMinerPartitions); + $callback!($crate::rpc::state::StateMinerPower); + $callback!($crate::rpc::state::StateMinerPreCommitDepositForPower); + $callback!($crate::rpc::state::StateMinerProvingDeadline); + $callback!($crate::rpc::state::StateMinerRecoveries); + $callback!($crate::rpc::state::StateMinerSectorAllocated); + $callback!($crate::rpc::state::StateMinerSectorCount); + $callback!($crate::rpc::state::StateMinerSectors); + $callback!($crate::rpc::state::StateNetworkName); + $callback!($crate::rpc::state::StateNetworkVersion); + $callback!($crate::rpc::state::StateReadState); + $callback!($crate::rpc::state::StateReplay); + $callback!($crate::rpc::state::StateSearchMsg); + $callback!($crate::rpc::state::StateSearchMsgLimited); + $callback!($crate::rpc::state::StateSectorExpiration); + $callback!($crate::rpc::state::StateSectorGetInfo); + $callback!($crate::rpc::state::StateSectorPartition); + $callback!($crate::rpc::state::StateSectorPreCommitInfo); + $callback!($crate::rpc::state::StateSectorPreCommitInfoV0); + $callback!($crate::rpc::state::StateVerifiedClientStatus); + $callback!($crate::rpc::state::StateVerifiedRegistryRootKey); + $callback!($crate::rpc::state::StateVerifierStatus); + $callback!($crate::rpc::state::StateVMCirculatingSupplyInternal); + $callback!($crate::rpc::state::StateWaitMsg); + $callback!($crate::rpc::state::StateWaitMsgV0); // sync vertical - $callback!(crate::rpc::sync::SyncCheckBad); - $callback!(crate::rpc::sync::SyncMarkBad); - $callback!(crate::rpc::sync::SyncState); - $callback!(crate::rpc::sync::SyncSubmitBlock); + $callback!($crate::rpc::sync::SyncCheckBad); + $callback!($crate::rpc::sync::SyncMarkBad); + $callback!($crate::rpc::sync::SyncState); + $callback!($crate::rpc::sync::SyncSubmitBlock); // wallet vertical - $callback!(crate::rpc::wallet::WalletBalance); - $callback!(crate::rpc::wallet::WalletDefaultAddress); - $callback!(crate::rpc::wallet::WalletDelete); - $callback!(crate::rpc::wallet::WalletExport); - $callback!(crate::rpc::wallet::WalletHas); - $callback!(crate::rpc::wallet::WalletImport); - $callback!(crate::rpc::wallet::WalletList); - $callback!(crate::rpc::wallet::WalletNew); - $callback!(crate::rpc::wallet::WalletSetDefault); - $callback!(crate::rpc::wallet::WalletSign); - $callback!(crate::rpc::wallet::WalletSignMessage); - $callback!(crate::rpc::wallet::WalletValidateAddress); - $callback!(crate::rpc::wallet::WalletVerify); + $callback!($crate::rpc::wallet::WalletBalance); + $callback!($crate::rpc::wallet::WalletDefaultAddress); + $callback!($crate::rpc::wallet::WalletDelete); + $callback!($crate::rpc::wallet::WalletExport); + $callback!($crate::rpc::wallet::WalletHas); + $callback!($crate::rpc::wallet::WalletImport); + $callback!($crate::rpc::wallet::WalletList); + $callback!($crate::rpc::wallet::WalletNew); + $callback!($crate::rpc::wallet::WalletSetDefault); + $callback!($crate::rpc::wallet::WalletSign); + $callback!($crate::rpc::wallet::WalletSignMessage); + $callback!($crate::rpc::wallet::WalletValidateAddress); + $callback!($crate::rpc::wallet::WalletVerify); // f3 - $callback!(crate::rpc::f3::F3GetCertificate); - $callback!(crate::rpc::f3::F3GetECPowerTable); - $callback!(crate::rpc::f3::F3GetF3PowerTable); - $callback!(crate::rpc::f3::F3IsRunning); - $callback!(crate::rpc::f3::F3GetProgress); - $callback!(crate::rpc::f3::F3GetManifest); - $callback!(crate::rpc::f3::F3ListParticipants); - $callback!(crate::rpc::f3::F3GetLatestCertificate); - $callback!(crate::rpc::f3::F3GetOrRenewParticipationTicket); - $callback!(crate::rpc::f3::F3Participate); - $callback!(crate::rpc::f3::GetHead); - $callback!(crate::rpc::f3::GetParent); - $callback!(crate::rpc::f3::GetParticipatingMinerIDs); - $callback!(crate::rpc::f3::GetPowerTable); - $callback!(crate::rpc::f3::GetTipset); - $callback!(crate::rpc::f3::GetTipsetByEpoch); - $callback!(crate::rpc::f3::Finalize); - $callback!(crate::rpc::f3::ProtectPeer); - $callback!(crate::rpc::f3::SignMessage); + $callback!($crate::rpc::f3::F3GetCertificate); + $callback!($crate::rpc::f3::F3GetECPowerTable); + $callback!($crate::rpc::f3::F3GetF3PowerTable); + $callback!($crate::rpc::f3::F3IsRunning); + $callback!($crate::rpc::f3::F3GetProgress); + $callback!($crate::rpc::f3::F3GetManifest); + $callback!($crate::rpc::f3::F3ListParticipants); + $callback!($crate::rpc::f3::F3GetLatestCertificate); + $callback!($crate::rpc::f3::F3GetOrRenewParticipationTicket); + $callback!($crate::rpc::f3::F3Participate); + $callback!($crate::rpc::f3::GetHead); + $callback!($crate::rpc::f3::GetParent); + $callback!($crate::rpc::f3::GetParticipatingMinerIDs); + $callback!($crate::rpc::f3::GetPowerTable); + $callback!($crate::rpc::f3::GetTipset); + $callback!($crate::rpc::f3::GetTipsetByEpoch); + $callback!($crate::rpc::f3::Finalize); + $callback!($crate::rpc::f3::ProtectPeer); + $callback!($crate::rpc::f3::SignMessage); // misc - $callback!(crate::rpc::misc::GetActorEventsRaw); + $callback!($crate::rpc::misc::GetActorEventsRaw); }; } pub(crate) use for_each_method; diff --git a/src/rpc/reflect/mod.rs b/src/rpc/reflect/mod.rs index 5d4f789a2220..026f710bf95c 100644 --- a/src/rpc/reflect/mod.rs +++ b/src/rpc/reflect/mod.rs @@ -150,6 +150,21 @@ pub trait RpcMethodExt: RpcMethod { )), } } + + fn parse_params( + params_raw: Option>, + calling_convention: ParamStructure, + ) -> anyhow::Result { + Ok(Self::Params::parse( + params_raw + .map(|s| serde_json::from_str(s.as_ref())) + .transpose()?, + Self::PARAM_NAMES, + calling_convention, + Self::N_REQUIRED_PARAMS, + )?) + } + /// Generate a full `OpenRPC` method definition for this endpoint. fn openrpc<'de>( gen: &mut SchemaGenerator, @@ -214,17 +229,8 @@ pub trait RpcMethodExt: RpcMethod { ); module.register_async_method(Self::NAME, move |params, ctx, _extensions| async move { - let raw = params - .as_str() - .map(serde_json::from_str) - .transpose() + let params = Self::parse_params(params.as_str(), calling_convention) .map_err(|e| Error::invalid_params(e, None))?; - let params = Self::Params::parse( - raw, - Self::PARAM_NAMES, - calling_convention, - Self::N_REQUIRED_PARAMS, - )?; let ok = Self::handle(ctx, params).await?; Result::<_, jsonrpsee::types::ErrorObjectOwned>::Ok(ok.into_lotus_json()) }) diff --git a/src/tool/subcommands/api_cmd.rs b/src/tool/subcommands/api_cmd.rs index 5bcc3cae821f..5527324e8a87 100644 --- a/src/tool/subcommands/api_cmd.rs +++ b/src/tool/subcommands/api_cmd.rs @@ -1,6 +1,8 @@ // Copyright 2019-2024 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT +mod generate_test_snapshot; + use crate::blocks::{ElectionProof, Ticket, Tipset}; use crate::db::car::ManyCar; use crate::eth::{EthChainId as EthChainIdType, SAFE_EPOCH_DELAY}; @@ -143,6 +145,16 @@ pub enum ApiCommands { #[arg(long)] dump_dir: Option, }, + GenerateTestSnapshot { + #[arg(num_args = 1.., required = true)] + test_dump_files: Vec, + /// Path to the database folder that powers a Forest node + #[arg(long, required = true)] + db: PathBuf, + /// Filecoin network chain + #[arg(long, required = true)] + chain: NetworkChain, + }, DumpTests { #[command(flatten)] create_tests_args: CreateTestsArgs, @@ -217,6 +229,23 @@ impl ApiCommands { .await?; } } + Self::GenerateTestSnapshot { + test_dump_files, + db, + chain, + } => { + // + for test_dump_file in test_dump_files { + let test_dump = serde_json::from_reader(std::fs::File::open(&test_dump_file)?)?; + print!( + "Running RPC test with snapshot {} ...", + test_dump_file.display() + ); + generate_test_snapshot::run_test_with_dump(&test_dump, &db, &chain).await?; + println!(" Success"); + } + } + Self::DumpTests { create_tests_args, path, diff --git a/src/tool/subcommands/api_cmd/generate_test_snapshot.rs b/src/tool/subcommands/api_cmd/generate_test_snapshot.rs new file mode 100644 index 000000000000..296fb5e91344 --- /dev/null +++ b/src/tool/subcommands/api_cmd/generate_test_snapshot.rs @@ -0,0 +1,125 @@ +// Copyright 2019-2024 ChainSafe Systems +// SPDX-License-Identifier: Apache-2.0, MIT + +use super::*; +use crate::{ + chain::ChainStore, + chain_sync::{network_context::SyncNetworkContext, SyncConfig, SyncStage}, + daemon::db_util::load_all_forest_cars, + db::{db_engine::open_db, parity_db::ParityDb, CAR_DB_DIR_NAME}, + genesis::{get_network_name_from_genesis, read_genesis_header}, + libp2p::{NetworkMessage, PeerManager}, + message_pool::{MessagePool, MpoolRpcProvider}, + networks::ChainConfig, + shim::address::CurrentNetwork, + state_manager::StateManager, + KeyStore, KeyStoreConfig, +}; +use fvm_shared4::address::Network; +use openrpc_types::ParamStructure; +use parking_lot::RwLock; +use rpc::{eth::filter::EthEventHandler, RPCState, RpcMethod as _}; +use tokio::{sync::mpsc, task::JoinSet}; + +pub async fn run_test_with_dump( + test_dump: &TestDump, + db_root: &Path, + chain: &NetworkChain, +) -> anyhow::Result<()> { + if chain.is_testnet() { + CurrentNetwork::set_global(Network::Testnet); + } + let mut run = false; + let chain_config = Arc::new(ChainConfig::calibnet()); + let db = load_db(db_root)?; + let (ctx, _, _) = ctx(db, chain_config).await?; + let params_raw = Some(serde_json::to_string(&test_dump.request.params)?); + + macro_rules! run_test { + ($ty:ty) => { + if test_dump.request.method_name.as_ref() == <$ty>::NAME { + let params = <$ty>::parse_params(params_raw.clone(), ParamStructure::Either)?; + let result = <$ty>::handle(ctx.clone(), params).await?; + assert_eq!( + test_dump.forest_response, + Ok(result.into_lotus_json_value()?) + ); + run = true; + } + }; + } + + crate::for_each_method!(run_test); + + assert!(run, "RPC method not found"); + + Ok(()) +} + +fn load_db(db_root: &Path) -> anyhow::Result>>> { + let db_writer = Arc::new(open_db(db_root.into(), Default::default())?); + let db = Arc::new(ManyCar::new(db_writer.clone())); + let forest_car_db_dir = db_root.join(CAR_DB_DIR_NAME); + load_all_forest_cars(&db, &forest_car_db_dir)?; + Ok(db) +} + +async fn ctx( + db: Arc>>, + chain_config: Arc, +) -> anyhow::Result<( + Arc>>>, + flume::Receiver, + tokio::sync::mpsc::Receiver<()>, +)> { + let (network_send, network_rx) = flume::bounded(5); + let (tipset_send, _) = flume::bounded(5); + let sync_config = Arc::new(SyncConfig::default()); + let genesis_header = + read_genesis_header(None, chain_config.genesis_bytes(&db).await?.as_deref(), &db).await?; + + let chain_store = Arc::new( + ChainStore::new( + db.clone(), + db.clone(), + db, + chain_config.clone(), + genesis_header.clone(), + ) + .unwrap(), + ); + + let state_manager = + Arc::new(StateManager::new(chain_store.clone(), chain_config, sync_config).unwrap()); + let network_name = get_network_name_from_genesis(&genesis_header, &state_manager)?; + let message_pool = MessagePool::new( + MpoolRpcProvider::new(chain_store.publisher().clone(), state_manager.clone()), + network_name.clone(), + network_send.clone(), + Default::default(), + state_manager.chain_config().clone(), + &mut JoinSet::new(), + )?; + + let peer_manager = Arc::new(PeerManager::default()); + let sync_network_context = + SyncNetworkContext::new(network_send, peer_manager, state_manager.blockstore_owned()); + let (shutdown, shutdown_recv) = mpsc::channel(1); + let rpc_state = Arc::new(RPCState { + state_manager, + keystore: Arc::new(tokio::sync::RwLock::new(KeyStore::new( + KeyStoreConfig::Memory, + )?)), + mpool: Arc::new(message_pool), + bad_blocks: Default::default(), + sync_state: Arc::new(RwLock::new(Default::default())), + eth_event_handler: Arc::new(EthEventHandler::new()), + sync_network_context, + network_name, + start_time: chrono::Utc::now(), + shutdown, + tipset_send, + }); + rpc_state.sync_state.write().set_stage(SyncStage::Idle); + Ok((rpc_state, network_rx, shutdown_recv)) +}