state tree version 5 scaffolding

This commit is contained in:
vyzo 2022-11-09 10:44:51 +02:00
parent 046ca3fbb8
commit 674d127701
3 changed files with 130 additions and 29 deletions

View File

@ -14,6 +14,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"
builtin_types "github.com/filecoin-project/go-state-types/builtin"
"github.com/filecoin-project/go-state-types/network" "github.com/filecoin-project/go-state-types/network"
states0 "github.com/filecoin-project/specs-actors/actors/states" states0 "github.com/filecoin-project/specs-actors/actors/states"
states2 "github.com/filecoin-project/specs-actors/v2/actors/states" states2 "github.com/filecoin-project/specs-actors/v2/actors/states"
@ -168,7 +169,7 @@ func NewStateTree(cst cbor.IpldStore, ver types.StateTreeVersion) (*StateTree, e
switch ver { switch ver {
case types.StateTreeVersion0: case types.StateTreeVersion0:
// info is undefined // info is undefined
case types.StateTreeVersion1, types.StateTreeVersion2, types.StateTreeVersion3, types.StateTreeVersion4: case types.StateTreeVersion1, types.StateTreeVersion2, types.StateTreeVersion3, types.StateTreeVersion4, types.StateTreeVersion5:
var err error var err error
info, err = cst.Put(context.TODO(), new(types.StateInfo0)) info, err = cst.Put(context.TODO(), new(types.StateInfo0))
if err != nil { if err != nil {
@ -211,6 +212,13 @@ func NewStateTree(cst cbor.IpldStore, ver types.StateTreeVersion) (*StateTree, e
return nil, xerrors.Errorf("failed to create state tree: %w", err) return nil, xerrors.Errorf("failed to create state tree: %w", err)
} }
hamt = tree.Map hamt = tree.Map
case types.StateTreeVersion5:
tree, err := builtin_types.NewTree(store)
if err != nil {
return nil, xerrors.Errorf("failed to create state tree: %w", err)
}
hamt = tree.Map
default: default:
return nil, xerrors.Errorf("unsupported state tree version: %d", ver) return nil, xerrors.Errorf("unsupported state tree version: %d", ver)
} }
@ -272,6 +280,13 @@ func LoadStateTree(cst cbor.IpldStore, c cid.Cid) (*StateTree, error) {
if tree != nil { if tree != nil {
hamt = tree.Map hamt = tree.Map
} }
case types.StateTreeVersion5:
var tree *builtin_types.ActorTree
tree, err = builtin_types.LoadTree(store, root.Actors)
if tree != nil {
hamt = tree.Map
}
default: default:
return nil, xerrors.Errorf("unsupported state tree version: %d", root.Version) return nil, xerrors.Errorf("unsupported state tree version: %d", root.Version)
} }
@ -370,7 +385,17 @@ func (st *StateTree) GetActor(addr address.Address) (*types.Actor, error) {
} }
var act types.Actor var act types.Actor
if found, err := st.root.Get(abi.AddrKey(addr), &act); err != nil { var found bool
if st.version <= types.StateTreeVersion4 {
var act4 types.ActorV4
found, err = st.root.Get(abi.AddrKey(addr), &act4)
if found {
act = *types.AsActorV5(&act4)
}
} else {
found, err = st.root.Get(abi.AddrKey(addr), &act)
}
if err != nil {
return nil, xerrors.Errorf("hamt find failed: %w", err) return nil, xerrors.Errorf("hamt find failed: %w", err)
} else if !found { } else if !found {
return nil, types.ErrActorNotFound return nil, types.ErrActorNotFound
@ -419,8 +444,15 @@ func (st *StateTree) Flush(ctx context.Context) (cid.Cid, error) {
return cid.Undef, err return cid.Undef, err
} }
} else { } else {
if err := st.root.Put(abi.AddrKey(addr), &sto.Act); err != nil { if st.version <= types.StateTreeVersion4 {
return cid.Undef, err act4 := types.AsActorV4(&sto.Act)
if err := st.root.Put(abi.AddrKey(addr), act4); err != nil {
return cid.Undef, err
}
} else {
if err := st.root.Put(abi.AddrKey(addr), &sto.Act); err != nil {
return cid.Undef, err
}
} }
} }
} }
@ -528,22 +560,41 @@ func (st *StateTree) ForEach(f func(address.Address, *types.Actor) error) error
} }
// Now walk through the saved actors. // Now walk through the saved actors.
var act types.Actor if st.version <= types.StateTreeVersion4 {
return st.root.ForEach(&act, func(k string) error { var act types.ActorV4
act := act // copy return st.root.ForEach(&act, func(k string) error {
addr, err := address.NewFromBytes([]byte(k)) act := act // copy
if err != nil { addr, err := address.NewFromBytes([]byte(k))
return xerrors.Errorf("invalid address (%x) found in state tree key: %w", []byte(k), err) if err != nil {
} return xerrors.Errorf("invalid address (%x) found in state tree key: %w", []byte(k), err)
}
// no need to record anything here, there are no duplicates in the actors HAMT // no need to record anything here, there are no duplicates in the actors HAMT
// iself. // iself.
if _, ok := seen[addr]; ok { if _, ok := seen[addr]; ok {
return nil return nil
} }
return f(addr, &act) return f(addr, types.AsActorV5(&act))
}) })
} else {
var act types.Actor
return st.root.ForEach(&act, func(k string) error {
act := act // copy
addr, err := address.NewFromBytes([]byte(k))
if err != nil {
return xerrors.Errorf("invalid address (%x) found in state tree key: %w", []byte(k), err)
}
// no need to record anything here, there are no duplicates in the actors HAMT
// iself.
if _, ok := seen[addr]; ok {
return nil
}
return f(addr, &act)
})
}
} }
// Version returns the version of the StateTree data structure in use. // Version returns the version of the StateTree data structure in use.
@ -563,8 +614,6 @@ func Diff(ctx context.Context, oldTree, newTree *StateTree) (map[string]types.Ac
case <-ctx.Done(): case <-ctx.Done():
return ctx.Err() return ctx.Err()
default: default:
var act types.Actor
addr, err := address.NewFromBytes([]byte(k)) addr, err := address.NewFromBytes([]byte(k))
if err != nil { if err != nil {
return xerrors.Errorf("address in state tree was not valid: %w", err) return xerrors.Errorf("address in state tree was not valid: %w", err)
@ -579,16 +628,33 @@ func Diff(ctx context.Context, oldTree, newTree *StateTree) (map[string]types.Ac
return nil // not changed return nil // not changed
} }
buf.Reset(ncval.Raw) if newTree.version <= types.StateTreeVersion4 {
err = act.UnmarshalCBOR(buf) var act types.ActorV4
buf.Reset(nil)
if err != nil { buf.Reset(ncval.Raw)
return err err = act.UnmarshalCBOR(buf)
buf.Reset(nil)
if err != nil {
return err
}
out[addr.String()] = *types.AsActorV5(&act)
} else {
var act types.Actor
buf.Reset(ncval.Raw)
err = act.UnmarshalCBOR(buf)
buf.Reset(nil)
if err != nil {
return err
}
out[addr.String()] = act
} }
out[addr.String()] = act
return nil return nil
} }
}); err != nil { }); err != nil {

View File

@ -4,14 +4,48 @@ import (
"errors" "errors"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
"github.com/filecoin-project/go-address"
) )
var ErrActorNotFound = errors.New("actor not found") var ErrActorNotFound = errors.New("actor not found")
type Actor struct { // Actor State for state tree version up to 4
type ActorV4 struct {
// Identifies the type of actor (string coded as a CID), see `chain/actors/actors.go`. // Identifies the type of actor (string coded as a CID), see `chain/actors/actors.go`.
Code cid.Cid Code cid.Cid
Head cid.Cid Head cid.Cid
Nonce uint64 Nonce uint64
Balance BigInt Balance BigInt
} }
// Actor State for state tree version 5
type ActorV5 struct {
// Identifies the type of actor (string coded as a CID), see `chain/actors/actors.go`.
Code cid.Cid
Head cid.Cid
Nonce uint64
Balance BigInt
// Predictable Address
Address *address.Address
}
type Actor = ActorV5
func AsActorV4(a *ActorV5) *ActorV4 {
return &ActorV4{
Code: a.Code,
Head: a.Head,
Nonce: a.Nonce,
Balance: a.Balance,
}
}
func AsActorV5(a *ActorV4) *ActorV5 {
return &ActorV5{
Code: a.Code,
Head: a.Head,
Nonce: a.Nonce,
Balance: a.Balance,
}
}

View File

@ -26,7 +26,8 @@ func main() {
types.Message{}, types.Message{},
types.SignedMessage{}, types.SignedMessage{},
types.MsgMeta{}, types.MsgMeta{},
types.Actor{}, types.ActorV4{},
types.ActorV5{},
types.MessageReceipt{}, types.MessageReceipt{},
types.BlockMsg{}, types.BlockMsg{},
types.ExpTipSet{}, types.ExpTipSet{},