Skip to content

Commit

Permalink
cross-version state tree diff
Browse files Browse the repository at this point in the history
  • Loading branch information
Stebalien committed Sep 21, 2020
1 parent 4cf0c10 commit 26e68a7
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 52 deletions.
53 changes: 49 additions & 4 deletions chain/state/statetree.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package state

import (
"bytes"
"context"
"fmt"

Expand All @@ -14,6 +15,7 @@ import (
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/lotus/chain/actors/builtin"
init_ "github.com/filecoin-project/lotus/chain/actors/builtin/init"
cbg "github.com/whyrusleeping/cbor-gen"

"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/types"
Expand All @@ -24,7 +26,7 @@ var log = logging.Logger("statetree")
// StateTree stores actors state by their ID.
type StateTree struct {
root adt.Map
version builtin.Version // TODO
version types.StateVersion
info cid.Cid
Store cbor.IpldStore

Expand Down Expand Up @@ -118,15 +120,17 @@ func (ss *stateSnaps) deleteActor(addr address.Address) {
ss.layers[len(ss.layers)-1].actors[addr] = streeOp{Delete: true}
}

func NewStateTree(cst cbor.IpldStore, version builtin.Version) (*StateTree, error) {
func NewStateTree(cst cbor.IpldStore, version types.StateVersion) (*StateTree, error) {
var info cid.Cid
var mapVersion builtin.Version
switch version {
case builtin.Version0:
case types.StateVersion0:
mapVersion = builtin.Version0
// info is undefined
default:
return nil, xerrors.Errorf("unsupported state tree version: %d", version)
}
root, err := adt.NewMap(adt.WrapStore(context.TODO(), cst), version)
root, err := adt.NewMap(adt.WrapStore(context.TODO(), cst), mapVersion)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -391,3 +395,44 @@ func (st *StateTree) ForEach(f func(address.Address, *types.Actor) error) error
return f(addr, &act)
})
}

func Diff(oldTree, newTree *StateTree) (map[string]types.Actor, error) {
out := map[string]types.Actor{}

var (
ncval, ocval cbg.Deferred
buf = bytes.NewReader(nil)
)
if err := newTree.root.ForEach(&ncval, func(k string) error {
var act types.Actor

addr, err := address.NewFromBytes([]byte(k))
if err != nil {
return xerrors.Errorf("address in state tree was not valid: %w", err)
}

found, err := oldTree.root.Get(abi.AddrKey(addr), &ocval)
if err != nil {
return err
}

if found && bytes.Equal(ocval.Raw, ncval.Raw) {
return nil // not changed
}

buf.Reset(ncval.Raw)
err = act.UnmarshalCBOR(buf)
buf.Reset(nil)

if err != nil {
return err
}

out[addr.String()] = act

return nil
}); err != nil {
return nil, err
}
return out, nil
}
8 changes: 7 additions & 1 deletion chain/types/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import "github.com/ipfs/go-cid"

type StateRoot struct {
// State root version. Versioned along with actors (for now).
Version uint64
Version StateVersion
// Actors tree. The structure depends on the state root version.
Actors cid.Cid
// Info. The structure depends on the state root version.
Expand All @@ -13,3 +13,9 @@ type StateRoot struct {

// TODO: version this.
type StateInfo struct{}

type StateVersion uint64

type (
StateVersion0 StateVersion = iota
)
53 changes: 6 additions & 47 deletions node/impl/full/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import (

cid "github.com/ipfs/go-cid"
cbor "github.com/ipfs/go-ipld-cbor"
cbg "github.com/whyrusleeping/cbor-gen"
"go.uber.org/fx"
"golang.org/x/xerrors"

Expand All @@ -27,7 +26,6 @@ import (
"github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper"
"github.com/filecoin-project/specs-actors/actors/builtin"
miner0 "github.com/filecoin-project/specs-actors/actors/builtin/miner"
"github.com/filecoin-project/specs-actors/actors/util/adt"

"github.com/filecoin-project/lotus/api"
"github.com/filecoin-project/lotus/chain/actors/builtin/market"
Expand Down Expand Up @@ -618,58 +616,19 @@ func (a *StateAPI) StateMarketStorageDeal(ctx context.Context, dealId abi.DealID
}

func (a *StateAPI) StateChangedActors(ctx context.Context, old cid.Cid, new cid.Cid) (map[string]types.Actor, error) {
store := adt.WrapStore(ctx, cbor.NewCborStore(a.Chain.Blockstore()))
store := a.Chain.Store(ctx)

nh, err := adt.AsMap(store, new)
oldTree, err := state.LoadStateTree(store, old)
if err != nil {
return nil, err
return nil, xerrors.Errorf("failed to load old state tree: %w", err)
}

oh, err := adt.AsMap(store, old)
newTree, err := state.LoadStateTree(store, new)
if err != nil {
return nil, err
return nil, xerrors.Errorf("failed to load new state tree: %w", err)
}

out := map[string]types.Actor{}

var (
ncval, ocval cbg.Deferred
buf = bytes.NewReader(nil)
)
err = nh.ForEach(&ncval, func(k string) error {
var act types.Actor

addr, err := address.NewFromBytes([]byte(k))
if err != nil {
return xerrors.Errorf("address in state tree was not valid: %w", err)
}

found, err := oh.Get(abi.AddrKey(addr), &ocval)
if err != nil {
return err
}

if found && bytes.Equal(ocval.Raw, ncval.Raw) {
return nil // not changed
}

buf.Reset(ncval.Raw)
err = act.UnmarshalCBOR(buf)
buf.Reset(nil)

if err != nil {
return err
}

out[addr.String()] = act

return nil
})
if err != nil {
return nil, err
}

return out, nil
state.Diff(oldTree, newTree)
}

func (a *StateAPI) StateMinerSectorCount(ctx context.Context, addr address.Address, tsk types.TipSetKey) (api.MinerSectors, error) {
Expand Down

0 comments on commit 26e68a7

Please sign in to comment.