diff --git a/build/forks.go b/build/forks.go index 35990bfbf..976b54d6c 100644 --- a/build/forks.go +++ b/build/forks.go @@ -1,3 +1,4 @@ package build const ForkCCM = 1750 +const ForkNoPowerEPSUpdates = 20000 diff --git a/chain/actors/actor_miner.go b/chain/actors/actor_miner.go index 9b3c871a3..2fb5c668f 100644 --- a/chain/actors/actor_miner.go +++ b/chain/actors/actor_miner.go @@ -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 } diff --git a/chain/actors/actor_storagepower.go b/chain/actors/actor_storagepower.go index 8a6648ca6..2f164dbcb 100644 --- a/chain/actors/actor_storagepower.go +++ b/chain/actors/actor_storagepower.go @@ -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) diff --git a/chain/stmgr/fork_no_p_eps.go b/chain/stmgr/fork_no_p_eps.go new file mode 100644 index 000000000..0d01a01ba --- /dev/null +++ b/chain/stmgr/fork_no_p_eps.go @@ -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() +} diff --git a/chain/stmgr/forks.go b/chain/stmgr/forks.go new file mode 100644 index 000000000..90fcf974b --- /dev/null +++ b/chain/stmgr/forks.go @@ -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 + } +} diff --git a/chain/stmgr/stmgr.go b/chain/stmgr/stmgr.go index bd3e16032..782e7decf 100644 --- a/chain/stmgr/stmgr.go +++ b/chain/stmgr/stmgr.go @@ -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 {