2019-09-06 06:26:02 +00:00
package stmgr
import (
2020-04-30 22:11:14 +00:00
"bytes"
2019-09-06 06:26:02 +00:00
"context"
2020-09-04 03:28:42 +00:00
"fmt"
2020-04-20 17:43:02 +00:00
"os"
2020-07-03 16:57:58 +00:00
"reflect"
2020-09-04 03:28:42 +00:00
"runtime"
"strings"
2020-04-17 23:36:54 +00:00
2020-09-21 06:52:45 +00:00
"github.com/filecoin-project/specs-actors/actors/builtin/cron"
2020-09-17 06:34:15 +00:00
2020-09-07 06:08:53 +00:00
saruntime "github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/filecoin-project/specs-actors/actors/runtime/proof"
2020-04-20 17:43:02 +00:00
cid "github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-address"
2020-07-01 04:57:49 +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/crypto"
2020-09-14 22:43:12 +00:00
"github.com/filecoin-project/lotus/chain/actors/builtin/power"
2020-08-17 13:26:18 +00:00
"github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper"
2020-09-21 06:52:45 +00:00
builtin0 "github.com/filecoin-project/specs-actors/actors/builtin"
account0 "github.com/filecoin-project/specs-actors/actors/builtin/account"
init0 "github.com/filecoin-project/specs-actors/actors/builtin/init"
market0 "github.com/filecoin-project/specs-actors/actors/builtin/market"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
2020-09-18 21:59:27 +00:00
msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
2020-09-21 06:52:45 +00:00
paych0 "github.com/filecoin-project/specs-actors/actors/builtin/paych"
power0 "github.com/filecoin-project/specs-actors/actors/builtin/power"
2020-09-18 21:59:27 +00:00
reward0 "github.com/filecoin-project/specs-actors/actors/builtin/reward"
verifreg0 "github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
2020-02-08 02:18:32 +00:00
2019-10-18 04:47:41 +00:00
"github.com/filecoin-project/lotus/api"
2020-04-17 23:36:54 +00:00
"github.com/filecoin-project/lotus/build"
2020-09-14 22:43:12 +00:00
init_ "github.com/filecoin-project/lotus/chain/actors/builtin/init"
2020-09-15 13:29:25 +00:00
"github.com/filecoin-project/lotus/chain/actors/builtin/market"
2020-09-14 22:43:12 +00:00
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
2020-04-30 22:11:14 +00:00
"github.com/filecoin-project/lotus/chain/beacon"
2020-03-31 23:13:37 +00:00
"github.com/filecoin-project/lotus/chain/state"
2020-01-17 02:33:43 +00:00
"github.com/filecoin-project/lotus/chain/store"
2019-10-18 04:47:41 +00:00
"github.com/filecoin-project/lotus/chain/types"
2020-01-17 02:33:43 +00:00
"github.com/filecoin-project/lotus/chain/vm"
2020-03-31 23:13:37 +00:00
"github.com/filecoin-project/lotus/node/modules/dtypes"
2019-09-06 06:26:02 +00:00
)
2020-03-31 23:13:37 +00:00
func GetNetworkName ( ctx context . Context , sm * StateManager , st cid . Cid ) ( dtypes . NetworkName , error ) {
2020-09-14 22:43:12 +00:00
act , err := sm . LoadActorRaw ( ctx , init_ . Address , st )
if err != nil {
return "" , err
}
ias , err := init_ . Load ( sm . cs . Store ( ctx ) , act )
2020-03-31 23:13:37 +00:00
if err != nil {
2020-07-14 11:45:45 +00:00
return "" , err
2020-03-31 23:13:37 +00:00
}
2020-09-15 04:55:49 +00:00
return ias . NetworkName ( )
2020-03-31 23:13:37 +00:00
}
2019-10-23 17:39:14 +00:00
func GetMinerWorkerRaw ( ctx context . Context , sm * StateManager , st cid . Cid , maddr address . Address ) ( address . Address , error ) {
2020-09-15 04:55:49 +00:00
state , err := sm . StateTree ( st )
2019-09-06 06:26:02 +00:00
if err != nil {
2020-09-15 04:55:49 +00:00
return address . Undef , xerrors . Errorf ( "(get sset) failed to load state tree: %w" , err )
}
act , err := state . GetActor ( maddr )
if err != nil {
return address . Undef , xerrors . Errorf ( "(get sset) failed to load miner actor: %w" , err )
2019-09-06 06:26:02 +00:00
}
2020-09-14 22:43:12 +00:00
mas , err := miner . Load ( sm . cs . Store ( ctx ) , act )
2020-02-21 16:57:40 +00:00
if err != nil {
2020-09-15 04:55:49 +00:00
return address . Undef , xerrors . Errorf ( "(get sset) failed to load miner actor state: %w" , err )
2020-02-21 16:57:40 +00:00
}
2020-09-14 22:43:12 +00:00
info , err := mas . Info ( )
2020-07-01 11:47:40 +00:00
if err != nil {
2020-09-14 22:43:12 +00:00
return address . Undef , xerrors . Errorf ( "failed to load actor info: %w" , err )
2020-07-01 11:47:40 +00:00
}
2020-09-15 04:55:49 +00:00
return vm . ResolveToKeyAddr ( state , sm . cs . Store ( ctx ) , info . Worker )
2019-09-06 06:26:02 +00:00
}
2020-09-16 05:47:24 +00:00
func GetPower ( ctx context . Context , sm * StateManager , ts * types . TipSet , maddr address . Address ) ( power . Claim , power . Claim , bool , error ) {
2020-04-17 23:36:54 +00:00
return GetPowerRaw ( ctx , sm , ts . ParentState ( ) , maddr )
2020-04-02 01:25:58 +00:00
}
2020-09-16 05:47:24 +00:00
func GetPowerRaw ( ctx context . Context , sm * StateManager , st cid . Cid , maddr address . Address ) ( power . Claim , power . Claim , bool , error ) {
2020-09-22 04:12:07 +00:00
act , err := sm . LoadActorRaw ( ctx , power . Address , st )
2020-02-11 02:33:27 +00:00
if err != nil {
2020-09-16 05:47:24 +00:00
return power . Claim { } , power . Claim { } , false , xerrors . Errorf ( "(get sset) failed to load power actor state: %w" , err )
2020-02-11 02:33:27 +00:00
}
2019-09-09 20:03:10 +00:00
2020-09-16 05:47:24 +00:00
pas , err := power . Load ( sm . cs . Store ( ctx ) , act )
2020-09-14 22:43:12 +00:00
if err != nil {
2020-09-16 05:47:24 +00:00
return power . Claim { } , power . Claim { } , false , err
2020-09-14 22:43:12 +00:00
}
2020-09-16 05:47:24 +00:00
tpow , err := pas . TotalPower ( )
2020-09-14 22:43:12 +00:00
if err != nil {
2020-09-16 05:47:24 +00:00
return power . Claim { } , power . Claim { } , false , err
2020-09-14 22:43:12 +00:00
}
2020-04-17 22:02:04 +00:00
var mpow power . Claim
2019-09-09 20:03:10 +00:00
if maddr != address . Undef {
2020-09-15 19:13:13 +00:00
var found bool
2020-09-16 05:47:24 +00:00
mpow , found , err = pas . MinerPower ( maddr )
2020-09-15 19:13:13 +00:00
if err != nil || ! found {
// TODO: return an error when not found?
2020-09-16 05:47:24 +00:00
return power . Claim { } , power . Claim { } , false , err
2020-04-13 21:05:34 +00:00
}
2019-09-09 20:03:10 +00:00
}
2020-09-16 05:47:24 +00:00
minpow , err := pas . MinerNominalPowerMeetsConsensusMinimum ( maddr )
if err != nil {
return power . Claim { } , power . Claim { } , false , err
}
return mpow , tpow , minpow , nil
2019-09-09 20:03:10 +00:00
}
2019-09-17 08:00:38 +00:00
2020-09-15 04:55:49 +00:00
func PreCommitInfo ( ctx context . Context , sm * StateManager , maddr address . Address , sid abi . SectorNumber , ts * types . TipSet ) ( * miner . SectorPreCommitOnChainInfo , error ) {
2020-09-14 22:43:12 +00:00
act , err := sm . LoadActor ( ctx , maddr , ts )
2020-04-04 02:55:19 +00:00
if err != nil {
2020-09-15 04:55:49 +00:00
return nil , xerrors . Errorf ( "(get sset) failed to load miner actor: %w" , err )
2020-04-04 02:55:19 +00:00
}
2020-09-15 04:55:49 +00:00
mas , err := miner . Load ( sm . cs . Store ( ctx ) , act )
2020-04-04 02:55:19 +00:00
if err != nil {
2020-09-15 04:55:49 +00:00
return nil , xerrors . Errorf ( "(get sset) failed to load miner actor state: %w" , err )
2020-04-04 02:55:19 +00:00
}
2020-09-15 04:55:49 +00:00
return mas . GetPrecommittedSector ( sid )
2020-04-04 02:55:19 +00:00
}
2020-05-28 00:06:29 +00:00
func MinerSectorInfo ( ctx context . Context , sm * StateManager , maddr address . Address , sid abi . SectorNumber , ts * types . TipSet ) ( * miner . SectorOnChainInfo , error ) {
2020-09-15 04:55:49 +00:00
act , err := sm . LoadActor ( ctx , maddr , ts )
2020-05-28 00:06:29 +00:00
if err != nil {
2020-09-15 04:55:49 +00:00
return nil , xerrors . Errorf ( "(get sset) failed to load miner actor: %w" , err )
2020-05-28 00:06:29 +00:00
}
2020-09-15 04:55:49 +00:00
mas , err := miner . Load ( sm . cs . Store ( ctx ) , act )
2020-05-28 00:06:29 +00:00
if err != nil {
2020-09-15 04:55:49 +00:00
return nil , xerrors . Errorf ( "(get sset) failed to load miner actor state: %w" , err )
2020-05-28 00:06:29 +00:00
}
2020-09-15 04:55:49 +00:00
return mas . GetSector ( sid )
2020-05-28 00:06:29 +00:00
}
2020-09-21 19:05:01 +00:00
func GetMinerSectorSet ( ctx context . Context , sm * StateManager , ts * types . TipSet , maddr address . Address , snos * bitfield . BitField ) ( [ ] * miner . SectorOnChainInfo , error ) {
2020-09-15 11:04:45 +00:00
act , err := sm . LoadActor ( ctx , maddr , ts )
if err != nil {
return nil , xerrors . Errorf ( "(get sset) failed to load miner actor: %w" , err )
}
mas , err := miner . Load ( sm . cs . Store ( ctx ) , act )
2019-09-18 02:55:51 +00:00
if err != nil {
2019-11-30 04:31:16 +00:00
return nil , xerrors . Errorf ( "(get sset) failed to load miner actor state: %w" , err )
2019-09-18 02:55:51 +00:00
}
2020-09-21 19:05:01 +00:00
return mas . LoadSectors ( snos )
2019-09-18 02:55:51 +00:00
}
2020-09-07 03:49:10 +00:00
func GetSectorsForWinningPoSt ( ctx context . Context , pv ffiwrapper . Verifier , sm * StateManager , st cid . Cid , maddr address . Address , rand abi . PoStRandomness ) ( [ ] proof . SectorInfo , error ) {
2020-09-15 11:04:45 +00:00
act , err := sm . LoadActorRaw ( ctx , maddr , st )
if err != nil {
return nil , xerrors . Errorf ( "failed to load miner actor: %w" , err )
}
2020-07-14 11:45:45 +00:00
2020-09-15 11:04:45 +00:00
mas , err := miner . Load ( sm . cs . Store ( ctx ) , act )
2020-07-01 04:57:49 +00:00
if err != nil {
2020-09-15 11:04:45 +00:00
return nil , xerrors . Errorf ( "failed to load miner actor state: %w" , err )
2020-07-01 04:57:49 +00:00
}
2020-09-20 21:04:45 +00:00
// TODO (!!): Actor Update: Make this active sectors
2020-09-15 11:04:45 +00:00
2020-09-20 21:04:45 +00:00
allSectors , err := miner . AllPartSectors ( mas , miner . Partition . AllSectors )
2020-07-01 04:57:49 +00:00
if err != nil {
2020-09-20 21:04:45 +00:00
return nil , xerrors . Errorf ( "get all sectors: %w" , err )
}
faultySectors , err := miner . AllPartSectors ( mas , miner . Partition . FaultySectors )
if err != nil {
return nil , xerrors . Errorf ( "get faulty sectors: %w" , err )
}
provingSectors , err := bitfield . SubtractBitField ( allSectors , faultySectors ) // TODO: This is wrong, as it can contain faaults, change to just ActiveSectors in an upgrade
if err != nil {
return nil , xerrors . Errorf ( "calc proving sectors: %w" , err )
2020-07-01 04:57:49 +00:00
}
numProvSect , err := provingSectors . Count ( )
2020-04-17 14:47:19 +00:00
if err != nil {
2020-07-01 04:57:49 +00:00
return nil , xerrors . Errorf ( "failed to count bits: %w" , err )
2020-04-17 14:47:19 +00:00
}
2020-07-01 04:57:49 +00:00
// TODO(review): is this right? feels fishy to me
if numProvSect == 0 {
2020-04-23 21:12:42 +00:00
return nil , nil
}
2020-09-15 11:04:45 +00:00
info , err := mas . Info ( )
if err != nil {
return nil , xerrors . Errorf ( "getting miner info: %w" , err )
}
2020-07-01 11:47:40 +00:00
spt , err := ffiwrapper . SealProofTypeFromSectorSize ( info . SectorSize )
2020-04-17 14:47:19 +00:00
if err != nil {
return nil , xerrors . Errorf ( "getting seal proof type: %w" , err )
}
wpt , err := spt . RegisteredWinningPoStProof ( )
if err != nil {
return nil , xerrors . Errorf ( "getting window proof type: %w" , err )
}
mid , err := address . IDFromAddress ( maddr )
if err != nil {
return nil , xerrors . Errorf ( "getting miner ID: %w" , err )
}
2020-07-01 04:57:49 +00:00
ids , err := pv . GenerateWinningPoStSectorChallenge ( ctx , wpt , abi . ActorID ( mid ) , rand , numProvSect )
2020-04-17 14:47:19 +00:00
if err != nil {
return nil , xerrors . Errorf ( "generating winning post challenges: %w" , err )
}
2020-09-21 19:05:01 +00:00
iter , err := provingSectors . BitIterator ( )
2020-07-01 04:57:49 +00:00
if err != nil {
2020-09-21 19:05:01 +00:00
return nil , xerrors . Errorf ( "iterating over proving sectors: %w" , err )
2020-07-01 04:57:49 +00:00
}
2020-09-21 19:05:01 +00:00
// Select winning sectors by _index_ in the all-sectors bitfield.
selectedSectors := bitfield . New ( )
prev := uint64 ( 0 )
for _ , n := range ids {
sno , err := iter . Nth ( n - prev )
2020-09-17 06:34:15 +00:00
if err != nil {
2020-09-21 19:05:01 +00:00
return nil , xerrors . Errorf ( "iterating over proving sectors: %w" , err )
2020-09-17 06:34:15 +00:00
}
2020-09-21 19:05:01 +00:00
selectedSectors . Set ( sno )
prev = n
}
2020-09-17 06:34:15 +00:00
2020-09-21 19:05:01 +00:00
sectors , err := mas . LoadSectors ( & selectedSectors )
if err != nil {
return nil , xerrors . Errorf ( "loading proving sectors: %w" , err )
}
2020-07-01 04:57:49 +00:00
2020-09-21 19:05:01 +00:00
out := make ( [ ] proof . SectorInfo , len ( sectors ) )
for i , sinfo := range sectors {
2020-09-07 03:49:10 +00:00
out [ i ] = proof . SectorInfo {
2020-06-15 16:30:49 +00:00
SealProof : spt ,
2020-09-17 06:34:15 +00:00
SectorNumber : sinfo . SectorNumber ,
SealedCID : sinfo . SealedCID ,
2020-04-17 14:47:19 +00:00
}
}
return out , nil
2020-04-17 05:39:55 +00:00
}
2020-07-01 11:47:40 +00:00
func StateMinerInfo ( ctx context . Context , sm * StateManager , ts * types . TipSet , maddr address . Address ) ( * miner . MinerInfo , error ) {
2020-09-15 11:04:45 +00:00
act , err := sm . LoadActor ( ctx , maddr , ts )
2020-04-16 17:36:36 +00:00
if err != nil {
2020-09-15 11:04:45 +00:00
return nil , xerrors . Errorf ( "failed to load miner actor: %w" , err )
2020-04-16 17:36:36 +00:00
}
2020-09-15 11:04:45 +00:00
mas , err := miner . Load ( sm . cs . Store ( ctx ) , act )
if err != nil {
return nil , xerrors . Errorf ( "failed to load miner actor state: %w" , err )
}
mi , err := mas . Info ( )
if err != nil {
return nil , err
}
return & mi , err
2020-04-02 01:25:58 +00:00
}
2020-03-02 01:09:38 +00:00
func GetMinerSlashed ( ctx context . Context , sm * StateManager , ts * types . TipSet , maddr address . Address ) ( bool , error ) {
2020-09-22 04:12:07 +00:00
act , err := sm . LoadActor ( ctx , power . Address , ts )
2020-09-15 11:04:45 +00:00
if err != nil {
return false , xerrors . Errorf ( "failed to load power actor: %w" , err )
}
spas , err := power . Load ( sm . cs . Store ( ctx ) , act )
2020-03-02 01:09:38 +00:00
if err != nil {
2020-09-15 11:04:45 +00:00
return false , xerrors . Errorf ( "failed to load power actor state: %w" , err )
2020-03-02 01:09:38 +00:00
}
2020-09-15 13:29:25 +00:00
_ , ok , err := spas . MinerPower ( maddr )
2020-04-21 14:32:17 +00:00
if err != nil {
2020-09-15 13:29:25 +00:00
return false , xerrors . Errorf ( "getting miner power: %w" , err )
2020-03-02 01:09:38 +00:00
}
2020-04-16 20:52:40 +00:00
2020-04-21 14:32:17 +00:00
if ! ok {
return true , nil
2020-03-02 01:09:38 +00:00
}
return false , nil
2019-11-15 01:01:53 +00:00
}
2020-06-02 14:29:39 +00:00
func GetStorageDeal ( ctx context . Context , sm * StateManager , dealID abi . DealID , ts * types . TipSet ) ( * api . MarketDeal , error ) {
2020-09-22 04:12:07 +00:00
act , err := sm . LoadActor ( ctx , market . Address , ts )
2020-09-15 11:04:45 +00:00
if err != nil {
return nil , xerrors . Errorf ( "failed to load market actor: %w" , err )
}
state , err := market . Load ( sm . cs . Store ( ctx ) , act )
if err != nil {
return nil , xerrors . Errorf ( "failed to load market actor state: %w" , err )
2019-11-07 07:57:10 +00:00
}
2020-09-15 11:04:45 +00:00
2020-09-17 07:32:10 +00:00
proposals , err := state . Proposals ( )
2019-11-07 07:57:10 +00:00
if err != nil {
return nil , err
}
2020-09-17 07:32:10 +00:00
proposal , found , err := proposals . Get ( dealID )
if err != nil {
2019-11-07 07:57:10 +00:00
return nil , err
2020-07-23 00:14:54 +00:00
} else if ! found {
return nil , xerrors . Errorf ( "deal %d not found" , dealID )
2019-11-07 07:57:10 +00:00
}
2020-09-17 07:32:10 +00:00
states , err := state . States ( )
2020-04-13 21:05:34 +00:00
if err != nil {
return nil , err
}
2020-09-17 07:32:10 +00:00
st , found , err := states . Get ( dealID )
2020-02-09 06:06:32 +00:00
if err != nil {
return nil , err
}
2020-05-06 00:04:25 +00:00
if ! found {
2020-09-17 07:32:10 +00:00
st = market . EmptyDealState ( )
2020-05-06 00:04:25 +00:00
}
2020-02-09 06:06:32 +00:00
return & api . MarketDeal {
2020-09-17 07:32:10 +00:00
Proposal : * proposal ,
2020-02-23 15:50:36 +00:00
State : * st ,
2020-02-09 06:06:32 +00:00
} , nil
2019-11-07 07:57:10 +00:00
}
2019-12-17 06:51:41 +00:00
func ListMinerActors ( ctx context . Context , sm * StateManager , ts * types . TipSet ) ( [ ] address . Address , error ) {
2020-09-22 04:12:07 +00:00
act , err := sm . LoadActor ( ctx , power . Address , ts )
2020-09-15 11:04:45 +00:00
if err != nil {
return nil , xerrors . Errorf ( "failed to load power actor: %w" , err )
}
2020-09-16 05:00:00 +00:00
powState , err := power . Load ( sm . cs . Store ( ctx ) , act )
2020-09-15 11:04:45 +00:00
if err != nil {
return nil , xerrors . Errorf ( "failed to load power actor state: %w" , err )
2019-12-17 06:51:41 +00:00
}
2020-09-16 05:00:00 +00:00
return powState . ListAllMiners ( )
2019-09-17 22:43:47 +00:00
}
2020-01-17 02:33:43 +00:00
2020-03-08 02:31:36 +00:00
func ComputeState ( ctx context . Context , sm * StateManager , height abi . ChainEpoch , msgs [ ] * types . Message , ts * types . TipSet ) ( cid . Cid , [ ] * api . InvocResult , error ) {
2020-01-17 02:33:43 +00:00
if ts == nil {
ts = sm . cs . GetHeaviestTipSet ( )
}
2020-03-08 02:31:36 +00:00
base , trace , err := sm . ExecutionTrace ( ctx , ts )
2020-01-17 02:33:43 +00:00
if err != nil {
2020-03-08 02:31:36 +00:00
return cid . Undef , nil , err
2020-01-17 02:33:43 +00:00
}
2020-09-01 19:48:16 +00:00
r := store . NewChainRand ( sm . cs , ts . Cids ( ) )
2020-08-06 17:09:03 +00:00
vmopt := & vm . VMOpts {
2020-08-09 22:49:38 +00:00
StateBase : base ,
Epoch : height ,
Rand : r ,
Bstore : sm . cs . Blockstore ( ) ,
Syscalls : sm . cs . VMSys ( ) ,
CircSupplyCalc : sm . GetCirculatingSupply ,
2020-09-07 20:01:09 +00:00
NtwkVersion : sm . GetNtwkVersion ,
2020-08-09 22:49:38 +00:00
BaseFee : ts . Blocks ( ) [ 0 ] . ParentBaseFee ,
2020-08-06 17:09:03 +00:00
}
2020-09-15 11:04:45 +00:00
vmi , err := vm . NewVM ( ctx , vmopt )
2020-01-17 02:33:43 +00:00
if err != nil {
2020-03-08 02:31:36 +00:00
return cid . Undef , nil , err
2020-01-17 02:33:43 +00:00
}
2020-07-28 12:31:13 +00:00
for i := ts . Height ( ) ; i < height ; i ++ {
// handle state forks
2020-09-08 20:45:44 +00:00
err = sm . handleStateForks ( ctx , vmi . StateTree ( ) , i , ts )
2020-07-28 12:31:13 +00:00
if err != nil {
return cid . Undef , nil , xerrors . Errorf ( "error handling state forks: %w" , err )
}
// TODO: should we also run cron here?
2020-01-17 02:33:43 +00:00
}
for i , msg := range msgs {
2020-03-25 11:29:35 +00:00
// TODO: Use the signed message length for secp messages
2020-03-25 19:13:09 +00:00
ret , err := vmi . ApplyMessage ( ctx , msg )
2020-01-17 02:33:43 +00:00
if err != nil {
2020-03-08 02:31:36 +00:00
return cid . Undef , nil , xerrors . Errorf ( "applying message %s: %w" , msg . Cid ( ) , err )
2020-01-17 02:33:43 +00:00
}
if ret . ExitCode != 0 {
2020-01-17 06:14:00 +00:00
log . Infof ( "compute state apply message %d failed (exit: %d): %s" , i , ret . ExitCode , ret . ActorErr )
2020-01-17 02:33:43 +00:00
}
}
2020-03-08 02:31:36 +00:00
root , err := vmi . Flush ( ctx )
if err != nil {
return cid . Undef , nil , err
}
return root , trace , nil
2020-01-17 02:33:43 +00:00
}
2020-04-02 01:10:28 +00:00
2020-04-17 23:36:54 +00:00
func GetLookbackTipSetForRound ( ctx context . Context , sm * StateManager , ts * types . TipSet , round abi . ChainEpoch ) ( * types . TipSet , error ) {
var lbr abi . ChainEpoch
if round > build . WinningPoStSectorSetLookback {
lbr = round - build . WinningPoStSectorSetLookback
}
// more null blocks than our lookback
if lbr > ts . Height ( ) {
return ts , nil
}
2020-05-05 17:06:05 +00:00
lbts , err := sm . ChainStore ( ) . GetTipsetByHeight ( ctx , lbr , ts , true )
2020-04-17 23:36:54 +00:00
if err != nil {
return nil , xerrors . Errorf ( "failed to get lookback tipset: %w" , err )
}
return lbts , nil
}
2020-09-08 20:28:06 +00:00
func MinerGetBaseInfo ( ctx context . Context , sm * StateManager , bcs beacon . Schedule , tsk types . TipSetKey , round abi . ChainEpoch , maddr address . Address , pv ffiwrapper . Verifier ) ( * api . MiningBaseInfo , error ) {
2020-04-02 01:10:28 +00:00
ts , err := sm . ChainStore ( ) . LoadTipSet ( tsk )
if err != nil {
return nil , xerrors . Errorf ( "failed to load tipset for mining base: %w" , err )
}
2020-04-30 22:11:14 +00:00
prev , err := sm . ChainStore ( ) . GetLatestBeaconEntry ( ts )
if err != nil {
if os . Getenv ( "LOTUS_IGNORE_DRAND" ) != "_yes_" {
return nil , xerrors . Errorf ( "failed to get latest beacon entry: %w" , err )
}
prev = & types . BeaconEntry { }
}
2020-09-08 20:28:06 +00:00
entries , err := beacon . BeaconEntriesForBlock ( ctx , bcs , round , ts . Height ( ) , * prev )
2020-04-30 22:11:14 +00:00
if err != nil {
return nil , err
}
rbase := * prev
if len ( entries ) > 0 {
rbase = entries [ len ( entries ) - 1 ]
}
2020-04-17 23:36:54 +00:00
lbts , err := GetLookbackTipSetForRound ( ctx , sm , ts , round )
if err != nil {
return nil , xerrors . Errorf ( "getting lookback miner actor state: %w" , err )
}
lbst , _ , err := sm . TipSetState ( ctx , lbts )
2020-04-02 01:10:28 +00:00
if err != nil {
return nil , err
}
2020-09-15 11:04:45 +00:00
act , err := sm . LoadActorRaw ( ctx , maddr , lbst )
if err != nil {
return nil , xerrors . Errorf ( "failed to load miner actor: %w" , err )
}
mas , err := miner . Load ( sm . cs . Store ( ctx ) , act )
if err != nil {
return nil , xerrors . Errorf ( "failed to load miner actor state: %w" , err )
2020-04-17 23:36:54 +00:00
}
2020-04-30 22:11:14 +00:00
buf := new ( bytes . Buffer )
if err := maddr . MarshalCBOR ( buf ) ; err != nil {
return nil , xerrors . Errorf ( "failed to marshal miner address: %w" , err )
}
2020-05-01 19:42:59 +00:00
prand , err := store . DrawRandomness ( rbase . Data , crypto . DomainSeparationTag_WinningPoStChallengeSeed , round , buf . Bytes ( ) )
2020-04-02 01:10:28 +00:00
if err != nil {
2020-04-17 23:36:54 +00:00
return nil , xerrors . Errorf ( "failed to get randomness for winning post: %w" , err )
2020-04-02 01:10:28 +00:00
}
2020-04-17 23:36:54 +00:00
sectors , err := GetSectorsForWinningPoSt ( ctx , pv , sm , lbst , maddr , prand )
2020-04-02 01:10:28 +00:00
if err != nil {
2020-09-16 01:19:27 +00:00
return nil , xerrors . Errorf ( "getting winning post proving set: %w" , err )
2020-04-02 01:10:28 +00:00
}
2020-04-23 21:12:42 +00:00
if len ( sectors ) == 0 {
return nil , nil
}
2020-09-16 05:47:24 +00:00
mpow , tpow , hmp , err := GetPowerRaw ( ctx , sm , lbst , maddr )
2020-04-02 01:10:28 +00:00
if err != nil {
2020-04-15 19:59:11 +00:00
return nil , xerrors . Errorf ( "failed to get power: %w" , err )
2020-04-02 01:10:28 +00:00
}
2020-09-15 11:04:45 +00:00
info , err := mas . Info ( )
2020-07-01 11:47:40 +00:00
if err != nil {
return nil , err
}
worker , err := sm . ResolveToKeyAddress ( ctx , info . Worker , ts )
2020-04-16 17:17:56 +00:00
if err != nil {
return nil , xerrors . Errorf ( "resolving worker address: %w" , err )
}
2020-04-02 01:10:28 +00:00
return & api . MiningBaseInfo {
2020-04-17 22:02:04 +00:00
MinerPower : mpow . QualityAdjPower ,
NetworkPower : tpow . QualityAdjPower ,
2020-04-17 23:36:54 +00:00
Sectors : sectors ,
2020-04-16 17:17:56 +00:00
WorkerKey : worker ,
2020-07-01 11:47:40 +00:00
SectorSize : info . SectorSize ,
2020-04-09 17:13:09 +00:00
PrevBeaconEntry : * prev ,
2020-04-30 22:11:14 +00:00
BeaconEntries : entries ,
2020-07-27 23:51:30 +00:00
HasMinPower : hmp ,
2020-04-02 01:10:28 +00:00
} , nil
}
2020-06-26 13:49:39 +00:00
2020-09-04 03:28:42 +00:00
type MethodMeta struct {
2020-07-03 16:57:58 +00:00
Name string
Params reflect . Type
Ret reflect . Type
}
2020-09-04 03:28:42 +00:00
var MethodsMap = map [ cid . Cid ] map [ abi . MethodNum ] MethodMeta { }
2020-07-03 16:57:58 +00:00
func init ( ) {
cidToMethods := map [ cid . Cid ] [ 2 ] interface { } {
// builtin.SystemActorCodeID: {builtin.MethodsSystem, system.Actor{} }- apparently it doesn't have methods
2020-09-21 06:52:45 +00:00
builtin0 . InitActorCodeID : { builtin0 . MethodsInit , init0 . Actor { } } ,
builtin0 . CronActorCodeID : { builtin0 . MethodsCron , cron . Actor { } } ,
builtin0 . AccountActorCodeID : { builtin0 . MethodsAccount , account0 . Actor { } } ,
builtin0 . StoragePowerActorCodeID : { builtin0 . MethodsPower , power0 . Actor { } } ,
builtin0 . StorageMinerActorCodeID : { builtin0 . MethodsMiner , miner0 . Actor { } } ,
builtin0 . StorageMarketActorCodeID : { builtin0 . MethodsMarket , market0 . Actor { } } ,
builtin0 . PaymentChannelActorCodeID : { builtin0 . MethodsPaych , paych0 . Actor { } } ,
builtin0 . MultisigActorCodeID : { builtin0 . MethodsMultisig , msig0 . Actor { } } ,
builtin0 . RewardActorCodeID : { builtin0 . MethodsReward , reward0 . Actor { } } ,
builtin0 . VerifiedRegistryActorCodeID : { builtin0 . MethodsVerifiedRegistry , verifreg0 . Actor { } } ,
2020-07-03 16:57:58 +00:00
}
for c , m := range cidToMethods {
2020-09-07 03:49:10 +00:00
exports := m [ 1 ] . ( saruntime . Invokee ) . Exports ( )
2020-09-04 03:28:42 +00:00
methods := make ( map [ abi . MethodNum ] MethodMeta , len ( exports ) )
2020-07-03 16:57:58 +00:00
2020-09-04 03:28:42 +00:00
// Explicitly add send, it's special.
2020-09-21 06:52:45 +00:00
methods [ builtin0 . MethodSend ] = MethodMeta {
2020-07-03 16:57:58 +00:00
Name : "Send" ,
2020-09-10 06:21:38 +00:00
Params : reflect . TypeOf ( new ( abi . EmptyValue ) ) ,
Ret : reflect . TypeOf ( new ( abi . EmptyValue ) ) ,
2020-09-04 03:28:42 +00:00
}
2020-07-03 16:57:58 +00:00
2020-09-04 03:28:42 +00:00
// Learn method names from the builtin.Methods* structs.
rv := reflect . ValueOf ( m [ 0 ] )
rt := rv . Type ( )
nf := rt . NumField ( )
methodToName := make ( [ ] string , len ( exports ) )
2020-07-03 16:57:58 +00:00
for i := 0 ; i < nf ; i ++ {
2020-09-04 03:28:42 +00:00
name := rt . Field ( i ) . Name
number := rv . Field ( i ) . Interface ( ) . ( abi . MethodNum )
methodToName [ number ] = name
}
2020-07-03 16:57:58 +00:00
2020-09-04 03:28:42 +00:00
// Iterate over exported methods. Some of these _may_ be nil and
// must be skipped.
for number , export := range exports {
if export == nil {
continue
}
ev := reflect . ValueOf ( export )
et := ev . Type ( )
// Make sure the method name is correct.
// This is just a nice sanity check.
fnName := runtime . FuncForPC ( ev . Pointer ( ) ) . Name ( )
fnName = strings . TrimSuffix ( fnName [ strings . LastIndexByte ( fnName , '.' ) + 1 : ] , "-fm" )
mName := methodToName [ number ]
if mName != fnName {
panic ( fmt . Sprintf (
"actor method name is %s but exported method name is %s" ,
fnName , mName ,
) )
}
switch abi . MethodNum ( number ) {
2020-09-21 06:52:45 +00:00
case builtin0 . MethodSend :
2020-09-04 03:28:42 +00:00
panic ( "method 0 is reserved for Send" )
2020-09-21 06:52:45 +00:00
case builtin0 . MethodConstructor :
2020-09-04 03:28:42 +00:00
if fnName != "Constructor" {
panic ( "method 1 is reserved for Constructor" )
}
}
methods [ abi . MethodNum ( number ) ] = MethodMeta {
Name : fnName ,
Params : et . In ( 1 ) ,
Ret : et . Out ( 0 ) ,
}
2020-07-03 16:57:58 +00:00
}
2020-09-04 03:28:42 +00:00
MethodsMap [ c ] = methods
2020-07-03 16:57:58 +00:00
}
}
func GetReturnType ( ctx context . Context , sm * StateManager , to address . Address , method abi . MethodNum , ts * types . TipSet ) ( cbg . CBORUnmarshaler , error ) {
2020-09-15 11:04:45 +00:00
act , err := sm . LoadActor ( ctx , to , ts )
if err != nil {
return nil , xerrors . Errorf ( "(get sset) failed to load miner actor: %w" , err )
2020-07-03 16:57:58 +00:00
}
2020-09-04 03:28:42 +00:00
m , found := MethodsMap [ act . Code ] [ method ]
if ! found {
return nil , fmt . Errorf ( "unknown method %d for actor %s" , method , act . Code )
}
2020-07-03 16:57:58 +00:00
return reflect . New ( m . Ret . Elem ( ) ) . Interface ( ) . ( cbg . CBORUnmarshaler ) , nil
}
2020-07-27 23:51:30 +00:00
func MinerHasMinPower ( ctx context . Context , sm * StateManager , addr address . Address , ts * types . TipSet ) ( bool , error ) {
2020-09-22 04:12:07 +00:00
pact , err := sm . LoadActor ( ctx , power . Address , ts )
2020-07-27 23:51:30 +00:00
if err != nil {
return false , xerrors . Errorf ( "loading power actor state: %w" , err )
}
2020-09-14 22:43:12 +00:00
ps , err := power . Load ( sm . cs . Store ( ctx ) , pact )
2020-09-14 12:17:45 +00:00
if err != nil {
return false , err
}
2020-09-14 22:43:12 +00:00
return ps . MinerNominalPowerMeetsConsensusMinimum ( addr )
2020-07-27 23:51:30 +00:00
}
2020-08-12 22:20:32 +00:00
func CheckTotalFIL ( ctx context . Context , sm * StateManager , ts * types . TipSet ) ( abi . TokenAmount , error ) {
2020-09-14 22:43:12 +00:00
str , err := state . LoadStateTree ( sm . ChainStore ( ) . Store ( ctx ) , ts . ParentState ( ) )
2020-08-12 22:20:32 +00:00
if err != nil {
return abi . TokenAmount { } , err
}
sum := types . NewInt ( 0 )
err = str . ForEach ( func ( a address . Address , act * types . Actor ) error {
sum = types . BigAdd ( sum , act . Balance )
return nil
} )
if err != nil {
return abi . TokenAmount { } , err
}
return sum , nil
}