2019-08-20 16:48:33 +00:00
package full
import (
2019-10-22 19:29:05 +00:00
"bytes"
2019-08-20 16:48:33 +00:00
"context"
2019-10-22 19:29:05 +00:00
"strconv"
2019-09-03 04:36:07 +00:00
2019-09-19 20:25:18 +00:00
cid "github.com/ipfs/go-cid"
2020-02-04 22:19:05 +00:00
cbor "github.com/ipfs/go-ipld-cbor"
2019-09-16 20:11:17 +00:00
"go.uber.org/fx"
"golang.org/x/xerrors"
2019-12-19 20:13:17 +00:00
"github.com/filecoin-project/go-address"
2020-07-14 12:32:17 +00:00
"github.com/filecoin-project/go-bitfield"
2020-09-07 03:49:10 +00:00
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
2020-10-08 23:27:38 +00:00
"github.com/filecoin-project/go-state-types/dline"
"github.com/filecoin-project/go-state-types/network"
2020-08-17 13:26:18 +00:00
"github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper"
2020-06-26 13:49:39 +00:00
2019-10-18 04:47:41 +00:00
"github.com/filecoin-project/lotus/api"
2020-10-08 23:27:38 +00:00
"github.com/filecoin-project/lotus/chain/actors/builtin"
2020-09-17 07:32:10 +00:00
"github.com/filecoin-project/lotus/chain/actors/builtin/market"
2020-09-15 11:04:45 +00:00
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
2020-09-15 21:44:03 +00:00
"github.com/filecoin-project/lotus/chain/actors/builtin/multisig"
2020-09-15 23:47:58 +00:00
"github.com/filecoin-project/lotus/chain/actors/builtin/power"
"github.com/filecoin-project/lotus/chain/actors/builtin/reward"
2020-10-08 23:27:38 +00:00
"github.com/filecoin-project/lotus/chain/actors/builtin/verifreg"
"github.com/filecoin-project/lotus/chain/actors/policy"
2020-04-30 22:11:14 +00:00
"github.com/filecoin-project/lotus/chain/beacon"
2019-10-18 04:47:41 +00:00
"github.com/filecoin-project/lotus/chain/gen"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/lotus/chain/wallet"
"github.com/filecoin-project/lotus/lib/bufbstore"
2020-04-13 21:05:34 +00:00
"github.com/filecoin-project/lotus/node/modules/dtypes"
2019-08-20 16:48:33 +00:00
)
2020-10-01 15:51:27 +00:00
type StateModuleAPI interface {
StateAccountKey ( ctx context . Context , addr address . Address , tsk types . TipSetKey ) ( address . Address , error )
StateGetActor ( ctx context . Context , actor address . Address , tsk types . TipSetKey ) ( * types . Actor , error )
StateLookupID ( ctx context . Context , addr address . Address , tsk types . TipSetKey ) ( address . Address , error )
2020-10-02 14:14:30 +00:00
StateWaitMsg ( ctx context . Context , msg cid . Cid , confidence uint64 ) ( * api . MsgLookup , error )
2020-10-07 16:14:12 +00:00
MsigGetAvailableBalance ( ctx context . Context , addr address . Address , tsk types . TipSetKey ) ( types . BigInt , error )
MsigGetVested ( ctx context . Context , addr address . Address , start types . TipSetKey , end types . TipSetKey ) ( types . BigInt , error )
2020-10-01 15:51:27 +00:00
}
// StateModule provides a default implementation of StateModuleAPI.
// It can be swapped out with another implementation through Dependency
// Injection (for example with a thin RPC client).
type StateModule struct {
fx . In
StateManager * stmgr . StateManager
Chain * store . ChainStore
}
var _ StateModuleAPI = ( * StateModule ) ( nil )
2019-08-20 16:48:33 +00:00
type StateAPI struct {
fx . In
2019-09-06 06:26:02 +00:00
// TODO: the wallet here is only needed because we have the MinerCreateBlock
// API attached to the state API. It probably should live somewhere better
2020-10-08 23:27:49 +00:00
Wallet api . WalletAPI
2020-10-08 23:27:38 +00:00
DefWallet wallet . Default
2019-09-06 06:26:02 +00:00
2020-10-01 15:51:27 +00:00
StateModuleAPI
2020-04-17 23:36:54 +00:00
ProofVerifier ffiwrapper . Verifier
StateManager * stmgr . StateManager
Chain * store . ChainStore
2020-09-08 20:28:06 +00:00
Beacon beacon . Schedule
2019-08-20 16:48:33 +00:00
}
2020-03-31 23:13:37 +00:00
func ( a * StateAPI ) StateNetworkName ( ctx context . Context ) ( dtypes . NetworkName , error ) {
return stmgr . GetNetworkName ( ctx , a . StateManager , a . Chain . GetHeaviestTipSet ( ) . ParentState ( ) )
}
2020-09-21 19:05:01 +00:00
func ( a * StateAPI ) StateMinerSectors ( ctx context . Context , addr address . Address , sectorNos * bitfield . BitField , tsk types . TipSetKey ) ( [ ] * miner . SectorOnChainInfo , error ) {
2020-02-11 23:29:45 +00:00
ts , err := a . Chain . GetTipSetFromKey ( tsk )
if err != nil {
return nil , xerrors . Errorf ( "loading tipset %s: %w" , tsk , err )
}
2020-09-21 19:05:01 +00:00
return stmgr . GetMinerSectorSet ( ctx , a . StateManager , ts , addr , sectorNos )
2019-08-21 16:31:14 +00:00
}
2019-09-03 04:36:07 +00:00
2020-09-21 19:05:01 +00:00
func ( a * StateAPI ) StateMinerActiveSectors ( ctx context . Context , maddr address . Address , tsk types . TipSetKey ) ( [ ] * miner . SectorOnChainInfo , error ) { // TODO: only used in cli
2020-09-17 08:17:14 +00:00
ts , err := a . Chain . GetTipSetFromKey ( tsk )
2020-07-17 14:21:00 +00:00
if err != nil {
2020-09-17 08:17:14 +00:00
return nil , xerrors . Errorf ( "loading tipset %s: %w" , tsk , err )
2020-07-17 14:21:00 +00:00
}
2020-09-15 13:29:25 +00:00
act , err := a . StateManager . LoadActorTsk ( ctx , maddr , tsk )
2020-07-17 14:21:00 +00:00
if err != nil {
2020-09-15 13:29:25 +00:00
return nil , xerrors . Errorf ( "failed to load miner actor: %w" , err )
2020-07-17 14:21:00 +00:00
}
2020-09-15 13:29:25 +00:00
mas , err := miner . Load ( a . StateManager . ChainStore ( ) . Store ( ctx ) , act )
if err != nil {
return nil , xerrors . Errorf ( "failed to load miner actor state: %w" , err )
}
2020-04-15 20:40:46 +00:00
2020-09-15 13:29:25 +00:00
activeSectors , err := miner . AllPartSectors ( mas , miner . Partition . ActiveSectors )
2020-02-11 23:29:45 +00:00
if err != nil {
2020-09-15 13:29:25 +00:00
return nil , xerrors . Errorf ( "merge partition active sets: %w" , err )
2020-02-11 23:29:45 +00:00
}
2020-06-09 01:03:44 +00:00
2020-09-21 19:05:01 +00:00
return stmgr . GetMinerSectorSet ( ctx , a . StateManager , ts , maddr , & activeSectors )
2020-04-15 20:40:46 +00:00
}
2020-09-15 13:29:25 +00:00
func ( a * StateAPI ) StateMinerInfo ( ctx context . Context , actor address . Address , tsk types . TipSetKey ) ( miner . MinerInfo , error ) {
act , err := a . StateManager . LoadActorTsk ( ctx , actor , tsk )
2020-02-11 23:29:45 +00:00
if err != nil {
2020-09-15 13:29:25 +00:00
return miner . MinerInfo { } , xerrors . Errorf ( "failed to load miner actor: %w" , err )
2020-02-11 23:29:45 +00:00
}
2020-06-09 01:03:44 +00:00
2020-09-15 13:29:25 +00:00
mas , err := miner . Load ( a . StateManager . ChainStore ( ) . Store ( ctx ) , act )
2020-06-09 01:03:44 +00:00
if err != nil {
2020-09-15 13:29:25 +00:00
return miner . MinerInfo { } , xerrors . Errorf ( "failed to load miner actor state: %w" , err )
2020-06-09 01:03:44 +00:00
}
2020-09-15 13:29:25 +00:00
return mas . Info ( )
2019-10-16 07:07:16 +00:00
}
2020-09-17 15:30:15 +00:00
func ( a * StateAPI ) StateMinerDeadlines ( ctx context . Context , m address . Address , tsk types . TipSetKey ) ( [ ] api . Deadline , error ) {
2020-09-15 13:29:25 +00:00
act , err := a . StateManager . LoadActorTsk ( ctx , m , tsk )
2020-09-12 03:07:52 +00:00
if err != nil {
2020-09-15 13:29:25 +00:00
return nil , xerrors . Errorf ( "failed to load miner actor: %w" , err )
2020-09-12 03:07:52 +00:00
}
2020-09-15 13:29:25 +00:00
mas , err := miner . Load ( a . StateManager . ChainStore ( ) . Store ( ctx ) , act )
2020-09-12 03:07:52 +00:00
if err != nil {
2020-09-15 13:29:25 +00:00
return nil , xerrors . Errorf ( "failed to load miner actor state: %w" , err )
2020-09-12 03:07:52 +00:00
}
2020-09-15 13:29:25 +00:00
deadlines , err := mas . NumDeadlines ( )
2020-09-12 03:07:52 +00:00
if err != nil {
2020-09-15 13:29:25 +00:00
return nil , xerrors . Errorf ( "getting deadline count: %w" , err )
2020-09-12 03:07:52 +00:00
}
2020-09-15 13:29:25 +00:00
2020-09-17 15:30:15 +00:00
out := make ( [ ] api . Deadline , deadlines )
2020-09-15 13:29:25 +00:00
if err := mas . ForEachDeadline ( func ( i uint64 , dl miner . Deadline ) error {
2020-09-17 15:30:15 +00:00
ps , err := dl . PostSubmissions ( )
if err != nil {
return err
}
out [ i ] = api . Deadline {
PostSubmissions : ps ,
}
2020-09-12 03:07:52 +00:00
return nil
} ) ; err != nil {
2020-09-15 13:29:25 +00:00
return nil , err
2020-09-12 03:07:52 +00:00
}
2020-09-15 13:29:25 +00:00
return out , nil
2020-07-14 17:10:31 +00:00
}
2020-09-17 15:30:15 +00:00
func ( a * StateAPI ) StateMinerPartitions ( ctx context . Context , m address . Address , dlIdx uint64 , tsk types . TipSetKey ) ( [ ] api . Partition , error ) {
2020-09-15 13:29:25 +00:00
act , err := a . StateManager . LoadActorTsk ( ctx , m , tsk )
if err != nil {
return nil , xerrors . Errorf ( "failed to load miner actor: %w" , err )
}
mas , err := miner . Load ( a . StateManager . ChainStore ( ) . Store ( ctx ) , act )
if err != nil {
return nil , xerrors . Errorf ( "failed to load miner actor state: %w" , err )
}
dl , err := mas . LoadDeadline ( dlIdx )
if err != nil {
return nil , xerrors . Errorf ( "failed to load the deadline: %w" , err )
}
2020-09-17 15:30:15 +00:00
var out [ ] api . Partition
2020-09-15 13:29:25 +00:00
err = dl . ForEachPartition ( func ( _ uint64 , part miner . Partition ) error {
2020-09-17 15:30:15 +00:00
allSectors , err := part . AllSectors ( )
if err != nil {
return xerrors . Errorf ( "getting AllSectors: %w" , err )
}
faultySectors , err := part . FaultySectors ( )
if err != nil {
return xerrors . Errorf ( "getting FaultySectors: %w" , err )
}
recoveringSectors , err := part . RecoveringSectors ( )
if err != nil {
return xerrors . Errorf ( "getting RecoveringSectors: %w" , err )
}
liveSectors , err := part . LiveSectors ( )
if err != nil {
return xerrors . Errorf ( "getting LiveSectors: %w" , err )
}
activeSectors , err := part . ActiveSectors ( )
if err != nil {
return xerrors . Errorf ( "getting ActiveSectors: %w" , err )
}
out = append ( out , api . Partition {
AllSectors : allSectors ,
FaultySectors : faultySectors ,
RecoveringSectors : recoveringSectors ,
LiveSectors : liveSectors ,
ActiveSectors : activeSectors ,
} )
2020-09-15 13:29:25 +00:00
return nil
} )
return out , err
2020-04-15 20:22:58 +00:00
}
2020-09-10 06:30:47 +00:00
func ( a * StateAPI ) StateMinerProvingDeadline ( ctx context . Context , addr address . Address , tsk types . TipSetKey ) ( * dline . Info , error ) {
2020-09-15 13:29:25 +00:00
ts , err := a . StateManager . ChainStore ( ) . GetTipSetFromKey ( tsk )
2020-04-24 17:12:30 +00:00
if err != nil {
return nil , xerrors . Errorf ( "loading tipset %s: %w" , tsk , err )
}
2020-09-15 13:29:25 +00:00
act , err := a . StateManager . LoadActor ( ctx , addr , ts )
2020-04-24 17:12:30 +00:00
if err != nil {
2020-09-15 13:29:25 +00:00
return nil , xerrors . Errorf ( "failed to load miner actor: %w" , err )
}
mas , err := miner . Load ( a . StateManager . ChainStore ( ) . Store ( ctx ) , act )
2020-04-24 17:12:30 +00:00
if err != nil {
2020-09-15 13:29:25 +00:00
return nil , xerrors . Errorf ( "failed to load miner actor state: %w" , err )
2020-04-24 17:12:30 +00:00
}
2020-09-23 05:19:43 +00:00
di , err := mas . DeadlineInfo ( ts . Height ( ) )
if err != nil {
return nil , xerrors . Errorf ( "failed to get deadline info: %w" , err )
}
return di . NextNotElapsed ( ) , nil
2020-04-24 17:12:30 +00:00
}
2020-09-07 03:49:10 +00:00
func ( a * StateAPI ) StateMinerFaults ( ctx context . Context , addr address . Address , tsk types . TipSetKey ) ( bitfield . BitField , error ) {
2020-09-15 13:29:25 +00:00
act , err := a . StateManager . LoadActorTsk ( ctx , addr , tsk )
2020-02-11 23:29:45 +00:00
if err != nil {
2020-09-15 13:29:25 +00:00
return bitfield . BitField { } , xerrors . Errorf ( "failed to load miner actor: %w" , err )
2020-02-11 23:29:45 +00:00
}
2020-07-14 11:45:45 +00:00
2020-09-15 13:29:25 +00:00
mas , err := miner . Load ( a . StateManager . ChainStore ( ) . Store ( ctx ) , act )
2020-02-11 23:29:45 +00:00
if err != nil {
2020-09-15 13:29:25 +00:00
return bitfield . BitField { } , xerrors . Errorf ( "failed to load miner actor state: %w" , err )
2020-02-11 23:29:45 +00:00
}
2020-07-14 11:45:45 +00:00
2020-09-15 13:29:25 +00:00
return miner . AllPartSectors ( mas , miner . Partition . FaultySectors )
2020-01-30 00:50:58 +00:00
}
2020-05-21 20:28:59 +00:00
func ( a * StateAPI ) StateAllMinerFaults ( ctx context . Context , lookback abi . ChainEpoch , endTsk types . TipSetKey ) ( [ ] * api . Fault , error ) {
2020-07-14 11:45:45 +00:00
return nil , xerrors . Errorf ( "fixme" )
/ * endTs , err := a . Chain . GetTipSetFromKey ( endTsk )
2020-05-21 20:28:59 +00:00
if err != nil {
return nil , xerrors . Errorf ( "loading end tipset %s: %w" , endTsk , err )
}
cutoff := endTs . Height ( ) - lookback
miners , err := stmgr . ListMinerActors ( ctx , a . StateManager , endTs )
if err != nil {
return nil , xerrors . Errorf ( "loading miners: %w" , err )
}
var allFaults [ ] * api . Fault
for _ , m := range miners {
var mas miner . State
_ , err := a . StateManager . LoadActorState ( ctx , m , & mas , endTs )
if err != nil {
return nil , xerrors . Errorf ( "failed to load miner actor state %s: %w" , m , err )
}
2020-08-05 07:37:28 +00:00
err = mas . ForEachFaultEpoch ( a . Chain . Store ( ctx ) , func ( faultStart abi . ChainEpoch , faults abi . BitField ) error {
2020-05-21 20:28:59 +00:00
if faultStart >= cutoff {
allFaults = append ( allFaults , & api . Fault {
Miner : m ,
Epoch : faultStart ,
} )
return nil
}
return nil
} )
if err != nil {
return nil , xerrors . Errorf ( "failure when iterating over miner states: %w" , err )
}
}
2020-07-14 11:45:45 +00:00
return allFaults , nil * /
2020-05-21 20:28:59 +00:00
}
2020-09-07 03:49:10 +00:00
func ( a * StateAPI ) StateMinerRecoveries ( ctx context . Context , addr address . Address , tsk types . TipSetKey ) ( bitfield . BitField , error ) {
2020-09-15 13:29:25 +00:00
act , err := a . StateManager . LoadActorTsk ( ctx , addr , tsk )
2020-05-16 21:50:50 +00:00
if err != nil {
2020-09-15 13:29:25 +00:00
return bitfield . BitField { } , xerrors . Errorf ( "failed to load miner actor: %w" , err )
2020-05-16 21:50:50 +00:00
}
2020-07-14 11:45:45 +00:00
2020-09-15 13:29:25 +00:00
mas , err := miner . Load ( a . StateManager . ChainStore ( ) . Store ( ctx ) , act )
2020-05-16 21:50:50 +00:00
if err != nil {
2020-09-15 13:29:25 +00:00
return bitfield . BitField { } , xerrors . Errorf ( "failed to load miner actor state: %w" , err )
2020-05-16 21:50:50 +00:00
}
2020-07-14 11:45:45 +00:00
2020-09-15 13:29:25 +00:00
return miner . AllPartSectors ( mas , miner . Partition . RecoveringSectors )
2020-05-16 21:50:50 +00:00
}
2020-04-15 20:40:46 +00:00
func ( a * StateAPI ) StateMinerPower ( ctx context . Context , addr address . Address , tsk types . TipSetKey ) ( * api . MinerPower , error ) {
ts , err := a . Chain . GetTipSetFromKey ( tsk )
if err != nil {
return nil , xerrors . Errorf ( "loading tipset %s: %w" , tsk , err )
}
2020-09-16 05:47:24 +00:00
m , net , hmp , err := stmgr . GetPower ( ctx , a . StateManager , ts , addr )
2020-04-15 20:40:46 +00:00
if err != nil {
return nil , err
}
return & api . MinerPower {
2020-09-17 07:32:10 +00:00
MinerPower : m ,
TotalPower : net ,
2020-09-16 05:47:24 +00:00
HasMinPower : hmp ,
2020-04-15 20:40:46 +00:00
} , nil
}
2020-10-07 23:03:42 +00:00
func ( a * StateAPI ) StateCall ( ctx context . Context , msg * types . Message , tsk types . TipSetKey ) ( res * api . InvocResult , err error ) {
2020-02-11 23:29:45 +00:00
ts , err := a . Chain . GetTipSetFromKey ( tsk )
if err != nil {
return nil , xerrors . Errorf ( "loading tipset %s: %w" , tsk , err )
}
2020-10-07 23:03:42 +00:00
for {
res , err = a . StateManager . Call ( ctx , msg , ts )
2020-10-07 23:14:11 +00:00
if err != stmgr . ErrExpensiveFork {
2020-10-07 23:03:42 +00:00
break
}
ts , err = a . Chain . GetTipSetFromKey ( ts . Parents ( ) )
if err != nil {
return nil , xerrors . Errorf ( "getting parent tipset: %w" , err )
}
}
return res , err
2019-09-06 06:26:02 +00:00
}
2020-10-16 02:45:11 +00:00
func ( a * StateAPI ) StateReplay ( ctx context . Context , tsk types . TipSetKey , mc cid . Cid ) ( * api . InvocResult , error ) {
msgToReplay := mc
var ts * types . TipSet
2020-10-19 18:27:04 +00:00
var err error
2020-10-16 02:45:11 +00:00
if tsk == types . EmptyTSK {
mlkp , err := a . StateSearchMsg ( ctx , mc )
if err != nil {
return nil , xerrors . Errorf ( "searching for msg %s: %w" , mc , err )
}
if mlkp == nil {
return nil , xerrors . Errorf ( "didn't find msg %s" , mc )
}
2019-09-19 20:25:18 +00:00
2020-10-16 02:45:11 +00:00
msgToReplay = mlkp . Message
2020-10-15 23:47:02 +00:00
2020-10-16 02:45:11 +00:00
executionTs , err := a . Chain . GetTipSetFromKey ( mlkp . TipSet )
if err != nil {
return nil , xerrors . Errorf ( "loading tipset %s: %w" , mlkp . TipSet , err )
}
2020-10-15 23:47:02 +00:00
2020-10-16 02:45:11 +00:00
ts , err = a . Chain . LoadTipSet ( executionTs . Parents ( ) )
if err != nil {
return nil , xerrors . Errorf ( "loading parent tipset %s: %w" , mlkp . TipSet , err )
}
} else {
2020-10-19 18:27:04 +00:00
ts , err = a . Chain . LoadTipSet ( tsk )
if err != nil {
return nil , xerrors . Errorf ( "loading specified tipset %s: %w" , tsk , err )
}
2020-10-15 23:47:02 +00:00
}
2020-10-16 02:45:11 +00:00
m , r , err := a . StateManager . Replay ( ctx , ts , msgToReplay )
2020-10-15 23:47:02 +00:00
if err != nil {
return nil , err
}
var errstr string
if r . ActorErr != nil {
errstr = r . ActorErr . Error ( )
}
return & api . InvocResult {
2020-10-16 02:45:11 +00:00
MsgCid : msgToReplay ,
2020-10-15 23:47:02 +00:00
Msg : m ,
MsgRct : & r . MessageReceipt ,
GasCost : stmgr . MakeMsgGasCost ( m , r ) ,
ExecutionTrace : r . ExecutionTrace ,
Error : errstr ,
Duration : r . Duration ,
} , nil
}
2020-10-01 15:51:27 +00:00
func stateForTs ( ctx context . Context , ts * types . TipSet , cstore * store . ChainStore , smgr * stmgr . StateManager ) ( * state . StateTree , error ) {
2019-09-06 06:26:02 +00:00
if ts == nil {
2020-10-01 15:51:27 +00:00
ts = cstore . GetHeaviestTipSet ( )
2019-09-06 06:26:02 +00:00
}
2020-10-01 15:51:27 +00:00
st , _ , err := smgr . TipSetState ( ctx , ts )
2019-09-06 06:26:02 +00:00
if err != nil {
return nil , err
}
2020-10-01 15:51:27 +00:00
buf := bufbstore . NewBufferedBstore ( cstore . Blockstore ( ) )
2020-02-04 22:19:05 +00:00
cst := cbor . NewCborStore ( buf )
2019-09-06 06:26:02 +00:00
return state . LoadStateTree ( cst , st )
}
2020-10-01 15:51:27 +00:00
func ( a * StateAPI ) stateForTs ( ctx context . Context , ts * types . TipSet ) ( * state . StateTree , error ) {
return stateForTs ( ctx , ts , a . Chain , a . StateManager )
}
func ( m * StateModule ) stateForTs ( ctx context . Context , ts * types . TipSet ) ( * state . StateTree , error ) {
return stateForTs ( ctx , ts , m . Chain , m . StateManager )
}
2019-09-06 06:26:02 +00:00
2020-10-01 15:51:27 +00:00
func ( m * StateModule ) StateGetActor ( ctx context . Context , actor address . Address , tsk types . TipSetKey ) ( * types . Actor , error ) {
ts , err := m . Chain . GetTipSetFromKey ( tsk )
2020-02-11 23:29:45 +00:00
if err != nil {
return nil , xerrors . Errorf ( "loading tipset %s: %w" , tsk , err )
}
2020-10-01 15:51:27 +00:00
state , err := m . stateForTs ( ctx , ts )
2019-09-06 06:26:02 +00:00
if err != nil {
2019-12-07 16:24:42 +00:00
return nil , xerrors . Errorf ( "computing tipset state failed: %w" , err )
2019-09-06 06:26:02 +00:00
}
return state . GetActor ( actor )
}
2020-10-01 15:51:27 +00:00
func ( m * StateModule ) StateLookupID ( ctx context . Context , addr address . Address , tsk types . TipSetKey ) ( address . Address , error ) {
ts , err := m . Chain . GetTipSetFromKey ( tsk )
2020-02-11 23:29:45 +00:00
if err != nil {
return address . Undef , xerrors . Errorf ( "loading tipset %s: %w" , tsk , err )
}
2019-11-15 16:39:43 +00:00
2020-10-01 15:51:27 +00:00
return m . StateManager . LookupID ( ctx , addr , ts )
2019-11-15 16:39:43 +00:00
}
2020-10-01 15:51:27 +00:00
func ( m * StateModule ) StateAccountKey ( ctx context . Context , addr address . Address , tsk types . TipSetKey ) ( address . Address , error ) {
ts , err := m . Chain . GetTipSetFromKey ( tsk )
2020-04-16 20:38:42 +00:00
if err != nil {
return address . Undef , xerrors . Errorf ( "loading tipset %s: %w" , tsk , err )
}
2020-10-01 15:51:27 +00:00
return m . StateManager . ResolveToKeyAddress ( ctx , addr , ts )
2020-04-16 20:38:42 +00:00
}
2020-06-17 05:10:29 +00:00
func ( a * StateAPI ) StateReadState ( ctx context . Context , actor address . Address , tsk types . TipSetKey ) ( * api . ActorState , error ) {
2020-02-11 23:29:45 +00:00
ts , err := a . Chain . GetTipSetFromKey ( tsk )
if err != nil {
return nil , xerrors . Errorf ( "loading tipset %s: %w" , tsk , err )
}
2019-10-10 11:13:26 +00:00
state , err := a . stateForTs ( ctx , ts )
2019-09-06 06:26:02 +00:00
if err != nil {
2020-08-07 14:07:34 +00:00
return nil , xerrors . Errorf ( "getting state for tipset: %w" , err )
2019-09-06 06:26:02 +00:00
}
2020-06-17 05:10:29 +00:00
act , err := state . GetActor ( actor )
if err != nil {
2020-08-07 14:07:34 +00:00
return nil , xerrors . Errorf ( "getting actor: %w" , err )
2020-06-17 05:10:29 +00:00
}
2020-02-04 22:19:05 +00:00
blk , err := state . Store . ( * cbor . BasicIpldStore ) . Blocks . Get ( act . Head )
2019-09-06 06:26:02 +00:00
if err != nil {
2020-08-07 14:07:34 +00:00
return nil , xerrors . Errorf ( "getting actor head: %w" , err )
2019-09-06 06:26:02 +00:00
}
2020-09-25 00:51:34 +00:00
oif , err := vm . DumpActorState ( act , blk . RawData ( ) )
2019-09-06 06:26:02 +00:00
if err != nil {
2020-08-07 14:07:34 +00:00
return nil , xerrors . Errorf ( "dumping actor state (a:%s): %w" , actor , err )
2019-09-06 06:26:02 +00:00
}
return & api . ActorState {
Balance : act . Balance ,
State : oif ,
} , nil
}
2020-04-02 01:10:28 +00:00
// This is on StateAPI because miner.Miner requires this, and MinerAPI requires miner.Miner
2020-04-17 23:36:54 +00:00
func ( a * StateAPI ) MinerGetBaseInfo ( ctx context . Context , maddr address . Address , epoch abi . ChainEpoch , tsk types . TipSetKey ) ( * api . MiningBaseInfo , error ) {
2020-04-30 22:11:14 +00:00
return stmgr . MinerGetBaseInfo ( ctx , a . StateManager , a . Beacon , tsk , epoch , maddr , a . ProofVerifier )
2020-04-02 01:10:28 +00:00
}
2020-04-09 00:24:10 +00:00
func ( a * StateAPI ) MinerCreateBlock ( ctx context . Context , bt * api . BlockTemplate ) ( * types . BlockMsg , error ) {
fblk , err := gen . MinerCreateBlock ( ctx , a . StateManager , a . Wallet , bt )
2019-09-06 06:26:02 +00:00
if err != nil {
return nil , err
}
2019-09-18 02:50:03 +00:00
var out types . BlockMsg
2019-09-06 06:26:02 +00:00
out . Header = fblk . Header
for _ , msg := range fblk . BlsMessages {
out . BlsMessages = append ( out . BlsMessages , msg . Cid ( ) )
}
for _ , msg := range fblk . SecpkMessages {
out . SecpkMessages = append ( out . SecpkMessages , msg . Cid ( ) )
}
return & out , nil
}
2019-10-08 05:51:34 +00:00
2020-10-02 14:14:30 +00:00
func ( m * StateModule ) StateWaitMsg ( ctx context . Context , msg cid . Cid , confidence uint64 ) ( * api . MsgLookup , error ) {
return stateWaitMsgLimited ( ctx , m . StateManager , m . Chain , msg , confidence , stmgr . LookbackNoLimit )
}
func ( a * StateAPI ) StateWaitMsgLimited ( ctx context . Context , msg cid . Cid , confidence uint64 , lookbackLimit abi . ChainEpoch ) ( * api . MsgLookup , error ) {
return stateWaitMsgLimited ( ctx , a . StateManager , a . Chain , msg , confidence , lookbackLimit )
}
func stateWaitMsgLimited ( ctx context . Context , smgr * stmgr . StateManager , cstore * store . ChainStore , msg cid . Cid , confidence uint64 , lookbackLimit abi . ChainEpoch ) ( * api . MsgLookup , error ) {
ts , recpt , found , err := smgr . WaitForMessage ( ctx , msg , confidence , lookbackLimit )
2019-10-08 05:51:34 +00:00
if err != nil {
return nil , err
}
2020-07-03 16:57:58 +00:00
var returndec interface { }
if recpt . ExitCode == 0 && len ( recpt . Return ) > 0 {
2020-10-02 14:14:30 +00:00
cmsg , err := cstore . GetCMessage ( msg )
2020-07-03 16:57:58 +00:00
if err != nil {
return nil , xerrors . Errorf ( "failed to load message after successful receipt search: %w" , err )
}
vmsg := cmsg . VMMessage ( )
2020-10-02 14:14:30 +00:00
t , err := stmgr . GetReturnType ( ctx , smgr , vmsg . To , vmsg . Method , ts )
2020-07-03 16:57:58 +00:00
if err != nil {
return nil , xerrors . Errorf ( "failed to get return type: %w" , err )
}
if err := t . UnmarshalCBOR ( bytes . NewReader ( recpt . Return ) ) ; err != nil {
return nil , err
}
returndec = t
}
2020-03-18 23:06:53 +00:00
return & api . MsgLookup {
2020-08-10 12:55:27 +00:00
Message : found ,
2020-07-03 16:57:58 +00:00
Receipt : * recpt ,
ReturnDec : returndec ,
2020-07-12 03:54:25 +00:00
TipSet : ts . Key ( ) ,
Height : ts . Height ( ) ,
2019-10-08 05:51:34 +00:00
} , nil
}
2019-10-12 06:45:48 +00:00
2020-03-18 23:06:53 +00:00
func ( a * StateAPI ) StateSearchMsg ( ctx context . Context , msg cid . Cid ) ( * api . MsgLookup , error ) {
2020-08-10 12:55:27 +00:00
ts , recpt , found , err := a . StateManager . SearchForMessage ( ctx , msg )
2020-03-18 23:06:53 +00:00
if err != nil {
return nil , err
}
if ts != nil {
return & api . MsgLookup {
2020-08-10 12:55:27 +00:00
Message : found ,
2020-03-18 23:06:53 +00:00
Receipt : * recpt ,
2020-07-12 03:54:25 +00:00
TipSet : ts . Key ( ) ,
Height : ts . Height ( ) ,
2020-03-18 23:06:53 +00:00
} , nil
}
2020-08-20 04:49:10 +00:00
return nil , nil
2020-03-18 23:06:53 +00:00
}
2020-02-11 23:29:45 +00:00
func ( a * StateAPI ) StateGetReceipt ( ctx context . Context , msg cid . Cid , tsk types . TipSetKey ) ( * types . MessageReceipt , error ) {
ts , err := a . Chain . GetTipSetFromKey ( tsk )
if err != nil {
return nil , xerrors . Errorf ( "loading tipset %s: %w" , tsk , err )
}
2019-11-19 21:27:25 +00:00
return a . StateManager . GetReceipt ( ctx , msg , ts )
}
2020-02-11 23:29:45 +00:00
func ( a * StateAPI ) StateListMiners ( ctx context . Context , tsk types . TipSetKey ) ( [ ] address . Address , error ) {
ts , err := a . Chain . GetTipSetFromKey ( tsk )
if err != nil {
return nil , xerrors . Errorf ( "loading tipset %s: %w" , tsk , err )
}
2019-12-17 06:51:41 +00:00
return stmgr . ListMinerActors ( ctx , a . StateManager , ts )
2019-10-12 06:45:48 +00:00
}
2020-02-11 23:29:45 +00:00
func ( a * StateAPI ) StateListActors ( ctx context . Context , tsk types . TipSetKey ) ( [ ] address . Address , error ) {
ts , err := a . Chain . GetTipSetFromKey ( tsk )
if err != nil {
return nil , xerrors . Errorf ( "loading tipset %s: %w" , tsk , err )
}
2019-10-12 06:45:48 +00:00
return a . StateManager . ListAllActors ( ctx , ts )
}
2019-10-22 10:09:36 +00:00
2020-02-24 17:32:02 +00:00
func ( a * StateAPI ) StateMarketBalance ( ctx context . Context , addr address . Address , tsk types . TipSetKey ) ( api . MarketBalance , error ) {
2020-02-11 23:29:45 +00:00
ts , err := a . Chain . GetTipSetFromKey ( tsk )
if err != nil {
2020-02-24 17:32:02 +00:00
return api . MarketBalance { } , xerrors . Errorf ( "loading tipset %s: %w" , tsk , err )
2020-02-11 23:29:45 +00:00
}
2019-10-23 17:39:14 +00:00
return a . StateManager . MarketBalance ( ctx , addr , ts )
2019-10-22 10:09:36 +00:00
}
2019-10-22 19:29:05 +00:00
2020-02-24 17:32:02 +00:00
func ( a * StateAPI ) StateMarketParticipants ( ctx context . Context , tsk types . TipSetKey ) ( map [ string ] api . MarketBalance , error ) {
2020-02-08 02:18:32 +00:00
out := map [ string ] api . MarketBalance { }
2019-10-22 19:29:05 +00:00
2020-02-11 23:29:45 +00:00
ts , err := a . Chain . GetTipSetFromKey ( tsk )
if err != nil {
return nil , xerrors . Errorf ( "loading tipset %s: %w" , tsk , err )
}
2020-09-17 07:32:10 +00:00
state , err := a . StateManager . GetMarketState ( ctx , ts )
if err != nil {
2019-10-22 19:29:05 +00:00
return nil , err
}
2020-09-17 07:32:10 +00:00
escrow , err := state . EscrowTable ( )
2020-02-08 02:18:32 +00:00
if err != nil {
return nil , err
}
2020-09-17 07:32:10 +00:00
locked , err := state . LockedTable ( )
2019-10-22 19:29:05 +00:00
if err != nil {
return nil , err
}
2020-09-17 07:32:10 +00:00
err = escrow . ForEach ( func ( a address . Address , es abi . TokenAmount ) error {
2020-02-08 02:18:32 +00:00
2020-09-17 07:32:10 +00:00
lk , err := locked . Get ( a )
if err != nil {
2019-10-22 19:29:05 +00:00
return err
}
2020-02-08 02:18:32 +00:00
out [ a . String ( ) ] = api . MarketBalance {
Escrow : es ,
Locked : lk ,
}
2019-10-22 19:29:05 +00:00
return nil
} )
if err != nil {
return nil , err
}
return out , nil
}
2020-02-24 17:32:02 +00:00
func ( a * StateAPI ) StateMarketDeals ( ctx context . Context , tsk types . TipSetKey ) ( map [ string ] api . MarketDeal , error ) {
2020-02-09 06:06:32 +00:00
out := map [ string ] api . MarketDeal { }
2019-10-22 19:29:05 +00:00
2020-02-11 23:29:45 +00:00
ts , err := a . Chain . GetTipSetFromKey ( tsk )
if err != nil {
return nil , xerrors . Errorf ( "loading tipset %s: %w" , tsk , err )
}
2020-09-17 07:32:10 +00:00
state , err := a . StateManager . GetMarketState ( ctx , ts )
if err != nil {
2019-10-22 19:29:05 +00:00
return nil , err
}
2020-09-17 07:32:10 +00:00
da , err := state . Proposals ( )
2019-10-22 19:29:05 +00:00
if err != nil {
return nil , err
}
2020-09-17 07:32:10 +00:00
sa , err := state . States ( )
2020-02-09 06:06:32 +00:00
if err != nil {
return nil , err
}
2020-09-17 07:32:10 +00:00
if err := da . ForEach ( func ( dealID abi . DealID , d market . DealProposal ) error {
s , found , err := sa . Get ( dealID )
if err != nil {
2020-07-23 00:14:54 +00:00
return xerrors . Errorf ( "failed to get state for deal in proposals array: %w" , err )
} else if ! found {
2020-09-17 07:32:10 +00:00
s = market . EmptyDealState ( )
2020-02-09 06:06:32 +00:00
}
2020-09-17 07:32:10 +00:00
out [ strconv . FormatInt ( int64 ( dealID ) , 10 ) ] = api . MarketDeal {
2020-02-09 06:06:32 +00:00
Proposal : d ,
2020-09-17 07:32:10 +00:00
State : * s ,
2020-02-09 06:06:32 +00:00
}
2019-10-22 19:29:05 +00:00
return nil
} ) ; err != nil {
return nil , err
}
return out , nil
}
2019-11-07 07:57:10 +00:00
2020-02-24 17:32:02 +00:00
func ( a * StateAPI ) StateMarketStorageDeal ( ctx context . Context , dealId abi . DealID , tsk types . TipSetKey ) ( * api . MarketDeal , error ) {
2020-02-11 23:29:45 +00:00
ts , err := a . Chain . GetTipSetFromKey ( tsk )
if err != nil {
return nil , xerrors . Errorf ( "loading tipset %s: %w" , tsk , err )
}
2019-11-07 09:06:06 +00:00
return stmgr . GetStorageDeal ( ctx , a . StateManager , dealId , ts )
2019-11-07 07:57:10 +00:00
}
2019-11-15 18:38:09 +00:00
func ( a * StateAPI ) StateChangedActors ( ctx context . Context , old cid . Cid , new cid . Cid ) ( map [ string ] types . Actor , error ) {
2020-09-21 19:50:12 +00:00
store := a . Chain . Store ( ctx )
2019-11-15 18:38:09 +00:00
2020-09-21 19:50:12 +00:00
oldTree , err := state . LoadStateTree ( store , old )
2019-11-15 18:38:09 +00:00
if err != nil {
2020-09-21 19:50:12 +00:00
return nil , xerrors . Errorf ( "failed to load old state tree: %w" , err )
2019-11-15 18:38:09 +00:00
}
2020-09-21 19:50:12 +00:00
newTree , err := state . LoadStateTree ( store , new )
2019-11-15 18:38:09 +00:00
if err != nil {
2020-09-21 19:50:12 +00:00
return nil , xerrors . Errorf ( "failed to load new state tree: %w" , err )
2019-11-15 18:38:09 +00:00
}
2020-09-21 20:10:41 +00:00
return state . Diff ( oldTree , newTree )
2019-11-15 18:38:09 +00:00
}
2019-12-11 23:31:59 +00:00
2020-02-11 23:29:45 +00:00
func ( a * StateAPI ) StateMinerSectorCount ( ctx context . Context , addr address . Address , tsk types . TipSetKey ) ( api . MinerSectors , error ) {
2020-09-15 19:09:39 +00:00
act , err := a . StateManager . LoadActorTsk ( ctx , addr , tsk )
2020-07-18 12:54:21 +00:00
if err != nil {
return api . MinerSectors { } , err
}
2020-09-15 19:09:39 +00:00
mas , err := miner . Load ( a . Chain . Store ( ctx ) , act )
if err != nil {
return api . MinerSectors { } , err
}
var activeCount , liveCount , faultyCount uint64
if err := mas . ForEachDeadline ( func ( _ uint64 , dl miner . Deadline ) error {
return dl . ForEachPartition ( func ( _ uint64 , part miner . Partition ) error {
if active , err := part . ActiveSectors ( ) ; err != nil {
return err
} else if count , err := active . Count ( ) ; err != nil {
return err
} else {
activeCount += count
}
if live , err := part . LiveSectors ( ) ; err != nil {
return err
} else if count , err := live . Count ( ) ; err != nil {
return err
} else {
liveCount += count
}
if faulty , err := part . FaultySectors ( ) ; err != nil {
return err
} else if count , err := faulty . Count ( ) ; err != nil {
return err
} else {
faultyCount += count
}
return nil
} )
} ) ; err != nil {
return api . MinerSectors { } , err
}
return api . MinerSectors { Live : liveCount , Active : activeCount , Faulty : faultyCount } , nil
2019-12-11 23:31:59 +00:00
}
2020-01-07 19:03:11 +00:00
2020-04-04 02:55:19 +00:00
func ( a * StateAPI ) StateSectorPreCommitInfo ( ctx context . Context , maddr address . Address , n abi . SectorNumber , tsk types . TipSetKey ) ( miner . SectorPreCommitOnChainInfo , error ) {
ts , err := a . Chain . GetTipSetFromKey ( tsk )
if err != nil {
return miner . SectorPreCommitOnChainInfo { } , xerrors . Errorf ( "loading tipset %s: %w" , tsk , err )
}
2020-09-17 08:17:14 +00:00
pci , err := stmgr . PreCommitInfo ( ctx , a . StateManager , maddr , n , ts )
if err != nil {
return miner . SectorPreCommitOnChainInfo { } , err
}
return * pci , err
2020-04-04 02:55:19 +00:00
}
2020-05-28 00:06:29 +00:00
func ( a * StateAPI ) StateSectorGetInfo ( ctx context . Context , maddr address . Address , n abi . SectorNumber , tsk types . TipSetKey ) ( * miner . SectorOnChainInfo , error ) {
ts , err := a . Chain . GetTipSetFromKey ( tsk )
if err != nil {
return nil , xerrors . Errorf ( "loading tipset %s: %w" , tsk , err )
}
return stmgr . MinerSectorInfo ( ctx , a . StateManager , maddr , n , ts )
}
2020-09-15 19:09:39 +00:00
func ( a * StateAPI ) StateSectorExpiration ( ctx context . Context , maddr address . Address , sectorNumber abi . SectorNumber , tsk types . TipSetKey ) ( * miner . SectorExpiration , error ) {
2020-09-15 17:44:44 +00:00
act , err := a . StateManager . LoadActorTsk ( ctx , maddr , tsk )
2020-07-16 15:24:41 +00:00
if err != nil {
return nil , err
}
2020-09-15 17:44:44 +00:00
mas , err := miner . Load ( a . StateManager . ChainStore ( ) . Store ( ctx ) , act )
if err != nil {
return nil , err
2020-07-16 15:24:41 +00:00
}
2020-09-15 17:44:44 +00:00
return mas . GetSectorExpiration ( sectorNumber )
2020-07-16 15:24:41 +00:00
}
2020-09-15 19:09:39 +00:00
func ( a * StateAPI ) StateSectorPartition ( ctx context . Context , maddr address . Address , sectorNumber abi . SectorNumber , tsk types . TipSetKey ) ( * miner . SectorLocation , error ) {
2020-09-15 17:44:44 +00:00
act , err := a . StateManager . LoadActorTsk ( ctx , maddr , tsk )
2020-07-14 12:32:17 +00:00
if err != nil {
return nil , err
}
2020-09-15 17:44:44 +00:00
mas , err := miner . Load ( a . StateManager . ChainStore ( ) . Store ( ctx ) , act )
if err != nil {
return nil , err
}
return mas . FindSector ( sectorNumber )
2020-07-14 12:32:17 +00:00
}
2020-10-15 15:54:36 +00:00
func ( a * StateAPI ) StateListMessages ( ctx context . Context , match * api . MessageMatch , tsk types . TipSetKey , toheight abi . ChainEpoch ) ( [ ] cid . Cid , error ) {
2020-02-11 23:29:45 +00:00
ts , err := a . Chain . GetTipSetFromKey ( tsk )
if err != nil {
return nil , xerrors . Errorf ( "loading tipset %s: %w" , tsk , err )
}
2020-01-07 19:03:11 +00:00
if ts == nil {
ts = a . Chain . GetHeaviestTipSet ( )
}
if match . To == address . Undef && match . From == address . Undef {
return nil , xerrors . Errorf ( "must specify at least To or From in message filter" )
}
matchFunc := func ( msg * types . Message ) bool {
if match . From != address . Undef && match . From != msg . From {
return false
}
if match . To != address . Undef && match . To != msg . To {
return false
}
return true
}
var out [ ] cid . Cid
for ts . Height ( ) >= toheight {
msgs , err := a . Chain . MessagesForTipset ( ts )
if err != nil {
return nil , xerrors . Errorf ( "failed to get messages for tipset (%s): %w" , ts . Key ( ) , err )
}
for _ , msg := range msgs {
if matchFunc ( msg . VMMessage ( ) ) {
out = append ( out , msg . Cid ( ) )
}
}
if ts . Height ( ) == 0 {
break
}
next , err := a . Chain . LoadTipSet ( ts . Parents ( ) )
if err != nil {
return nil , xerrors . Errorf ( "loading next tipset: %w" , err )
}
ts = next
}
return out , nil
}
2020-01-17 02:33:43 +00:00
2020-03-08 02:31:36 +00:00
func ( a * StateAPI ) StateCompute ( ctx context . Context , height abi . ChainEpoch , msgs [ ] * types . Message , tsk types . TipSetKey ) ( * api . ComputeStateOutput , error ) {
2020-02-11 23:29:45 +00:00
ts , err := a . Chain . GetTipSetFromKey ( tsk )
if err != nil {
2020-03-08 02:31:36 +00:00
return nil , xerrors . Errorf ( "loading tipset %s: %w" , tsk , err )
}
st , t , err := stmgr . ComputeState ( ctx , a . StateManager , height , msgs , ts )
if err != nil {
return nil , err
2020-02-11 23:29:45 +00:00
}
2020-03-08 02:31:36 +00:00
return & api . ComputeStateOutput {
Root : st ,
Trace : t ,
} , nil
2020-01-17 02:33:43 +00:00
}
2020-01-30 01:23:16 +00:00
2020-10-07 16:14:12 +00:00
func ( m * StateModule ) MsigGetAvailableBalance ( ctx context . Context , addr address . Address , tsk types . TipSetKey ) ( types . BigInt , error ) {
ts , err := m . Chain . GetTipSetFromKey ( tsk )
2020-02-11 23:29:45 +00:00
if err != nil {
return types . EmptyInt , xerrors . Errorf ( "loading tipset %s: %w" , tsk , err )
2020-01-30 01:23:16 +00:00
}
2020-10-07 16:14:12 +00:00
act , err := m . StateManager . LoadActor ( ctx , addr , ts )
2020-01-30 01:23:16 +00:00
if err != nil {
2020-09-15 21:44:03 +00:00
return types . EmptyInt , xerrors . Errorf ( "failed to load multisig actor: %w" , err )
2020-01-30 01:23:16 +00:00
}
2020-10-07 16:14:12 +00:00
msas , err := multisig . Load ( m . Chain . Store ( ctx ) , act )
2020-01-30 01:23:16 +00:00
if err != nil {
return types . EmptyInt , xerrors . Errorf ( "failed to load multisig actor state: %w" , err )
}
2020-09-15 21:44:03 +00:00
locked , err := msas . LockedBalance ( ts . Height ( ) )
if err != nil {
return types . EmptyInt , xerrors . Errorf ( "failed to compute locked multisig balance: %w" , err )
2020-01-30 01:23:16 +00:00
}
2020-09-15 21:44:03 +00:00
return types . BigSub ( act . Balance , locked ) , nil
2020-01-30 01:23:16 +00:00
}
2020-04-23 19:39:34 +00:00
2020-10-08 19:19:39 +00:00
func ( a * StateAPI ) MsigGetVestingSchedule ( ctx context . Context , addr address . Address , tsk types . TipSetKey ) ( api . MsigVesting , error ) {
ts , err := a . Chain . GetTipSetFromKey ( tsk )
if err != nil {
return api . EmptyVesting , xerrors . Errorf ( "loading tipset %s: %w" , tsk , err )
}
act , err := a . StateManager . LoadActor ( ctx , addr , ts )
if err != nil {
return api . EmptyVesting , xerrors . Errorf ( "failed to load multisig actor: %w" , err )
}
msas , err := multisig . Load ( a . Chain . Store ( ctx ) , act )
if err != nil {
return api . EmptyVesting , xerrors . Errorf ( "failed to load multisig actor state: %w" , err )
}
ib , err := msas . InitialBalance ( )
if err != nil {
return api . EmptyVesting , xerrors . Errorf ( "failed to load multisig initial balance: %w" , err )
}
se , err := msas . StartEpoch ( )
if err != nil {
return api . EmptyVesting , xerrors . Errorf ( "failed to load multisig start epoch: %w" , err )
}
ud , err := msas . UnlockDuration ( )
if err != nil {
return api . EmptyVesting , xerrors . Errorf ( "failed to load multisig unlock duration: %w" , err )
}
return api . MsigVesting {
InitialBalance : ib ,
StartEpoch : se ,
UnlockDuration : ud ,
} , nil
}
2020-10-07 16:14:12 +00:00
func ( m * StateModule ) MsigGetVested ( ctx context . Context , addr address . Address , start types . TipSetKey , end types . TipSetKey ) ( types . BigInt , error ) {
startTs , err := m . Chain . GetTipSetFromKey ( start )
2020-09-06 00:29:26 +00:00
if err != nil {
return types . EmptyInt , xerrors . Errorf ( "loading start tipset %s: %w" , start , err )
}
2020-10-07 16:14:12 +00:00
endTs , err := m . Chain . GetTipSetFromKey ( end )
2020-09-06 00:29:26 +00:00
if err != nil {
return types . EmptyInt , xerrors . Errorf ( "loading end tipset %s: %w" , end , err )
}
if startTs . Height ( ) > endTs . Height ( ) {
return types . EmptyInt , xerrors . Errorf ( "start tipset %d is after end tipset %d" , startTs . Height ( ) , endTs . Height ( ) )
} else if startTs . Height ( ) == endTs . Height ( ) {
return big . Zero ( ) , nil
}
2020-01-30 01:23:16 +00:00
2020-10-07 16:14:12 +00:00
act , err := m . StateManager . LoadActor ( ctx , addr , endTs )
2020-09-06 00:29:26 +00:00
if err != nil {
2020-09-15 21:44:03 +00:00
return types . EmptyInt , xerrors . Errorf ( "failed to load multisig actor at end epoch: %w" , err )
2020-01-30 01:23:16 +00:00
}
2020-10-07 16:14:12 +00:00
msas , err := multisig . Load ( m . Chain . Store ( ctx ) , act )
2020-09-15 21:44:03 +00:00
if err != nil {
return types . EmptyInt , xerrors . Errorf ( "failed to load multisig actor state: %w" , err )
2020-01-30 01:23:16 +00:00
}
2020-09-15 21:44:03 +00:00
startLk , err := msas . LockedBalance ( startTs . Height ( ) )
if err != nil {
return types . EmptyInt , xerrors . Errorf ( "failed to compute locked balance at start height: %w" , err )
2020-01-30 01:23:16 +00:00
}
2020-09-15 21:44:03 +00:00
endLk , err := msas . LockedBalance ( endTs . Height ( ) )
if err != nil {
return types . EmptyInt , xerrors . Errorf ( "failed to compute locked balance at end height: %w" , err )
2020-09-06 00:29:26 +00:00
}
2020-09-15 21:44:03 +00:00
return types . BigSub ( startLk , endLk ) , nil
2020-01-30 01:23:16 +00:00
}
2020-04-23 19:39:34 +00:00
2020-07-30 00:06:22 +00:00
var initialPledgeNum = types . NewInt ( 110 )
2020-05-15 14:53:35 +00:00
var initialPledgeDen = types . NewInt ( 100 )
2020-07-28 18:55:20 +00:00
func ( a * StateAPI ) StateMinerPreCommitDepositForPower ( ctx context . Context , maddr address . Address , pci miner . SectorPreCommitInfo , tsk types . TipSetKey ) ( types . BigInt , error ) {
ts , err := a . Chain . GetTipSetFromKey ( tsk )
if err != nil {
return types . EmptyInt , xerrors . Errorf ( "loading tipset %s: %w" , tsk , err )
}
2020-09-15 23:47:58 +00:00
state , err := a . StateManager . ParentState ( ts )
2020-07-28 18:55:20 +00:00
if err != nil {
2020-09-15 23:47:58 +00:00
return types . EmptyInt , xerrors . Errorf ( "loading state %s: %w" , tsk , err )
2020-07-28 18:55:20 +00:00
}
2020-09-15 23:47:58 +00:00
ssize , err := pci . SealProof . SectorSize ( )
if err != nil {
return types . EmptyInt , xerrors . Errorf ( "failed to get resolve size: %w" , err )
2020-07-28 18:55:20 +00:00
}
2020-09-15 23:47:58 +00:00
store := a . Chain . Store ( ctx )
2020-07-28 18:55:20 +00:00
2020-09-15 23:47:58 +00:00
var sectorWeight abi . StoragePower
if act , err := state . GetActor ( market . Address ) ; err != nil {
2020-09-22 04:12:07 +00:00
return types . EmptyInt , xerrors . Errorf ( "loading market actor %s: %w" , maddr , err )
2020-09-17 07:32:10 +00:00
} else if s , err := market . Load ( store , act ) ; err != nil {
2020-09-15 23:47:58 +00:00
return types . EmptyInt , xerrors . Errorf ( "loading market actor state %s: %w" , maddr , err )
} else if w , vw , err := s . VerifyDealsForActivation ( maddr , pci . DealIDs , ts . Height ( ) , pci . Expiration ) ; err != nil {
2020-09-17 07:32:10 +00:00
return types . EmptyInt , xerrors . Errorf ( "verifying deals for activation: %w" , err )
2020-09-15 23:47:58 +00:00
} else {
// NB: not exactly accurate, but should always lead us to *over* estimate, not under
duration := pci . Expiration - ts . Height ( )
2020-09-30 20:30:24 +00:00
sectorWeight = builtin . QAPowerForWeight ( ssize , duration , w , vw )
2020-07-28 18:55:20 +00:00
}
2020-09-30 20:30:24 +00:00
var powerSmoothed builtin . FilterEstimate
2020-09-15 23:47:58 +00:00
if act , err := state . GetActor ( power . Address ) ; err != nil {
2020-09-22 04:12:07 +00:00
return types . EmptyInt , xerrors . Errorf ( "loading power actor: %w" , err )
2020-09-17 07:32:10 +00:00
} else if s , err := power . Load ( store , act ) ; err != nil {
2020-09-15 23:47:58 +00:00
return types . EmptyInt , xerrors . Errorf ( "loading power actor state: %w" , err )
2020-09-17 07:32:10 +00:00
} else if p , err := s . TotalPowerSmoothed ( ) ; err != nil {
2020-09-15 23:47:58 +00:00
return types . EmptyInt , xerrors . Errorf ( "failed to determine total power: %w" , err )
} else {
powerSmoothed = p
2020-07-28 18:55:20 +00:00
}
2020-09-19 04:30:24 +00:00
rewardActor , err := state . GetActor ( reward . Address )
2020-07-28 18:55:20 +00:00
if err != nil {
2020-09-15 23:47:58 +00:00
return types . EmptyInt , xerrors . Errorf ( "loading miner actor: %w" , err )
2020-07-28 18:55:20 +00:00
}
2020-09-19 04:30:24 +00:00
rewardState , err := reward . Load ( store , rewardActor )
if err != nil {
2020-09-15 23:47:58 +00:00
return types . EmptyInt , xerrors . Errorf ( "loading reward actor state: %w" , err )
}
2020-07-28 18:55:20 +00:00
2020-09-19 04:30:24 +00:00
deposit , err := rewardState . PreCommitDepositForPower ( powerSmoothed , sectorWeight )
if err != nil {
return big . Zero ( ) , xerrors . Errorf ( "calculating precommit deposit: %w" , err )
}
2020-07-28 18:55:20 +00:00
return types . BigDiv ( types . BigMul ( deposit , initialPledgeNum ) , initialPledgeDen ) , nil
}
2020-06-26 15:59:34 +00:00
func ( a * StateAPI ) StateMinerInitialPledgeCollateral ( ctx context . Context , maddr address . Address , pci miner . SectorPreCommitInfo , tsk types . TipSetKey ) ( types . BigInt , error ) {
2020-09-16 01:05:33 +00:00
// TODO: this repeats a lot of the previous function. Fix that.
2020-04-23 19:39:34 +00:00
ts , err := a . Chain . GetTipSetFromKey ( tsk )
if err != nil {
return types . EmptyInt , xerrors . Errorf ( "loading tipset %s: %w" , tsk , err )
}
2020-09-16 01:05:33 +00:00
state , err := a . StateManager . ParentState ( ts )
2020-07-14 11:45:45 +00:00
if err != nil {
2020-09-16 01:05:33 +00:00
return types . EmptyInt , xerrors . Errorf ( "loading state %s: %w" , tsk , err )
2020-04-23 19:39:34 +00:00
}
2020-09-16 01:05:33 +00:00
ssize , err := pci . SealProof . SectorSize ( )
if err != nil {
return types . EmptyInt , xerrors . Errorf ( "failed to get resolve size: %w" , err )
2020-07-24 22:21:34 +00:00
}
2020-09-16 01:05:33 +00:00
store := a . Chain . Store ( ctx )
2020-04-23 19:39:34 +00:00
2020-09-16 01:05:33 +00:00
var sectorWeight abi . StoragePower
if act , err := state . GetActor ( market . Address ) ; err != nil {
return types . EmptyInt , xerrors . Errorf ( "loading miner actor %s: %w" , maddr , err )
2020-09-17 07:32:10 +00:00
} else if s , err := market . Load ( store , act ) ; err != nil {
2020-09-16 01:05:33 +00:00
return types . EmptyInt , xerrors . Errorf ( "loading market actor state %s: %w" , maddr , err )
} else if w , vw , err := s . VerifyDealsForActivation ( maddr , pci . DealIDs , ts . Height ( ) , pci . Expiration ) ; err != nil {
2020-09-17 07:32:10 +00:00
return types . EmptyInt , xerrors . Errorf ( "verifying deals for activation: %w" , err )
2020-09-16 01:05:33 +00:00
} else {
// NB: not exactly accurate, but should always lead us to *over* estimate, not under
duration := pci . Expiration - ts . Height ( )
2020-09-30 20:30:24 +00:00
sectorWeight = builtin . QAPowerForWeight ( ssize , duration , w , vw )
2020-04-23 19:39:34 +00:00
}
2020-09-16 01:05:33 +00:00
var (
2020-09-30 20:30:24 +00:00
powerSmoothed builtin . FilterEstimate
2020-09-17 08:17:14 +00:00
pledgeCollateral abi . TokenAmount
2020-09-16 01:05:33 +00:00
)
if act , err := state . GetActor ( power . Address ) ; err != nil {
return types . EmptyInt , xerrors . Errorf ( "loading miner actor: %w" , err )
2020-09-17 07:32:10 +00:00
} else if s , err := power . Load ( store , act ) ; err != nil {
2020-09-16 01:05:33 +00:00
return types . EmptyInt , xerrors . Errorf ( "loading power actor state: %w" , err )
2020-09-17 07:32:10 +00:00
} else if p , err := s . TotalPowerSmoothed ( ) ; err != nil {
2020-09-16 01:05:33 +00:00
return types . EmptyInt , xerrors . Errorf ( "failed to determine total power: %w" , err )
2020-09-17 07:32:10 +00:00
} else if c , err := s . TotalLocked ( ) ; err != nil {
2020-09-16 01:05:33 +00:00
return types . EmptyInt , xerrors . Errorf ( "failed to determine pledge collateral: %w" , err )
} else {
powerSmoothed = p
pledgeCollateral = c
2020-04-23 19:39:34 +00:00
}
2020-09-19 04:30:24 +00:00
rewardActor , err := state . GetActor ( reward . Address )
2020-06-26 13:49:39 +00:00
if err != nil {
2020-09-16 01:05:33 +00:00
return types . EmptyInt , xerrors . Errorf ( "loading miner actor: %w" , err )
2020-06-26 13:49:39 +00:00
}
2020-04-23 19:39:34 +00:00
2020-09-19 04:30:24 +00:00
rewardState , err := reward . Load ( store , rewardActor )
if err != nil {
2020-09-16 01:05:33 +00:00
return types . EmptyInt , xerrors . Errorf ( "loading reward actor state: %w" , err )
}
2020-04-23 19:39:34 +00:00
2020-10-12 20:41:27 +00:00
circSupply , err := a . StateVMCirculatingSupplyInternal ( ctx , ts . Key ( ) )
2020-06-26 13:49:39 +00:00
if err != nil {
return big . Zero ( ) , xerrors . Errorf ( "getting circulating supply: %w" , err )
2020-04-23 19:39:34 +00:00
}
2020-09-19 04:30:24 +00:00
initialPledge , err := rewardState . InitialPledgeForPower (
2020-07-28 14:36:32 +00:00
sectorWeight ,
2020-09-16 01:05:33 +00:00
pledgeCollateral ,
2020-09-17 08:17:14 +00:00
& powerSmoothed ,
2020-08-14 20:44:33 +00:00
circSupply . FilCirculating ,
2020-07-28 18:55:20 +00:00
)
2020-09-19 04:30:24 +00:00
if err != nil {
return big . Zero ( ) , xerrors . Errorf ( "calculating initial pledge: %w" , err )
}
2020-06-26 13:49:39 +00:00
2020-05-15 14:53:35 +00:00
return types . BigDiv ( types . BigMul ( initialPledge , initialPledgeNum ) , initialPledgeDen ) , nil
2020-04-23 19:39:34 +00:00
}
func ( a * StateAPI ) StateMinerAvailableBalance ( ctx context . Context , maddr address . Address , tsk types . TipSetKey ) ( types . BigInt , error ) {
ts , err := a . Chain . GetTipSetFromKey ( tsk )
if err != nil {
return types . EmptyInt , xerrors . Errorf ( "loading tipset %s: %w" , tsk , err )
}
2020-09-17 08:17:14 +00:00
act , err := a . StateManager . LoadActor ( ctx , maddr , ts )
if err != nil {
return types . EmptyInt , xerrors . Errorf ( "failed to load miner actor: %w" , err )
}
2020-04-23 19:39:34 +00:00
2020-09-17 08:17:14 +00:00
mas , err := miner . Load ( a . StateManager . ChainStore ( ) . Store ( ctx ) , act )
if err != nil {
return types . EmptyInt , xerrors . Errorf ( "failed to load miner actor state: %w" , err )
2020-04-23 19:39:34 +00:00
}
2020-09-17 08:17:14 +00:00
vested , err := mas . VestedFunds ( ts . Height ( ) )
2020-04-23 19:39:34 +00:00
if err != nil {
return types . EmptyInt , err
}
2020-09-17 08:17:14 +00:00
abal , err := mas . AvailableBalance ( act . Balance )
2020-04-23 19:39:34 +00:00
if err != nil {
return types . EmptyInt , err
}
2020-09-17 08:17:14 +00:00
return types . BigAdd ( abal , vested ) , nil
2020-04-23 19:39:34 +00:00
}
2020-07-02 15:57:10 +00:00
2020-07-02 18:49:08 +00:00
// StateVerifiedClientStatus returns the data cap for the given address.
2020-10-01 07:14:59 +00:00
// Returns zero if there is no entry in the data cap table for the
2020-07-02 18:49:08 +00:00
// address.
2020-10-01 07:14:59 +00:00
func ( a * StateAPI ) StateVerifierStatus ( ctx context . Context , addr address . Address , tsk types . TipSetKey ) ( * abi . StoragePower , error ) {
act , err := a . StateGetActor ( ctx , verifreg . Address , tsk )
2020-07-02 15:57:10 +00:00
if err != nil {
2020-07-07 13:59:14 +00:00
return nil , err
2020-07-02 15:57:10 +00:00
}
2020-08-19 12:27:50 +00:00
aid , err := a . StateLookupID ( ctx , addr , tsk )
if err != nil {
log . Warnf ( "lookup failure %v" , err )
return nil , err
}
2020-10-01 07:14:59 +00:00
vrs , err := verifreg . Load ( a . StateManager . ChainStore ( ) . Store ( ctx ) , act )
if err != nil {
return nil , xerrors . Errorf ( "failed to load verified registry state: %w" , err )
}
2020-07-02 15:57:10 +00:00
2020-10-01 07:14:59 +00:00
verified , dcap , err := vrs . VerifierDataCap ( aid )
if err != nil {
return nil , xerrors . Errorf ( "looking up verifier: %w" , err )
}
if ! verified {
return nil , nil
2020-07-02 15:57:10 +00:00
}
2020-10-01 07:14:59 +00:00
return & dcap , nil
}
2020-07-02 18:49:08 +00:00
// StateVerifiedClientStatus returns the data cap for the given address.
2020-09-17 07:48:39 +00:00
// Returns zero if there is no entry in the data cap table for the
2020-07-02 18:49:08 +00:00
// address.
2020-09-17 15:30:15 +00:00
func ( a * StateAPI ) StateVerifiedClientStatus ( ctx context . Context , addr address . Address , tsk types . TipSetKey ) ( * abi . StoragePower , error ) {
2020-09-30 20:30:24 +00:00
act , err := a . StateGetActor ( ctx , verifreg . Address , tsk )
2020-07-02 15:57:10 +00:00
if err != nil {
2020-07-07 13:59:14 +00:00
return nil , err
2020-07-02 15:57:10 +00:00
}
2020-07-07 14:01:08 +00:00
2020-08-19 12:27:50 +00:00
aid , err := a . StateLookupID ( ctx , addr , tsk )
if err != nil {
log . Warnf ( "lookup failure %v" , err )
2020-07-07 13:59:14 +00:00
return nil , err
2020-08-19 12:27:50 +00:00
}
2020-09-17 07:48:39 +00:00
vrs , err := verifreg . Load ( a . StateManager . ChainStore ( ) . Store ( ctx ) , act )
2020-07-02 15:57:10 +00:00
if err != nil {
2020-09-17 15:30:15 +00:00
return nil , xerrors . Errorf ( "failed to load verified registry state: %w" , err )
2020-07-02 15:57:10 +00:00
}
2020-07-07 14:01:08 +00:00
2020-09-17 15:30:15 +00:00
verified , dcap , err := vrs . VerifiedClientDataCap ( aid )
2020-09-17 07:48:39 +00:00
if err != nil {
2020-09-17 15:30:15 +00:00
return nil , xerrors . Errorf ( "looking up verified client: %w" , err )
}
if ! verified {
2020-07-23 00:14:54 +00:00
return nil , nil
2020-07-02 15:57:10 +00:00
}
2020-07-07 13:59:14 +00:00
return & dcap , nil
2020-07-06 20:47:39 +00:00
}
2020-07-30 04:55:37 +00:00
2020-10-01 07:14:59 +00:00
func ( a * StateAPI ) StateVerifiedRegistryRootKey ( ctx context . Context , tsk types . TipSetKey ) ( address . Address , error ) {
vact , err := a . StateGetActor ( ctx , verifreg . Address , tsk )
if err != nil {
return address . Undef , err
}
vst , err := verifreg . Load ( a . StateManager . ChainStore ( ) . Store ( ctx ) , vact )
if err != nil {
return address . Undef , err
}
return vst . RootKey ( )
}
2020-07-30 04:55:37 +00:00
var dealProviderCollateralNum = types . NewInt ( 110 )
var dealProviderCollateralDen = types . NewInt ( 100 )
// StateDealProviderCollateralBounds returns the min and max collateral a storage provider
// can issue. It takes the deal size and verified status as parameters.
2020-07-30 12:31:31 +00:00
func ( a * StateAPI ) StateDealProviderCollateralBounds ( ctx context . Context , size abi . PaddedPieceSize , verified bool , tsk types . TipSetKey ) ( api . DealCollateralBounds , error ) {
2020-07-30 04:55:37 +00:00
ts , err := a . Chain . GetTipSetFromKey ( tsk )
if err != nil {
2020-07-30 12:31:31 +00:00
return api . DealCollateralBounds { } , xerrors . Errorf ( "loading tipset %s: %w" , tsk , err )
2020-07-30 04:55:37 +00:00
}
2020-09-30 20:30:24 +00:00
pact , err := a . StateGetActor ( ctx , power . Address , tsk )
2020-09-17 08:17:14 +00:00
if err != nil {
return api . DealCollateralBounds { } , xerrors . Errorf ( "failed to load power actor: %w" , err )
}
2020-07-30 04:55:37 +00:00
2020-09-30 20:30:24 +00:00
ract , err := a . StateGetActor ( ctx , reward . Address , tsk )
2020-09-17 08:17:14 +00:00
if err != nil {
return api . DealCollateralBounds { } , xerrors . Errorf ( "failed to load reward actor: %w" , err )
}
2020-07-30 04:55:37 +00:00
2020-09-17 08:17:14 +00:00
pst , err := power . Load ( a . StateManager . ChainStore ( ) . Store ( ctx ) , pact )
if err != nil {
return api . DealCollateralBounds { } , xerrors . Errorf ( "failed to load power actor state: %w" , err )
}
2020-07-30 04:55:37 +00:00
2020-09-17 08:17:14 +00:00
rst , err := reward . Load ( a . StateManager . ChainStore ( ) . Store ( ctx ) , ract )
2020-07-30 04:55:37 +00:00
if err != nil {
2020-09-17 08:17:14 +00:00
return api . DealCollateralBounds { } , xerrors . Errorf ( "failed to load reward actor state: %w" , err )
2020-07-30 04:55:37 +00:00
}
2020-10-12 20:41:27 +00:00
circ , err := a . StateVMCirculatingSupplyInternal ( ctx , ts . Key ( ) )
2020-07-30 04:55:37 +00:00
if err != nil {
2020-08-20 04:49:10 +00:00
return api . DealCollateralBounds { } , xerrors . Errorf ( "getting total circulating supply: %w" , err )
2020-07-30 04:55:37 +00:00
}
2020-09-17 08:17:14 +00:00
powClaim , err := pst . TotalPower ( )
if err != nil {
return api . DealCollateralBounds { } , xerrors . Errorf ( "getting total power: %w" , err )
}
rewPow , err := rst . ThisEpochBaselinePower ( )
if err != nil {
return api . DealCollateralBounds { } , xerrors . Errorf ( "getting reward baseline power: %w" , err )
}
2020-09-30 20:30:24 +00:00
min , max := policy . DealProviderCollateralBounds ( size ,
2020-09-07 20:01:09 +00:00
verified ,
2020-09-17 08:17:14 +00:00
powClaim . RawBytePower ,
powClaim . QualityAdjPower ,
rewPow ,
2020-09-07 20:01:09 +00:00
circ . FilCirculating ,
a . StateManager . GetNtwkVersion ( ctx , ts . Height ( ) ) )
2020-07-30 12:31:31 +00:00
return api . DealCollateralBounds {
Min : types . BigDiv ( types . BigMul ( min , dealProviderCollateralNum ) , dealProviderCollateralDen ) ,
Max : max ,
} , nil
2020-07-30 04:55:37 +00:00
}
2020-08-07 19:57:03 +00:00
2020-10-11 22:17:28 +00:00
func ( a * StateAPI ) StateCirculatingSupply ( ctx context . Context , tsk types . TipSetKey ) ( abi . TokenAmount , error ) {
ts , err := a . Chain . GetTipSetFromKey ( tsk )
if err != nil {
return types . EmptyInt , xerrors . Errorf ( "loading tipset %s: %w" , tsk , err )
}
sTree , err := a . stateForTs ( ctx , ts )
if err != nil {
return types . EmptyInt , err
}
return a . StateManager . GetCirculatingSupply ( ctx , ts . Height ( ) , sTree )
}
2020-10-12 20:41:27 +00:00
func ( a * StateAPI ) StateVMCirculatingSupplyInternal ( ctx context . Context , tsk types . TipSetKey ) ( api . CirculatingSupply , error ) {
2020-08-07 19:57:03 +00:00
ts , err := a . Chain . GetTipSetFromKey ( tsk )
if err != nil {
2020-08-14 20:44:33 +00:00
return api . CirculatingSupply { } , xerrors . Errorf ( "loading tipset %s: %w" , tsk , err )
2020-08-07 19:57:03 +00:00
}
2020-09-12 03:07:52 +00:00
sTree , err := a . stateForTs ( ctx , ts )
2020-08-09 22:49:38 +00:00
if err != nil {
2020-08-14 20:44:33 +00:00
return api . CirculatingSupply { } , err
2020-08-09 22:49:38 +00:00
}
2020-10-11 22:17:28 +00:00
return a . StateManager . GetVMCirculatingSupplyDetailed ( ctx , ts . Height ( ) , sTree )
2020-08-07 19:57:03 +00:00
}
2020-08-09 22:49:38 +00:00
2020-09-17 01:56:02 +00:00
func ( a * StateAPI ) StateNetworkVersion ( ctx context . Context , tsk types . TipSetKey ) ( network . Version , error ) {
ts , err := a . Chain . GetTipSetFromKey ( tsk )
2020-08-20 04:49:10 +00:00
if err != nil {
2020-09-17 08:17:14 +00:00
return network . VersionMax , xerrors . Errorf ( "loading tipset %s: %w" , tsk , err )
2020-08-20 04:49:10 +00:00
}
2020-08-09 22:49:38 +00:00
2020-09-17 01:56:02 +00:00
return a . StateManager . GetNtwkVersion ( ctx , ts . Height ( ) ) , nil
}