Skip to content

Commit

Permalink
feat: implement StateVMCirculatingSupplyInternal and validate against…
Browse files Browse the repository at this point in the history
… Lotus (#3773)
  • Loading branch information
elmattic authored Dec 1, 2023
1 parent 3f25ce8 commit 69f3a06
Show file tree
Hide file tree
Showing 9 changed files with 87 additions and 9 deletions.
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

0 comments on commit 69f3a06

Please sign in to comment.