From f2340579a5d00b43006af1047f358e34d113576f Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Thu, 30 Jan 2020 14:01:15 -0800 Subject: [PATCH 01/10] Fix power calculations Signed-off-by: Jakub Sztandera --- build/forks.go | 2 ++ chain/actors/actor_miner2.go | 18 ++++++++++- chain/actors/actor_storagepower.go | 50 +++++++++++++++++++++++++----- cli/chain.go | 8 +++++ 4 files changed, 69 insertions(+), 9 deletions(-) diff --git a/build/forks.go b/build/forks.go index e57550005..6002f89eb 100644 --- a/build/forks.go +++ b/build/forks.go @@ -5,3 +5,5 @@ const ForkBlizzardHeight = 6288 const ForkFrigidHeight = 7950 const ForkBootyBayHeight = 11000 + +const ForkMissingSnowballs = 32000 diff --git a/chain/actors/actor_miner2.go b/chain/actors/actor_miner2.go index b6408621d..3fe14a6f5 100644 --- a/chain/actors/actor_miner2.go +++ b/chain/actors/actor_miner2.go @@ -33,7 +33,10 @@ func (sma StorageMinerActor2) Exports() []interface{} { //8: sma.DePledge, 9: sma.GetOwner, 10: sma.GetWorkerAddr, - 11: sma.GetPower, // TODO: Remove + 11: withUpdates( + update{0, sma.GetPower}, + update{build.ForkMissingSnowballs, sma.GetPower2}, + ), // TODO: Remove 12: sma.GetPeerID, 13: sma.GetSectorSize, 14: sma.UpdatePeerID, @@ -404,6 +407,19 @@ func (sma StorageMinerActor2) GetPower(act *types.Actor, vmctx types.VMContext, return self.Power.Bytes(), nil } +func (sma StorageMinerActor2) GetPower2(act *types.Actor, vmctx types.VMContext, params *struct{}) ([]byte, ActorError) { + _, self, err := loadState(vmctx) + if err != nil { + return nil, err + } + + if self.SlashedAt != 0 { + return types.NewInt(0).Bytes(), nil + } + + return self.Power.Bytes(), nil +} + func SectorIsUnique2(ctx context.Context, s types.Storage, sroot cid.Cid, sid uint64) (bool, ActorError) { found, _, _, err := GetFromSectorSet2(ctx, s, sroot, sid) if err != nil { diff --git a/chain/actors/actor_storagepower.go b/chain/actors/actor_storagepower.go index 4bd5a0cb7..3b68a6f95 100644 --- a/chain/actors/actor_storagepower.go +++ b/chain/actors/actor_storagepower.go @@ -648,6 +648,8 @@ func checkProofSubmissionsAtH(vmctx types.VMContext, self *StoragePowerState, he return aerrors.HandleExternalError(err, "failed to load proving bucket") } + forRemoval := make([]address.Address, 0) + err = bhamt.ForEach(vmctx.Context(), func(k string, val interface{}) error { _, span := trace.StartSpan(vmctx.Context(), "StoragePowerActor.CheckProofSubmissions.loop") defer span.End() @@ -657,6 +659,18 @@ func checkProofSubmissionsAtH(vmctx types.VMContext, self *StoragePowerState, he return aerrors.Escalate(err, "parsing miner address") } + if vmctx.BlockHeight() >= build.ForkMissingSnowballs { + has, aerr := MinerSetHas(vmctx, self.Miners, maddr) + if aerr != nil { + return aerr + } + + if !has { + forRemoval = append(forRemoval, maddr) + } + + } + span.AddAttributes(trace.StringAttribute("miner", maddr.String())) params, err := SerializeParams(&CheckMinerParams{NetworkPower: self.TotalStorage}) @@ -690,6 +704,24 @@ func checkProofSubmissionsAtH(vmctx types.VMContext, self *StoragePowerState, he return aerrors.HandleExternalError(err, "iterating miners in proving bucket") } + if vmctx.BlockHeight() >= build.ForkMissingSnowballs { + nBucket, err := MinerSetRemove(vmctx.Context(), vmctx, bucket, forRemoval...) + + if err != nil { + return aerrors.Wrap(err, "could not remove miners from set") + } + + eerr := buckets.Set(bucketID, nBucket) + if err != nil { + return aerrors.HandleExternalError(eerr, "could not set the bucket") + } + ncid, eerr := buckets.Flush() + if err != nil { + return aerrors.HandleExternalError(eerr, "could not flush buckets") + } + self.ProvingBuckets = ncid + } + return nil } @@ -764,19 +796,21 @@ func MinerSetAdd(ctx context.Context, vmctx types.VMContext, rcid cid.Cid, maddr return c, nil } -func MinerSetRemove(ctx context.Context, vmctx types.VMContext, rcid cid.Cid, maddr address.Address) (cid.Cid, aerrors.ActorError) { +func MinerSetRemove(ctx context.Context, vmctx types.VMContext, rcid cid.Cid, maddrs ...address.Address) (cid.Cid, aerrors.ActorError) { nd, err := hamt.LoadNode(ctx, vmctx.Ipld(), rcid) if err != nil { return cid.Undef, aerrors.HandleExternalError(err, "failed to load miner set") } - mkey := string(maddr.Bytes()) - switch nd.Delete(ctx, mkey) { - default: - return cid.Undef, aerrors.HandleExternalError(err, "failed to delete miner from set") - case hamt.ErrNotFound: - return cid.Undef, aerrors.New(1, "miner not found in set on delete") - case nil: + for _, maddr := range maddrs { + mkey := string(maddr.Bytes()) + switch nd.Delete(ctx, mkey) { + default: + return cid.Undef, aerrors.HandleExternalError(err, "failed to delete miner from set") + case hamt.ErrNotFound: + return cid.Undef, aerrors.New(1, "miner not found in set on delete") + case nil: + } } if err := nd.Flush(ctx); err != nil { diff --git a/cli/chain.go b/cli/chain.go index aed541f8c..b9f27a685 100644 --- a/cli/chain.go +++ b/cli/chain.go @@ -388,6 +388,14 @@ func printTipSet(format string, ts *types.TipSet) { blks += fmt.Sprintf("%s: %s,", b.Cid(), b.Miner) } blks += " ]" + + sCids := make([]string, 0, len(blks)) + + for _, c := range ts.Cids() { + sCids = append(sCids, c.String()) + } + + format = strings.ReplaceAll(format, "", strings.Join(sCids, ",")) format = strings.ReplaceAll(format, "", blks) format = strings.ReplaceAll(format, "", fmt.Sprint(ts.Blocks()[0].ParentWeight)) From 8ad8fa902def75f6c4acf6555ac9821564efc4b0 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Thu, 30 Jan 2020 16:36:18 -0800 Subject: [PATCH 02/10] extra careful power checks on slashing --- chain/actors/actor_miner2.go | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/chain/actors/actor_miner2.go b/chain/actors/actor_miner2.go index 3fe14a6f5..c957d9b86 100644 --- a/chain/actors/actor_miner2.go +++ b/chain/actors/actor_miner2.go @@ -404,6 +404,7 @@ func (sma StorageMinerActor2) GetPower(act *types.Actor, vmctx types.VMContext, if err != nil { return nil, err } + return self.Power.Bytes(), nil } @@ -631,6 +632,8 @@ func (sma StorageMinerActor2) CheckMiner(act *types.Actor, vmctx types.VMContext // Slash for being late self.SlashedAt = vmctx.BlockHeight() + oldPower := self.Power + self.Power = types.NewInt(0) nstate, err := vmctx.Storage().Put(self) if err != nil { @@ -641,7 +644,7 @@ func (sma StorageMinerActor2) CheckMiner(act *types.Actor, vmctx types.VMContext } var out bytes.Buffer - if err := self.Power.MarshalCBOR(&out); err != nil { + if err := oldPower.MarshalCBOR(&out); err != nil { return nil, aerrors.HandleExternalError(err, "marshaling return value") } return out.Bytes(), nil @@ -726,6 +729,21 @@ func (sma StorageMinerActor2) SlashConsensusFault(act *types.Actor, vmctx types. return nil, aerrors.Wrap(err, "failed to burn funds") } + oldstate, self, err := loadState(vmctx) + if err != nil { + return nil, aerrors.Wrap(err, "failed to load state for slashing") + } + + self.Power = types.NewInt(0) + + ncid, err := vmctx.Storage().Put(self) + if err != nil { + return nil, err + } + if err := vmctx.Storage().Commit(oldstate, ncid); err != nil { + return nil, err + } + // TODO: this still allows the miner to commit sectors and submit posts, // their users could potentially be unaffected, but the miner will never be // able to mine a block again From c6fd45727dda5f598f673677d018cfee8c8db5bf Mon Sep 17 00:00:00 2001 From: Jakub Sztandera Date: Thu, 30 Jan 2020 17:17:34 -0800 Subject: [PATCH 03/10] Add state fork logic Signed-off-by: Jakub Sztandera --- chain/stmgr/forks.go | 58 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/chain/stmgr/forks.go b/chain/stmgr/forks.go index 2db04c695..eb98029c6 100644 --- a/chain/stmgr/forks.go +++ b/chain/stmgr/forks.go @@ -2,6 +2,7 @@ package stmgr import ( "context" + "math/big" amt "github.com/filecoin-project/go-amt-ipld/v2" "github.com/filecoin-project/lotus/build" @@ -35,12 +36,69 @@ func (sm *StateManager) handleStateForks(ctx context.Context, pstate cid.Cid, he 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("booty bay bug fix failed: %w", err) + } } } return pstate, nil } +func fixTooFewSnowballs(ctx context.Context, sm *StateManager, pstate cid.Cid) (cid.Cid, error) { + cst := hamt.CSTFromBstore(sm.cs.Blockstore()) + st, err := state.LoadStateTree(cst, pstate) + if err != nil { + return cid.Undef, err + } + + spa, err := st.GetActor(actors.StoragePowerAddress) + if err != nil { + return cid.Undef, xerrors.Errorf("failed to get storage power actor: %w", err) + } + + var spast actors.StoragePowerState + if err := cst.Get(ctx, spa.Head, &spast); err != nil { + return cid.Undef, err + } + + miners, err := actors.MinerSetList(ctx, cst, spast.Miners) + if err != nil { + return cid.Undef, err + } + + sum := new(big.Int) + for _, m := range miners { + mact, err := st.GetActor(m) + if err != nil { + return cid.Undef, xerrors.Errorf("getting miner actor to fix: %w", err) + } + + var mstate actors.StorageMinerActorState + if err := cst.Get(ctx, mact.Head, &mstate); err != nil { + return cid.Undef, xerrors.Errorf("failed to load miner actor state: %w", err) + } + + if mstate.SlashedAt != 0 { + continue + } + sum = sum.Add(sum, mstate.Power.Int) + } + + spast.TotalStorage.Int = sum + nspahead, err := cst.Put(ctx, spast) + if err != nil { + return cid.Undef, err + } + + spa.Head = nspahead + + return st.Flush(ctx) +} + /* 1) Iterate through each miner in the chain: 1.1) Fixup their sector set and proving set From 0622eb7634f83318f5645fda38fbf195637ce5c2 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Thu, 30 Jan 2020 17:36:33 -0800 Subject: [PATCH 04/10] put miner changes behind a fork switch --- chain/actors/actor_miner2.go | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/chain/actors/actor_miner2.go b/chain/actors/actor_miner2.go index c957d9b86..aef1dad95 100644 --- a/chain/actors/actor_miner2.go +++ b/chain/actors/actor_miner2.go @@ -633,7 +633,10 @@ func (sma StorageMinerActor2) CheckMiner(act *types.Actor, vmctx types.VMContext self.SlashedAt = vmctx.BlockHeight() oldPower := self.Power - self.Power = types.NewInt(0) + + if vmctx.BlockHeight() > build.ForkMissingSnowballs { + self.Power = types.NewInt(0) + } nstate, err := vmctx.Storage().Put(self) if err != nil { @@ -729,19 +732,21 @@ func (sma StorageMinerActor2) SlashConsensusFault(act *types.Actor, vmctx types. return nil, aerrors.Wrap(err, "failed to burn funds") } - oldstate, self, err := loadState(vmctx) - if err != nil { - return nil, aerrors.Wrap(err, "failed to load state for slashing") - } + if vmctx.BlockHeight() > build.ForkMissingSnowballs { + oldstate, self, err := loadState(vmctx) + if err != nil { + return nil, aerrors.Wrap(err, "failed to load state for slashing") + } - self.Power = types.NewInt(0) + self.Power = types.NewInt(0) - ncid, err := vmctx.Storage().Put(self) - if err != nil { - return nil, err - } - if err := vmctx.Storage().Commit(oldstate, ncid); err != nil { - return nil, err + ncid, err := vmctx.Storage().Put(self) + if err != nil { + return nil, err + } + if err := vmctx.Storage().Commit(oldstate, ncid); err != nil { + return nil, err + } } // TODO: this still allows the miner to commit sectors and submit posts, From 7402b14df3cae2377fd3f4328fb05bc56d5d22d4 Mon Sep 17 00:00:00 2001 From: Whyrusleeping Date: Thu, 30 Jan 2020 17:51:19 -0800 Subject: [PATCH 05/10] Update chain/actors/actor_miner2.go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Ɓukasz Magiera --- chain/actors/actor_miner2.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chain/actors/actor_miner2.go b/chain/actors/actor_miner2.go index aef1dad95..c3639eebc 100644 --- a/chain/actors/actor_miner2.go +++ b/chain/actors/actor_miner2.go @@ -36,7 +36,7 @@ func (sma StorageMinerActor2) Exports() []interface{} { 11: withUpdates( update{0, sma.GetPower}, update{build.ForkMissingSnowballs, sma.GetPower2}, - ), // TODO: Remove + ), // FORK 12: sma.GetPeerID, 13: sma.GetSectorSize, 14: sma.UpdatePeerID, From 19a65319ee2bd120e87f1b68120fe10e8a83bcdf Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Thu, 30 Jan 2020 18:13:53 -0800 Subject: [PATCH 06/10] test and fix fork, add bigint parsing to lotus shed --- build/forks.go | 2 +- chain/stmgr/forks.go | 4 ++-- cmd/lotus-shed/bigint.go | 47 ++++++++++++++++++++++++++++++++++++++++ cmd/lotus-shed/main.go | 1 + 4 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 cmd/lotus-shed/bigint.go diff --git a/build/forks.go b/build/forks.go index 6002f89eb..02c0282bb 100644 --- a/build/forks.go +++ b/build/forks.go @@ -6,4 +6,4 @@ const ForkFrigidHeight = 7950 const ForkBootyBayHeight = 11000 -const ForkMissingSnowballs = 32000 +const ForkMissingSnowballs = 33000 diff --git a/chain/stmgr/forks.go b/chain/stmgr/forks.go index eb98029c6..8576b923f 100644 --- a/chain/stmgr/forks.go +++ b/chain/stmgr/forks.go @@ -40,7 +40,7 @@ func (sm *StateManager) handleStateForks(ctx context.Context, pstate cid.Cid, he log.Warnw("Adding more snow to the world", "height", i) pstate, err = fixTooFewSnowballs(ctx, sm, pstate) if err != nil { - return cid.Undef, xerrors.Errorf("booty bay bug fix failed: %w", err) + return cid.Undef, xerrors.Errorf("missing snowballs bug fix failed: %w", err) } } } @@ -89,7 +89,7 @@ func fixTooFewSnowballs(ctx context.Context, sm *StateManager, pstate cid.Cid) ( } spast.TotalStorage.Int = sum - nspahead, err := cst.Put(ctx, spast) + nspahead, err := cst.Put(ctx, &spast) if err != nil { return cid.Undef, err } diff --git a/cmd/lotus-shed/bigint.go b/cmd/lotus-shed/bigint.go new file mode 100644 index 000000000..3db0de68d --- /dev/null +++ b/cmd/lotus-shed/bigint.go @@ -0,0 +1,47 @@ +package main + +import ( + "encoding/base64" + "encoding/hex" + "fmt" + + "github.com/filecoin-project/lotus/chain/types" + "gopkg.in/urfave/cli.v2" +) + +var bigIntParseCmd = &cli.Command{ + Name: "bigint", + Description: "parse encoded big ints", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "enc", + Value: "base64", + Usage: "specify input encoding to parse", + }, + }, + Action: func(cctx *cli.Context) error { + val := cctx.Args().Get(0) + + var dec []byte + switch cctx.String("enc") { + case "base64": + d, err := base64.StdEncoding.DecodeString(val) + if err != nil { + return fmt.Errorf("decoding base64 value: %w", err) + } + dec = d + case "hex": + d, err := hex.DecodeString(val) + if err != nil { + return fmt.Errorf("decoding hex value: %w", err) + } + dec = d + default: + return fmt.Errorf("unrecognized encoding: %s", cctx.String("enc")) + } + + iv := types.BigFromBytes(dec) + fmt.Println(iv.String()) + return nil + }, +} diff --git a/cmd/lotus-shed/main.go b/cmd/lotus-shed/main.go index fe8abb233..749ff2945 100644 --- a/cmd/lotus-shed/main.go +++ b/cmd/lotus-shed/main.go @@ -20,6 +20,7 @@ func main() { keyinfoCmd, peerkeyCmd, noncefix, + bigIntParseCmd, } app := &cli.App{ From cda7f08b767588e2ada0ccb4ff40951f87bb3af8 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Thu, 30 Jan 2020 21:05:41 -0800 Subject: [PATCH 07/10] use less than, not equals --- chain/actors/actor_storagepower.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chain/actors/actor_storagepower.go b/chain/actors/actor_storagepower.go index 3b68a6f95..05d6a2269 100644 --- a/chain/actors/actor_storagepower.go +++ b/chain/actors/actor_storagepower.go @@ -659,7 +659,7 @@ func checkProofSubmissionsAtH(vmctx types.VMContext, self *StoragePowerState, he return aerrors.Escalate(err, "parsing miner address") } - if vmctx.BlockHeight() >= build.ForkMissingSnowballs { + if vmctx.BlockHeight() > build.ForkMissingSnowballs { has, aerr := MinerSetHas(vmctx, self.Miners, maddr) if aerr != nil { return aerr @@ -704,7 +704,7 @@ func checkProofSubmissionsAtH(vmctx types.VMContext, self *StoragePowerState, he return aerrors.HandleExternalError(err, "iterating miners in proving bucket") } - if vmctx.BlockHeight() >= build.ForkMissingSnowballs { + if vmctx.BlockHeight() > build.ForkMissingSnowballs { nBucket, err := MinerSetRemove(vmctx.Context(), vmctx, bucket, forRemoval...) if err != nil { From d70ebd2ba58a813921d664b47ec6c9fbd24dd5a7 Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Thu, 30 Jan 2020 21:10:37 -0800 Subject: [PATCH 08/10] some code review --- chain/actors/actor_storagepower.go | 2 +- chain/stmgr/forks.go | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/chain/actors/actor_storagepower.go b/chain/actors/actor_storagepower.go index 05d6a2269..af56e0deb 100644 --- a/chain/actors/actor_storagepower.go +++ b/chain/actors/actor_storagepower.go @@ -704,7 +704,7 @@ func checkProofSubmissionsAtH(vmctx types.VMContext, self *StoragePowerState, he return aerrors.HandleExternalError(err, "iterating miners in proving bucket") } - if vmctx.BlockHeight() > build.ForkMissingSnowballs { + if vmctx.BlockHeight() > build.ForkMissingSnowballs && len(forRemoval) > 0 { nBucket, err := MinerSetRemove(vmctx.Context(), vmctx, bucket, forRemoval...) if err != nil { diff --git a/chain/stmgr/forks.go b/chain/stmgr/forks.go index 8576b923f..634855aa0 100644 --- a/chain/stmgr/forks.go +++ b/chain/stmgr/forks.go @@ -2,12 +2,12 @@ package stmgr import ( "context" - "math/big" amt "github.com/filecoin-project/go-amt-ipld/v2" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/state" + "github.com/filecoin-project/lotus/chain/types" "github.com/ipfs/go-cid" hamt "github.com/ipfs/go-hamt-ipld" blockstore "github.com/ipfs/go-ipfs-blockstore" @@ -70,7 +70,7 @@ func fixTooFewSnowballs(ctx context.Context, sm *StateManager, pstate cid.Cid) ( return cid.Undef, err } - sum := new(big.Int) + sum := types.NewInt(0) for _, m := range miners { mact, err := st.GetActor(m) if err != nil { @@ -85,10 +85,10 @@ func fixTooFewSnowballs(ctx context.Context, sm *StateManager, pstate cid.Cid) ( if mstate.SlashedAt != 0 { continue } - sum = sum.Add(sum, mstate.Power.Int) + sum = types.BigAdd(sum, mstate.Power) } - spast.TotalStorage.Int = sum + spast.TotalStorage = sum nspahead, err := cst.Put(ctx, &spast) if err != nil { return cid.Undef, err From c071b2dc47efdffadd557aafa9694d83dcbaa66f Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Thu, 30 Jan 2020 21:15:00 -0800 Subject: [PATCH 09/10] move back fork point, set new version --- build/forks.go | 2 +- build/version.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build/forks.go b/build/forks.go index 02c0282bb..e03eb9f08 100644 --- a/build/forks.go +++ b/build/forks.go @@ -6,4 +6,4 @@ const ForkFrigidHeight = 7950 const ForkBootyBayHeight = 11000 -const ForkMissingSnowballs = 33000 +const ForkMissingSnowballs = 34000 diff --git a/build/version.go b/build/version.go index 97372e836..21cb88a82 100644 --- a/build/version.go +++ b/build/version.go @@ -5,7 +5,7 @@ import "fmt" var CurrentCommit string // BuildVersion is the local build version, set by build system -const BuildVersion = "0.2.6" +const BuildVersion = "0.2.7" var UserVersion = BuildVersion + CurrentCommit From d117cb61b6b86e7a7efa8897c8c5c640e6b1f41c Mon Sep 17 00:00:00 2001 From: whyrusleeping Date: Thu, 30 Jan 2020 21:20:57 -0800 Subject: [PATCH 10/10] change withUpdates to match fork height logic --- chain/actors/forks.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chain/actors/forks.go b/chain/actors/forks.go index 46f8cafd8..3cc5d5b74 100644 --- a/chain/actors/forks.go +++ b/chain/actors/forks.go @@ -26,7 +26,7 @@ func withUpdates(updates ...update) interface{} { vmctx := args[1].Interface().(types.VMContext) for _, u := range updates { - if vmctx.BlockHeight() >= u.start { + if vmctx.BlockHeight() > u.start { return reflect.ValueOf(u.method).Call(args) } }