Skip to content

Commit

Permalink
Merge pull request #4197 from filecoin-project/steb/state-tree-version
Browse files Browse the repository at this point in the history
introduce separate state-tree versions
  • Loading branch information
Stebalien committed Oct 7, 2020
2 parents 5ef929f + 767c346 commit de3f411
Show file tree
Hide file tree
Showing 10 changed files with 77 additions and 45 deletions.
4 changes: 2 additions & 2 deletions chain/actors/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import (
type Version int

const (
Version0 = 0
Version2 = 2
Version0 Version = 0
Version2 Version = 2
)

// Converts a network version into an actors adt version.
Expand Down
3 changes: 1 addition & 2 deletions chain/gen/genesis/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import (
adt0 "github.com/filecoin-project/specs-actors/actors/util/adt"

"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/store"
"github.com/filecoin-project/lotus/chain/types"
Expand Down Expand Up @@ -117,7 +116,7 @@ func MakeInitialStateTree(ctx context.Context, bs bstore.Blockstore, template ge
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 {
return nil, nil, xerrors.Errorf("making new state tree: %w", err)
}
Expand Down
56 changes: 40 additions & 16 deletions chain/state/statetree.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/network"
"github.com/filecoin-project/lotus/chain/actors"
init_ "github.com/filecoin-project/lotus/chain/actors/builtin/init"
cbg "github.com/whyrusleeping/cbor-gen"
Expand All @@ -26,7 +27,7 @@ var log = logging.Logger("statetree")
// StateTree stores actors state by their ID.
type StateTree struct {
root adt.Map
version actors.Version // TODO
version types.StateTreeVersion
info cid.Cid
Store cbor.IpldStore

Expand Down Expand Up @@ -120,29 +121,49 @@ func (ss *stateSnaps) deleteActor(addr address.Address) {
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
switch version {
case actors.Version0:
switch ver {
case types.StateTreeVersion0:
// info is undefined
case actors.Version2:
case types.StateTreeVersion1:
var err error
info, err = cst.Put(context.TODO(), new(types.StateInfo))
info, err = cst.Put(context.TODO(), new(types.StateInfo0))
if err != nil {
return nil, err
}
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 {
return nil, err
}

return &StateTree{
root: root,
info: info,
version: version,
version: ver,
Store: cst,
snaps: newStateSnaps(),
}, nil
Expand All @@ -154,13 +175,16 @@ func LoadStateTree(cst cbor.IpldStore, c cid.Cid) (*StateTree, error) {
if err := cst.Get(context.TODO(), c, &root); err != nil {
// We failed to decode as the new version, must be an old version.
root.Actors = c
root.Version = actors.Version0
root.Version = types.StateTreeVersion0
}

switch root.Version {
case actors.Version0, actors.Version2:
case types.StateTreeVersion0, types.StateTreeVersion1:
// 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 {
log.Errorf("loading hamt node %s failed: %s", c, err)
return nil, err
Expand All @@ -169,7 +193,7 @@ func LoadStateTree(cst cbor.IpldStore, c cid.Cid) (*StateTree, error) {
return &StateTree{
root: nd,
info: root.Info,
version: actors.Version(root.Version),
version: root.Version,
Store: cst,
snaps: newStateSnaps(),
}, nil
Expand Down Expand Up @@ -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)
}
// If we're version 0, return a raw tree.
if st.version == actors.Version0 {
if st.version == types.StateTreeVersion0 {
return root, nil
}
// 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 {
Expand Down Expand Up @@ -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.
func (st *StateTree) Version() actors.Version {
func (st *StateTree) Version() types.StateTreeVersion {
return st.version
}

Expand Down
13 changes: 6 additions & 7 deletions chain/state/statetree_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,12 @@ import (
"github.com/filecoin-project/specs-actors/actors/builtin"

"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/types"
)

func BenchmarkStateTreeSet(b *testing.B) {
cst := cbor.NewMemCborStore()
st, err := NewStateTree(cst, actors.VersionForNetwork(build.NewestNetworkVersion))
st, err := NewStateTree(cst, VersionForNetwork(build.NewestNetworkVersion))
if err != nil {
b.Fatal(err)
}
Expand All @@ -46,7 +45,7 @@ func BenchmarkStateTreeSet(b *testing.B) {

func BenchmarkStateTreeSetFlush(b *testing.B) {
cst := cbor.NewMemCborStore()
st, err := NewStateTree(cst, actors.VersionForNetwork(build.NewestNetworkVersion))
st, err := NewStateTree(cst, VersionForNetwork(build.NewestNetworkVersion))
if err != nil {
b.Fatal(err)
}
Expand Down Expand Up @@ -76,7 +75,7 @@ func BenchmarkStateTreeSetFlush(b *testing.B) {

func BenchmarkStateTree10kGetActor(b *testing.B) {
cst := cbor.NewMemCborStore()
st, err := NewStateTree(cst, actors.VersionForNetwork(build.NewestNetworkVersion))
st, err := NewStateTree(cst, VersionForNetwork(build.NewestNetworkVersion))
if err != nil {
b.Fatal(err)
}
Expand Down Expand Up @@ -118,7 +117,7 @@ func BenchmarkStateTree10kGetActor(b *testing.B) {

func TestSetCache(t *testing.T) {
cst := cbor.NewMemCborStore()
st, err := NewStateTree(cst, actors.VersionForNetwork(build.NewestNetworkVersion))
st, err := NewStateTree(cst, VersionForNetwork(build.NewestNetworkVersion))
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -155,7 +154,7 @@ func TestSetCache(t *testing.T) {
func TestSnapshots(t *testing.T) {
ctx := context.Background()
cst := cbor.NewMemCborStore()
st, err := NewStateTree(cst, actors.VersionForNetwork(build.NewestNetworkVersion))
st, err := NewStateTree(cst, VersionForNetwork(build.NewestNetworkVersion))
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -239,7 +238,7 @@ func assertNotHas(t *testing.T, st *StateTree, addr address.Address) {
func TestStateTreeConsistency(t *testing.T) {
cst := cbor.NewMemCborStore()
// 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 {
t.Fatal(err)
}
Expand Down
6 changes: 2 additions & 4 deletions chain/stmgr/forks.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import (
states2 "github.com/filecoin-project/specs-actors/v2/actors/states"

"github.com/filecoin-project/lotus/build"
"github.com/filecoin-project/lotus/chain/actors"
"github.com/filecoin-project/lotus/chain/actors/adt"
init_ "github.com/filecoin-project/lotus/chain/actors/builtin/init"
"github.com/filecoin-project/lotus/chain/actors/builtin/multisig"
Expand Down Expand Up @@ -494,7 +493,7 @@ func UpgradeActorsV2(ctx context.Context, sm *StateManager, cb ExecCallback, roo

epoch := ts.Height() - 1

info, err := store.Put(ctx, new(types.StateInfo))
info, err := store.Put(ctx, new(types.StateInfo0))
if err != nil {
return cid.Undef, xerrors.Errorf("failed to create new state info for actors v2: %w", err)
}
Expand All @@ -518,8 +517,7 @@ func UpgradeActorsV2(ctx context.Context, sm *StateManager, cb ExecCallback, roo
}

newRoot, err := store.Put(ctx, &types.StateRoot{
// TODO: ActorUpgrade: should be state-tree specific, not just the actors version.
Version: actors.Version2,
Version: types.StateTreeVersion1,
Actors: newHamtRoot,
Info: info,
})
Expand Down
16 changes: 8 additions & 8 deletions chain/types/cbor_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 14 additions & 3 deletions chain/types/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,25 @@ package types

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 {
// State root version. Versioned along with actors (for now).
Version uint64
// State tree version.
Version StateTreeVersion
// Actors tree. The structure depends on the state root version.
Actors cid.Cid
// Info. The structure depends on the state root version.
Info cid.Cid
}

// TODO: version this.
type StateInfo struct{}
type StateInfo0 struct{}
2 changes: 1 addition & 1 deletion extern/test-vectors
Submodule test-vectors updated 462 files
2 changes: 1 addition & 1 deletion gen/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func main() {
types.ExpTipSet{},
types.BeaconEntry{},
types.StateRoot{},
types.StateInfo{},
types.StateInfo0{},
)
if err != nil {
fmt.Println(err)
Expand Down
3 changes: 2 additions & 1 deletion lotuspond/front/src/chain/methods.json
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,8 @@
"CompactPartitions",
"CompactSectorNumbers",
"ConfirmUpdateWorkerKey",
"RepayDebt"
"RepayDebt",
"ChangeOwnerAddress"
],
"fil/2/storagepower": [
"Send",
Expand Down

0 comments on commit de3f411

Please sign in to comment.