Merge branch 'master' into feat/new-sb-fs

This commit is contained in:
Łukasz Magiera 2020-02-04 04:08:01 +01:00
commit 90ecfbe0e4
20 changed files with 483 additions and 93 deletions

View File

@ -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

View File

@ -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

View 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{}

View File

@ -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)
}

View File

@ -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 {

View File

@ -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,
}
}

View File

@ -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{

View File

@ -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
View 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)
}
}
}

View File

@ -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
}

View File

@ -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 {

View File

@ -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")

View File

@ -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
View File

@ -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=

View File

@ -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)
}

View File

@ -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
}

View File

@ -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,

View File

@ -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()

View File

@ -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)

View File

@ -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)
}