introduce separate state-tree versions
Instead of versioning the state tree along with the actors, version it separately. This structure may not upgrade every time we update actors.
This commit is contained in:
parent
5ef929f130
commit
e803cf151f
@ -26,7 +26,6 @@ import (
|
|||||||
adt0 "github.com/filecoin-project/specs-actors/actors/util/adt"
|
adt0 "github.com/filecoin-project/specs-actors/actors/util/adt"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/build"
|
"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/state"
|
||||||
"github.com/filecoin-project/lotus/chain/store"
|
"github.com/filecoin-project/lotus/chain/store"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
@ -117,7 +116,7 @@ func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template ge
|
|||||||
return nil, nil, xerrors.Errorf("putting empty object: %w", err)
|
return nil, nil, xerrors.Errorf("putting empty object: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
state, err := state.NewStateTree(cst, actors.Version0)
|
state, err := state.NewStateTree(cst, types.StateTreeVersion0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, xerrors.Errorf("making new state tree: %w", err)
|
return nil, nil, xerrors.Errorf("making new state tree: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ import (
|
|||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
"github.com/filecoin-project/go-state-types/abi"
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
|
"github.com/filecoin-project/go-state-types/network"
|
||||||
"github.com/filecoin-project/lotus/chain/actors"
|
"github.com/filecoin-project/lotus/chain/actors"
|
||||||
init_ "github.com/filecoin-project/lotus/chain/actors/builtin/init"
|
init_ "github.com/filecoin-project/lotus/chain/actors/builtin/init"
|
||||||
cbg "github.com/whyrusleeping/cbor-gen"
|
cbg "github.com/whyrusleeping/cbor-gen"
|
||||||
@ -26,7 +27,7 @@ var log = logging.Logger("statetree")
|
|||||||
// StateTree stores actors state by their ID.
|
// StateTree stores actors state by their ID.
|
||||||
type StateTree struct {
|
type StateTree struct {
|
||||||
root adt.Map
|
root adt.Map
|
||||||
version actors.Version // TODO
|
version types.StateTreeVersion
|
||||||
info cid.Cid
|
info cid.Cid
|
||||||
Store cbor.IpldStore
|
Store cbor.IpldStore
|
||||||
|
|
||||||
@ -120,21 +121,41 @@ func (ss *stateSnaps) deleteActor(addr address.Address) {
|
|||||||
ss.layers[len(ss.layers)-1].actors[addr] = streeOp{Delete: true}
|
ss.layers[len(ss.layers)-1].actors[addr] = streeOp{Delete: true}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewStateTree(cst cbor.IpldStore, version actors.Version) (*StateTree, error) {
|
// VersionForNetwork returns the state tree version for the given network
|
||||||
|
// version.
|
||||||
|
func VersionForNetwork(ver network.Version) types.StateTreeVersion {
|
||||||
|
if actors.VersionForNetwork(ver) == actors.Version0 {
|
||||||
|
return types.StateTreeVersion0
|
||||||
|
}
|
||||||
|
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
|
var info cid.Cid
|
||||||
switch version {
|
switch ver {
|
||||||
case actors.Version0:
|
case types.StateTreeVersion0:
|
||||||
// info is undefined
|
// info is undefined
|
||||||
case actors.Version2:
|
case types.StateTreeVersion1:
|
||||||
var err error
|
var err error
|
||||||
info, err = cst.Put(context.TODO(), new(types.StateInfo))
|
info, err = cst.Put(context.TODO(), new(types.StateInfo0))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return nil, xerrors.Errorf("unsupported state tree version: %d", version)
|
return nil, xerrors.Errorf("unsupported state tree version: %d", ver)
|
||||||
}
|
}
|
||||||
root, err := adt.NewMap(adt.WrapStore(context.TODO(), cst), version)
|
root, err := adt.NewMap(adt.WrapStore(context.TODO(), cst), adtForSTVersion(ver))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -142,7 +163,7 @@ func NewStateTree(cst cbor.IpldStore, version actors.Version) (*StateTree, error
|
|||||||
return &StateTree{
|
return &StateTree{
|
||||||
root: root,
|
root: root,
|
||||||
info: info,
|
info: info,
|
||||||
version: version,
|
version: ver,
|
||||||
Store: cst,
|
Store: cst,
|
||||||
snaps: newStateSnaps(),
|
snaps: newStateSnaps(),
|
||||||
}, nil
|
}, nil
|
||||||
@ -154,13 +175,16 @@ func LoadStateTree(cst cbor.IpldStore, c cid.Cid) (*StateTree, error) {
|
|||||||
if err := cst.Get(context.TODO(), c, &root); err != nil {
|
if err := cst.Get(context.TODO(), c, &root); err != nil {
|
||||||
// We failed to decode as the new version, must be an old version.
|
// We failed to decode as the new version, must be an old version.
|
||||||
root.Actors = c
|
root.Actors = c
|
||||||
root.Version = actors.Version0
|
root.Version = types.StateTreeVersion0
|
||||||
}
|
}
|
||||||
|
|
||||||
switch root.Version {
|
switch root.Version {
|
||||||
case actors.Version0, actors.Version2:
|
case types.StateTreeVersion0, types.StateTreeVersion1:
|
||||||
// Load the actual state-tree HAMT.
|
// Load the actual state-tree HAMT.
|
||||||
nd, err := adt.AsMap(adt.WrapStore(context.TODO(), cst), root.Actors, actors.Version(root.Version))
|
nd, err := adt.AsMap(
|
||||||
|
adt.WrapStore(context.TODO(), cst), root.Actors,
|
||||||
|
adtForSTVersion(root.Version),
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("loading hamt node %s failed: %s", c, err)
|
log.Errorf("loading hamt node %s failed: %s", c, err)
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -169,7 +193,7 @@ func LoadStateTree(cst cbor.IpldStore, c cid.Cid) (*StateTree, error) {
|
|||||||
return &StateTree{
|
return &StateTree{
|
||||||
root: nd,
|
root: nd,
|
||||||
info: root.Info,
|
info: root.Info,
|
||||||
version: actors.Version(root.Version),
|
version: root.Version,
|
||||||
Store: cst,
|
Store: cst,
|
||||||
snaps: newStateSnaps(),
|
snaps: newStateSnaps(),
|
||||||
}, nil
|
}, nil
|
||||||
@ -309,11 +333,11 @@ func (st *StateTree) Flush(ctx context.Context) (cid.Cid, error) {
|
|||||||
return cid.Undef, xerrors.Errorf("failed to flush state-tree hamt: %w", err)
|
return cid.Undef, xerrors.Errorf("failed to flush state-tree hamt: %w", err)
|
||||||
}
|
}
|
||||||
// If we're version 0, return a raw tree.
|
// If we're version 0, return a raw tree.
|
||||||
if st.version == actors.Version0 {
|
if st.version == types.StateTreeVersion0 {
|
||||||
return root, nil
|
return root, nil
|
||||||
}
|
}
|
||||||
// Otherwise, return a versioned tree.
|
// Otherwise, return a versioned tree.
|
||||||
return st.Store.Put(ctx, &types.StateRoot{Version: uint64(st.version), Actors: root, Info: st.info})
|
return st.Store.Put(ctx, &types.StateRoot{Version: st.version, Actors: root, Info: st.info})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *StateTree) Snapshot(ctx context.Context) error {
|
func (st *StateTree) Snapshot(ctx context.Context) error {
|
||||||
@ -400,7 +424,7 @@ func (st *StateTree) ForEach(f func(address.Address, *types.Actor) error) error
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Version returns the version of the StateTree data structure in use.
|
// Version returns the version of the StateTree data structure in use.
|
||||||
func (st *StateTree) Version() actors.Version {
|
func (st *StateTree) Version() types.StateTreeVersion {
|
||||||
return st.version
|
return st.version
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,13 +13,12 @@ import (
|
|||||||
"github.com/filecoin-project/specs-actors/actors/builtin"
|
"github.com/filecoin-project/specs-actors/actors/builtin"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/build"
|
"github.com/filecoin-project/lotus/build"
|
||||||
"github.com/filecoin-project/lotus/chain/actors"
|
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
func BenchmarkStateTreeSet(b *testing.B) {
|
func BenchmarkStateTreeSet(b *testing.B) {
|
||||||
cst := cbor.NewMemCborStore()
|
cst := cbor.NewMemCborStore()
|
||||||
st, err := NewStateTree(cst, actors.VersionForNetwork(build.NewestNetworkVersion))
|
st, err := NewStateTree(cst, VersionForNetwork(build.NewestNetworkVersion))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatal(err)
|
b.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -46,7 +45,7 @@ func BenchmarkStateTreeSet(b *testing.B) {
|
|||||||
|
|
||||||
func BenchmarkStateTreeSetFlush(b *testing.B) {
|
func BenchmarkStateTreeSetFlush(b *testing.B) {
|
||||||
cst := cbor.NewMemCborStore()
|
cst := cbor.NewMemCborStore()
|
||||||
st, err := NewStateTree(cst, actors.VersionForNetwork(build.NewestNetworkVersion))
|
st, err := NewStateTree(cst, VersionForNetwork(build.NewestNetworkVersion))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatal(err)
|
b.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -76,7 +75,7 @@ func BenchmarkStateTreeSetFlush(b *testing.B) {
|
|||||||
|
|
||||||
func BenchmarkStateTree10kGetActor(b *testing.B) {
|
func BenchmarkStateTree10kGetActor(b *testing.B) {
|
||||||
cst := cbor.NewMemCborStore()
|
cst := cbor.NewMemCborStore()
|
||||||
st, err := NewStateTree(cst, actors.VersionForNetwork(build.NewestNetworkVersion))
|
st, err := NewStateTree(cst, VersionForNetwork(build.NewestNetworkVersion))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatal(err)
|
b.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -118,7 +117,7 @@ func BenchmarkStateTree10kGetActor(b *testing.B) {
|
|||||||
|
|
||||||
func TestSetCache(t *testing.T) {
|
func TestSetCache(t *testing.T) {
|
||||||
cst := cbor.NewMemCborStore()
|
cst := cbor.NewMemCborStore()
|
||||||
st, err := NewStateTree(cst, actors.VersionForNetwork(build.NewestNetworkVersion))
|
st, err := NewStateTree(cst, VersionForNetwork(build.NewestNetworkVersion))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -155,7 +154,7 @@ func TestSetCache(t *testing.T) {
|
|||||||
func TestSnapshots(t *testing.T) {
|
func TestSnapshots(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
cst := cbor.NewMemCborStore()
|
cst := cbor.NewMemCborStore()
|
||||||
st, err := NewStateTree(cst, actors.VersionForNetwork(build.NewestNetworkVersion))
|
st, err := NewStateTree(cst, VersionForNetwork(build.NewestNetworkVersion))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -239,7 +238,7 @@ func assertNotHas(t *testing.T, st *StateTree, addr address.Address) {
|
|||||||
func TestStateTreeConsistency(t *testing.T) {
|
func TestStateTreeConsistency(t *testing.T) {
|
||||||
cst := cbor.NewMemCborStore()
|
cst := cbor.NewMemCborStore()
|
||||||
// TODO: ActorUpgrade: this test tests pre actors v2
|
// TODO: ActorUpgrade: this test tests pre actors v2
|
||||||
st, err := NewStateTree(cst, actors.VersionForNetwork(network.Version3))
|
st, err := NewStateTree(cst, VersionForNetwork(network.Version3))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -494,7 +494,7 @@ func UpgradeActorsV2(ctx context.Context, sm *StateManager, cb ExecCallback, roo
|
|||||||
|
|
||||||
epoch := ts.Height() - 1
|
epoch := ts.Height() - 1
|
||||||
|
|
||||||
info, err := store.Put(ctx, new(types.StateInfo))
|
info, err := store.Put(ctx, new(types.StateInfo0))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cid.Undef, xerrors.Errorf("failed to create new state info for actors v2: %w", err)
|
return cid.Undef, xerrors.Errorf("failed to create new state info for actors v2: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -1648,7 +1648,7 @@ func (t *StateRoot) MarshalCBOR(w io.Writer) error {
|
|||||||
|
|
||||||
scratch := make([]byte, 9)
|
scratch := make([]byte, 9)
|
||||||
|
|
||||||
// t.Version (uint64) (uint64)
|
// t.Version (types.StateTreeVersion) (uint64)
|
||||||
|
|
||||||
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.Version)); err != nil {
|
if err := cbg.WriteMajorTypeHeaderBuf(scratch, w, cbg.MajUnsignedInt, uint64(t.Version)); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -1687,7 +1687,7 @@ func (t *StateRoot) UnmarshalCBOR(r io.Reader) error {
|
|||||||
return fmt.Errorf("cbor input had wrong number of fields")
|
return fmt.Errorf("cbor input had wrong number of fields")
|
||||||
}
|
}
|
||||||
|
|
||||||
// t.Version (uint64) (uint64)
|
// t.Version (types.StateTreeVersion) (uint64)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -1698,7 +1698,7 @@ func (t *StateRoot) UnmarshalCBOR(r io.Reader) error {
|
|||||||
if maj != cbg.MajUnsignedInt {
|
if maj != cbg.MajUnsignedInt {
|
||||||
return fmt.Errorf("wrong type for uint64 field")
|
return fmt.Errorf("wrong type for uint64 field")
|
||||||
}
|
}
|
||||||
t.Version = uint64(extra)
|
t.Version = StateTreeVersion(extra)
|
||||||
|
|
||||||
}
|
}
|
||||||
// t.Actors (cid.Cid) (struct)
|
// t.Actors (cid.Cid) (struct)
|
||||||
@ -1728,22 +1728,22 @@ func (t *StateRoot) UnmarshalCBOR(r io.Reader) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var lengthBufStateInfo = []byte{128}
|
var lengthBufStateInfo0 = []byte{128}
|
||||||
|
|
||||||
func (t *StateInfo) MarshalCBOR(w io.Writer) error {
|
func (t *StateInfo0) MarshalCBOR(w io.Writer) error {
|
||||||
if t == nil {
|
if t == nil {
|
||||||
_, err := w.Write(cbg.CborNull)
|
_, err := w.Write(cbg.CborNull)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if _, err := w.Write(lengthBufStateInfo); err != nil {
|
if _, err := w.Write(lengthBufStateInfo0); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *StateInfo) UnmarshalCBOR(r io.Reader) error {
|
func (t *StateInfo0) UnmarshalCBOR(r io.Reader) error {
|
||||||
*t = StateInfo{}
|
*t = StateInfo0{}
|
||||||
|
|
||||||
br := cbg.GetPeeker(r)
|
br := cbg.GetPeeker(r)
|
||||||
scratch := make([]byte, 8)
|
scratch := make([]byte, 8)
|
||||||
|
@ -2,9 +2,20 @@ package types
|
|||||||
|
|
||||||
import "github.com/ipfs/go-cid"
|
import "github.com/ipfs/go-cid"
|
||||||
|
|
||||||
|
// StateTreeVersion is the version of the state tree itself, independent of the
|
||||||
|
// network version or the actors version.
|
||||||
|
type StateTreeVersion uint64
|
||||||
|
|
||||||
|
const (
|
||||||
|
// StateTreeVersion0 corresponds to actors < v2.
|
||||||
|
StateTreeVersion0 StateTreeVersion = iota
|
||||||
|
// StateTreeVersion1 corresponds to actors >= v2.
|
||||||
|
StateTreeVersion1
|
||||||
|
)
|
||||||
|
|
||||||
type StateRoot struct {
|
type StateRoot struct {
|
||||||
// State root version. Versioned along with actors (for now).
|
// State tree version.
|
||||||
Version uint64
|
Version StateTreeVersion
|
||||||
// Actors tree. The structure depends on the state root version.
|
// Actors tree. The structure depends on the state root version.
|
||||||
Actors cid.Cid
|
Actors cid.Cid
|
||||||
// Info. The structure depends on the state root version.
|
// Info. The structure depends on the state root version.
|
||||||
@ -12,4 +23,4 @@ type StateRoot struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: version this.
|
// TODO: version this.
|
||||||
type StateInfo struct{}
|
type StateInfo0 struct{}
|
||||||
|
@ -27,7 +27,7 @@ func main() {
|
|||||||
types.ExpTipSet{},
|
types.ExpTipSet{},
|
||||||
types.BeaconEntry{},
|
types.BeaconEntry{},
|
||||||
types.StateRoot{},
|
types.StateRoot{},
|
||||||
types.StateInfo{},
|
types.StateInfo0{},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
|
@ -176,7 +176,8 @@
|
|||||||
"CompactPartitions",
|
"CompactPartitions",
|
||||||
"CompactSectorNumbers",
|
"CompactSectorNumbers",
|
||||||
"ConfirmUpdateWorkerKey",
|
"ConfirmUpdateWorkerKey",
|
||||||
"RepayDebt"
|
"RepayDebt",
|
||||||
|
"ChangeOwnerAddress"
|
||||||
],
|
],
|
||||||
"fil/2/storagepower": [
|
"fil/2/storagepower": [
|
||||||
"Send",
|
"Send",
|
||||||
|
Loading…
Reference in New Issue
Block a user