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: implement StateVMCirculatingSupplyInternal and validate against Lotus #3773

Merged
merged 9 commits into from
Dec 1, 2023
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@

### Added

- [#3773](https://github.com/ChainSafe/forest/pull/3773) Implement the
`Filecoin.StateVMCirculatingSupplyInternal` lotus-compatible RPC API.
- [#3748](https://github.com/ChainSafe/forest/pull/3748) Add timing for each
message and gas charge in the JSON output of
`forest-tool snapshot compute-state` and `Filecoin.StateCall` RPC API.
Expand Down
4 changes: 4 additions & 0 deletions src/rpc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@ where
)
.with_method(STATE_READ_STATE, state_read_state::<DB>)
.with_method(STATE_SECTOR_GET_INFO, state_sector_get_info::<DB>)
.with_method(
STATE_VM_CIRCULATING_SUPPLY_INTERNAL,
state_vm_circulating_supply_internal::<DB>,
)
// Gas API
.with_method(GAS_ESTIMATE_FEE_CAP, gas_estimate_fee_cap::<DB>)
.with_method(GAS_ESTIMATE_GAS_LIMIT, gas_estimate_gas_limit::<DB>)
Expand Down
22 changes: 20 additions & 2 deletions src/rpc/state_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ use crate::cid_collections::CidHashSet;
use crate::libp2p::NetworkMessage;
use crate::lotus_json::LotusJson;
use crate::rpc_api::data_types::{
ApiActorState, ApiDeadline, ApiInvocResult, MarketDeal, MessageLookup, RPCState,
SectorOnChainInfo,
ApiActorState, ApiDeadline, ApiInvocResult, CirculatingSupply, MarketDeal, MessageLookup,
RPCState, SectorOnChainInfo,
};
use crate::shim::{
address::Address, clock::ChainEpoch, executor::Receipt, message::Message,
state_tree::ActorState, version::NetworkVersion,
};
use crate::state_manager::chain_rand::ChainRand;
use crate::state_manager::vm_circ_supply::GenesisInfo;
use crate::state_manager::{InvocResult, MarketBalance};
use crate::utils::db::car_stream::{CarBlock, CarWriter};
use ahash::{HashMap, HashMapExt};
Expand Down Expand Up @@ -586,3 +587,20 @@ pub(in crate::rpc) async fn state_sector_get_info<DB: Blockstore + Send + Sync +
.ok_or(format!("Info for sector number {sector_no} not found"))?,
))
}

pub(in crate::rpc) async fn state_vm_circulating_supply_internal<
DB: Blockstore + Send + Sync + 'static,
>(
data: Data<RPCState<DB>>,
Params(LotusJson((tsk,))): Params<LotusJson<(TipsetKeys,)>>,
) -> Result<LotusJson<CirculatingSupply>, JsonRpcError> {
let ts = data.chain_store.load_required_tipset(&tsk)?;

let genesis_info = GenesisInfo::from_chain_config(data.state_manager.chain_config());

Ok(LotusJson(genesis_info.get_vm_circulating_supply_detailed(
ts.epoch(),
&data.state_manager.blockstore_owned(),
ts.parent_state(),
)?))
}
19 changes: 19 additions & 0 deletions src/rpc_api/data_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -763,3 +763,22 @@ impl PartialEq for GasTrace {
&& self.storage_gas == other.storage_gas
}
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct CirculatingSupply {
#[serde(with = "crate::lotus_json")]
pub fil_vested: TokenAmount,
#[serde(with = "crate::lotus_json")]
pub fil_mined: TokenAmount,
#[serde(with = "crate::lotus_json")]
pub fil_burnt: TokenAmount,
#[serde(with = "crate::lotus_json")]
pub fil_locked: TokenAmount,
#[serde(with = "crate::lotus_json")]
pub fil_circulating: TokenAmount,
#[serde(with = "crate::lotus_json")]
pub fil_reserve_disbursed: TokenAmount,
}

lotus_json_with_self!(CirculatingSupply);
6 changes: 6 additions & 0 deletions src/rpc_api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ pub static ACCESS_MAP: Lazy<HashMap<&str, Access>> = Lazy::new(|| {
access.insert(state_api::STATE_GET_RANDOMNESS_FROM_BEACON, Access::Read);
access.insert(state_api::STATE_READ_STATE, Access::Read);
access.insert(state_api::STATE_SECTOR_GET_INFO, Access::Read);
access.insert(
state_api::STATE_VM_CIRCULATING_SUPPLY_INTERNAL,
Access::Read,
);

// Gas API
access.insert(gas_api::GAS_ESTIMATE_GAS_LIMIT, Access::Read);
Expand Down Expand Up @@ -257,6 +261,8 @@ pub mod state_api {
pub const STATE_SECTOR_GET_INFO: &str = "Filecoin.StateSectorGetInfo";
pub const STATE_SEARCH_MSG: &str = "Filecoin.StateSearchMsg";
pub const STATE_SEARCH_MSG_LIMITED: &str = "Filecoin.StateSearchMsgLimited";
pub const STATE_VM_CIRCULATING_SUPPLY_INTERNAL: &str =
"Filecoin.StateVMCirculatingSupplyInternal";
}

/// Gas API
Expand Down
9 changes: 8 additions & 1 deletion src/rpc_client/state_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ use crate::{
blocks::TipsetKeys,
rpc_api::{
data_types::{
ApiActorState, ApiDeadline, ApiInvocResult, MessageLookup, SectorOnChainInfo,
ApiActorState, ApiDeadline, ApiInvocResult, CirculatingSupply, MessageLookup,
SectorOnChainInfo,
},
state_api::*,
},
Expand Down Expand Up @@ -134,6 +135,12 @@ impl ApiInfo {
RpcRequest::new(STATE_CIRCULATING_SUPPLY, (tsk,))
}

pub fn state_vm_circulating_supply_internal_req(
tsk: TipsetKeys,
) -> RpcRequest<CirculatingSupply> {
RpcRequest::new(STATE_VM_CIRCULATING_SUPPLY_INTERNAL, (tsk,))
}

pub fn state_decode_params_req(
recipient: Address,
method_number: MethodNum,
Expand Down
2 changes: 1 addition & 1 deletion src/state_manager/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use anyhow::{bail, Context as _};
use fil_actor_interface::init::{self, State};
use rayon::prelude::ParallelBridge;
pub use utils::is_valid_for_sending;
mod vm_circ_supply;
pub mod vm_circ_supply;
pub use self::errors::*;
use crate::beacon::BeaconSchedule;
use crate::blocks::{Tipset, TipsetKeys};
Expand Down
29 changes: 24 additions & 5 deletions src/state_manager/vm_circ_supply.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use std::sync::Arc;

use crate::chain::*;
use crate::networks::{ChainConfig, Height};
use crate::rpc_api::data_types::CirculatingSupply;
use crate::shim::{
address::Address,
clock::{ChainEpoch, EPOCHS_IN_DAY},
Expand Down Expand Up @@ -36,7 +37,7 @@ const CALICO_VESTING: [(ChainEpoch, usize); 6] = [

/// Genesis information used when calculating circulating supply.
#[derive(Default, Clone)]
pub(in crate::state_manager) struct GenesisInfo {
pub struct GenesisInfo {
vesting: GenesisInfoVesting,

/// info about the Accounts in the genesis state
Expand Down Expand Up @@ -71,22 +72,40 @@ impl GenesisInfo {
db: &Arc<DB>,
root: &Cid,
) -> Result<TokenAmount, anyhow::Error> {
let detailed = self.get_vm_circulating_supply_detailed(height, db, root)?;

Ok(detailed.fil_circulating)
}

pub fn get_vm_circulating_supply_detailed<DB: Blockstore>(
&self,
height: ChainEpoch,
db: &Arc<DB>,
root: &Cid,
) -> anyhow::Result<CirculatingSupply> {
let state_tree = StateTree::new_from_root(Arc::clone(db), root)?;

let fil_vested = get_fil_vested(self, height);
let fil_mined = get_fil_mined(&state_tree)?;
let fil_burnt = get_fil_burnt(&state_tree)?;
let fil_locked = get_fil_locked(&state_tree)?;
let fil_reserve_distributed = if height > self.actors_v2_height {
let fil_reserve_disbursed = if height > self.actors_v2_height {
get_fil_reserve_disbursed(&state_tree)?
} else {
TokenAmount::default()
};
let fil_circulating = TokenAmount::max(
&fil_vested + &fil_mined + &fil_reserve_distributed - &fil_burnt - &fil_locked,
&fil_vested + &fil_mined + &fil_reserve_disbursed - &fil_burnt - &fil_locked,
TokenAmount::default(),
);

Ok(fil_circulating)
Ok(CirculatingSupply {
fil_vested,
fil_mined,
fil_burnt,
fil_locked,
fil_circulating,
fil_reserve_disbursed,
})
}
}

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 @@ -440,6 +440,9 @@ fn snapshot_tests(store: &ManyCar, n_tipsets: usize) -> anyhow::Result<Vec<RpcTe
tests.push(RpcTest::basic(ApiInfo::state_circulating_supply_req(
tipset.key().clone(),
)));
tests.push(RpcTest::identity(
ApiInfo::state_vm_circulating_supply_internal_req(tipset.key().clone()),
));

for block in tipset.blocks() {
let (bls_messages, secp_messages) = crate::chain::store::block_messages(&store, block)?;
Expand Down
Loading