FORK: No power EPS Fix

This commit is contained in:
Łukasz Magiera 2019-12-19 19:46:30 +01:00
parent d2600ec46f
commit 3f54cbabe0
6 changed files with 167 additions and 7 deletions

View File

@ -1,3 +1,4 @@
package build
const ForkCCM = 1750
const ForkNoPowerEPSUpdates = 20000

View File

@ -238,7 +238,7 @@ func (sma StorageMinerActor) PreCommitSector(act *types.Actor, vmctx types.VMCon
}
if vmctx.Message().From != mi.Worker {
return nil, aerrors.New(1, "not authorized to commit sector for miner")
return nil, aerrors.New(1, "not authorized to precommit sector for miner")
}
// make sure the miner isnt trying to submit a pre-existing sector
@ -303,6 +303,10 @@ func (sma StorageMinerActor) ProveCommitSector(act *types.Actor, vmctx types.VMC
return nil, err
}
if vmctx.Message().From != mi.Worker {
return nil, aerrors.New(1, "not authorized to sector proof for miner")
}
us, ok := self.PreCommittedSectors[uintToStringKey(params.SectorID)]
if !ok {
return nil, aerrors.New(1, "no pre-commitment found for sector")
@ -368,7 +372,7 @@ func (sma StorageMinerActor) ProveCommitSector(act *types.Actor, vmctx types.VMC
return nil, aerrors.HandleExternalError(lerr, "could not load proving set node")
}
if pss.Count == 0 {
if pss.Count == 0 && (!self.Active || vmctx.BlockHeight() < build.ForkNoPowerEPSUpdates) { // FORK
self.ProvingSet = self.Sectors
// TODO: probably want to wait until the miner is above a certain
// threshold before starting this
@ -814,6 +818,15 @@ func (sma StorageMinerActor) DeclareFaults(act *types.Actor, vmctx types.VMConte
return nil, aerr
}
mi, aerr := loadMinerInfo(vmctx, self)
if aerr != nil {
return nil, aerr
}
if vmctx.Message().From != mi.Worker {
return nil, aerrors.New(1, "not authorized to declare faults for miner")
}
nfaults, err := types.MergeBitFields(params.Faults, self.FaultSet)
if err != nil {
return nil, aerrors.Absorb(err, 1, "failed to merge bitfields")
@ -824,7 +837,7 @@ func (sma StorageMinerActor) DeclareFaults(act *types.Actor, vmctx types.VMConte
self.LastFaultSubmission = vmctx.BlockHeight()
nstate, aerr := vmctx.Storage().Put(self)
if err != nil { // TODO: FORK: should be aerr
if aerr != nil {
return nil, aerr
}
if err := vmctx.Storage().Commit(oldstate, nstate); err != nil {
@ -965,6 +978,8 @@ func onSuccessfulPoSt(self *StorageMinerActorState, vmctx types.VMContext) aerro
if err != nil {
return aerrors.Wrap(err, "updating storage failed")
}
self.ElectionPeriodStart = vmctx.BlockHeight()
}
ncid, err := RemoveFromSectorSet(vmctx.Context(), vmctx.Storage(), self.Sectors, faults)
@ -974,7 +989,9 @@ func onSuccessfulPoSt(self *StorageMinerActorState, vmctx types.VMContext) aerro
self.Sectors = ncid
self.ProvingSet = ncid
self.ElectionPeriodStart = vmctx.BlockHeight()
if vmctx.BlockHeight() < build.ForkNoPowerEPSUpdates { // FORK
self.ElectionPeriodStart = vmctx.BlockHeight()
}
return nil
}

View File

@ -393,7 +393,7 @@ func addMinerToBucket(vmctx types.VMContext, buckets *amt.Root, nextBucket uint6
return aerrors.HandleExternalError(err, "getting proving bucket")
}
err = bhamt.Set(vmctx.Context(), string(vmctx.Message().From.Bytes()), cborNull)
err = bhamt.Set(vmctx.Context(), string(vmctx.Message().From.Bytes()), CborNull)
if err != nil {
return aerrors.HandleExternalError(err, "setting miner in proving bucket")
}
@ -768,7 +768,7 @@ func MinerSetRemove(ctx context.Context, vmctx types.VMContext, rcid cid.Cid, ma
type cbgNull struct{}
var cborNull = &cbgNull{}
var CborNull = &cbgNull{}
func (cbgNull) MarshalCBOR(w io.Writer) error {
n, err := w.Write(cbg.CborNull)

View File

@ -0,0 +1,122 @@
package stmgr
import (
"context"
"github.com/filecoin-project/go-amt-ipld"
"github.com/ipfs/go-cid"
"github.com/ipfs/go-hamt-ipld"
cbor "github.com/ipfs/go-ipld-cbor"
"github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/address"
"github.com/filecoin-project/lotus/chain/state"
"github.com/filecoin-project/lotus/chain/types"
)
func (sm *StateManager) forkNoPowerEPS(ctx context.Context, pstate cid.Cid) (cid.Cid, error) {
cst := hamt.CSTFromBstore(sm.cs.Blockstore())
st, err := state.LoadStateTree(cst, pstate)
if err != nil {
return cid.Undef, xerrors.Errorf("loading parent state tree: %w", err)
}
if err := st.MutateActor(actors.StoragePowerAddress, func(spa *types.Actor) error {
var head actors.StoragePowerState
if err := cst.Get(ctx, spa.Head, &head); err != nil {
return xerrors.Errorf("reading StoragePower state: %w", err)
}
buckets, err := amt.LoadAMT(amt.WrapBlockstore(sm.cs.Blockstore()), head.ProvingBuckets)
if err != nil {
return xerrors.Errorf("opening proving buckets AMT: %w", err)
}
fixedBuckets := map[uint64]map[address.Address]struct{}{}
if err := buckets.ForEach(func(bucketId uint64, ent *typegen.Deferred) error {
var bcid cid.Cid
if err := cbor.DecodeInto(ent.Raw, &bcid); err != nil {
return xerrors.Errorf("decoding bucket cid: %w", err)
}
bucket, err := hamt.LoadNode(ctx, cst, bcid)
if err != nil {
return xerrors.Errorf("loading bucket hamt: %w", err)
}
return bucket.ForEach(ctx, func(abytes string, _ interface{}) error {
addr, err := address.NewFromBytes([]byte(abytes))
if err != nil {
return xerrors.Errorf("parsing address in proving bucket: %w", err)
}
// now find the correct bucket
miner, err := st.GetActor(addr)
if err != nil {
return xerrors.Errorf("getting miner %s: %w", addr, err)
}
var minerHead actors.StorageMinerActorState
if err := cst.Get(ctx, miner.Head, &minerHead); err != nil {
return xerrors.Errorf("reading miner %s state: %w", addr, err)
}
correctBucket := minerHead.ElectionPeriodStart % build.SlashablePowerDelay
if correctBucket != bucketId {
log.Warnf("miner %s was in wrong proving bucket %d, putting in %d (eps: %d)", addr, bucketId, correctBucket, minerHead.ElectionPeriodStart)
}
if _, ok := fixedBuckets[correctBucket]; !ok {
fixedBuckets[correctBucket] = map[address.Address]struct{}{}
}
fixedBuckets[correctBucket][addr] = struct{}{}
return nil
})
}); err != nil {
return err
}
// /////
// Write fixed buckets
fixed := amt.NewAMT(amt.WrapBlockstore(sm.cs.Blockstore()))
for bucketId, addrss := range fixedBuckets {
bucket := hamt.NewNode(cst)
for addr := range addrss {
if err := bucket.Set(ctx, string(addr.Bytes()), actors.CborNull); err != nil {
return xerrors.Errorf("setting address in bucket: %w", err)
}
}
if err := bucket.Flush(ctx); err != nil {
return xerrors.Errorf("flushing bucket amt: %w", err)
}
bcid, err := cst.Put(context.TODO(), bucket)
if err != nil {
return xerrors.Errorf("put bucket: %w", err)
}
if err := fixed.Set(bucketId, bcid); err != nil {
return xerrors.Errorf("set bucket: %w", err)
}
}
spa.Head, err = fixed.Flush()
if err != nil {
return xerrors.Errorf("flushing bucket amt: %w", err)
}
return nil
}); err != nil {
return cid.Undef, err
}
return st.Flush()
}

17
chain/stmgr/forks.go Normal file
View File

@ -0,0 +1,17 @@
package stmgr
import (
"context"
"github.com/ipfs/go-cid"
"github.com/filecoin-project/lotus/build"
)
func (sm *StateManager) handleStateForks(ctx context.Context, pstate cid.Cid, height uint64) (cid.Cid, error) {
switch height {
case build.ForkNoPowerEPSUpdates: // TODO: +1?
return sm.forkNoPowerEPS(ctx, pstate)
default:
return pstate, nil
}
}

View File

@ -119,7 +119,10 @@ func (sm *StateManager) computeTipSetState(ctx context.Context, blks []*types.Bl
}
}
pstate := blks[0].ParentStateRoot
pstate, err := sm.handleStateForks(ctx, blks[0].ParentStateRoot, blks[0].Height)
if err != nil {
return cid.Undef, cid.Undef, xerrors.Errorf("error handling state forks: %w", err)
}
cids := make([]cid.Cid, len(blks))
for i, v := range blks {