From 9d2c430138a4fd7d3c2e4b1c4d8abaf8eaea39bd Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Mon, 18 Jan 2021 16:06:16 -0800 Subject: [PATCH] remove abstract map constructor/loader Different maps have different parameters now so we just construct/load them manually where needed. --- chain/actors/adt/adt.go | 56 ----------------- chain/actors/builtin/verifreg/util.go | 17 ++--- chain/actors/builtin/verifreg/v0.go | 17 +++-- chain/actors/builtin/verifreg/v2.go | 17 +++-- chain/actors/builtin/verifreg/v3.go | 18 ++++-- chain/state/statetree.go | 90 +++++++++++++++------------ chain/stmgr/stmgr.go | 9 ++- chain/types/state.go | 4 +- 8 files changed, 106 insertions(+), 122 deletions(-) diff --git a/chain/actors/adt/adt.go b/chain/actors/adt/adt.go index 7a3007fa8..084471bb8 100644 --- a/chain/actors/adt/adt.go +++ b/chain/actors/adt/adt.go @@ -2,17 +2,9 @@ package adt import ( "github.com/ipfs/go-cid" - "golang.org/x/xerrors" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/go-state-types/cbor" - "github.com/filecoin-project/go-state-types/network" - - "github.com/filecoin-project/lotus/chain/actors" - - adt0 "github.com/filecoin-project/specs-actors/actors/util/adt" - adt2 "github.com/filecoin-project/specs-actors/v2/actors/util/adt" - adt3 "github.com/filecoin-project/specs-actors/v3/actors/util/adt" ) type Map interface { @@ -25,30 +17,6 @@ type Map interface { ForEach(v cbor.Unmarshaler, fn func(key string) error) error } -func AsMap(store Store, root cid.Cid, version actors.Version, v3bitwidth int) (Map, error) { - switch version { - case actors.Version0: - return adt0.AsMap(store, root) - case actors.Version2: - return adt2.AsMap(store, root) - case actors.Version3: - return adt3.AsMap(store, root, v3bitwidth) - } - return nil, xerrors.Errorf("unknown network version: %d", version) -} - -func NewMap(store Store, version actors.Version, bitwidth int) (Map, error) { - switch version { - case actors.Version0: - return adt0.MakeEmptyMap(store), nil - case actors.Version2: - return adt2.MakeEmptyMap(store), nil - case actors.Version3: - return adt3.MakeEmptyMap(store, bitwidth), nil - } - return nil, xerrors.Errorf("unknown network version: %d", version) -} - type Array interface { Root() (cid.Cid, error) @@ -59,27 +27,3 @@ type Array interface { ForEach(v cbor.Unmarshaler, fn func(idx int64) error) error } - -func AsArray(store Store, root cid.Cid, version network.Version, bitwidth int) (Array, error) { - switch actors.VersionForNetwork(version) { - case actors.Version0: - return adt0.AsArray(store, root) - case actors.Version2: - return adt2.AsArray(store, root) - case actors.Version3: - return adt3.AsArray(store, root, bitwidth) - } - return nil, xerrors.Errorf("unknown network version: %d", version) -} - -func NewArray(store Store, version actors.Version, bitwidth int) (Array, error) { - switch version { - case actors.Version0: - return adt0.MakeEmptyArray(store), nil - case actors.Version2: - return adt2.MakeEmptyArray(store), nil - case actors.Version3: - return adt3.MakeEmptyArray(store, bitwidth) - } - return nil, xerrors.Errorf("unknown network version: %d", version) -} diff --git a/chain/actors/builtin/verifreg/util.go b/chain/actors/builtin/verifreg/util.go index b7768439c..16e50c50a 100644 --- a/chain/actors/builtin/verifreg/util.go +++ b/chain/actors/builtin/verifreg/util.go @@ -6,18 +6,21 @@ import ( "github.com/filecoin-project/go-state-types/big" "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors/adt" - builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" - "github.com/ipfs/go-cid" "golang.org/x/xerrors" ) +// taking this as a function instead of asking the caller to call it helps reduce some of the error +// checking boilerplate. +// +// "go made me do it" +type rootFunc func() (adt.Map, error) + // Assumes that the bitwidth for v3 HAMTs is the DefaultHamtBitwidth -func getDataCap(store adt.Store, ver actors.Version, root cid.Cid, addr address.Address) (bool, abi.StoragePower, error) { +func getDataCap(store adt.Store, ver actors.Version, root rootFunc, addr address.Address) (bool, abi.StoragePower, error) { if addr.Protocol() != address.ID { return false, big.Zero(), xerrors.Errorf("can only look up ID addresses") } - - vh, err := adt.AsMap(store, root, ver, builtin3.DefaultHamtBitwidth) + vh, err := root() if err != nil { return false, big.Zero(), xerrors.Errorf("loading verifreg: %w", err) } @@ -33,8 +36,8 @@ func getDataCap(store adt.Store, ver actors.Version, root cid.Cid, addr address. } // Assumes that the bitwidth for v3 HAMTs is the DefaultHamtBitwidth -func forEachCap(store adt.Store, ver actors.Version, root cid.Cid, cb func(addr address.Address, dcap abi.StoragePower) error) error { - vh, err := adt.AsMap(store, root, ver, builtin3.DefaultHamtBitwidth) +func forEachCap(store adt.Store, ver actors.Version, root rootFunc, cb func(addr address.Address, dcap abi.StoragePower) error) error { + vh, err := root() if err != nil { return xerrors.Errorf("loading verified clients: %w", err) } diff --git a/chain/actors/builtin/verifreg/v0.go b/chain/actors/builtin/verifreg/v0.go index 64def4706..0dc4696f4 100644 --- a/chain/actors/builtin/verifreg/v0.go +++ b/chain/actors/builtin/verifreg/v0.go @@ -9,6 +9,7 @@ import ( "github.com/filecoin-project/lotus/chain/actors/adt" verifreg0 "github.com/filecoin-project/specs-actors/actors/builtin/verifreg" + adt0 "github.com/filecoin-project/specs-actors/actors/util/adt" ) var _ State = (*state0)(nil) @@ -32,17 +33,25 @@ func (s *state0) RootKey() (address.Address, error) { } func (s *state0) VerifiedClientDataCap(addr address.Address) (bool, abi.StoragePower, error) { - return getDataCap(s.store, actors.Version0, s.State.VerifiedClients, addr) + return getDataCap(s.store, actors.Version0, s.verifiedClients, addr) } func (s *state0) VerifierDataCap(addr address.Address) (bool, abi.StoragePower, error) { - return getDataCap(s.store, actors.Version0, s.State.Verifiers, addr) + return getDataCap(s.store, actors.Version0, s.verifiers, addr) } func (s *state0) ForEachVerifier(cb func(addr address.Address, dcap abi.StoragePower) error) error { - return forEachCap(s.store, actors.Version0, s.State.Verifiers, cb) + return forEachCap(s.store, actors.Version0, s.verifiers, cb) } func (s *state0) ForEachClient(cb func(addr address.Address, dcap abi.StoragePower) error) error { - return forEachCap(s.store, actors.Version0, s.State.VerifiedClients, cb) + return forEachCap(s.store, actors.Version0, s.verifiedClients, cb) +} + +func (s *state0) verifiedClients() (adt.Map, error) { + return adt0.AsMap(s.store, s.VerifiedClients) +} + +func (s *state0) verifiers() (adt.Map, error) { + return adt0.AsMap(s.store, s.Verifiers) } diff --git a/chain/actors/builtin/verifreg/v2.go b/chain/actors/builtin/verifreg/v2.go index 5ee3bad05..a5ef84532 100644 --- a/chain/actors/builtin/verifreg/v2.go +++ b/chain/actors/builtin/verifreg/v2.go @@ -9,6 +9,7 @@ import ( "github.com/filecoin-project/lotus/chain/actors/adt" verifreg2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/verifreg" + adt2 "github.com/filecoin-project/specs-actors/v2/actors/util/adt" ) var _ State = (*state2)(nil) @@ -32,17 +33,25 @@ func (s *state2) RootKey() (address.Address, error) { } func (s *state2) VerifiedClientDataCap(addr address.Address) (bool, abi.StoragePower, error) { - return getDataCap(s.store, actors.Version2, s.State.VerifiedClients, addr) + return getDataCap(s.store, actors.Version2, s.verifiedClients, addr) } func (s *state2) VerifierDataCap(addr address.Address) (bool, abi.StoragePower, error) { - return getDataCap(s.store, actors.Version2, s.State.Verifiers, addr) + return getDataCap(s.store, actors.Version2, s.verifiers, addr) } func (s *state2) ForEachVerifier(cb func(addr address.Address, dcap abi.StoragePower) error) error { - return forEachCap(s.store, actors.Version2, s.State.Verifiers, cb) + return forEachCap(s.store, actors.Version2, s.verifiers, cb) } func (s *state2) ForEachClient(cb func(addr address.Address, dcap abi.StoragePower) error) error { - return forEachCap(s.store, actors.Version2, s.State.VerifiedClients, cb) + return forEachCap(s.store, actors.Version2, s.verifiedClients, cb) +} + +func (s *state2) verifiedClients() (adt.Map, error) { + return adt2.AsMap(s.store, s.VerifiedClients) +} + +func (s *state2) verifiers() (adt.Map, error) { + return adt2.AsMap(s.store, s.Verifiers) } diff --git a/chain/actors/builtin/verifreg/v3.go b/chain/actors/builtin/verifreg/v3.go index 4667412c5..fb0c46d0c 100644 --- a/chain/actors/builtin/verifreg/v3.go +++ b/chain/actors/builtin/verifreg/v3.go @@ -8,7 +8,9 @@ import ( "github.com/filecoin-project/lotus/chain/actors" "github.com/filecoin-project/lotus/chain/actors/adt" + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" verifreg3 "github.com/filecoin-project/specs-actors/v3/actors/builtin/verifreg" + adt3 "github.com/filecoin-project/specs-actors/v3/actors/util/adt" ) var _ State = (*state3)(nil) @@ -32,17 +34,25 @@ func (s *state3) RootKey() (address.Address, error) { } func (s *state3) VerifiedClientDataCap(addr address.Address) (bool, abi.StoragePower, error) { - return getDataCap(s.store, actors.Version3, s.State.VerifiedClients, addr) + return getDataCap(s.store, actors.Version3, s.verifiedClients, addr) } func (s *state3) VerifierDataCap(addr address.Address) (bool, abi.StoragePower, error) { - return getDataCap(s.store, actors.Version3, s.State.Verifiers, addr) + return getDataCap(s.store, actors.Version3, s.verifiers, addr) } func (s *state3) ForEachVerifier(cb func(addr address.Address, dcap abi.StoragePower) error) error { - return forEachCap(s.store, actors.Version3, s.State.Verifiers, cb) + return forEachCap(s.store, actors.Version3, s.verifiers, cb) } func (s *state3) ForEachClient(cb func(addr address.Address, dcap abi.StoragePower) error) error { - return forEachCap(s.store, actors.Version3, s.State.VerifiedClients, cb) + return forEachCap(s.store, actors.Version3, s.verifiedClients, cb) +} + +func (s *state3) verifiedClients() (adt.Map, error) { + return adt3.AsMap(s.store, s.VerifiedClients, builtin3.DefaultHamtBitwidth) +} + +func (s *state3) verifiers() (adt.Map, error) { + return adt3.AsMap(s.store, s.Verifiers, builtin3.DefaultHamtBitwidth) } diff --git a/chain/state/statetree.go b/chain/state/statetree.go index d8cdca73a..d31296040 100644 --- a/chain/state/statetree.go +++ b/chain/state/statetree.go @@ -5,8 +5,6 @@ import ( "context" "fmt" - builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" - "github.com/ipfs/go-cid" cbor "github.com/ipfs/go-ipld-cbor" logging "github.com/ipfs/go-log/v2" @@ -22,6 +20,12 @@ import ( "github.com/filecoin-project/lotus/chain/actors/adt" "github.com/filecoin-project/lotus/chain/types" + + adt0 "github.com/filecoin-project/specs-actors/actors/util/adt" + adt2 "github.com/filecoin-project/specs-actors/v2/actors/util/adt" + adt3 "github.com/filecoin-project/specs-actors/v3/actors/util/adt" + + builtin3 "github.com/filecoin-project/specs-actors/v3/actors/builtin" ) var log = logging.Logger("statetree") @@ -146,23 +150,12 @@ func VersionForNetwork(ver network.Version) types.StateTreeVersion { return types.StateTreeVersion1 } -func adtForSTVersion(ver types.StateTreeVersion) actors.Version { - switch ver { - case types.StateTreeVersion0: - return actors.Version0 - case types.StateTreeVersion1: - return actors.Version2 - default: - panic("unhandled state tree version") - } -} - func NewStateTree(cst cbor.IpldStore, ver types.StateTreeVersion) (*StateTree, error) { var info cid.Cid switch ver { case types.StateTreeVersion0: // info is undefined - case types.StateTreeVersion1: + case types.StateTreeVersion1, types.StateTreeVersion2: var err error info, err = cst.Put(context.TODO(), new(types.StateInfo0)) if err != nil { @@ -171,14 +164,22 @@ func NewStateTree(cst cbor.IpldStore, ver types.StateTreeVersion) (*StateTree, e default: return nil, xerrors.Errorf("unsupported state tree version: %d", ver) } - // TODO: Confirm this is correct - root, err := adt.NewMap(adt.WrapStore(context.TODO(), cst), adtForSTVersion(ver), builtin3.DefaultHamtBitwidth) - if err != nil { - return nil, err + + var hamt adt.Map + store := adt.WrapStore(context.TODO(), cst) + switch ver { + case types.StateTreeVersion0: + hamt = adt0.MakeEmptyMap(store) + case types.StateTreeVersion1: + hamt = adt2.MakeEmptyMap(store) + case types.StateTreeVersion2: + hamt = adt3.MakeEmptyMap(store, builtin3.DefaultHamtBitwidth) + default: + return nil, xerrors.Errorf("unsupported state tree version: %d", ver) } s := &StateTree{ - root: root, + root: hamt, info: info, version: ver, Store: cst, @@ -197,32 +198,39 @@ func LoadStateTree(cst cbor.IpldStore, c cid.Cid) (*StateTree, error) { root.Version = types.StateTreeVersion0 } - switch root.Version { - case types.StateTreeVersion0, types.StateTreeVersion1: - // Load the actual state-tree HAMT. - nd, err := adt.AsMap( - adt.WrapStore(context.TODO(), cst), root.Actors, - adtForSTVersion(root.Version), - // TODO: Confirm this is correct - builtin3.DefaultHamtBitwidth, - ) - if err != nil { - log.Errorf("loading hamt node %s failed: %s", c, err) - return nil, err - } + store := adt.WrapStore(context.TODO(), cst) - s := &StateTree{ - root: nd, - info: root.Info, - version: root.Version, - Store: cst, - snaps: newStateSnaps(), - } - s.lookupIDFun = s.lookupIDinternal - return s, nil + var ( + hamt adt.Map + err error + ) + + switch root.Version { + case types.StateTreeVersion0: + hamt, err = adt0.AsMap(store, root.Actors) + case types.StateTreeVersion1: + hamt, err = adt2.AsMap(store, root.Actors) + case types.StateTreeVersion2: + hamt, err = adt3.AsMap(store, root.Actors, builtin3.DefaultHamtBitwidth) default: return nil, xerrors.Errorf("unsupported state tree version: %d", root.Version) } + + if err != nil { + log.Errorf("loading hamt node %s failed: %s", c, err) + return nil, err + } + + s := &StateTree{ + root: hamt, + info: root.Info, + version: root.Version, + Store: cst, + snaps: newStateSnaps(), + } + s.lookupIDFun = s.lookupIDinternal + + return s, nil } func (st *StateTree) SetActor(addr address.Address, act *types.Actor) error { diff --git a/chain/stmgr/stmgr.go b/chain/stmgr/stmgr.go index 8a6315deb..84e9e1744 100644 --- a/chain/stmgr/stmgr.go +++ b/chain/stmgr/stmgr.go @@ -21,6 +21,9 @@ import ( // Used for genesis. msig0 "github.com/filecoin-project/specs-actors/actors/builtin/multisig" + // we use the same adt for all receipts + blockadt "github.com/filecoin-project/specs-actors/actors/util/adt" + "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/build" "github.com/filecoin-project/lotus/chain/actors" @@ -385,11 +388,7 @@ func (sm *StateManager) ApplyBlocks(ctx context.Context, parentEpoch abi.ChainEp return cid.Cid{}, cid.Cid{}, err } - // XXX: Is the height correct? Or should it be epoch-1? - rectarr, err := adt.NewArray(sm.cs.Store(ctx), actors.VersionForNetwork(sm.GetNtwkVersion(ctx, epoch)), ReceiptAmtBitwidth) - if err != nil { - return cid.Undef, cid.Undef, xerrors.Errorf("failed to create receipts amt: %w", err) - } + rectarr := blockadt.MakeEmptyArray(sm.cs.Store(ctx)) for i, receipt := range receipts { if err := rectarr.Set(uint64(i), receipt); err != nil { return cid.Undef, cid.Undef, xerrors.Errorf("failed to build receipts amt: %w", err) diff --git a/chain/types/state.go b/chain/types/state.go index a96883604..f6a3472f8 100644 --- a/chain/types/state.go +++ b/chain/types/state.go @@ -9,8 +9,10 @@ type StateTreeVersion uint64 const ( // StateTreeVersion0 corresponds to actors < v2. StateTreeVersion0 StateTreeVersion = iota - // StateTreeVersion1 corresponds to actors >= v2. + // StateTreeVersion1 corresponds to actors [v2, v3) StateTreeVersion1 + // StateTreeVersion2 corresponds to actors >= v3. + StateTreeVersion2 ) type StateRoot struct {