b7a4dbb07f
And use the new CidBuilder from the spec actors. This patch does not switch over to inline CIDs by default, but paves the way.
657 lines
19 KiB
Go
657 lines
19 KiB
Go
package stmgr
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"os"
|
|
"reflect"
|
|
|
|
cid "github.com/ipfs/go-cid"
|
|
cbor "github.com/ipfs/go-ipld-cbor"
|
|
cbg "github.com/whyrusleeping/cbor-gen"
|
|
"golang.org/x/xerrors"
|
|
|
|
"github.com/filecoin-project/go-address"
|
|
"github.com/filecoin-project/go-bitfield"
|
|
"github.com/filecoin-project/sector-storage/ffiwrapper"
|
|
"github.com/filecoin-project/specs-actors/actors/abi"
|
|
"github.com/filecoin-project/specs-actors/actors/abi/big"
|
|
"github.com/filecoin-project/specs-actors/actors/builtin"
|
|
"github.com/filecoin-project/specs-actors/actors/builtin/account"
|
|
"github.com/filecoin-project/specs-actors/actors/builtin/cron"
|
|
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
|
|
"github.com/filecoin-project/specs-actors/actors/builtin/market"
|
|
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
|
|
"github.com/filecoin-project/specs-actors/actors/builtin/multisig"
|
|
"github.com/filecoin-project/specs-actors/actors/builtin/paych"
|
|
"github.com/filecoin-project/specs-actors/actors/builtin/power"
|
|
"github.com/filecoin-project/specs-actors/actors/builtin/reward"
|
|
"github.com/filecoin-project/specs-actors/actors/builtin/verifreg"
|
|
"github.com/filecoin-project/specs-actors/actors/crypto"
|
|
"github.com/filecoin-project/specs-actors/actors/util/adt"
|
|
|
|
"github.com/filecoin-project/lotus/api"
|
|
"github.com/filecoin-project/lotus/build"
|
|
"github.com/filecoin-project/lotus/chain/beacon"
|
|
"github.com/filecoin-project/lotus/chain/state"
|
|
"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/lib/blockstore"
|
|
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
|
)
|
|
|
|
func GetNetworkName(ctx context.Context, sm *StateManager, st cid.Cid) (dtypes.NetworkName, error) {
|
|
var state init_.State
|
|
err := sm.WithStateTree(st, sm.WithActor(builtin.InitActorAddr, sm.WithActorState(ctx, &state)))
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return dtypes.NetworkName(state.NetworkName), nil
|
|
}
|
|
|
|
func (sm *StateManager) LoadActorState(ctx context.Context, addr address.Address, out interface{}, ts *types.TipSet) (*types.Actor, error) {
|
|
var a *types.Actor
|
|
if err := sm.WithParentState(ts, sm.WithActor(addr, func(act *types.Actor) error {
|
|
a = act
|
|
return sm.WithActorState(ctx, out)(act)
|
|
})); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return a, nil
|
|
}
|
|
|
|
func (sm *StateManager) LoadActorStateRaw(ctx context.Context, addr address.Address, out interface{}, st cid.Cid) (*types.Actor, error) {
|
|
var a *types.Actor
|
|
if err := sm.WithStateTree(st, sm.WithActor(addr, func(act *types.Actor) error {
|
|
a = act
|
|
return sm.WithActorState(ctx, out)(act)
|
|
})); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return a, nil
|
|
}
|
|
|
|
func GetMinerWorkerRaw(ctx context.Context, sm *StateManager, st cid.Cid, maddr address.Address) (address.Address, error) {
|
|
var mas miner.State
|
|
_, err := sm.LoadActorStateRaw(ctx, maddr, &mas, st)
|
|
if err != nil {
|
|
return address.Undef, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
|
|
}
|
|
|
|
cst := cbor.NewCborStore(sm.cs.Blockstore())
|
|
state, err := state.LoadStateTree(cst, st)
|
|
if err != nil {
|
|
return address.Undef, xerrors.Errorf("load state tree: %w", err)
|
|
}
|
|
|
|
info, err := mas.GetInfo(sm.cs.Store(ctx))
|
|
if err != nil {
|
|
return address.Address{}, err
|
|
}
|
|
|
|
return vm.ResolveToKeyAddr(state, cst, info.Worker)
|
|
}
|
|
|
|
func GetPower(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (power.Claim, power.Claim, error) {
|
|
return GetPowerRaw(ctx, sm, ts.ParentState(), maddr)
|
|
}
|
|
|
|
func GetPowerRaw(ctx context.Context, sm *StateManager, st cid.Cid, maddr address.Address) (power.Claim, power.Claim, error) {
|
|
var ps power.State
|
|
_, err := sm.LoadActorStateRaw(ctx, builtin.StoragePowerActorAddr, &ps, st)
|
|
if err != nil {
|
|
return power.Claim{}, power.Claim{}, xerrors.Errorf("(get sset) failed to load power actor state: %w", err)
|
|
}
|
|
|
|
var mpow power.Claim
|
|
if maddr != address.Undef {
|
|
cm, err := adt.AsMap(sm.cs.Store(ctx), ps.Claims)
|
|
if err != nil {
|
|
return power.Claim{}, power.Claim{}, err
|
|
}
|
|
|
|
var claim power.Claim
|
|
if _, err := cm.Get(adt.AddrKey(maddr), &claim); err != nil {
|
|
return power.Claim{}, power.Claim{}, err
|
|
}
|
|
|
|
mpow = claim
|
|
}
|
|
|
|
return mpow, power.Claim{
|
|
RawBytePower: ps.TotalRawBytePower,
|
|
QualityAdjPower: ps.TotalQualityAdjPower,
|
|
}, nil
|
|
}
|
|
|
|
func PreCommitInfo(ctx context.Context, sm *StateManager, maddr address.Address, sid abi.SectorNumber, ts *types.TipSet) (miner.SectorPreCommitOnChainInfo, error) {
|
|
var mas miner.State
|
|
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
|
|
if err != nil {
|
|
return miner.SectorPreCommitOnChainInfo{}, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
|
|
}
|
|
|
|
i, ok, err := mas.GetPrecommittedSector(sm.cs.Store(ctx), sid)
|
|
if err != nil {
|
|
return miner.SectorPreCommitOnChainInfo{}, err
|
|
}
|
|
if !ok {
|
|
return miner.SectorPreCommitOnChainInfo{}, xerrors.New("precommit not found")
|
|
}
|
|
|
|
return *i, nil
|
|
}
|
|
|
|
func MinerSectorInfo(ctx context.Context, sm *StateManager, maddr address.Address, sid abi.SectorNumber, ts *types.TipSet) (*miner.SectorOnChainInfo, error) {
|
|
var mas miner.State
|
|
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
|
|
}
|
|
|
|
sectorInfo, ok, err := mas.GetSector(sm.cs.Store(ctx), sid)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if !ok {
|
|
return nil, xerrors.New("sector not found")
|
|
}
|
|
|
|
return sectorInfo, nil
|
|
}
|
|
|
|
func GetMinerSectorSet(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address, filter *abi.BitField, filterOut bool) ([]*api.ChainSectorInfo, error) {
|
|
var mas miner.State
|
|
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("(get sset) failed to load miner actor state: %w", err)
|
|
}
|
|
|
|
return LoadSectorsFromSet(ctx, sm.ChainStore().Blockstore(), mas.Sectors, filter, filterOut)
|
|
}
|
|
|
|
func GetSectorsForWinningPoSt(ctx context.Context, pv ffiwrapper.Verifier, sm *StateManager, st cid.Cid, maddr address.Address, rand abi.PoStRandomness) ([]abi.SectorInfo, error) {
|
|
var partsProving []*abi.BitField
|
|
var mas *miner.State
|
|
var info *miner.MinerInfo
|
|
|
|
err := sm.WithStateTree(st, sm.WithActor(maddr, sm.WithActorState(ctx, func(store adt.Store, mst *miner.State) error {
|
|
var err error
|
|
|
|
mas = mst
|
|
|
|
info, err = mas.GetInfo(store)
|
|
if err != nil {
|
|
return xerrors.Errorf("getting miner info: %w", err)
|
|
}
|
|
|
|
deadlines, err := mas.LoadDeadlines(store)
|
|
if err != nil {
|
|
return xerrors.Errorf("loading deadlines: %w", err)
|
|
}
|
|
|
|
return deadlines.ForEach(store, func(dlIdx uint64, deadline *miner.Deadline) error {
|
|
partitions, err := deadline.PartitionsArray(store)
|
|
if err != nil {
|
|
return xerrors.Errorf("getting partition array: %w", err)
|
|
}
|
|
|
|
var partition miner.Partition
|
|
return partitions.ForEach(&partition, func(partIdx int64) error {
|
|
p, err := bitfield.SubtractBitField(partition.Sectors, partition.Faults)
|
|
if err != nil {
|
|
return xerrors.Errorf("subtract faults from partition sectors: %w", err)
|
|
}
|
|
|
|
partsProving = append(partsProving, p)
|
|
|
|
return nil
|
|
})
|
|
})
|
|
})))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
provingSectors, err := bitfield.MultiMerge(partsProving...)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("merge partition proving sets: %w", err)
|
|
}
|
|
|
|
numProvSect, err := provingSectors.Count()
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("failed to count bits: %w", err)
|
|
}
|
|
|
|
// TODO(review): is this right? feels fishy to me
|
|
if numProvSect == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
spt, err := ffiwrapper.SealProofTypeFromSectorSize(info.SectorSize)
|
|
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)
|
|
}
|
|
|
|
ids, err := pv.GenerateWinningPoStSectorChallenge(ctx, wpt, abi.ActorID(mid), rand, numProvSect)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("generating winning post challenges: %w", err)
|
|
}
|
|
|
|
sectors, err := provingSectors.All(miner.SectorsMax)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("failed to enumerate all sector IDs: %w", err)
|
|
}
|
|
|
|
sectorAmt, err := adt.AsArray(sm.cs.Store(ctx), mas.Sectors)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("failed to load sectors amt: %w", err)
|
|
}
|
|
|
|
out := make([]abi.SectorInfo, len(ids))
|
|
for i, n := range ids {
|
|
sid := sectors[n]
|
|
|
|
var sinfo miner.SectorOnChainInfo
|
|
if found, err := sectorAmt.Get(sid, &sinfo); err != nil {
|
|
return nil, xerrors.Errorf("failed to get sector %d: %w", sid, err)
|
|
} else if !found {
|
|
return nil, xerrors.Errorf("failed to find sector %d", sid)
|
|
}
|
|
|
|
out[i] = abi.SectorInfo{
|
|
SealProof: spt,
|
|
SectorNumber: sinfo.SectorNumber,
|
|
SealedCID: sinfo.SealedCID,
|
|
}
|
|
}
|
|
|
|
return out, nil
|
|
}
|
|
|
|
func StateMinerInfo(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (*miner.MinerInfo, error) {
|
|
var mas miner.State
|
|
_, err := sm.LoadActorStateRaw(ctx, maddr, &mas, ts.ParentState())
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("(get ssize) failed to load miner actor state: %w", err)
|
|
}
|
|
|
|
return mas.GetInfo(sm.cs.Store(ctx))
|
|
}
|
|
|
|
func GetMinerSlashed(ctx context.Context, sm *StateManager, ts *types.TipSet, maddr address.Address) (bool, error) {
|
|
var mas miner.State
|
|
_, err := sm.LoadActorState(ctx, maddr, &mas, ts)
|
|
if err != nil {
|
|
return false, xerrors.Errorf("(get miner slashed) failed to load miner actor state")
|
|
}
|
|
|
|
var spas power.State
|
|
_, err = sm.LoadActorState(ctx, builtin.StoragePowerActorAddr, &spas, ts)
|
|
if err != nil {
|
|
return false, xerrors.Errorf("(get miner slashed) failed to load power actor state")
|
|
}
|
|
|
|
store := sm.cs.Store(ctx)
|
|
|
|
claims, err := adt.AsMap(store, spas.Claims)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
ok, err := claims.Get(power.AddrKey(maddr), nil)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
if !ok {
|
|
return true, nil
|
|
}
|
|
|
|
return false, nil
|
|
}
|
|
|
|
func GetStorageDeal(ctx context.Context, sm *StateManager, dealID abi.DealID, ts *types.TipSet) (*api.MarketDeal, error) {
|
|
var state market.State
|
|
if _, err := sm.LoadActorState(ctx, builtin.StorageMarketActorAddr, &state, ts); err != nil {
|
|
return nil, err
|
|
}
|
|
store := sm.ChainStore().Store(ctx)
|
|
|
|
da, err := adt.AsArray(store, state.Proposals)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var dp market.DealProposal
|
|
if found, err := da.Get(uint64(dealID), &dp); err != nil {
|
|
return nil, err
|
|
} else if !found {
|
|
return nil, xerrors.Errorf("deal %d not found", dealID)
|
|
}
|
|
|
|
sa, err := market.AsDealStateArray(store, state.States)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
st, found, err := sa.Get(dealID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if !found {
|
|
st = &market.DealState{
|
|
SectorStartEpoch: -1,
|
|
LastUpdatedEpoch: -1,
|
|
SlashEpoch: -1,
|
|
}
|
|
}
|
|
|
|
return &api.MarketDeal{
|
|
Proposal: dp,
|
|
State: *st,
|
|
}, nil
|
|
}
|
|
|
|
func ListMinerActors(ctx context.Context, sm *StateManager, ts *types.TipSet) ([]address.Address, error) {
|
|
var state power.State
|
|
if _, err := sm.LoadActorState(ctx, builtin.StoragePowerActorAddr, &state, ts); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
m, err := adt.AsMap(sm.cs.Store(ctx), state.Claims)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var miners []address.Address
|
|
err = m.ForEach(nil, func(k string) error {
|
|
a, err := address.NewFromBytes([]byte(k))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
miners = append(miners, a)
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return miners, nil
|
|
}
|
|
|
|
func LoadSectorsFromSet(ctx context.Context, bs blockstore.Blockstore, ssc cid.Cid, filter *abi.BitField, filterOut bool) ([]*api.ChainSectorInfo, error) {
|
|
a, err := adt.AsArray(store.ActorStore(ctx, bs), ssc)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var sset []*api.ChainSectorInfo
|
|
var v cbg.Deferred
|
|
if err := a.ForEach(&v, func(i int64) error {
|
|
if filter != nil {
|
|
set, err := filter.IsSet(uint64(i))
|
|
if err != nil {
|
|
return xerrors.Errorf("filter check error: %w", err)
|
|
}
|
|
if set == filterOut {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
var oci miner.SectorOnChainInfo
|
|
if err := cbor.DecodeInto(v.Raw, &oci); err != nil {
|
|
return err
|
|
}
|
|
sset = append(sset, &api.ChainSectorInfo{
|
|
Info: oci,
|
|
ID: abi.SectorNumber(i),
|
|
})
|
|
return nil
|
|
}); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return sset, nil
|
|
}
|
|
|
|
func ComputeState(ctx context.Context, sm *StateManager, height abi.ChainEpoch, msgs []*types.Message, ts *types.TipSet) (cid.Cid, []*api.InvocResult, error) {
|
|
if ts == nil {
|
|
ts = sm.cs.GetHeaviestTipSet()
|
|
}
|
|
|
|
base, trace, err := sm.ExecutionTrace(ctx, ts)
|
|
if err != nil {
|
|
return cid.Undef, nil, err
|
|
}
|
|
|
|
fstate, err := sm.handleStateForks(ctx, base, height, ts.Height())
|
|
if err != nil {
|
|
return cid.Undef, nil, err
|
|
}
|
|
|
|
r := store.NewChainRand(sm.cs, ts.Cids(), height)
|
|
vmi, err := vm.NewVM(fstate, height, r, sm.cs.Blockstore(), sm.cs.VMSys())
|
|
if err != nil {
|
|
return cid.Undef, nil, err
|
|
}
|
|
|
|
for i, msg := range msgs {
|
|
// TODO: Use the signed message length for secp messages
|
|
ret, err := vmi.ApplyMessage(ctx, msg)
|
|
if err != nil {
|
|
return cid.Undef, nil, xerrors.Errorf("applying message %s: %w", msg.Cid(), err)
|
|
}
|
|
if ret.ExitCode != 0 {
|
|
log.Infof("compute state apply message %d failed (exit: %d): %s", i, ret.ExitCode, ret.ActorErr)
|
|
}
|
|
}
|
|
|
|
root, err := vmi.Flush(ctx)
|
|
if err != nil {
|
|
return cid.Undef, nil, err
|
|
}
|
|
|
|
return root, trace, nil
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
lbts, err := sm.ChainStore().GetTipsetByHeight(ctx, lbr, ts, true)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("failed to get lookback tipset: %w", err)
|
|
}
|
|
|
|
return lbts, nil
|
|
}
|
|
|
|
func MinerGetBaseInfo(ctx context.Context, sm *StateManager, bcn beacon.RandomBeacon, tsk types.TipSetKey, round abi.ChainEpoch, maddr address.Address, pv ffiwrapper.Verifier) (*api.MiningBaseInfo, error) {
|
|
ts, err := sm.ChainStore().LoadTipSet(tsk)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("failed to load tipset for mining base: %w", err)
|
|
}
|
|
|
|
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{}
|
|
}
|
|
|
|
entries, err := beacon.BeaconEntriesForBlock(ctx, bcn, round, *prev)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
rbase := *prev
|
|
if len(entries) > 0 {
|
|
rbase = entries[len(entries)-1]
|
|
}
|
|
|
|
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)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var mas miner.State
|
|
if _, err := sm.LoadActorStateRaw(ctx, maddr, &mas, lbst); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
buf := new(bytes.Buffer)
|
|
if err := maddr.MarshalCBOR(buf); err != nil {
|
|
return nil, xerrors.Errorf("failed to marshal miner address: %w", err)
|
|
}
|
|
|
|
prand, err := store.DrawRandomness(rbase.Data, crypto.DomainSeparationTag_WinningPoStChallengeSeed, round, buf.Bytes())
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("failed to get randomness for winning post: %w", err)
|
|
}
|
|
|
|
sectors, err := GetSectorsForWinningPoSt(ctx, pv, sm, lbst, maddr, prand)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("getting wpost proving set: %w", err)
|
|
}
|
|
|
|
if len(sectors) == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
mpow, tpow, err := GetPowerRaw(ctx, sm, lbst, maddr)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("failed to get power: %w", err)
|
|
}
|
|
|
|
info, err := mas.GetInfo(sm.cs.Store(ctx))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
worker, err := sm.ResolveToKeyAddress(ctx, info.Worker, ts)
|
|
if err != nil {
|
|
return nil, xerrors.Errorf("resolving worker address: %w", err)
|
|
}
|
|
|
|
return &api.MiningBaseInfo{
|
|
MinerPower: mpow.QualityAdjPower,
|
|
NetworkPower: tpow.QualityAdjPower,
|
|
Sectors: sectors,
|
|
WorkerKey: worker,
|
|
SectorSize: info.SectorSize,
|
|
PrevBeaconEntry: *prev,
|
|
BeaconEntries: entries,
|
|
}, nil
|
|
}
|
|
|
|
func (sm *StateManager) CirculatingSupply(ctx context.Context, ts *types.TipSet) (abi.TokenAmount, error) {
|
|
if ts == nil {
|
|
ts = sm.cs.GetHeaviestTipSet()
|
|
}
|
|
|
|
st, _, err := sm.TipSetState(ctx, ts)
|
|
if err != nil {
|
|
return big.Zero(), err
|
|
}
|
|
|
|
r := store.NewChainRand(sm.cs, ts.Cids(), ts.Height())
|
|
vmi, err := vm.NewVM(st, ts.Height(), r, sm.cs.Blockstore(), sm.cs.VMSys())
|
|
if err != nil {
|
|
return big.Zero(), err
|
|
}
|
|
|
|
unsafeVM := &vm.UnsafeVM{VM: vmi}
|
|
rt := unsafeVM.MakeRuntime(ctx, &types.Message{
|
|
GasLimit: 100e6,
|
|
From: builtin.SystemActorAddr,
|
|
}, builtin.SystemActorAddr, 0, 0, 0)
|
|
|
|
return rt.TotalFilCircSupply(), nil
|
|
}
|
|
|
|
type methodMeta struct {
|
|
Name string
|
|
|
|
Params reflect.Type
|
|
Ret reflect.Type
|
|
}
|
|
|
|
var MethodsMap = map[cid.Cid][]methodMeta{}
|
|
|
|
func init() {
|
|
cidToMethods := map[cid.Cid][2]interface{}{
|
|
// builtin.SystemActorCodeID: {builtin.MethodsSystem, system.Actor{} }- apparently it doesn't have methods
|
|
builtin.InitActorCodeID: {builtin.MethodsInit, init_.Actor{}},
|
|
builtin.CronActorCodeID: {builtin.MethodsCron, cron.Actor{}},
|
|
builtin.AccountActorCodeID: {builtin.MethodsAccount, account.Actor{}},
|
|
builtin.StoragePowerActorCodeID: {builtin.MethodsPower, power.Actor{}},
|
|
builtin.StorageMinerActorCodeID: {builtin.MethodsMiner, miner.Actor{}},
|
|
builtin.StorageMarketActorCodeID: {builtin.MethodsMarket, market.Actor{}},
|
|
builtin.PaymentChannelActorCodeID: {builtin.MethodsPaych, paych.Actor{}},
|
|
builtin.MultisigActorCodeID: {builtin.MethodsMultisig, multisig.Actor{}},
|
|
builtin.RewardActorCodeID: {builtin.MethodsReward, reward.Actor{}},
|
|
builtin.VerifiedRegistryActorCodeID: {builtin.MethodsVerifiedRegistry, verifreg.Actor{}},
|
|
}
|
|
|
|
for c, m := range cidToMethods {
|
|
rt := reflect.TypeOf(m[0])
|
|
nf := rt.NumField()
|
|
|
|
MethodsMap[c] = append(MethodsMap[c], methodMeta{
|
|
Name: "Send",
|
|
Params: reflect.TypeOf(new(adt.EmptyValue)),
|
|
Ret: reflect.TypeOf(new(adt.EmptyValue)),
|
|
})
|
|
|
|
exports := m[1].(abi.Invokee).Exports()
|
|
for i := 0; i < nf; i++ {
|
|
export := reflect.TypeOf(exports[i+1])
|
|
|
|
MethodsMap[c] = append(MethodsMap[c], methodMeta{
|
|
Name: rt.Field(i).Name,
|
|
Params: export.In(1),
|
|
Ret: export.Out(0),
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
func GetReturnType(ctx context.Context, sm *StateManager, to address.Address, method abi.MethodNum, ts *types.TipSet) (cbg.CBORUnmarshaler, error) {
|
|
var act types.Actor
|
|
if err := sm.WithParentState(ts, sm.WithActor(to, GetActor(&act))); err != nil {
|
|
return nil, xerrors.Errorf("getting actor: %w", err)
|
|
}
|
|
|
|
m := MethodsMap[act.Code][method]
|
|
return reflect.New(m.Ret.Elem()).Interface().(cbg.CBORUnmarshaler), nil
|
|
}
|