Merge branch 'master' into feat/new-sb-fs
This commit is contained in:
commit
90ecfbe0e4
@ -2,7 +2,7 @@
|
||||
|
||||
# Project Lotus - 莲
|
||||
|
||||
Lotus is an experimental implementation of the Filecoin Distributed Storage Network. For more details about Filecoin, check out the [Filecoin Spec](https://github.com/filecoin-project/specs).
|
||||
Lotus is an implementation of the Filecoin Distributed Storage Network. For more details about Filecoin, check out the [Filecoin Spec](https://github.com/filecoin-project/specs).
|
||||
|
||||
## Development
|
||||
|
||||
|
@ -4,11 +4,11 @@ import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/ipfs/go-filestore"
|
||||
"github.com/libp2p/go-libp2p-core/peer"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
"github.com/filecoin-project/lotus/chain/store"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
@ -32,6 +32,7 @@ type FullNode interface {
|
||||
ChainGetParentMessages(context.Context, cid.Cid) ([]Message, error)
|
||||
ChainGetTipSetByHeight(context.Context, uint64, *types.TipSet) (*types.TipSet, error)
|
||||
ChainReadObj(context.Context, cid.Cid) ([]byte, error)
|
||||
ChainHasObj(context.Context, cid.Cid) (bool, error)
|
||||
ChainSetHead(context.Context, *types.TipSet) error
|
||||
ChainGetGenesis(context.Context) (*types.TipSet, error)
|
||||
ChainTipSetWeight(context.Context, *types.TipSet) (types.BigInt, error)
|
||||
@ -123,6 +124,8 @@ type FullNode interface {
|
||||
StateMinerSectorCount(context.Context, address.Address, *types.TipSet) (MinerSectors, error)
|
||||
StateCompute(context.Context, uint64, []*types.Message, *types.TipSet) (cid.Cid, error)
|
||||
|
||||
MsigGetAvailableBalance(context.Context, address.Address, *types.TipSet) (types.BigInt, error)
|
||||
|
||||
MarketEnsureAvailable(context.Context, address.Address, types.BigInt) error
|
||||
// MarketFreeBalance
|
||||
|
||||
|
61
api/apibstore/apibstore.go
Normal file
61
api/apibstore/apibstore.go
Normal file
@ -0,0 +1,61 @@
|
||||
package apibstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
blocks "github.com/ipfs/go-block-format"
|
||||
"github.com/ipfs/go-cid"
|
||||
blockstore "github.com/ipfs/go-ipfs-blockstore"
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
type ChainIO interface {
|
||||
ChainReadObj(context.Context, cid.Cid) ([]byte, error)
|
||||
ChainHasObj(context.Context, cid.Cid) (bool, error)
|
||||
}
|
||||
|
||||
type apiBStore struct {
|
||||
api ChainIO
|
||||
}
|
||||
|
||||
func (a *apiBStore) DeleteBlock(cid.Cid) error {
|
||||
return xerrors.New("not supported")
|
||||
}
|
||||
|
||||
func (a *apiBStore) Has(c cid.Cid) (bool, error) {
|
||||
return a.api.ChainHasObj(context.TODO(), c)
|
||||
}
|
||||
|
||||
func (a *apiBStore) Get(c cid.Cid) (blocks.Block, error) {
|
||||
bb, err := a.api.ChainReadObj(context.TODO(), c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return blocks.NewBlockWithCid(bb, c)
|
||||
}
|
||||
|
||||
func (a *apiBStore) GetSize(c cid.Cid) (int, error) {
|
||||
bb, err := a.api.ChainReadObj(context.TODO(), c)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return len(bb), nil
|
||||
}
|
||||
|
||||
func (a *apiBStore) Put(blocks.Block) error {
|
||||
return xerrors.New("not supported")
|
||||
}
|
||||
|
||||
func (a *apiBStore) PutMany([]blocks.Block) error {
|
||||
return xerrors.New("not supported")
|
||||
}
|
||||
|
||||
func (a *apiBStore) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
|
||||
return nil, xerrors.New("not supported")
|
||||
}
|
||||
|
||||
func (a *apiBStore) HashOnRead(enabled bool) {
|
||||
return
|
||||
}
|
||||
|
||||
var _ blockstore.Blockstore = &apiBStore{}
|
@ -50,6 +50,7 @@ type FullNodeStruct struct {
|
||||
ChainGetParentMessages func(context.Context, cid.Cid) ([]api.Message, error) `perm:"read"`
|
||||
ChainGetTipSetByHeight func(context.Context, uint64, *types.TipSet) (*types.TipSet, error) `perm:"read"`
|
||||
ChainReadObj func(context.Context, cid.Cid) ([]byte, error) `perm:"read"`
|
||||
ChainHasObj func(context.Context, cid.Cid) (bool, error) `perm:"read"`
|
||||
ChainSetHead func(context.Context, *types.TipSet) error `perm:"admin"`
|
||||
ChainGetGenesis func(context.Context) (*types.TipSet, error) `perm:"read"`
|
||||
ChainTipSetWeight func(context.Context, *types.TipSet) (types.BigInt, error) `perm:"read"`
|
||||
@ -119,6 +120,8 @@ type FullNodeStruct struct {
|
||||
StateListMessages func(ctx context.Context, match *types.Message, ts *types.TipSet, toht uint64) ([]cid.Cid, error) `perm:"read"`
|
||||
StateCompute func(context.Context, uint64, []*types.Message, *types.TipSet) (cid.Cid, error) `perm:"read"`
|
||||
|
||||
MsigGetAvailableBalance func(context.Context, address.Address, *types.TipSet) (types.BigInt, error) `perm:"read"`
|
||||
|
||||
MarketEnsureAvailable func(context.Context, address.Address, types.BigInt) error `perm:"sign"`
|
||||
|
||||
PaychGet func(ctx context.Context, from, to address.Address, ensureFunds types.BigInt) (*api.ChannelInfo, error) `perm:"sign"`
|
||||
@ -339,6 +342,10 @@ func (c *FullNodeStruct) ChainReadObj(ctx context.Context, obj cid.Cid) ([]byte,
|
||||
return c.Internal.ChainReadObj(ctx, obj)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) ChainHasObj(ctx context.Context, o cid.Cid) (bool, error) {
|
||||
return c.Internal.ChainHasObj(ctx, o)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) ChainSetHead(ctx context.Context, ts *types.TipSet) error {
|
||||
return c.Internal.ChainSetHead(ctx, ts)
|
||||
}
|
||||
@ -482,6 +489,10 @@ func (c *FullNodeStruct) StateCompute(ctx context.Context, height uint64, msgs [
|
||||
return c.Internal.StateCompute(ctx, height, msgs, ts)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) MsigGetAvailableBalance(ctx context.Context, a address.Address, ts *types.TipSet) (types.BigInt, error) {
|
||||
return c.Internal.MsigGetAvailableBalance(ctx, a, ts)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) MarketEnsureAvailable(ctx context.Context, addr address.Address, amt types.BigInt) error {
|
||||
return c.Internal.MarketEnsureAvailable(ctx, addr, amt)
|
||||
}
|
||||
|
@ -27,6 +27,8 @@ const (
|
||||
GasCreateActor = 100
|
||||
)
|
||||
|
||||
var BuiltInActors map[cid.Cid]bool
|
||||
|
||||
func init() {
|
||||
|
||||
n, err := cbor.WrapObject(map[string]string{}, mh.SHA2_256, -1)
|
||||
@ -160,12 +162,7 @@ func (ia InitActor) Exec(act *types.Actor, vmctx types.VMContext, p *ExecParams)
|
||||
}
|
||||
|
||||
func IsBuiltinActor(code cid.Cid) bool {
|
||||
switch code {
|
||||
case StorageMarketCodeCid, StoragePowerCodeCid, StorageMinerCodeCid, StorageMiner2CodeCid, AccountCodeCid, InitCodeCid, MultisigCodeCid, PaymentChannelCodeCid:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
return BuiltInActors[code]
|
||||
}
|
||||
|
||||
func IsSingletonActor(code cid.Cid) bool {
|
||||
|
@ -51,4 +51,15 @@ func init() {
|
||||
MultisigCodeCid = mustSum("fil/1/multisig")
|
||||
InitCodeCid = mustSum("fil/1/init")
|
||||
PaymentChannelCodeCid = mustSum("fil/1/paych")
|
||||
|
||||
BuiltInActors = map[cid.Cid]bool{
|
||||
StorageMarketCodeCid: true,
|
||||
StoragePowerCodeCid: true,
|
||||
StorageMinerCodeCid: true,
|
||||
StorageMiner2CodeCid: true,
|
||||
AccountCodeCid: true,
|
||||
InitCodeCid: true,
|
||||
MultisigCodeCid: true,
|
||||
PaymentChannelCodeCid: true,
|
||||
}
|
||||
}
|
||||
|
@ -6,10 +6,11 @@ import (
|
||||
"crypto/sha256"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"github.com/filecoin-project/lotus/chain/vm"
|
||||
"io/ioutil"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/vm"
|
||||
|
||||
ffi "github.com/filecoin-project/filecoin-ffi"
|
||||
|
||||
sectorbuilder "github.com/filecoin-project/go-sectorbuilder"
|
||||
@ -56,6 +57,8 @@ type ChainGen struct {
|
||||
|
||||
Timestamper func(*types.TipSet, uint64) uint64
|
||||
|
||||
GetMessages func(*ChainGen) ([]*types.SignedMessage, error)
|
||||
|
||||
w *wallet.Wallet
|
||||
|
||||
eppProvs map[address.Address]ElectionPoStProver
|
||||
@ -210,10 +213,11 @@ func NewGenerator() (*ChainGen, error) {
|
||||
genesis: genb.Genesis,
|
||||
w: w,
|
||||
|
||||
Miners: minercfg.MinerAddrs,
|
||||
eppProvs: mgen,
|
||||
banker: banker,
|
||||
receivers: receievers,
|
||||
GetMessages: getRandomMessages,
|
||||
Miners: minercfg.MinerAddrs,
|
||||
eppProvs: mgen,
|
||||
banker: banker,
|
||||
receivers: receievers,
|
||||
|
||||
CurTipset: gents,
|
||||
|
||||
@ -224,6 +228,14 @@ func NewGenerator() (*ChainGen, error) {
|
||||
return gen, nil
|
||||
}
|
||||
|
||||
func (cg *ChainGen) SetStateManager(sm *stmgr.StateManager) {
|
||||
cg.sm = sm
|
||||
}
|
||||
|
||||
func (cg *ChainGen) ChainStore() *store.ChainStore {
|
||||
return cg.cs
|
||||
}
|
||||
|
||||
func (cg *ChainGen) Genesis() *types.BlockHeader {
|
||||
return cg.genesis
|
||||
}
|
||||
@ -295,7 +307,7 @@ func (cg *ChainGen) NextTipSet() (*MinedTipSet, error) {
|
||||
func (cg *ChainGen) NextTipSetFromMiners(base *types.TipSet, miners []address.Address) (*MinedTipSet, error) {
|
||||
var blks []*types.FullBlock
|
||||
|
||||
msgs, err := cg.getRandomMessages()
|
||||
msgs, err := cg.GetMessages(cg)
|
||||
if err != nil {
|
||||
return nil, xerrors.Errorf("get random messages: %w", err)
|
||||
}
|
||||
@ -359,7 +371,15 @@ func (cg *ChainGen) ResyncBankerNonce(ts *types.TipSet) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cg *ChainGen) getRandomMessages() ([]*types.SignedMessage, error) {
|
||||
func (cg *ChainGen) Banker() address.Address {
|
||||
return cg.banker
|
||||
}
|
||||
|
||||
func (cg *ChainGen) Wallet() *wallet.Wallet {
|
||||
return cg.w
|
||||
}
|
||||
|
||||
func getRandomMessages(cg *ChainGen) ([]*types.SignedMessage, error) {
|
||||
msgs := make([]*types.SignedMessage, cg.msgsPerBlock)
|
||||
for m := range msgs {
|
||||
msg := types.Message{
|
||||
|
@ -15,33 +15,50 @@ import (
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
var ForksAtHeight = map[uint64]func(context.Context, *StateManager, cid.Cid) (cid.Cid, error){
|
||||
build.ForkBlizzardHeight: func(ctx context.Context, sm *StateManager, pstate cid.Cid) (cid.Cid, error) {
|
||||
log.Warnw("Executing blizzard fork logic")
|
||||
nstate, err := fixBlizzardAMTBug(ctx, sm, pstate)
|
||||
if err != nil {
|
||||
return cid.Undef, xerrors.Errorf("blizzard bug fix failed: %w", err)
|
||||
}
|
||||
return nstate, nil
|
||||
},
|
||||
build.ForkFrigidHeight: func(ctx context.Context, sm *StateManager, pstate cid.Cid) (cid.Cid, error) {
|
||||
log.Warnw("Executing frigid fork logic")
|
||||
nstate, err := fixBlizzardAMTBug(ctx, sm, pstate)
|
||||
if err != nil {
|
||||
return cid.Undef, xerrors.Errorf("frigid bug fix failed: %w", err)
|
||||
}
|
||||
return nstate, nil
|
||||
},
|
||||
build.ForkBootyBayHeight: func(ctx context.Context, sm *StateManager, pstate cid.Cid) (cid.Cid, error) {
|
||||
log.Warnw("Executing booty bay fork logic")
|
||||
nstate, err := fixBlizzardAMTBug(ctx, sm, pstate)
|
||||
if err != nil {
|
||||
return cid.Undef, xerrors.Errorf("booty bay bug fix failed: %w", err)
|
||||
}
|
||||
return nstate, nil
|
||||
},
|
||||
build.ForkMissingSnowballs: func(ctx context.Context, sm *StateManager, pstate cid.Cid) (cid.Cid, error) {
|
||||
log.Warnw("Adding more snow to the world")
|
||||
nstate, err := fixTooFewSnowballs(ctx, sm, pstate)
|
||||
if err != nil {
|
||||
return cid.Undef, xerrors.Errorf("missing snowballs bug fix failed: %w", err)
|
||||
}
|
||||
return nstate, nil
|
||||
},
|
||||
}
|
||||
|
||||
func (sm *StateManager) handleStateForks(ctx context.Context, pstate cid.Cid, height, parentH uint64) (_ cid.Cid, err error) {
|
||||
for i := parentH; i < height; i++ {
|
||||
switch i {
|
||||
case build.ForkBlizzardHeight:
|
||||
log.Warnw("Executing blizzard fork logic", "height", i)
|
||||
pstate, err = fixBlizzardAMTBug(ctx, sm, pstate)
|
||||
f, ok := ForksAtHeight[i]
|
||||
if ok {
|
||||
nstate, err := f(ctx, sm, pstate)
|
||||
if err != nil {
|
||||
return cid.Undef, xerrors.Errorf("blizzard bug fix failed: %w", err)
|
||||
}
|
||||
case build.ForkFrigidHeight:
|
||||
log.Warnw("Executing frigid fork logic", "height", i)
|
||||
pstate, err = fixBlizzardAMTBug(ctx, sm, pstate)
|
||||
if err != nil {
|
||||
return cid.Undef, xerrors.Errorf("frigid bug fix failed: %w", err)
|
||||
}
|
||||
case build.ForkBootyBayHeight:
|
||||
log.Warnw("Executing booty bay fork logic", "height", i)
|
||||
pstate, err = fixBlizzardAMTBug(ctx, sm, pstate)
|
||||
if err != nil {
|
||||
return cid.Undef, xerrors.Errorf("booty bay bug fix failed: %w", err)
|
||||
}
|
||||
case build.ForkMissingSnowballs:
|
||||
log.Warnw("Adding more snow to the world", "height", i)
|
||||
pstate, err = fixTooFewSnowballs(ctx, sm, pstate)
|
||||
if err != nil {
|
||||
return cid.Undef, xerrors.Errorf("missing snowballs bug fix failed: %w", err)
|
||||
return cid.Undef, err
|
||||
}
|
||||
pstate = nstate
|
||||
}
|
||||
}
|
||||
|
||||
|
231
chain/stmgr/forks_test.go
Normal file
231
chain/stmgr/forks_test.go
Normal file
@ -0,0 +1,231 @@
|
||||
package stmgr_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
"github.com/filecoin-project/lotus/chain/actors/aerrors"
|
||||
"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/stmgr"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/vm"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
hamt "github.com/ipfs/go-hamt-ipld"
|
||||
blockstore "github.com/ipfs/go-ipfs-blockstore"
|
||||
logging "github.com/ipfs/go-log"
|
||||
mh "github.com/multiformats/go-multihash"
|
||||
cbg "github.com/whyrusleeping/cbor-gen"
|
||||
)
|
||||
|
||||
func init() {
|
||||
build.SectorSizes = []uint64{1024}
|
||||
build.MinimumMinerPower = 1024
|
||||
}
|
||||
|
||||
const testForkHeight = 40
|
||||
|
||||
type testActor struct {
|
||||
}
|
||||
|
||||
type testActorState struct {
|
||||
HasUpgraded uint64
|
||||
}
|
||||
|
||||
func (tas *testActorState) MarshalCBOR(w io.Writer) error {
|
||||
return cbg.CborWriteHeader(w, cbg.MajUnsignedInt, tas.HasUpgraded)
|
||||
}
|
||||
|
||||
func (tas *testActorState) UnmarshalCBOR(r io.Reader) error {
|
||||
t, v, err := cbg.CborReadHeader(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if t != cbg.MajUnsignedInt {
|
||||
return fmt.Errorf("wrong type in test actor state")
|
||||
}
|
||||
tas.HasUpgraded = v
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ta *testActor) Exports() []interface{} {
|
||||
return []interface{}{
|
||||
1: ta.Constructor,
|
||||
2: ta.TestMethod,
|
||||
}
|
||||
}
|
||||
|
||||
func (ta *testActor) Constructor(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, aerrors.ActorError) {
|
||||
c, err := vmctx.Storage().Put(&testActorState{11})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fmt.Println("NEW ACTOR ADDRESS IS: ", vmctx.Message().To.String())
|
||||
|
||||
return nil, vmctx.Storage().Commit(actors.EmptyCBOR, c)
|
||||
}
|
||||
|
||||
func (ta *testActor) TestMethod(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, aerrors.ActorError) {
|
||||
var st testActorState
|
||||
if err := vmctx.Storage().Get(vmctx.Storage().GetHead(), &st); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if vmctx.BlockHeight() > testForkHeight {
|
||||
if st.HasUpgraded != 55 {
|
||||
return nil, aerrors.Fatal("fork updating applied in wrong order")
|
||||
}
|
||||
} else {
|
||||
if st.HasUpgraded != 11 {
|
||||
return nil, aerrors.Fatal("fork updating happened too early")
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func TestForkHeightTriggers(t *testing.T) {
|
||||
logging.SetAllLoggers(logging.LevelInfo)
|
||||
|
||||
ctx := context.TODO()
|
||||
|
||||
cg, err := gen.NewGenerator()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
sm := NewStateManager(cg.ChainStore())
|
||||
|
||||
inv := vm.NewInvoker()
|
||||
|
||||
pref := cid.NewPrefixV1(cid.Raw, mh.IDENTITY)
|
||||
actcid, err := pref.Sum([]byte("testactor"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
actors.BuiltInActors[actcid] = true
|
||||
|
||||
// predicting the address here... may break if other assumptions change
|
||||
taddr, err := address.NewIDAddress(1000)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
stmgr.ForksAtHeight[testForkHeight] = func(ctx context.Context, sm *StateManager, pstate cid.Cid) (cid.Cid, error) {
|
||||
cst := hamt.CSTFromBstore(sm.ChainStore().Blockstore())
|
||||
st, err := state.LoadStateTree(cst, pstate)
|
||||
if err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
act, err := st.GetActor(taddr)
|
||||
if err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
var tas testActorState
|
||||
if err := cst.Get(ctx, act.Head, &tas); err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
tas.HasUpgraded = 55
|
||||
|
||||
ns, err := cst.Put(ctx, &tas)
|
||||
if err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
act.Head = ns
|
||||
|
||||
if err := st.SetActor(taddr, act); err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
return st.Flush(ctx)
|
||||
}
|
||||
|
||||
inv.Register(actcid, &testActor{}, &testActorState{})
|
||||
sm.SetVMConstructor(func(c cid.Cid, h uint64, r vm.Rand, a address.Address, b blockstore.Blockstore, s *types.VMSyscalls) (*vm.VM, error) {
|
||||
nvm, err := vm.NewVM(c, h, r, a, b, s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
nvm.SetInvoker(inv)
|
||||
return nvm, nil
|
||||
})
|
||||
|
||||
cg.SetStateManager(sm)
|
||||
|
||||
var msgs []*types.SignedMessage
|
||||
|
||||
enc, err := actors.SerializeParams(&actors.ExecParams{Code: actcid})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
m := &types.Message{
|
||||
From: cg.Banker(),
|
||||
To: actors.InitAddress,
|
||||
Method: actors.IAMethods.Exec,
|
||||
Params: enc,
|
||||
GasLimit: types.NewInt(10000),
|
||||
GasPrice: types.NewInt(0),
|
||||
}
|
||||
sig, err := cg.Wallet().Sign(ctx, cg.Banker(), m.Cid().Bytes())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
msgs = append(msgs, &types.SignedMessage{
|
||||
Signature: *sig,
|
||||
Message: *m,
|
||||
})
|
||||
|
||||
nonce := uint64(1)
|
||||
cg.GetMessages = func(cg *gen.ChainGen) ([]*types.SignedMessage, error) {
|
||||
if len(msgs) > 0 {
|
||||
fmt.Println("added construct method")
|
||||
m := msgs
|
||||
msgs = nil
|
||||
return m, nil
|
||||
}
|
||||
|
||||
m := &types.Message{
|
||||
From: cg.Banker(),
|
||||
To: taddr,
|
||||
Method: 2,
|
||||
Params: nil,
|
||||
Nonce: nonce,
|
||||
GasLimit: types.NewInt(10000),
|
||||
GasPrice: types.NewInt(0),
|
||||
}
|
||||
nonce++
|
||||
|
||||
sig, err := cg.Wallet().Sign(ctx, cg.Banker(), m.Cid().Bytes())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return []*types.SignedMessage{
|
||||
&types.SignedMessage{
|
||||
Signature: *sig,
|
||||
Message: *m,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
for i := 0; i < 50; i++ {
|
||||
_, err = cg.NextTipSet()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
@ -18,6 +18,7 @@ import (
|
||||
bls "github.com/filecoin-project/filecoin-ffi"
|
||||
"github.com/ipfs/go-cid"
|
||||
hamt "github.com/ipfs/go-hamt-ipld"
|
||||
blockstore "github.com/ipfs/go-ipfs-blockstore"
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
@ -30,10 +31,12 @@ type StateManager struct {
|
||||
stCache map[string][]cid.Cid
|
||||
compWait map[string]chan struct{}
|
||||
stlk sync.Mutex
|
||||
newVM func(cid.Cid, uint64, vm.Rand, address.Address, blockstore.Blockstore, *types.VMSyscalls) (*vm.VM, error)
|
||||
}
|
||||
|
||||
func NewStateManager(cs *store.ChainStore) *StateManager {
|
||||
return &StateManager{
|
||||
newVM: vm.NewVM,
|
||||
cs: cs,
|
||||
stCache: make(map[string][]cid.Cid),
|
||||
compWait: make(map[string]chan struct{}),
|
||||
@ -139,7 +142,7 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.Bl
|
||||
|
||||
r := store.NewChainRand(sm.cs, cids, blks[0].Height)
|
||||
|
||||
vmi, err := vm.NewVM(pstate, blks[0].Height, r, address.Undef, sm.cs.Blockstore(), sm.cs.VMSys())
|
||||
vmi, err := sm.newVM(pstate, blks[0].Height, r, address.Undef, sm.cs.Blockstore(), sm.cs.VMSys())
|
||||
if err != nil {
|
||||
return cid.Undef, cid.Undef, xerrors.Errorf("instantiating VM failed: %w", err)
|
||||
}
|
||||
@ -636,3 +639,7 @@ func (sm *StateManager) ValidateChain(ctx context.Context, ts *types.TipSet) err
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sm *StateManager) SetVMConstructor(nvm func(cid.Cid, uint64, vm.Rand, address.Address, blockstore.Blockstore, *types.VMSyscalls) (*vm.VM, error)) {
|
||||
sm.newVM = nvm
|
||||
}
|
||||
|
@ -23,21 +23,21 @@ type invoker struct {
|
||||
type invokeFunc func(act *types.Actor, vmctx types.VMContext, params []byte) ([]byte, aerrors.ActorError)
|
||||
type nativeCode []invokeFunc
|
||||
|
||||
func newInvoker() *invoker {
|
||||
func NewInvoker() *invoker {
|
||||
inv := &invoker{
|
||||
builtInCode: make(map[cid.Cid]nativeCode),
|
||||
builtInState: make(map[cid.Cid]reflect.Type),
|
||||
}
|
||||
|
||||
// add builtInCode using: register(cid, singleton)
|
||||
inv.register(actors.InitCodeCid, actors.InitActor{}, actors.InitActorState{})
|
||||
inv.register(actors.CronCodeCid, actors.CronActor{}, actors.CronActorState{})
|
||||
inv.register(actors.StoragePowerCodeCid, actors.StoragePowerActor{}, actors.StoragePowerState{})
|
||||
inv.register(actors.StorageMarketCodeCid, actors.StorageMarketActor{}, actors.StorageMarketState{})
|
||||
inv.register(actors.StorageMinerCodeCid, actors.StorageMinerActor{}, actors.StorageMinerActorState{})
|
||||
inv.register(actors.StorageMiner2CodeCid, actors.StorageMinerActor2{}, actors.StorageMinerActorState{})
|
||||
inv.register(actors.MultisigCodeCid, actors.MultiSigActor{}, actors.MultiSigActorState{})
|
||||
inv.register(actors.PaymentChannelCodeCid, actors.PaymentChannelActor{}, actors.PaymentChannelActorState{})
|
||||
inv.Register(actors.InitCodeCid, actors.InitActor{}, actors.InitActorState{})
|
||||
inv.Register(actors.CronCodeCid, actors.CronActor{}, actors.CronActorState{})
|
||||
inv.Register(actors.StoragePowerCodeCid, actors.StoragePowerActor{}, actors.StoragePowerState{})
|
||||
inv.Register(actors.StorageMarketCodeCid, actors.StorageMarketActor{}, actors.StorageMarketState{})
|
||||
inv.Register(actors.StorageMinerCodeCid, actors.StorageMinerActor{}, actors.StorageMinerActorState{})
|
||||
inv.Register(actors.StorageMiner2CodeCid, actors.StorageMinerActor2{}, actors.StorageMinerActorState{})
|
||||
inv.Register(actors.MultisigCodeCid, actors.MultiSigActor{}, actors.MultiSigActorState{})
|
||||
inv.Register(actors.PaymentChannelCodeCid, actors.PaymentChannelActor{}, actors.PaymentChannelActorState{})
|
||||
|
||||
return inv
|
||||
}
|
||||
@ -60,7 +60,7 @@ func (inv *invoker) Invoke(act *types.Actor, vmctx types.VMContext, method uint6
|
||||
|
||||
}
|
||||
|
||||
func (inv *invoker) register(c cid.Cid, instance Invokee, state interface{}) {
|
||||
func (inv *invoker) Register(c cid.Cid, instance Invokee, state interface{}) {
|
||||
code, err := inv.transform(instance)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@ -165,7 +165,7 @@ func DumpActorState(code cid.Cid, b []byte) (interface{}, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
i := newInvoker() // TODO: register builtins in init block
|
||||
i := NewInvoker() // TODO: register builtins in init block
|
||||
|
||||
typ, ok := i.builtInState[code]
|
||||
if !ok {
|
||||
|
@ -327,7 +327,7 @@ func NewVM(base cid.Cid, height uint64, r Rand, maddr address.Address, cbs block
|
||||
buf: buf,
|
||||
blockHeight: height,
|
||||
blockMiner: maddr,
|
||||
inv: newInvoker(),
|
||||
inv: NewInvoker(),
|
||||
rand: r, // TODO: Probably should be a syscall
|
||||
Syscalls: syscalls,
|
||||
}, nil
|
||||
@ -671,6 +671,10 @@ func Transfer(from, to *types.Actor, amt types.BigInt) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VM) SetInvoker(i *invoker) {
|
||||
vm.inv = i
|
||||
}
|
||||
|
||||
func deductFunds(act *types.Actor, amt types.BigInt) error {
|
||||
if act.Balance.LessThan(amt) {
|
||||
return fmt.Errorf("not enough funds")
|
||||
|
@ -470,7 +470,7 @@ var slashConsensusFault = &cli.Command{
|
||||
return xerrors.Errorf("getting block 1: %w", err)
|
||||
}
|
||||
|
||||
c2, err := cid.Parse(cctx.Args().Get(0))
|
||||
c2, err := cid.Parse(cctx.Args().Get(1))
|
||||
if err != nil {
|
||||
return xerrors.Errorf("parsing cid 2: %w", err)
|
||||
}
|
||||
|
2
go.sum
2
go.sum
@ -117,8 +117,6 @@ github.com/filecoin-project/go-paramfetch v0.0.0-20200102181131-b20d579f2878/go.
|
||||
github.com/filecoin-project/go-paramfetch v0.0.1 h1:gV7bs5YaqlgpGFMiLxInGK2L1FyCXUE0rimz4L7ghoE=
|
||||
github.com/filecoin-project/go-paramfetch v0.0.1/go.mod h1:fZzmf4tftbwf9S37XRifoJlz7nCjRdIrMGLR07dKLCc=
|
||||
github.com/filecoin-project/go-sectorbuilder v0.0.1/go.mod h1:3OZ4E3B2OuwhJjtxR4r7hPU9bCfB+A+hm4alLEsaeDc=
|
||||
github.com/filecoin-project/go-sectorbuilder v0.0.2-0.20200131010043-6b57024f839c h1:qv1tEab/IklFknEM8VK2WgxxM7aZ5/uwm5xFgvHTp4A=
|
||||
github.com/filecoin-project/go-sectorbuilder v0.0.2-0.20200131010043-6b57024f839c/go.mod h1:jNGVCDihkMFnraYVLH1xl4ceZQVxx/u4dOORrTKeRi0=
|
||||
github.com/filecoin-project/go-sectorbuilder v0.0.2-0.20200203173614-42d67726bb62 h1:/+xdjMkIdiRs6vA2lJU56iqtEcl9BQgYXi8b2KuuYCg=
|
||||
github.com/filecoin-project/go-sectorbuilder v0.0.2-0.20200203173614-42d67726bb62/go.mod h1:jNGVCDihkMFnraYVLH1xl4ceZQVxx/u4dOORrTKeRi0=
|
||||
github.com/filecoin-project/go-statestore v0.1.0 h1:t56reH59843TwXHkMcwyuayStBIiWBRilQjQ+5IiwdQ=
|
||||
|
@ -170,6 +170,10 @@ func (a *ChainAPI) ChainReadObj(ctx context.Context, obj cid.Cid) ([]byte, error
|
||||
return blk.RawData(), nil
|
||||
}
|
||||
|
||||
func (a *ChainAPI) ChainHasObj(ctx context.Context, obj cid.Cid) (bool, error) {
|
||||
return a.Chain.Blockstore().Has(obj)
|
||||
}
|
||||
|
||||
func (a *ChainAPI) ChainSetHead(ctx context.Context, ts *types.TipSet) error {
|
||||
return a.Chain.SetHead(ts)
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package full
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"github.com/filecoin-project/go-amt-ipld"
|
||||
@ -408,3 +409,32 @@ func (a *StateAPI) StateListMessages(ctx context.Context, match *types.Message,
|
||||
func (a *StateAPI) StateCompute(ctx context.Context, height uint64, msgs []*types.Message, ts *types.TipSet) (cid.Cid, error) {
|
||||
return stmgr.ComputeState(ctx, a.StateManager, height, msgs, ts)
|
||||
}
|
||||
|
||||
func (a *StateAPI) MsigGetAvailableBalance(ctx context.Context, addr address.Address, ts *types.TipSet) (types.BigInt, error) {
|
||||
if ts == nil {
|
||||
ts = a.Chain.GetHeaviestTipSet()
|
||||
}
|
||||
|
||||
var st actors.MultiSigActorState
|
||||
act, err := a.StateManager.LoadActorState(ctx, addr, &st, ts)
|
||||
if err != nil {
|
||||
return types.EmptyInt, xerrors.Errorf("failed to load multisig actor state: %w", err)
|
||||
}
|
||||
|
||||
if act.Code != actors.MultisigCodeCid {
|
||||
return types.EmptyInt, fmt.Errorf("given actor was not a multisig")
|
||||
}
|
||||
|
||||
if st.UnlockDuration == 0 {
|
||||
return act.Balance, nil
|
||||
}
|
||||
|
||||
offset := ts.Height() - st.StartingBlock
|
||||
if offset > st.UnlockDuration {
|
||||
return act.Balance, nil
|
||||
}
|
||||
|
||||
minBalance := types.BigDiv(st.InitialBalance, types.NewInt(st.UnlockDuration))
|
||||
minBalance = types.BigMul(minBalance, types.NewInt(offset))
|
||||
return types.BigSub(act.Balance, minBalance), nil
|
||||
}
|
||||
|
@ -107,15 +107,23 @@ func StorageMiner(mctx helpers.MetricsCtx, lc fx.Lifecycle, api api.FullNode, h
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sm, err := storage.NewMiner(api, maddr, h, ds, sb, tktFn)
|
||||
ctx := helpers.LifecycleCtx(mctx, lc)
|
||||
|
||||
worker, err := api.StateMinerWorker(ctx, maddr, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx := helpers.LifecycleCtx(mctx, lc)
|
||||
fps := storage.NewFPoStScheduler(api, sb, maddr, worker)
|
||||
|
||||
sm, err := storage.NewMiner(api, maddr, worker, h, ds, sb, tktFn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
lc.Append(fx.Hook{
|
||||
OnStart: func(context.Context) error {
|
||||
go fps.Run(ctx)
|
||||
return sm.Run(ctx)
|
||||
},
|
||||
OnStop: sm.Stop,
|
||||
|
@ -14,7 +14,7 @@ import (
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
|
||||
func (s *fpostScheduler) failPost(eps uint64) {
|
||||
func (s *FPoStScheduler) failPost(eps uint64) {
|
||||
s.failLk.Lock()
|
||||
if eps > s.failed {
|
||||
s.failed = eps
|
||||
@ -22,7 +22,7 @@ func (s *fpostScheduler) failPost(eps uint64) {
|
||||
s.failLk.Unlock()
|
||||
}
|
||||
|
||||
func (s *fpostScheduler) doPost(ctx context.Context, eps uint64, ts *types.TipSet) {
|
||||
func (s *FPoStScheduler) doPost(ctx context.Context, eps uint64, ts *types.TipSet) {
|
||||
ctx, abort := context.WithCancel(ctx)
|
||||
|
||||
s.abort = abort
|
||||
@ -31,7 +31,7 @@ func (s *fpostScheduler) doPost(ctx context.Context, eps uint64, ts *types.TipSe
|
||||
go func() {
|
||||
defer abort()
|
||||
|
||||
ctx, span := trace.StartSpan(ctx, "fpostScheduler.doPost")
|
||||
ctx, span := trace.StartSpan(ctx, "FPoStScheduler.doPost")
|
||||
defer span.End()
|
||||
|
||||
proof, err := s.runPost(ctx, eps, ts)
|
||||
@ -50,7 +50,7 @@ func (s *fpostScheduler) doPost(ctx context.Context, eps uint64, ts *types.TipSe
|
||||
}()
|
||||
}
|
||||
|
||||
func (s *fpostScheduler) declareFaults(ctx context.Context, fc uint64, params *actors.DeclareFaultsParams) error {
|
||||
func (s *FPoStScheduler) declareFaults(ctx context.Context, fc uint64, params *actors.DeclareFaultsParams) error {
|
||||
log.Warnf("DECLARING %d FAULTS", fc)
|
||||
|
||||
enc, aerr := actors.SerializeParams(params)
|
||||
@ -86,7 +86,7 @@ func (s *fpostScheduler) declareFaults(ctx context.Context, fc uint64, params *a
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *fpostScheduler) checkFaults(ctx context.Context, ssi sectorbuilder.SortedPublicSectorInfo) ([]uint64, error) {
|
||||
func (s *FPoStScheduler) checkFaults(ctx context.Context, ssi sectorbuilder.SortedPublicSectorInfo) ([]uint64, error) {
|
||||
faults := s.sb.Scrub(ssi)
|
||||
|
||||
declaredFaults := map[uint64]struct{}{}
|
||||
@ -134,7 +134,7 @@ func (s *fpostScheduler) checkFaults(ctx context.Context, ssi sectorbuilder.Sort
|
||||
return faultIDs, nil
|
||||
}
|
||||
|
||||
func (s *fpostScheduler) runPost(ctx context.Context, eps uint64, ts *types.TipSet) (*actors.SubmitFallbackPoStParams, error) {
|
||||
func (s *FPoStScheduler) runPost(ctx context.Context, eps uint64, ts *types.TipSet) (*actors.SubmitFallbackPoStParams, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "storage.runPost")
|
||||
defer span.End()
|
||||
|
||||
@ -194,7 +194,7 @@ func (s *fpostScheduler) runPost(ctx context.Context, eps uint64, ts *types.TipS
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *fpostScheduler) sortedSectorInfo(ctx context.Context, ts *types.TipSet) (sectorbuilder.SortedPublicSectorInfo, error) {
|
||||
func (s *FPoStScheduler) sortedSectorInfo(ctx context.Context, ts *types.TipSet) (sectorbuilder.SortedPublicSectorInfo, error) {
|
||||
sset, err := s.api.StateMinerProvingSet(ctx, s.actor, ts)
|
||||
if err != nil {
|
||||
return sectorbuilder.SortedPublicSectorInfo{}, xerrors.Errorf("failed to get proving set for miner (tsH: %d): %w", ts.Height(), err)
|
||||
@ -217,7 +217,7 @@ func (s *fpostScheduler) sortedSectorInfo(ctx context.Context, ts *types.TipSet)
|
||||
return sectorbuilder.NewSortedPublicSectorInfo(sbsi), nil
|
||||
}
|
||||
|
||||
func (s *fpostScheduler) submitPost(ctx context.Context, proof *actors.SubmitFallbackPoStParams) error {
|
||||
func (s *FPoStScheduler) submitPost(ctx context.Context, proof *actors.SubmitFallbackPoStParams) error {
|
||||
ctx, span := trace.StartSpan(ctx, "storage.commitPost")
|
||||
defer span.End()
|
||||
|
||||
|
@ -19,7 +19,7 @@ const Inactive = 0
|
||||
|
||||
const StartConfidence = 4 // TODO: config
|
||||
|
||||
type fpostScheduler struct {
|
||||
type FPoStScheduler struct {
|
||||
api storageMinerApi
|
||||
sb sectorbuilder.Interface
|
||||
|
||||
@ -36,7 +36,11 @@ type fpostScheduler struct {
|
||||
failLk sync.Mutex
|
||||
}
|
||||
|
||||
func (s *fpostScheduler) run(ctx context.Context) {
|
||||
func NewFPoStScheduler(api storageMinerApi, sb sectorbuilder.Interface, actor address.Address, worker address.Address) *FPoStScheduler {
|
||||
return &FPoStScheduler{api: api, sb: sb, actor: actor, worker: worker}
|
||||
}
|
||||
|
||||
func (s *FPoStScheduler) Run(ctx context.Context) {
|
||||
notifs, err := s.api.ChainNotify(ctx)
|
||||
if err != nil {
|
||||
return
|
||||
@ -61,11 +65,11 @@ func (s *fpostScheduler) run(ctx context.Context) {
|
||||
select {
|
||||
case changes, ok := <-notifs:
|
||||
if !ok {
|
||||
log.Warn("fpostScheduler notifs channel closed")
|
||||
log.Warn("FPoStScheduler notifs channel closed")
|
||||
return
|
||||
}
|
||||
|
||||
ctx, span := trace.StartSpan(ctx, "fpostScheduler.headChange")
|
||||
ctx, span := trace.StartSpan(ctx, "FPoStScheduler.headChange")
|
||||
|
||||
var lowest, highest *types.TipSet = s.cur, nil
|
||||
|
||||
@ -95,7 +99,7 @@ func (s *fpostScheduler) run(ctx context.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *fpostScheduler) revert(ctx context.Context, newLowest *types.TipSet) error {
|
||||
func (s *FPoStScheduler) revert(ctx context.Context, newLowest *types.TipSet) error {
|
||||
if s.cur == newLowest {
|
||||
return nil
|
||||
}
|
||||
@ -113,9 +117,9 @@ func (s *fpostScheduler) revert(ctx context.Context, newLowest *types.TipSet) er
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *fpostScheduler) update(ctx context.Context, new *types.TipSet) error {
|
||||
func (s *FPoStScheduler) update(ctx context.Context, new *types.TipSet) error {
|
||||
if new == nil {
|
||||
return xerrors.Errorf("no new tipset in fpostScheduler.update")
|
||||
return xerrors.Errorf("no new tipset in FPoStScheduler.update")
|
||||
}
|
||||
newEPS, start, err := s.shouldFallbackPost(ctx, new)
|
||||
if err != nil {
|
||||
@ -142,7 +146,7 @@ func (s *fpostScheduler) update(ctx context.Context, new *types.TipSet) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *fpostScheduler) abortActivePoSt() {
|
||||
func (s *FPoStScheduler) abortActivePoSt() {
|
||||
if s.activeEPS == Inactive {
|
||||
return // noop
|
||||
}
|
||||
@ -157,7 +161,7 @@ func (s *fpostScheduler) abortActivePoSt() {
|
||||
s.abort = nil
|
||||
}
|
||||
|
||||
func (s *fpostScheduler) shouldFallbackPost(ctx context.Context, ts *types.TipSet) (uint64, bool, error) {
|
||||
func (s *FPoStScheduler) shouldFallbackPost(ctx context.Context, ts *types.TipSet) (uint64, bool, error) {
|
||||
eps, err := s.api.StateMinerElectionPeriodStart(ctx, s.actor, ts)
|
||||
if err != nil {
|
||||
return 0, false, xerrors.Errorf("getting ElectionPeriodStart: %w", err)
|
||||
|
@ -66,7 +66,7 @@ type storageMinerApi interface {
|
||||
WalletHas(context.Context, address.Address) (bool, error)
|
||||
}
|
||||
|
||||
func NewMiner(api storageMinerApi, addr address.Address, h host.Host, ds datastore.Batching, sb sectorbuilder.Interface, tktFn sealing.TicketFn) (*Miner, error) {
|
||||
func NewMiner(api storageMinerApi, maddr, worker address.Address, h host.Host, ds datastore.Batching, sb sectorbuilder.Interface, tktFn sealing.TicketFn) (*Miner, error) {
|
||||
m := &Miner{
|
||||
api: api,
|
||||
h: h,
|
||||
@ -74,7 +74,8 @@ func NewMiner(api storageMinerApi, addr address.Address, h host.Host, ds datasto
|
||||
ds: ds,
|
||||
tktFn: tktFn,
|
||||
|
||||
maddr: addr,
|
||||
maddr: maddr,
|
||||
worker: worker,
|
||||
}
|
||||
|
||||
return m, nil
|
||||
@ -85,16 +86,6 @@ func (m *Miner) Run(ctx context.Context) error {
|
||||
return xerrors.Errorf("miner preflight checks failed: %w", err)
|
||||
}
|
||||
|
||||
fps := &fpostScheduler{
|
||||
api: m.api,
|
||||
sb: m.sb,
|
||||
|
||||
actor: m.maddr,
|
||||
worker: m.worker,
|
||||
}
|
||||
|
||||
go fps.run(ctx)
|
||||
|
||||
evts := events.NewEvents(ctx, m.api)
|
||||
m.sealing = sealing.New(m.api, evts, m.maddr, m.worker, m.ds, m.sb, m.tktFn)
|
||||
|
||||
@ -109,14 +100,7 @@ func (m *Miner) Stop(ctx context.Context) error {
|
||||
}
|
||||
|
||||
func (m *Miner) runPreflightChecks(ctx context.Context) error {
|
||||
worker, err := m.api.StateMinerWorker(ctx, m.maddr, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m.worker = worker
|
||||
|
||||
has, err := m.api.WalletHas(ctx, worker)
|
||||
has, err := m.api.WalletHas(ctx, m.worker)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("failed to check wallet for worker key: %w", err)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user