[WIP] Network upgrade support

This patch starts adding support for network upgrades.

* It adds an actors abstraction layer for loading abstract (cross-version) actors.
* It starts switching over to a shared deadline type.
* It adds an abstraction for ADTs (hamt/amt).
* It removes the callback-based API in the StateManager (difficult to abstract
across actor versions).
* It _does not_ actually add support for actors v2. We can do that in a followup
patch but that should be relatively easy.

This patch is heavily WIP and does not compile. Feel free to push changes
directly to this branch.

Notes:

* State tree access now needs a network version, because the HAMT type will change.
* I haven't figured out a nice way to abstract over changes to the _message_
types. However, many of them will be type aliased to actors v0 in actors v2 so
we can likely continue using the v0 versions (or use the v2 versions
everywhere). I've been renaming imports to `v0*` to make it clear that we're
importing types from a _specific_ actors version.

TODO:

* Consider merging incremental improvements? We'd have to get this compiling
again first but we could merge in the new abstractions, and slowly switch over.
* Finish migrating to the new abstractions.
* Remove all actor state types from the public API. See `miner.State.Info()` for
the planned approach here.
* Fix the tests. This is likely going to be a massive pain.
This commit is contained in:
Steven Allen 2020-09-11 20:07:52 -07:00
parent a2f1e76fea
commit d3594835c4
33 changed files with 735 additions and 392 deletions

View File

@ -18,6 +18,7 @@ import (
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/go-state-types/dline"
"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/paych"
@ -312,15 +313,11 @@ type FullNode interface {
StateMinerActiveSectors(context.Context, address.Address, types.TipSetKey) ([]*ChainSectorInfo, error)
// StateMinerProvingDeadline calculates the deadline at some epoch for a proving period
// and returns the deadline-related calculations.
StateMinerProvingDeadline(context.Context, address.Address, types.TipSetKey) (*miner.DeadlineInfo, error)
StateMinerProvingDeadline(context.Context, address.Address, types.TipSetKey) (*dline.Info, error)
// StateMinerPower returns the power of the indicated miner
StateMinerPower(context.Context, address.Address, types.TipSetKey) (*MinerPower, error)
// StateMinerInfo returns info about the indicated miner
StateMinerInfo(context.Context, address.Address, types.TipSetKey) (MinerInfo, error)
// StateMinerDeadlines returns all the proving deadlines for the given miner
StateMinerDeadlines(context.Context, address.Address, types.TipSetKey) ([]*miner.Deadline, error)
// StateMinerPartitions loads miner partitions for the specified miner/deadline
StateMinerPartitions(context.Context, address.Address, uint64, types.TipSetKey) ([]*miner.Partition, error)
// StateMinerFaults returns a bitfield indicating the faulty sectors of the given miner
StateMinerFaults(context.Context, address.Address, types.TipSetKey) (bitfield.BitField, error)
// StateAllMinerFaults returns all non-expired Faults that occur within lookback epochs of the given tipset

View File

@ -8,9 +8,10 @@ import (
datatransfer "github.com/filecoin-project/go-data-transfer"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/ipfs/go-cid"
v0miner "github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/libp2p/go-libp2p-core/peer"
pubsub "github.com/libp2p/go-libp2p-pubsub"
ma "github.com/multiformats/go-multiaddr"
@ -49,48 +50,6 @@ type PubsubScore struct {
Score *pubsub.PeerScoreSnapshot
}
type MinerInfo struct {
Owner address.Address // Must be an ID-address.
Worker address.Address // Must be an ID-address.
NewWorker address.Address // Must be an ID-address.
ControlAddresses []address.Address // Must be an ID-addresses.
WorkerChangeEpoch abi.ChainEpoch
PeerId *peer.ID
Multiaddrs []abi.Multiaddrs
SealProofType abi.RegisteredSealProof
SectorSize abi.SectorSize
WindowPoStPartitionSectors uint64
}
func NewApiMinerInfo(info *miner.MinerInfo) MinerInfo {
var pid *peer.ID
if peerID, err := peer.IDFromBytes(info.PeerId); err == nil {
pid = &peerID
}
mi := MinerInfo{
Owner: info.Owner,
Worker: info.Worker,
ControlAddresses: info.ControlAddresses,
NewWorker: address.Undef,
WorkerChangeEpoch: -1,
PeerId: pid,
Multiaddrs: info.Multiaddrs,
SealProofType: info.SealProofType,
SectorSize: info.SectorSize,
WindowPoStPartitionSectors: info.WindowPoStPartitionSectors,
}
if info.PendingWorkerKey != nil {
mi.NewWorker = info.PendingWorkerKey.NewWorker
mi.WorkerChangeEpoch = info.PendingWorkerKey.EffectiveAt
}
return mi
}
type MessageSendSpec struct {
MaxFee abi.TokenAmount
}
@ -151,3 +110,5 @@ func NewDataTransferChannel(hostID peer.ID, channelState datatransfer.ChannelSta
}
return channel
}
type

57
chain/actors/adt/adt.go Normal file
View File

@ -0,0 +1,57 @@
package adt
import (
"github.com/ipfs/go-cid"
"golang.org/x/xerrors"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/cbor"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/lotus/chain/actors/builtin"
v0adt "github.com/filecoin-project/specs-actors/actors/util/adt"
)
type Map interface {
Root() (cid.Cid, error)
Put(k abi.Keyer, v cbor.Marshaler) error
Get(k abi.Keyer, v cbor.Unmarshaler) (bool, error)
Delete(k abi.Keyer) error
ForEach(v cbor.Unmarshaler, fn func(key string) error) error
}
func AsMap(store Store, root cid.Cid, version network.Version) (Map, error) {
switch builtin.VersionForNetwork(version) {
case builtin.Version0:
return v0adt.AsMap(store, root)
}
return nil, xerrors.Errorf("unknown network version: %d", version)
}
func NewMap(store Store, version network.Version) (Map, error) {
switch builtin.VersionForNetwork(version) {
case builtin.Version0:
return v0adt.MakeEmptyMap(store)
}
return nil, xerrors.Errorf("unknown network version: %d", version)
}
type Array interface {
Root() (cid.Cid, error)
Set(idx uint64, v cbor.Marshaler) error
Get(idx uint64, v cbor.Unmarshaler) (bool, error)
Delete(idx uint64) error
Length() uint64
ForEach(v cbor.Unmarshaler, fn func(idx int) error) error
}
func AsArray(store Store, root cid.Cid, version network.Version) (Array, error) {
switch builtin.VersionForNetwork(version) {
case builtin.Version0:
return v0adt.AsArray(store, root)
}
return nil, xerrors.Errorf("unknown network version: %d", version)
}

17
chain/actors/adt/store.go Normal file
View File

@ -0,0 +1,17 @@
package adt
import (
"context"
adt "github.com/filecoin-project/specs-actors/actors/util/adt"
cbor "github.com/ipfs/go-ipld-cbor"
)
type Store interface {
Context() context.Context
cbor.IpldStore
}
func WrapStore(ctx context.Context, store cbor.IpldStore) Store {
return adt.WrapStore(ctx, store)
}

View File

@ -0,0 +1,29 @@
# Actors
This package contains shims for abstracting over different actor versions.
## Design
Shims in this package follow a few common design principles.
### Structure Agnostic
Shims interfaces defined in this package should (ideally) not change even if the
structure of the underlying data changes. For example:
* All shims store an internal "store" object. That way, state can be moved into
a separate object without needing to add a store to the function signature.
* All functions must return an error, even if unused for now.
### Minimal
These interfaces should be expanded only as necessary to reduce maintenance burden.
### Queries, not field assessors.
When possible, functions should query the state instead of simply acting as
field assessors. These queries are more likely to remain stable across
specs-actor upgrades than specific state fields.
Note: there is a trade-off here. Avoid implementing _complicated_ query logic
inside these shims, as it will need to be replicated in every shim.

View File

@ -0,0 +1,23 @@
package builtin
import (
"fmt"
"github.com/filecoin-project/go-state-types/network"
)
type Version int
const (
Version0 = iota
)
// Converts a network version into a specs-actors version.
func VersionForNetwork(version network.Version) Version {
switch version {
case network.Version0, network.Version1:
return Version
default:
panic(fmt.Sprintf("unsupported network version %d", version))
}
}

View File

@ -0,0 +1,32 @@
package init
import (
"github.com/filecoin-project/go-bitfield"
"github.com/filecoin-project/go-state-types/cbor"
"golang.org/x/xerrors"
v0builtin "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/types"
)
func Load(store adt.Store, act *types.Actor) (State, error) {
switch act.Code {
case v0builtin.InitActorCodeID:
out := v0State{store: store}
err := store.Get(store.Context(), act.Head, &out)
if err != nil {
return nil, err
}
return &out, nil
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
type State interface {
cbor.Marshaler
ResolveAddress(address addr.Address) (address.Address, bool, error)
MapAddressToNewID(address addr.Address) (address.Address, error)
}

View File

@ -0,0 +1,22 @@
package init
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/builtin/init"
"github.com/filecoin-project/lotus/chain/actors/adt"
)
type v0State struct {
init.State
store adt.Store
}
func (s *v0State) ResolveAddress(address address.Address) (address.Address, bool, error) {
return s.State.ResolveAddress(s.store, address)
}
func (s *v0State) MapAddressToNewID(address address.Address) (address.Address, error) {
return s.State.MapAddressToNewID(s.store, address)
}

View File

@ -0,0 +1,32 @@
package market
import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/cbor"
"github.com/ipfs/go-cid"
)
func Load(store adt.Store, act *types.Actor) (st State, err error) {
switch act.Code {
case v0builtin.MarketActorCodeID:
out := v0State{store: store}
err := store.Get(store.Context(), act.Head, &out)
if err != nil {
return nil, err
}
return &out, nil
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
type State interface {
cbor.Marshaler
EscrowTable() (BalanceTable, error)
LockedTable() (BalanceTable, error)
TotalLocked() (abi.TokenAmount, error)
}
type BalanceTable interface {
Get(key address.Address) (abi.TokenAmount, error)
}

View File

@ -0,0 +1,25 @@
package market
import (
"github.com/filecoin-project/specs-actors/actors/builtin/market"
"github.com/filecoin-project/specs-actors/actors/util/adt"
)
type v0State struct {
market.State
store adt.Store
}
func (s *v0State) TotalLocked() (abi.TokenAmount, error) {
fml := types.BigAdd(s.TotalClientLockedCollateral, s.TotalProviderLockedCollateral)
fml = types.BigAdd(fml, s.TotalClientStorageFee)
return fml, nil
}
func (s *v0State) EscrowTable() (BalanceTable, error) {
return adt.AsBalanceTable(s.store, s.State.EscrowTable)
}
func (s *v0State) Lockedtable() (BalanceTable, error) {
return adt.AsBalanceTable(s.store, s.State.LockedTable)
}

View File

@ -0,0 +1,59 @@
package miner
import (
"github.com/filecoin-project/go-bitfield"
"github.com/filecoin-project/go-state-types/abi"
"golang.org/x/xerrors"
v0builtin "github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/types"
)
func Load(store adt.Store, act *types.Actor) (st State, err error) {
switch act.Code {
case v0builtin.StorageMinerActorCodeID:
out := v0State{store: store}
err := store.Get(store.Context(), act.Head, &out)
if err != nil {
return nil, err
}
return &out, nil
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
type State interface {
cbor.Marshaler
LoadDeadline(idx uint64) (Deadline, error)
ForEachDeadline(cb func(idx uint64, dl Deadline) error) error
NumDeadlines() (uint64, error)
}
type Deadline interface {
LoadPartition(idx uint64) (Partition, error)
ForEachPartition(cb func(idx uint64, part Partition) error) error
}
type Partition interface {
AllSectors() (bitfield.BitField, error)
FaultySectors() (bitfield.BitField, error)
RecoveringSectors() (bitfield.BitField, error)
LiveSectors() (bitfield.BitField, error)
ActiveSectors() (bitfield.BitField, error)
}
type MinerInfo struct {
Owner address.Address // Must be an ID-address.
Worker address.Address // Must be an ID-address.
NewWorker address.Address // Must be an ID-address.
ControlAddresses []address.Address // Must be an ID-addresses.
WorkerChangeEpoch abi.ChainEpoch
PeerId *peer.ID
Multiaddrs []abi.Multiaddrs
SealProofType abi.RegisteredSealProof
SectorSize abi.SectorSize
WindowPoStPartitionSectors uint64
}

View File

@ -0,0 +1,112 @@
package miner
import (
"github.com/filecoin-project/go-bitfield"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
)
type v0State struct {
miner.State
store adt.Store
}
type v0Deadline struct {
miner.Deadline
store adt.Store
}
type v0Partition struct {
miner.Partition
store adt.Store
}
func (s *v0State) LoadDeadline(idx uint64) (Deadline, error) {
dls, err := s.State.LoadDeadlines(s.store)
if err != nil {
return nil, err
}
dl, err := dls.LoadDeadline(s.store, idx)
if err != nil {
return nil, err
}
return &v0Deadline{*dl, s.store}, nil
}
func (s *v0State) ForEachDeadline(cb func(uint64, Deadline) error) error {
dls, err := s.State.LoadDeadlines(s.store)
if err != nil {
return err
}
return dls.ForEach(s.store, func(i uint64, dl *miner.Deadline) error {
return cb(i, &v0Deadline{*dl, s.store})
})
}
func (s *v0State) NumDeadlines() (uint64, error) {
return miner.WPoStPeriodDeadlines, nil
}
func (s *v0State) Info() (MinerInfo, error) {
info, err := s.State.GetInfo(s.store)
var pid *peer.ID
if peerID, err := peer.IDFromBytes(info.PeerId); err == nil {
pid = &peerID
}
mi := MinerInfo{
Owner: info.Owner,
Worker: info.Worker,
ControlAddresses: info.ControlAddresses,
NewWorker: address.Undef,
WorkerChangeEpoch: -1,
PeerId: pid,
Multiaddrs: info.Multiaddrs,
SealProofType: info.SealProofType,
SectorSize: info.SectorSize,
WindowPoStPartitionSectors: info.WindowPoStPartitionSectors,
}
if info.PendingWorkerKey != nil {
mi.NewWorker = info.PendingWorkerKey.NewWorker
mi.WorkerChangeEpoch = info.PendingWorkerKey.EffectiveAt
}
return mi
}
func (d *v0Deadline) LoadPartition(idx uint64) (Partition, error) {
p, err := d.Deadline.LoadPartition(d.store, idx)
if err != nil {
return nil, err
}
return &v0Partition{*p, d.store}, nil
}
func (d *v0Deadline) ForEachPartition(cb func(uint64, Partition) error) error {
ps, err := d.Deadline.PartitionsArray(d.store)
if err != nil {
return err
}
var part miner.Partition
return ps.ForEach(&part, func(i int64) error {
return cb(uint64(i), &v0Partition{part, d.store})
})
}
func (p *v0Partition) AllSectors() (bitfield.BitField, error) {
return p.Partition.Sectors, nil
}
func (p *v0Partition) FaultySectors() (bitfield.BitField, error) {
return p.Partition.Faults, nil
}
func (p *v0Partition) RecoveringSectors() (bitfield.BitField, error) {
return p.Partition.Recoveries, nil
}

View File

@ -0,0 +1,28 @@
package power
import (
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/cbor"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/types"
"golang.org/x/xerrors"
)
func Load(store adt.Store, act *types.Actor) (st State, err error) {
switch act.Code {
case v0builtin.PowerActorCodeID:
out := v0State{store: store}
err := store.Get(store.Context(), act.Head, &out)
if err != nil {
return nil, err
}
return &out, nil
}
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}
type State interface {
cbor.Marshaler
TotalLocked() (abi.TokenAmount, error)
}

View File

@ -0,0 +1,16 @@
package power
import (
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/specs-actors/actors/builtin/power"
)
type v0State struct {
power.State
store adt.Store
}
func (s *v0State) TotalLocked() (abi.TokenAmount, error) {
return s.TotalPledgeCollateral, nil
}

24
chain/actors/version.go Normal file
View File

@ -0,0 +1,24 @@
package actors
import (
"fmt"
"github.com/filecoin-project/go-state-types/network"
)
type Version int
const (
Version0 = iota
Version1
)
// VersionForNetwork resolves the network version into an specs-actors version.
func VersionForNetwork(v network.Version) Version {
switch v {
case network.Version0, network.Version1:
return Version0
default:
panic(fmt.Sprintf("unimplemented network version: %d", v))
}
}

View File

@ -52,8 +52,8 @@ func (mpp *mpoolProvider) GetActorAfter(addr address.Address, ts *types.TipSet)
if err != nil {
return nil, xerrors.Errorf("computing tipset state for GetActor: %w", err)
}
return &act, mpp.sm.WithStateTree(stcid, mpp.sm.WithActor(addr, stmgr.GetActor(&act)))
version := mpp.sm.GetNtwkVersion(context.TODO(), ts.Height())
return &act, mpp.sm.WithStateTree(stcid, version, mpp.sm.WithActor(addr, stmgr.GetActor(&act)))
}
func (mpp *mpoolProvider) StateAccountKey(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) {

View File

@ -4,10 +4,12 @@ import (
"context"
"fmt"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/lotus/chain/actors/builtin/init"
init_ "github.com/filecoin-project/lotus/chain/actors/builtin/init"
"github.com/filecoin-project/specs-actors/actors/builtin"
init_ "github.com/filecoin-project/specs-actors/actors/builtin/init"
"github.com/filecoin-project/specs-actors/actors/util/adt"
"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor"
logging "github.com/ipfs/go-log/v2"
@ -22,7 +24,7 @@ var log = logging.Logger("statetree")
// StateTree stores actors state by their ID.
type StateTree struct {
root *adt.Map
root adt.Map
Store cbor.IpldStore
snaps *stateSnaps
@ -115,17 +117,18 @@ func (ss *stateSnaps) deleteActor(addr address.Address) {
ss.layers[len(ss.layers)-1].actors[addr] = streeOp{Delete: true}
}
func NewStateTree(cst cbor.IpldStore) (*StateTree, error) {
func NewStateTree(cst cbor.IpldStore, version network.Version) (*StateTree, error) {
return &StateTree{
root: adt.MakeEmptyMap(adt.WrapStore(context.TODO(), cst)),
root: adt.NewMap(adt.WrapStore(context.TODO(), cst), version),
Store: cst,
snaps: newStateSnaps(),
}, nil
}
func LoadStateTree(cst cbor.IpldStore, c cid.Cid) (*StateTree, error) {
nd, err := adt.AsMap(adt.WrapStore(context.TODO(), cst), c)
func LoadStateTree(cst cbor.IpldStore, c cid.Cid, version network.Version) (*StateTree, error) {
// NETUPGRADE: switch map adt type on version upgrade.
nd, err := adt.AsMap(adt.WrapStore(context.TODO(), cst), c, version)
if err != nil {
log.Errorf("loading hamt node %s failed: %s", c, err)
return nil, err
@ -165,12 +168,12 @@ func (st *StateTree) LookupID(addr address.Address) (address.Address, error) {
return address.Undef, xerrors.Errorf("getting init actor: %w", err)
}
var ias init_.State
if err := st.Store.Get(context.TODO(), act.Head, &ias); err != nil {
ias, err := init.Load(&AdtStore{st.Store}, &act)
if err != nil {
return address.Undef, xerrors.Errorf("loading init actor state: %w", err)
}
a, found, err := ias.ResolveAddress(&AdtStore{st.Store}, addr)
a, found, err := ias.ResolveAddress(addr)
if err == nil && !found {
err = types.ErrActorNotFound
}
@ -283,18 +286,18 @@ func (st *StateTree) ClearSnapshot() {
func (st *StateTree) RegisterNewAddress(addr address.Address) (address.Address, error) {
var out address.Address
err := st.MutateActor(builtin.InitActorAddr, func(initact *types.Actor) error {
var ias init_.State
if err := st.Store.Get(context.TODO(), initact.Head, &ias); err != nil {
ias, err := init.Load(&AdtStore{st.Store}, initact)
if err != nil {
return err
}
oaddr, err := ias.MapAddressToNewID(&AdtStore{st.Store}, addr)
oaddr, err := ias.MapAddressToNewID(addr)
if err != nil {
return err
}
out = oaddr
ncid, err := st.Store.Put(context.TODO(), &ias)
ncid, err := st.Store.Put(context.TODO(), ias)
if err != nil {
return err
}

View File

@ -10,146 +10,54 @@ import (
cbor "github.com/ipfs/go-ipld-cbor"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/util/adt"
)
type StateTreeCB func(state *state.StateTree) error
func (sm *StateManager) WithParentStateTsk(tsk types.TipSetKey, cb StateTreeCB) error {
func (sm *StateManager) ParentStateTsk(tsk types.TipSetKey) (*state.StateTree, error) {
ts, err := sm.cs.GetTipSetFromKey(tsk)
if err != nil {
return xerrors.Errorf("loading tipset %s: %w", tsk, err)
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
return sm.ParentState(ts, cb)
}
func (sm *StateManager) ParentState(ts *types.TipSet) (*state.StateTree, error) {
cst := cbor.NewCborStore(sm.cs.Blockstore())
state, err := state.LoadStateTree(cst, sm.parentState(ts))
version := sm.GetNtwkVersion(context.TODO(), ts.Height()-1)
state, err := state.LoadStateTree(cst, sm.parentState(ts), version)
if err != nil {
return xerrors.Errorf("load state tree: %w", err)
return nil, xerrors.Errorf("load state tree: %w", err)
}
return cb(state)
return state, nil
}
func (sm *StateManager) WithParentState(ts *types.TipSet, cb StateTreeCB) error {
func (sm *StateManager) StateTree(st cid.Cid, ntwkVersion network.Version) (*state.StateTree, error) {
cst := cbor.NewCborStore(sm.cs.Blockstore())
state, err := state.LoadStateTree(cst, sm.parentState(ts))
state, err := state.LoadStateTree(cst, st, ntwkVersion)
if err != nil {
return xerrors.Errorf("load state tree: %w", err)
return nil, xerrors.Errorf("load state tree: %w", err)
}
return cb(state)
return state, nil
}
func (sm *StateManager) WithStateTree(st cid.Cid, cb StateTreeCB) error {
cst := cbor.NewCborStore(sm.cs.Blockstore())
state, err := state.LoadStateTree(cst, st)
func (sm *StateManager) LoadActor(_ context.Context, addr address.Address, ts *types.TipSet) (*types.Actor, error) {
state, err := sm.ParentState(ts)
if err != nil {
return xerrors.Errorf("load state tree: %w", err)
return nil, err
}
return cb(state)
return state.GetActor(addr)
}
type ActorCB func(act *types.Actor) error
func GetActor(out *types.Actor) ActorCB {
return func(act *types.Actor) error {
*out = *act
return nil
}
}
func (sm *StateManager) WithActor(addr address.Address, cb ActorCB) StateTreeCB {
return func(state *state.StateTree) error {
act, err := state.GetActor(addr)
if err != nil {
return xerrors.Errorf("get actor: %w", err)
}
return cb(act)
}
}
// WithActorState usage:
// Option 1: WithActorState(ctx, idAddr, func(store adt.Store, st *ActorStateType) error {...})
// Option 2: WithActorState(ctx, idAddr, actorStatePtr)
func (sm *StateManager) WithActorState(ctx context.Context, out interface{}) ActorCB {
return func(act *types.Actor) error {
store := sm.cs.Store(ctx)
outCallback := reflect.TypeOf(out).Kind() == reflect.Func
var st reflect.Value
if outCallback {
st = reflect.New(reflect.TypeOf(out).In(1).Elem())
} else {
st = reflect.ValueOf(out)
}
if err := store.Get(ctx, act.Head, st.Interface()); err != nil {
return xerrors.Errorf("read actor head: %w", err)
}
if outCallback {
out := reflect.ValueOf(out).Call([]reflect.Value{reflect.ValueOf(store), st})
if !out[0].IsNil() && out[0].Interface().(error) != nil {
return out[0].Interface().(error)
}
}
return nil
}
}
type DeadlinesCB func(store adt.Store, deadlines *miner.Deadlines) error
func (sm *StateManager) WithDeadlines(cb DeadlinesCB) func(store adt.Store, mas *miner.State) error {
return func(store adt.Store, mas *miner.State) error {
deadlines, err := mas.LoadDeadlines(store)
if err != nil {
return err
}
return cb(store, deadlines)
}
}
type DeadlineCB func(store adt.Store, idx uint64, deadline *miner.Deadline) error
func (sm *StateManager) WithDeadline(idx uint64, cb DeadlineCB) DeadlinesCB {
return func(store adt.Store, deadlines *miner.Deadlines) error {
d, err := deadlines.LoadDeadline(store, idx)
if err != nil {
return err
}
return cb(store, idx, d)
}
}
func (sm *StateManager) WithEachDeadline(cb DeadlineCB) DeadlinesCB {
return func(store adt.Store, deadlines *miner.Deadlines) error {
return deadlines.ForEach(store, func(dlIdx uint64, dl *miner.Deadline) error {
return cb(store, dlIdx, dl)
})
}
}
type PartitionCB func(store adt.Store, idx uint64, partition *miner.Partition) error
func (sm *StateManager) WithEachPartition(cb PartitionCB) DeadlineCB {
return func(store adt.Store, idx uint64, deadline *miner.Deadline) error {
parts, err := deadline.PartitionsArray(store)
if err != nil {
return err
}
var partition miner.Partition
return parts.ForEach(&partition, func(i int64) error {
p := partition
return cb(store, uint64(i), &p)
})
func (sm *StateManager) LoadActorTsk(_ context.Context, addr address.Address, tsk types.TipSetKey) (*types.Actor, error) {
state, err := sm.ParentStateTsk(tsk)
if err != nil {
return nil, err
}
return state.GetActor(addr)
}

View File

@ -7,14 +7,14 @@ import (
"github.com/filecoin-project/specs-actors/actors/runtime"
"github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/filecoin-project/specs-actors/actors/builtin/multisig"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/builtin/market"
"github.com/filecoin-project/lotus/chain/actors/builtin/power"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
@ -23,7 +23,6 @@ import (
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/market"
"github.com/filecoin-project/specs-actors/actors/builtin/reward"
"github.com/filecoin-project/specs-actors/actors/util/adt"
@ -201,6 +200,7 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp
for i := parentEpoch; i < epoch; i++ {
// handle state forks
// XXX: The state tre
err = sm.handleStateForks(ctx, vmi.StateTree(), i, ts)
if err != nil {
return cid.Undef, cid.Undef, xerrors.Errorf("error handling state forks: %w", err)
@ -711,11 +711,14 @@ func (sm *StateManager) ListAllActors(ctx context.Context, ts *types.TipSet) ([]
}
func (sm *StateManager) MarketBalance(ctx context.Context, addr address.Address, ts *types.TipSet) (api.MarketBalance, error) {
var state market.State
_, err := sm.LoadActorState(ctx, builtin.StorageMarketActorAddr, &state, ts)
st, err := sm.ParentState(ts)
if err != nil {
return api.MarketBalance{}, err
}
act, err := st.GetActor(builtin.StorageMarketActorAddr)
if err != nil {
return nil, err
}
addr, err = sm.LookupID(ctx, addr, ts)
if err != nil {
@ -1016,19 +1019,17 @@ func GetFilMined(ctx context.Context, st *state.StateTree) (abi.TokenAmount, err
}
func getFilMarketLocked(ctx context.Context, st *state.StateTree) (abi.TokenAmount, error) {
mactor, err := st.GetActor(builtin.StorageMarketActorAddr)
act, err := st.GetActor(builtin.StorageMarketActorAddr)
if err != nil {
return big.Zero(), xerrors.Errorf("failed to load market actor: %w", err)
}
var mst market.State
if err := st.Store.Get(ctx, mactor.Head, &mst); err != nil {
mst, err := market.Load(adt.WrapStore(ctx, st.Store), act)
if err != nil {
return big.Zero(), xerrors.Errorf("failed to load market state: %w", err)
}
fml := types.BigAdd(mst.TotalClientLockedCollateral, mst.TotalProviderLockedCollateral)
fml = types.BigAdd(fml, mst.TotalClientStorageFee)
return fml, nil
return mst.TotalLocked()
}
func getFilPowerLocked(ctx context.Context, st *state.StateTree) (abi.TokenAmount, error) {
@ -1037,11 +1038,12 @@ func getFilPowerLocked(ctx context.Context, st *state.StateTree) (abi.TokenAmoun
return big.Zero(), xerrors.Errorf("failed to load power actor: %w", err)
}
var pst power.State
if err := st.Store.Get(ctx, pactor.Head, &pst); err != nil {
pst, err := power.Load(adt.WrapStore(ctx, st.Store), act)
if err != nil {
return big.Zero(), xerrors.Errorf("failed to load power state: %w", err)
}
return pst.TotalPledgeCollateral, nil
return pst.TotalLocked(), nil
}
func (sm *StateManager) GetFilLocked(ctx context.Context, st *state.StateTree) (abi.TokenAmount, error) {

View File

@ -56,30 +56,6 @@ func GetNetworkName(ctx context.Context, sm *StateManager, st cid.Cid) (dtypes.N
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)

View File

@ -11,7 +11,6 @@ import (
"golang.org/x/xerrors"
address "github.com/filecoin-project/go-address"
miner "github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/util/adt"
lru "github.com/hashicorp/golang-lru"
blocks "github.com/ipfs/go-block-format"
@ -28,6 +27,7 @@ import (
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
"github.com/filecoin-project/lotus/chain/messagepool"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/stmgr"
@ -432,9 +432,10 @@ func (bv *BlockValidator) checkPowerAndGetWorkerKey(ctx context.Context, bh *typ
if err != nil {
return address.Undef, err
}
buf := bufbstore.NewBufferedBstore(bv.chain.Blockstore())
cst := cbor.NewCborStore(buf)
state, err := state.LoadStateTree(cst, st)
state, err := state.LoadStateTree(cst, st, bv.stmgr.GetNtwkVersion(ctx, ts.Height()))
if err != nil {
return address.Undef, err
}
@ -443,19 +444,12 @@ func (bv *BlockValidator) checkPowerAndGetWorkerKey(ctx context.Context, bh *typ
return address.Undef, err
}
blk, err := bv.chain.Blockstore().Get(act.Head)
if err != nil {
return address.Undef, err
}
aso := blk.RawData()
var mst miner.State
err = mst.UnmarshalCBOR(bytes.NewReader(aso))
mst, err := miner.Load(bv.chain.Store(ctx), act)
if err != nil {
return address.Undef, err
}
info, err := mst.GetInfo(adt.WrapStore(ctx, cst))
info, err := mst.Info()
if err != nil {
return address.Undef, err
}

View File

@ -1027,9 +1027,10 @@ func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock
if err != nil {
return err
}
nwVersion := syncer.sm.GetNtwkVersion(ctx, baseTs.Height())
cst := cbor.NewCborStore(syncer.store.Blockstore())
st, err := state.LoadStateTree(cst, stateroot)
st, err := state.LoadStateTree(cst, stateroot, nwVersion)
if err != nil {
return xerrors.Errorf("failed to load base state tree: %w", err)
}

View File

@ -47,6 +47,7 @@ func NewInvoker() *Invoker {
}
// add builtInCode using: register(cid, singleton)
// NETUPGRADE: register code IDs for v2, etc.
inv.Register(builtin.SystemActorCodeID, system.Actor{}, adt.EmptyValue{})
inv.Register(builtin.InitActorCodeID, init_.Actor{}, init_.State{})
inv.Register(builtin.RewardActorCodeID, reward.Actor{}, reward.State{})

View File

@ -12,6 +12,7 @@ import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/stmgr"
"github.com/filecoin-project/lotus/chain/store"
@ -170,7 +171,9 @@ var chainBalanceStateCmd = &cli.Command{
sm := stmgr.NewStateManager(cs)
tree, err := state.LoadStateTree(cst, sroot)
// NETUPGRADE: FIXME.
// Options: (a) encode the version in the chain or (b) pass a flag.
tree, err := state.LoadStateTree(cst, sroot, network.Version0)
if err != nil {
return err
}

View File

@ -79,7 +79,7 @@ var genesisVerifyCmd = &cli.Command{
cst := cbor.NewCborStore(bs)
stree, err := state.LoadStateTree(cst, ts.ParentState())
stree, err := state.LoadStateTree(cst, ts.ParentState(), sm.GetNtwkVersion())
if err != nil {
return err
}

View File

@ -12,9 +12,11 @@ import (
"golang.org/x/xerrors"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/lotus/api/apibstore"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
lcli "github.com/filecoin-project/lotus/cli"
)
@ -49,54 +51,41 @@ var provingFaultsCmd = &cli.Command{
ctx := lcli.ReqContext(cctx)
stor := store.ActorStore(ctx, apibstore.NewAPIBlockstore(api))
maddr, err := getActorAddress(ctx, nodeApi, cctx.String("actor"))
if err != nil {
return err
}
var mas miner.State
{
mact, err := api.StateGetActor(ctx, maddr, types.EmptyTSK)
if err != nil {
return err
}
rmas, err := api.ChainReadObj(ctx, mact.Head)
if err != nil {
return err
}
if err := mas.UnmarshalCBOR(bytes.NewReader(rmas)); err != nil {
return err
}
mact, err := api.StateGetActor(ctx, maddr, types.EmptyTSK)
if err != nil {
return err
}
mas, err := miner.Load(stor, mact)
if err != nil {
return err
}
fmt.Printf("Miner: %s\n", color.BlueString("%s", maddr))
head, err := api.ChainHead(ctx)
if err != nil {
return xerrors.Errorf("getting chain head: %w", err)
}
deadlines, err := api.StateMinerDeadlines(ctx, maddr, head.Key())
if err != nil {
return xerrors.Errorf("getting miner deadlines: %w", err)
}
tw := tabwriter.NewWriter(os.Stdout, 2, 4, 2, ' ', 0)
_, _ = fmt.Fprintln(tw, "deadline\tpartition\tsectors")
for dlIdx := range deadlines {
partitions, err := api.StateMinerPartitions(ctx, maddr, uint64(dlIdx), types.EmptyTSK)
if err != nil {
return xerrors.Errorf("loading partitions for deadline %d: %w", dlIdx, err)
}
for partIdx, partition := range partitions {
faulty, err := partition.Faults.All(10000000)
err = mas.ForEachDeadline(func(dlIdx uint64, dl miner.Deadline) error {
dl.ForEachPartition(func(partIdx uint64, part miner.Partition) error {
faults, err := part.Faults()
if err != nil {
return err
}
for _, num := range faulty {
faults.ForEach(func(num uint64) error {
_, _ = fmt.Fprintf(tw, "%d\t%d\t%d\n", dlIdx, partIdx, num)
}
}
return nil
})
})
})
if err != nil {
return err
}
return tw.Flush()
},
@ -132,67 +121,61 @@ var provingInfoCmd = &cli.Command{
return xerrors.Errorf("getting chain head: %w", err)
}
mact, err := api.StateGetActor(ctx, maddr, head.Key())
if err != nil {
return err
}
stor := store.ActorStore(ctx, apibstore.NewAPIBlockstore(api))
mas, err := miner.Load(stor, mact)
if err != nil {
return err
}
cd, err := api.StateMinerProvingDeadline(ctx, maddr, head.Key())
if err != nil {
return xerrors.Errorf("getting miner info: %w", err)
}
deadlines, err := api.StateMinerDeadlines(ctx, maddr, head.Key())
if err != nil {
return xerrors.Errorf("getting miner deadlines: %w", err)
}
fmt.Printf("Miner: %s\n", color.BlueString("%s", maddr))
var mas miner.State
{
mact, err := api.StateGetActor(ctx, maddr, types.EmptyTSK)
if err != nil {
return err
}
rmas, err := api.ChainReadObj(ctx, mact.Head)
if err != nil {
return err
}
if err := mas.UnmarshalCBOR(bytes.NewReader(rmas)); err != nil {
return err
}
}
parts := map[uint64][]*miner.Partition{}
for dlIdx := range deadlines {
part, err := api.StateMinerPartitions(ctx, maddr, uint64(dlIdx), types.EmptyTSK)
if err != nil {
return xerrors.Errorf("getting miner partition: %w", err)
}
parts[uint64(dlIdx)] = part
}
proving := uint64(0)
faults := uint64(0)
recovering := uint64(0)
curDeadlineSectors := uint64(0)
for _, partitions := range parts {
for _, partition := range partitions {
sc, err := partition.Sectors.Count()
if err != nil {
return xerrors.Errorf("count partition sectors: %w", err)
if err := mas.ForEachDeadline(func(dlIdx uint64, dl miner.Deadline) error {
return dl.ForEachPartition(func(partIdx uint64, part miner.Partition) error {
if bf, err := part.LiveSectors(); err != nil {
return err
} else if count, err := bf.Count(); err != nil {
return err
} else {
proving += count
if dlIdx == cd.Index {
curDeadlineSectors += count
}
}
proving += sc
fc, err := partition.Faults.Count()
if err != nil {
return xerrors.Errorf("count partition faults: %w", err)
if bf, err := part.Faults(); err != nil {
return err
} else if count, err := bf.Count(); err != nil {
return err
} else {
faults += count
}
faults += fc
rc, err := partition.Recoveries.Count()
if err != nil {
return xerrors.Errorf("count partition recoveries: %w", err)
if bf, err := part.Recovering(); err != nil {
return err
} else if count, err := bf.Count(); err != nil {
return err
} else {
recovering += count
}
recovering += rc
}
})
}); err != nil {
return xerrors.Errorf("walking miner deadlines and partitions: %w", err)
}
var faultPerc float64
@ -202,28 +185,15 @@ var provingInfoCmd = &cli.Command{
fmt.Printf("Current Epoch: %d\n", cd.CurrentEpoch)
fmt.Printf("Proving Period Boundary: %d\n", cd.PeriodStart%miner.WPoStProvingPeriod)
fmt.Printf("Proving Period Boundary: %d\n", cd.PeriodStart%cd.WPoStProvingPeriod)
fmt.Printf("Proving Period Start: %s\n", epochTime(cd.CurrentEpoch, cd.PeriodStart))
fmt.Printf("Next Period Start: %s\n\n", epochTime(cd.CurrentEpoch, cd.PeriodStart+miner.WPoStProvingPeriod))
fmt.Printf("Next Period Start: %s\n\n", epochTime(cd.CurrentEpoch, cd.PeriodStart+cd.WPoStProvingPeriod))
fmt.Printf("Faults: %d (%.2f%%)\n", faults, faultPerc)
fmt.Printf("Recovering: %d\n", recovering)
fmt.Printf("Deadline Index: %d\n", cd.Index)
if cd.Index < miner.WPoStPeriodDeadlines {
curDeadlineSectors := uint64(0)
for _, partition := range parts[cd.Index] {
sc, err := partition.Sectors.Count()
if err != nil {
return xerrors.Errorf("counting current deadline sectors: %w", err)
}
curDeadlineSectors += sc
}
fmt.Printf("Deadline Sectors: %d\n", curDeadlineSectors)
}
fmt.Printf("Deadline Sectors: %d\n", curDeadlineSectors)
fmt.Printf("Deadline Open: %s\n", epochTime(cd.CurrentEpoch, cd.Open))
fmt.Printf("Deadline Close: %s\n", epochTime(cd.CurrentEpoch, cd.Close))
fmt.Printf("Deadline Challenge: %s\n", epochTime(cd.CurrentEpoch, cd.Challenge))
@ -286,6 +256,7 @@ var provingDeadlinesCmd = &cli.Command{
if err != nil {
return err
}
miner.Load
rmas, err := api.ChainReadObj(ctx, mact.Head)
if err != nil {
return err

View File

@ -4,7 +4,7 @@ import (
"bytes"
"context"
saproof "github.com/filecoin-project/specs-actors/actors/runtime/proof"
v0proof "github.com/filecoin-project/specs-actors/actors/runtime/proof"
"golang.org/x/xerrors"
@ -170,7 +170,7 @@ func (m *Sealing) checkCommit(ctx context.Context, si SectorInfo, proof []byte,
log.Warn("on-chain sealed CID doesn't match!")
}
ok, err := m.verif.VerifySeal(saproof.SealVerifyInfo{
ok, err := m.verif.VerifySeal(v0proof.SealVerifyInfo{
SectorID: m.minerSector(si.SectorNumber),
SealedCID: pci.Info.SealedCID,
SealProof: spt,

4
go.mod
View File

@ -34,11 +34,11 @@ require (
github.com/filecoin-project/go-multistore v0.0.3
github.com/filecoin-project/go-padreader v0.0.0-20200903213702-ed5fae088b20
github.com/filecoin-project/go-paramfetch v0.0.2-0.20200701152213-3e0f0afdc261
github.com/filecoin-project/go-state-types v0.0.0-20200905071437-95828685f9df
github.com/filecoin-project/go-state-types v0.0.0-20200911004822-964d6c679cfc
github.com/filecoin-project/go-statemachine v0.0.0-20200813232949-df9b130df370
github.com/filecoin-project/go-statestore v0.1.0
github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b
github.com/filecoin-project/specs-actors v0.9.7
github.com/filecoin-project/specs-actors v0.9.9-0.20200911231631-727cd8845d30
github.com/filecoin-project/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796
github.com/filecoin-project/test-vectors/schema v0.0.1
github.com/gbrlsnchs/jwt/v3 v3.0.0-beta.1

6
go.sum
View File

@ -226,6 +226,8 @@ github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f h1
github.com/filecoin-project/go-fil-commcid v0.0.0-20200716160307-8f644712406f/go.mod h1:Eaox7Hvus1JgPrL5+M3+h7aSPHc0cVqpSxA+TxIEpZQ=
github.com/filecoin-project/go-fil-markets v0.6.0 h1:gfxMweUHo4u+2BZh2Q7/7+cV0/ttikuJfhkkxLRsE2Q=
github.com/filecoin-project/go-fil-markets v0.6.0/go.mod h1:LhSFYLkjaoe0vFRKABGYyw1Jz+9jCpF1sPA7yOftLTw=
github.com/filecoin-project/go-hamt-ipld v0.1.5 h1:uoXrKbCQZ49OHpsTCkrThPNelC4W3LPEk0OrS/ytIBM=
github.com/filecoin-project/go-hamt-ipld v0.1.5/go.mod h1:6Is+ONR5Cd5R6XZoCse1CWaXZc0Hdb/JeX+EQCQzX24=
github.com/filecoin-project/go-jsonrpc v0.1.2-0.20200822201400-474f4fdccc52 h1:FXtCp0ybqdQL9knb3OGDpkNTaBbPxgkqPeWKotUwkH0=
github.com/filecoin-project/go-jsonrpc v0.1.2-0.20200822201400-474f4fdccc52/go.mod h1:XBBpuKIMaXIIzeqzO1iucq4GvbF8CxmXRFoezRh+Cx4=
github.com/filecoin-project/go-multistore v0.0.3 h1:vaRBY4YiA2UZFPK57RNuewypB8u0DzzQwqsL0XarpnI=
@ -238,6 +240,8 @@ github.com/filecoin-project/go-state-types v0.0.0-20200903145444-247639ffa6ad/go
github.com/filecoin-project/go-state-types v0.0.0-20200904021452-1883f36ca2f4/go.mod h1:IQ0MBPnonv35CJHtWSN3YY1Hz2gkPru1Q9qoaYLxx9I=
github.com/filecoin-project/go-state-types v0.0.0-20200905071437-95828685f9df h1:m2esXSuGBkuXlRyCsl1a/7/FkFam63o1OzIgzaHtOfI=
github.com/filecoin-project/go-state-types v0.0.0-20200905071437-95828685f9df/go.mod h1:IQ0MBPnonv35CJHtWSN3YY1Hz2gkPru1Q9qoaYLxx9I=
github.com/filecoin-project/go-state-types v0.0.0-20200911004822-964d6c679cfc h1:1vr/LoqGq5m5g37Q3sNSAjfwF1uJY0zmiHcvnxY6hik=
github.com/filecoin-project/go-state-types v0.0.0-20200911004822-964d6c679cfc/go.mod h1:ezYnPf0bNkTsDibL/psSz5dy4B5awOJ/E7P2Saeep8g=
github.com/filecoin-project/go-statemachine v0.0.0-20200714194326-a77c3ae20989/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig=
github.com/filecoin-project/go-statemachine v0.0.0-20200813232949-df9b130df370 h1:Jbburj7Ih2iaJ/o5Q9A+EAeTabME6YII7FLi9SKUf5c=
github.com/filecoin-project/go-statemachine v0.0.0-20200813232949-df9b130df370/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig=
@ -248,6 +252,8 @@ github.com/filecoin-project/go-storedcounter v0.0.0-20200421200003-1c99c62e8a5b/
github.com/filecoin-project/specs-actors v0.9.4/go.mod h1:BStZQzx5x7TmCkLv0Bpa07U6cPKol6fd3w9KjMPZ6Z4=
github.com/filecoin-project/specs-actors v0.9.7 h1:7PAZ8kdqwBdmgf/23FCkQZLCXcVu02XJrkpkhBikiA8=
github.com/filecoin-project/specs-actors v0.9.7/go.mod h1:wM2z+kwqYgXn5Z7scV1YHLyd1Q1cy0R8HfTIWQ0BFGU=
github.com/filecoin-project/specs-actors v0.9.9-0.20200911231631-727cd8845d30 h1:6Kn6y3TpJbk5BsvhVha+3jr7C3gAAJq0rCnwUYOWRl0=
github.com/filecoin-project/specs-actors v0.9.9-0.20200911231631-727cd8845d30/go.mod h1:czlvLQGEX0fjLLfdNHD7xLymy6L3n7aQzRWzsYGf+ys=
github.com/filecoin-project/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796 h1:dJsTPWpG2pcTeojO2pyn0c6l+x/3MZYCBgo/9d11JEk=
github.com/filecoin-project/specs-storage v0.1.1-0.20200907031224-ed2e5cd13796/go.mod h1:nJRRM7Aa9XVvygr3W9k6xGF46RWzr2zxF/iGoAIfA/g=
github.com/filecoin-project/test-vectors/schema v0.0.1 h1:5fNF76nl4qolEvcIsjc0kUADlTMVHO73tW4kXXPnsus=

View File

@ -20,7 +20,6 @@ import (
"github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/market"
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
samsig "github.com/filecoin-project/specs-actors/actors/builtin/multisig"
"github.com/filecoin-project/specs-actors/actors/builtin/power"
"github.com/filecoin-project/specs-actors/actors/builtin/reward"
@ -33,6 +32,7 @@ import (
"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/actors/builtin/miner"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
@ -112,6 +112,8 @@ func (a *StateAPI) StateMinerInfo(ctx context.Context, actor address.Address, ts
return api.MinerInfo{}, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
a.StateManager.LoadActorStateRaw(ctx context.Context, addr address.Address, out interface{}, st cid.Cid)
mi, err := stmgr.StateMinerInfo(ctx, a.StateManager, ts, actor)
if err != nil {
return api.MinerInfo{}, err
@ -119,17 +121,28 @@ func (a *StateAPI) StateMinerInfo(ctx context.Context, actor address.Address, ts
return api.NewApiMinerInfo(mi), nil
}
func (a *StateAPI) StateMinerDeadlines(ctx context.Context, m address.Address, tsk types.TipSetKey) ([]*miner.Deadline, error) {
func (a *StateAPI) StateMinerDeadlines(ctx context.Context, m address.Address, tsk types.TipSetKey) ([]miner.Deadline, error) {
var out []*miner.Deadline
return out, a.StateManager.WithParentStateTsk(tsk,
a.StateManager.WithActor(m,
a.StateManager.WithActorState(ctx,
a.StateManager.WithDeadlines(
a.StateManager.WithEachDeadline(
func(store adt.Store, idx uint64, deadline *miner.Deadline) error {
out = append(out, deadline)
return nil
})))))
state, err := a.StateManager.LoadParentStateTsk(tsk)
if err != nil {
return nil, err
}
act, err := state.GetActor(addr)
if err != nil {
return nil, err
}
mas, err := miner.Load(a.Chain.Store(ctx), act)
if err != nil {
return nil, err
}
var deadlines []miner.Deadline
if err := mas.ForEachDeadline(func(_ uint64, dl miner.Deadline) error {
deadlines = append(deadlines, dl)
return nil
}); err != nil {
return err
}
return deadlines, nil
}
func (a *StateAPI) StateMinerPartitions(ctx context.Context, m address.Address, dlIdx uint64, tsk types.TipSetKey) ([]*miner.Partition, error) {
@ -302,7 +315,7 @@ func (a *StateAPI) stateForTs(ctx context.Context, ts *types.TipSet) (*state.Sta
buf := bufbstore.NewBufferedBstore(a.Chain.Blockstore())
cst := cbor.NewCborStore(buf)
return state.LoadStateTree(cst, st)
return state.LoadStateTree(cst, st, a.StateManager.GetNtwkVersion(ctx, ts.Height()))
}
func (a *StateAPI) StateGetActor(ctx context.Context, actor address.Address, tsk types.TipSetKey) (*types.Actor, error) {
@ -1169,16 +1182,9 @@ func (a *StateAPI) StateCirculatingSupply(ctx context.Context, tsk types.TipSetK
return api.CirculatingSupply{}, xerrors.Errorf("loading tipset %s: %w", tsk, err)
}
st, _, err := a.StateManager.TipSetState(ctx, ts)
sTree, err := a.stateForTs(ctx, ts)
if err != nil {
return api.CirculatingSupply{}, err
}
cst := cbor.NewCborStore(a.Chain.Blockstore())
sTree, err := state.LoadStateTree(cst, st)
if err != nil {
return api.CirculatingSupply{}, err
}
return a.StateManager.GetCirculatingSupplyDetailed(ctx, ts.Height(), sTree)
}

View File

@ -16,13 +16,13 @@ import (
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/specs-actors/actors/builtin"
"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/util/adt"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/apibstore"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
sealing "github.com/filecoin-project/lotus/extern/storage-sealing"
@ -179,14 +179,11 @@ func (s SealingAPIAdapter) StateSectorPreCommitInfo(ctx context.Context, maddr a
return nil, xerrors.Errorf("handleSealFailed(%d): temp error: %+v", sectorNumber, err)
}
st, err := s.delegate.ChainReadObj(ctx, act.Head)
if err != nil {
return nil, xerrors.Errorf("handleSealFailed(%d): temp error: %+v", sectorNumber, err)
}
stor := store.ActorStore(ctx, apibstore.NewAPIBlockstore(s.delegate))
var state miner.State
if err := state.UnmarshalCBOR(bytes.NewReader(st)); err != nil {
return nil, xerrors.Errorf("handleSealFailed(%d): temp error: unmarshaling miner state: %+v", sectorNumber, err)
state, err := miner.Load(stor, act)
if err != nil {
return nil, xerrors.Errorf("handleSealFailed(%d): temp error: loading miner state: %+v", sectorNumber, err)
}
stor := store.ActorStore(ctx, apibstore.NewAPIBlockstore(s.delegate))
precommits, err := adt.AsMap(stor, state.PreCommittedSectors)

View File

@ -6,28 +6,32 @@ import (
"errors"
"time"
"github.com/filecoin-project/specs-actors/actors/runtime/proof"
"github.com/filecoin-project/go-bitfield"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/big"
"github.com/filecoin-project/go-state-types/crypto"
"github.com/filecoin-project/go-state-types/dline"
"github.com/filecoin-project/specs-actors/actors/builtin"
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
"go.opencensus.io/trace"
"golang.org/x/xerrors"
v0miner "github.com/filecoin-project/specs-actors/actors/builtin/miner"
v0proof "github.com/filecoin-project/specs-actors/actors/runtime/proof"
"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/api/apibstore"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/builtin/miner"
"github.com/filecoin-project/lotus/chain/store"
"github.com/filecoin-project/lotus/chain/types"
)
var errNoPartitions = errors.New("no partitions")
func (s *WindowPoStScheduler) failPost(deadline *miner.DeadlineInfo) {
func (s *WindowPoStScheduler) failPost(deadline *dline.Info) {
log.Errorf("TODO")
/*s.failLk.Lock()
if eps > s.failed {
@ -36,7 +40,7 @@ func (s *WindowPoStScheduler) failPost(deadline *miner.DeadlineInfo) {
s.failLk.Unlock()*/
}
func (s *WindowPoStScheduler) doPost(ctx context.Context, deadline *miner.DeadlineInfo, ts *types.TipSet) {
func (s *WindowPoStScheduler) doPost(ctx context.Context, deadline *dline.Info, ts *types.TipSet) {
ctx, abort := context.WithCancel(ctx)
s.abort = abort
@ -111,18 +115,26 @@ func (s *WindowPoStScheduler) checkSectors(ctx context.Context, check bitfield.B
return sbf, nil
}
func (s *WindowPoStScheduler) checkNextRecoveries(ctx context.Context, dlIdx uint64, partitions []*miner.Partition) error {
func (s *WindowPoStScheduler) checkNextRecoveries(ctx context.Context, dlIdx uint64, partitions []miner.Partition) error {
ctx, span := trace.StartSpan(ctx, "storage.checkNextRecoveries")
defer span.End()
params := &miner.DeclareFaultsRecoveredParams{
Recoveries: []miner.RecoveryDeclaration{},
params := &v0miner.DeclareFaultsRecoveredParams{
Recoveries: []v0miner.RecoveryDeclaration{},
}
faulty := uint64(0)
for partIdx, partition := range partitions {
unrecovered, err := bitfield.SubtractBitField(partition.Faults, partition.Recoveries)
faults, err := partition.FaultySectors()
if err != nil {
return xerrors.Errorf("getting faults: %w", err)
}
recovering, err := partition.RecoveringSectors()
if err != nil {
return xerrors.Errorf("getting recovering: %w", err)
}
unrecovered, err := bitfield.SubtractBitField(faults, recovering)
if err != nil {
return xerrors.Errorf("subtracting recovered set from fault set: %w", err)
}
@ -153,7 +165,7 @@ func (s *WindowPoStScheduler) checkNextRecoveries(ctx context.Context, dlIdx uin
continue
}
params.Recoveries = append(params.Recoveries, miner.RecoveryDeclaration{
params.Recoveries = append(params.Recoveries, v0miner.RecoveryDeclaration{
Deadline: dlIdx,
Partition: uint64(partIdx),
Sectors: recovered,
@ -202,17 +214,17 @@ func (s *WindowPoStScheduler) checkNextRecoveries(ctx context.Context, dlIdx uin
return nil
}
func (s *WindowPoStScheduler) checkNextFaults(ctx context.Context, dlIdx uint64, partitions []*miner.Partition) error {
func (s *WindowPoStScheduler) checkNextFaults(ctx context.Context, dlIdx uint64, partitions []miner.Partition) error {
ctx, span := trace.StartSpan(ctx, "storage.checkNextFaults")
defer span.End()
params := &miner.DeclareFaultsParams{
Faults: []miner.FaultDeclaration{},
params := &v0miner.DeclareFaultsParams{
Faults: []v0miner.FaultDeclaration{},
}
bad := uint64(0)
for partIdx, partition := range partitions {
for _, partition := range partitions {
toCheck, err := partition.ActiveSectors()
if err != nil {
return xerrors.Errorf("getting active sectors: %w", err)
@ -239,7 +251,7 @@ func (s *WindowPoStScheduler) checkNextFaults(ctx context.Context, dlIdx uint64,
bad += c
params.Faults = append(params.Faults, miner.FaultDeclaration{
params.Faults = append(params.Faults, v0miner.FaultDeclaration{
Deadline: dlIdx,
Partition: uint64(partIdx),
Sectors: faulty,
@ -286,20 +298,40 @@ func (s *WindowPoStScheduler) checkNextFaults(ctx context.Context, dlIdx uint64,
return nil
}
func (s *WindowPoStScheduler) runPost(ctx context.Context, di miner.DeadlineInfo, ts *types.TipSet) (*miner.SubmitWindowedPoStParams, error) {
func (s *WindowPoStScheduler) runPost(ctx context.Context, di dline.Info, ts *types.TipSet) (*v0miner.SubmitWindowedPoStParams, error) {
ctx, span := trace.StartSpan(ctx, "storage.runPost")
defer span.End()
stor := store.ActorStore(ctx, apibstore.NewAPIBlockstore(s.api))
act, err := s.api.StateGetActor(context.TODO(), s.actor, ts.Key())
if err != nil {
return nil, xerrors.Errorf("resolving actor: %w", err)
}
mas, err := miner.Load(stor, act)
if err != nil {
return nil, xerrors.Errorf("getting miner state: %w", err)
}
go func() {
// TODO: extract from runPost, run on fault cutoff boundaries
// check faults / recoveries for the *next* deadline. It's already too
// late to declare them for this deadline
declDeadline := (di.Index + 2) % miner.WPoStPeriodDeadlines
declDeadline := (di.Index + 2) % di.WPoStPeriodDeadlines
partitions, err := s.api.StateMinerPartitions(context.TODO(), s.actor, declDeadline, ts.Key())
dl, err := mas.LoadDeadline(declDeadline)
if err != nil {
log.Errorf("getting partitions: %v", err)
log.Errorf("loading deadline: %v", err)
return
}
var partitions []miner.Partition
err = dl.ForEachPartition(func(_ uint64, part miner.Partition) error {
partitions = append(partitions, part)
return nil
})
if err != nil {
log.Errorf("loading partitions: %v", err)
return
}
@ -324,18 +356,27 @@ func (s *WindowPoStScheduler) runPost(ctx context.Context, di miner.DeadlineInfo
return nil, xerrors.Errorf("failed to get chain randomness for windowPost (ts=%d; deadline=%d): %w", ts.Height(), di, err)
}
partitions, err := s.api.StateMinerPartitions(ctx, s.actor, di.Index, ts.Key())
dl, err := mas.LoadDeadline(di.Index)
if err != nil {
return nil, xerrors.Errorf("getting partitions: %w", err)
return nil, xerrors.Errorf("loading deadline: %w", err)
}
params := &miner.SubmitWindowedPoStParams{
var partitions []miner.Partitions
err = dl.ForEachPartition(func(_ uint64, part miner.Partition) error {
partitions = apppend(partitions, part)
return nil
})
if err != nil {
return nil, xerrors.Errorf("loading partitions: %w", err)
}
params := &v0miner.SubmitWindowedPoStParams{
Deadline: di.Index,
Partitions: make([]miner.PoStPartition, 0, len(partitions)),
Partitions: make([]v0miner.PoStPartition, 0, len(partitions)),
Proofs: nil,
}
var sinfos []proof.SectorInfo
var sinfos []v0proof.SectorInfo
sidToPart := map[abi.SectorNumber]uint64{}
skipCount := uint64(0)
@ -382,7 +423,7 @@ func (s *WindowPoStScheduler) runPost(ctx context.Context, di miner.DeadlineInfo
sidToPart[si.SectorNumber] = uint64(partIdx)
}
params.Partitions = append(params.Partitions, miner.PoStPartition{
params.Partitions = append(params.Partitions, v0miner.PoStPartition{
Index: uint64(partIdx),
Skipped: skipped,
})
@ -436,7 +477,7 @@ func (s *WindowPoStScheduler) runPost(ctx context.Context, di miner.DeadlineInfo
return params, nil
}
func (s *WindowPoStScheduler) sectorsForProof(ctx context.Context, goodSectors, allSectors bitfield.BitField, ts *types.TipSet) ([]proof.SectorInfo, error) {
func (s *WindowPoStScheduler) sectorsForProof(ctx context.Context, goodSectors, allSectors bitfield.BitField, ts *types.TipSet) ([]v0proof.SectorInfo, error) {
sset, err := s.api.StateMinerSectors(ctx, s.actor, &goodSectors, false, ts.Key())
if err != nil {
return nil, err
@ -446,22 +487,22 @@ func (s *WindowPoStScheduler) sectorsForProof(ctx context.Context, goodSectors,
return nil, nil
}
substitute := proof.SectorInfo{
substitute := v0proof.SectorInfo{
SectorNumber: sset[0].ID,
SealedCID: sset[0].Info.SealedCID,
SealProof: sset[0].Info.SealProof,
}
sectorByID := make(map[uint64]proof.SectorInfo, len(sset))
sectorByID := make(map[uint64]v0proof.SectorInfo, len(sset))
for _, sector := range sset {
sectorByID[uint64(sector.ID)] = proof.SectorInfo{
sectorByID[uint64(sector.ID)] = v0proof.SectorInfo{
SectorNumber: sector.ID,
SealedCID: sector.Info.SealedCID,
SealProof: sector.Info.SealProof,
}
}
proofSectors := make([]proof.SectorInfo, 0, len(sset))
proofSectors := make([]v0proof.SectorInfo, 0, len(sset))
if err := allSectors.ForEach(func(sectorNo uint64) error {
if info, found := sectorByID[sectorNo]; found {
proofSectors = append(proofSectors, info)
@ -476,7 +517,7 @@ func (s *WindowPoStScheduler) sectorsForProof(ctx context.Context, goodSectors,
return proofSectors, nil
}
func (s *WindowPoStScheduler) submitPost(ctx context.Context, proof *miner.SubmitWindowedPoStParams) error {
func (s *WindowPoStScheduler) submitPost(ctx context.Context, proof *v0miner.SubmitWindowedPoStParams) error {
ctx, span := trace.StartSpan(ctx, "storage.commitPost")
defer span.End()

View File

@ -8,7 +8,7 @@ import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/go-state-types/dline"
"github.com/filecoin-project/specs-storage/storage"
"github.com/filecoin-project/lotus/api"
@ -37,7 +37,7 @@ type WindowPoStScheduler struct {
cur *types.TipSet
// if a post is in progress, this indicates for which ElectionPeriodStart
activeDeadline *miner.DeadlineInfo
activeDeadline *dline.Info
abort context.CancelFunc
//failed abi.ChainEpoch // eps
@ -68,7 +68,7 @@ func NewWindowedPoStScheduler(api storageMinerApi, fc config.MinerFeeConfig, sb
}, nil
}
func deadlineEquals(a, b *miner.DeadlineInfo) bool {
func deadlineEquals(a, b *dline.Info) bool {
if a == nil || b == nil {
return b == a
}