feat: actors: Integrate datacap actor into lotus (#9348)
* Integrate datacap actor * Implement datacap actor in chain/builtin
This commit is contained in:
parent
ff994155df
commit
37be57610c
@ -25,7 +25,7 @@ func TestRegistration(t *testing.T) {
|
||||
require.True(t, found)
|
||||
require.True(t, manifestCid.Defined())
|
||||
|
||||
for _, key := range actors.GetBuiltinActorsKeys() {
|
||||
for _, key := range actors.GetBuiltinActorsKeys(actorstypes.Version8) {
|
||||
actorCid, found := actors.GetActorCodeID(actorstypes.Version8, key)
|
||||
require.True(t, found)
|
||||
name, version, found := actors.GetActorMetaByCode(actorCid)
|
||||
|
@ -314,7 +314,7 @@ func GetActorCodeIDs(av actorstypes.Version) (map[string]cid.Cid, error) {
|
||||
return cids, nil
|
||||
}
|
||||
|
||||
actorsKeys := GetBuiltinActorsKeys()
|
||||
actorsKeys := GetBuiltinActorsKeys(av)
|
||||
synthCids := make(map[string]cid.Cid)
|
||||
|
||||
for _, key := range actorsKeys {
|
||||
|
@ -27,6 +27,7 @@ var actors = map[string][]int{
|
||||
"system": lotusactors.Versions,
|
||||
"reward": lotusactors.Versions,
|
||||
"verifreg": lotusactors.Versions,
|
||||
"datacap": lotusactors.Versions[8:],
|
||||
}
|
||||
|
||||
func main() {
|
||||
@ -55,7 +56,7 @@ func generateAdapters() error {
|
||||
for act, versions := range actors {
|
||||
actDir := filepath.Join("chain/actors/builtin", act)
|
||||
|
||||
if err := generateState(actDir); err != nil {
|
||||
if err := generateState(actDir, versions); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -97,7 +98,7 @@ func generateAdapters() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func generateState(actDir string) error {
|
||||
func generateState(actDir string, versions []int) error {
|
||||
af, err := ioutil.ReadFile(filepath.Join(actDir, "state.go.template"))
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
@ -107,7 +108,7 @@ func generateState(actDir string) error {
|
||||
return xerrors.Errorf("loading state adapter template: %w", err)
|
||||
}
|
||||
|
||||
for _, version := range lotusactors.Versions {
|
||||
for _, version := range versions {
|
||||
tpl := template.Must(template.New("").Funcs(template.FuncMap{}).Parse(string(af)))
|
||||
|
||||
var b bytes.Buffer
|
||||
|
55
chain/actors/builtin/datacap/actor.go.template
Normal file
55
chain/actors/builtin/datacap/actor.go.template
Normal file
@ -0,0 +1,55 @@
|
||||
package datacap
|
||||
|
||||
import (
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
actorstypes "github.com/filecoin-project/go-state-types/actors"
|
||||
builtin{{.latestVersion}} "github.com/filecoin-project/go-state-types/builtin"
|
||||
"github.com/filecoin-project/go-state-types/cbor"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
"github.com/filecoin-project/lotus/chain/actors/adt"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
|
||||
var (
|
||||
Address = builtin9.DatacapActorAddr
|
||||
Methods = builtin9.MethodsDatacap
|
||||
)
|
||||
|
||||
func Load(store adt.Store, act *types.Actor) (State, error) {
|
||||
if name, av, ok := actors.GetActorMetaByCode(act.Code); ok {
|
||||
if name != actors.DatacapKey {
|
||||
return nil, xerrors.Errorf("actor code is not datacap: %s", name)
|
||||
}
|
||||
|
||||
switch av {
|
||||
{{range .versions}}
|
||||
case actorstypes.Version{{.}}:
|
||||
return load{{.}}(store, act.Head)
|
||||
{{end}}
|
||||
}
|
||||
}
|
||||
|
||||
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
|
||||
}
|
||||
|
||||
func MakeState(store adt.Store, av actorstypes.Version, governor address.Address, bitwidth uint64) (State, error) {
|
||||
switch av {
|
||||
{{range .versions}}
|
||||
case actorstypes.Version{{.}}:
|
||||
return make{{.}}(store, governor, bitwidth)
|
||||
|
||||
default: return nil, xerrors.Errorf("datacap actor only valid for actors v9 and above, got %d", av)
|
||||
{{end}}
|
||||
}
|
||||
}
|
||||
|
||||
type State interface {
|
||||
cbor.Marshaler
|
||||
|
||||
Governor() (address.Address, error)
|
||||
GetState() interface{}
|
||||
}
|
55
chain/actors/builtin/datacap/datacap.go
Normal file
55
chain/actors/builtin/datacap/datacap.go
Normal file
@ -0,0 +1,55 @@
|
||||
package datacap
|
||||
|
||||
import (
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
actorstypes "github.com/filecoin-project/go-state-types/actors"
|
||||
builtin9 "github.com/filecoin-project/go-state-types/builtin"
|
||||
"github.com/filecoin-project/go-state-types/cbor"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
"github.com/filecoin-project/lotus/chain/actors/adt"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
)
|
||||
|
||||
var (
|
||||
Address = builtin9.DatacapActorAddr
|
||||
Methods = builtin9.MethodsDatacap
|
||||
)
|
||||
|
||||
func Load(store adt.Store, act *types.Actor) (State, error) {
|
||||
if name, av, ok := actors.GetActorMetaByCode(act.Code); ok {
|
||||
if name != actors.DatacapKey {
|
||||
return nil, xerrors.Errorf("actor code is not datacap: %s", name)
|
||||
}
|
||||
|
||||
switch av {
|
||||
|
||||
case actorstypes.Version9:
|
||||
return load9(store, act.Head)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
|
||||
}
|
||||
|
||||
func MakeState(store adt.Store, av actorstypes.Version, governor address.Address, bitwidth uint64) (State, error) {
|
||||
switch av {
|
||||
|
||||
case actorstypes.Version9:
|
||||
return make9(store, governor, bitwidth)
|
||||
|
||||
default:
|
||||
return nil, xerrors.Errorf("datacap actor only valid for actors v9 and above, got %d", av)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
type State interface {
|
||||
cbor.Marshaler
|
||||
|
||||
Governor() (address.Address, error)
|
||||
GetState() interface{}
|
||||
}
|
50
chain/actors/builtin/datacap/state.go.template
Normal file
50
chain/actors/builtin/datacap/state.go.template
Normal file
@ -0,0 +1,50 @@
|
||||
package datacap
|
||||
|
||||
import (
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/ipfs/go-cid"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
"github.com/filecoin-project/lotus/chain/actors/adt"
|
||||
|
||||
datacap{{.v}} "github.com/filecoin-project/go-state-types/builtin{{.import}}datacap"
|
||||
adt{{.v}} "github.com/filecoin-project/go-state-types/builtin{{.import}}util/adt"
|
||||
builtin{{.v}} "github.com/filecoin-project/go-state-types/builtin"
|
||||
)
|
||||
|
||||
var _ State = (*state{{.v}})(nil)
|
||||
|
||||
func load{{.v}}(store adt.Store, root cid.Cid) (State, error) {
|
||||
out := state{{.v}}{store: store}
|
||||
err := store.Get(store.Context(), root, &out)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &out, nil
|
||||
}
|
||||
|
||||
func make{{.v}}(store adt.Store, governor address.Address, bitwidth uint64) (State, error) {
|
||||
out := state{{.v}}{store: store}
|
||||
s, err := datacap{{.v}}.ConstructState(store, governor, bitwidth)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out.State = *s
|
||||
|
||||
return &out, nil
|
||||
}
|
||||
|
||||
type state{{.v}} struct {
|
||||
datacap{{.v}}.State
|
||||
store adt.Store
|
||||
}
|
||||
|
||||
func (s *state{{.v}}) Governor() (address.Address, error) {
|
||||
return s.State.Governor, nil
|
||||
}
|
||||
|
||||
func (s *state{{.v}}) GetState() interface{} {
|
||||
return &s.State
|
||||
}
|
46
chain/actors/builtin/datacap/v9.go
Normal file
46
chain/actors/builtin/datacap/v9.go
Normal file
@ -0,0 +1,46 @@
|
||||
package datacap
|
||||
|
||||
import (
|
||||
"github.com/ipfs/go-cid"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
datacap9 "github.com/filecoin-project/go-state-types/builtin/v9/datacap"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/actors/adt"
|
||||
)
|
||||
|
||||
var _ State = (*state9)(nil)
|
||||
|
||||
func load9(store adt.Store, root cid.Cid) (State, error) {
|
||||
out := state9{store: store}
|
||||
err := store.Get(store.Context(), root, &out)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &out, nil
|
||||
}
|
||||
|
||||
func make9(store adt.Store, governor address.Address, bitwidth uint64) (State, error) {
|
||||
out := state9{store: store}
|
||||
s, err := datacap9.ConstructState(store, governor, bitwidth)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out.State = *s
|
||||
|
||||
return &out, nil
|
||||
}
|
||||
|
||||
type state9 struct {
|
||||
datacap9.State
|
||||
store adt.Store
|
||||
}
|
||||
|
||||
func (s *state9) Governor() (address.Address, error) {
|
||||
return s.State.Governor, nil
|
||||
}
|
||||
|
||||
func (s *state9) GetState() interface{} {
|
||||
return &s.State
|
||||
}
|
@ -31,10 +31,11 @@ const (
|
||||
RewardKey = "reward"
|
||||
SystemKey = "system"
|
||||
VerifregKey = "verifiedregistry"
|
||||
DatacapKey = "datacap"
|
||||
)
|
||||
|
||||
func GetBuiltinActorsKeys() []string {
|
||||
return []string{
|
||||
func GetBuiltinActorsKeys(av actorstypes.Version) []string {
|
||||
keys := []string{
|
||||
AccountKey,
|
||||
CronKey,
|
||||
InitKey,
|
||||
@ -47,6 +48,10 @@ func GetBuiltinActorsKeys() []string {
|
||||
SystemKey,
|
||||
VerifregKey,
|
||||
}
|
||||
if av >= 9 {
|
||||
keys = append(keys, DatacapKey)
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
||||
var (
|
||||
@ -58,7 +63,7 @@ type actorEntry struct {
|
||||
version actorstypes.Version
|
||||
}
|
||||
|
||||
// ClearManifest clears all known manifests. This is usually used in tests that need to switch networks.
|
||||
// ClearManifests clears all known manifests. This is usually used in tests that need to switch networks.
|
||||
func ClearManifests() {
|
||||
manifestMx.Lock()
|
||||
defer manifestMx.Unlock()
|
||||
@ -103,12 +108,14 @@ func ReadManifest(ctx context.Context, store cbor.IpldStore, mfCid cid.Cid) (map
|
||||
return nil, xerrors.Errorf("error loading manifest (cid: %s): %w", mfCid, err)
|
||||
}
|
||||
|
||||
actorKeys := GetBuiltinActorsKeys() // TODO: we should be able to enumerate manifests directly.
|
||||
metadata := make(map[string]cid.Cid, len(actorKeys))
|
||||
for _, name := range actorKeys {
|
||||
if c, ok := mf.Get(name); ok {
|
||||
metadata[name] = c
|
||||
}
|
||||
var manifestData manifest.ManifestData
|
||||
if err := store.Get(ctx, mf.Data, &manifestData); err != nil {
|
||||
return nil, xerrors.Errorf("error loading manifest data: %w", err)
|
||||
}
|
||||
|
||||
metadata := make(map[string]cid.Cid)
|
||||
for _, entry := range manifestData.Entries {
|
||||
metadata[entry.Name] = entry.Code
|
||||
}
|
||||
|
||||
return metadata, nil
|
||||
|
@ -1575,7 +1575,7 @@ func upgradeActorsV9Common(
|
||||
// return LiteMigration(ctx, bstore, newActorsManifestCid, root, av, types.StateTreeVersion4, newStateTreeVersion)
|
||||
//}
|
||||
|
||||
func LiteMigration(ctx context.Context, bstore blockstore.Blockstore, newActorsManifestCid cid.Cid, root cid.Cid, av actorstypes.Version, oldStateTreeVersion types.StateTreeVersion, newStateTreeVersion types.StateTreeVersion) (cid.Cid, error) {
|
||||
func LiteMigration(ctx context.Context, bstore blockstore.Blockstore, newActorsManifestCid cid.Cid, root cid.Cid, oldAv actorstypes.Version, newAv actorstypes.Version, oldStateTreeVersion types.StateTreeVersion, newStateTreeVersion types.StateTreeVersion) (cid.Cid, error) {
|
||||
buf := blockstore.NewTieredBstore(bstore, blockstore.NewMemorySync())
|
||||
store := store.ActorStore(ctx, buf)
|
||||
adtStore := gstStore.WrapStore(ctx, store)
|
||||
@ -1615,10 +1615,10 @@ func LiteMigration(ctx context.Context, bstore blockstore.Blockstore, newActorsM
|
||||
return cid.Undef, xerrors.Errorf("error loading new manifest data: %w", err)
|
||||
}
|
||||
|
||||
if len(oldManifestData.Entries) != len(actors.GetBuiltinActorsKeys()) {
|
||||
if len(oldManifestData.Entries) != len(actors.GetBuiltinActorsKeys(oldAv)) {
|
||||
return cid.Undef, xerrors.Errorf("incomplete old manifest with %d code CIDs", len(oldManifestData.Entries))
|
||||
}
|
||||
if len(newManifestData.Entries) != len(actors.GetBuiltinActorsKeys()) {
|
||||
if len(newManifestData.Entries) != len(actors.GetBuiltinActorsKeys(newAv)) {
|
||||
return cid.Undef, xerrors.Errorf("incomplete new manifest with %d code CIDs", len(newManifestData.Entries))
|
||||
}
|
||||
|
||||
@ -1650,7 +1650,7 @@ func LiteMigration(ctx context.Context, bstore blockstore.Blockstore, newActorsM
|
||||
}
|
||||
var head cid.Cid
|
||||
if addr == system.Address {
|
||||
newSystemState, err := system.MakeState(store, av, newManifest.Data)
|
||||
newSystemState, err := system.MakeState(store, newAv, newManifest.Data)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("could not make system actor state: %w", err)
|
||||
}
|
||||
|
@ -384,10 +384,15 @@ func NewDebugFVM(ctx context.Context, opts *VMOpts) (*FVM, error) {
|
||||
return xerrors.Errorf("loading debug manifest: %w", err)
|
||||
}
|
||||
|
||||
av, err := actorstypes.VersionForNetwork(opts.NetworkVersion)
|
||||
if err != nil {
|
||||
return xerrors.Errorf("getting actors version: %w", err)
|
||||
}
|
||||
|
||||
// create actor redirect mapping
|
||||
actorRedirect := make(map[cid.Cid]cid.Cid)
|
||||
for _, key := range actors.GetBuiltinActorsKeys() {
|
||||
from, ok := actors.GetActorCodeID(actorstypes.Version8, key)
|
||||
for _, key := range actors.GetBuiltinActorsKeys(av) {
|
||||
from, ok := actors.GetActorCodeID(av, key)
|
||||
if !ok {
|
||||
log.Warnf("actor missing in the from manifest %s", key)
|
||||
continue
|
||||
|
2
go.mod
2
go.mod
@ -42,7 +42,7 @@ require (
|
||||
github.com/filecoin-project/go-legs v0.4.4
|
||||
github.com/filecoin-project/go-padreader v0.0.1
|
||||
github.com/filecoin-project/go-paramfetch v0.0.4
|
||||
github.com/filecoin-project/go-state-types v0.1.12-beta.0.20220920181425-d683559e386b
|
||||
github.com/filecoin-project/go-state-types v0.1.12-beta.0.20220921193302-60676bda3cb5
|
||||
github.com/filecoin-project/go-statemachine v1.0.2
|
||||
github.com/filecoin-project/go-statestore v0.2.0
|
||||
github.com/filecoin-project/go-storedcounter v0.1.0
|
||||
|
4
go.sum
4
go.sum
@ -343,8 +343,8 @@ github.com/filecoin-project/go-state-types v0.1.0/go.mod h1:ezYnPf0bNkTsDibL/psS
|
||||
github.com/filecoin-project/go-state-types v0.1.6/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q=
|
||||
github.com/filecoin-project/go-state-types v0.1.8/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q=
|
||||
github.com/filecoin-project/go-state-types v0.1.10/go.mod h1:UwGVoMsULoCK+bWjEdd/xLCvLAQFBC7EDT477SKml+Q=
|
||||
github.com/filecoin-project/go-state-types v0.1.12-beta.0.20220920181425-d683559e386b h1:s4F3e3EBo56j+4xmrzmoAIvtgvDwLn4nsIf5bqcU0Qg=
|
||||
github.com/filecoin-project/go-state-types v0.1.12-beta.0.20220920181425-d683559e386b/go.mod h1:n/kujdC9JphvYTrmaD1+vJpvDPy/DwzckoMzP0nBKWI=
|
||||
github.com/filecoin-project/go-state-types v0.1.12-beta.0.20220921193302-60676bda3cb5 h1:5FCdArFQ/nzsv2vBJ7ibLnocTf+pnnTVxcF0Ohe97O0=
|
||||
github.com/filecoin-project/go-state-types v0.1.12-beta.0.20220921193302-60676bda3cb5/go.mod h1:n/kujdC9JphvYTrmaD1+vJpvDPy/DwzckoMzP0nBKWI=
|
||||
github.com/filecoin-project/go-statemachine v0.0.0-20200925024713-05bd7c71fbfe/go.mod h1:FGwQgZAt2Gh5mjlwJUlVB62JeYdo+if0xWxSEfBD9ig=
|
||||
github.com/filecoin-project/go-statemachine v1.0.2 h1:421SSWBk8GIoCoWYYTE/d+qCWccgmRH0uXotXRDjUbc=
|
||||
github.com/filecoin-project/go-statemachine v1.0.2/go.mod h1:jZdXXiHa61n4NmgWFG4w8tnqgvZVHYbJ3yW7+y8bF54=
|
||||
|
@ -19,6 +19,7 @@ import (
|
||||
"github.com/filecoin-project/specs-actors/v8/actors/util/adt"
|
||||
|
||||
"github.com/filecoin-project/lotus/blockstore"
|
||||
"github.com/filecoin-project/lotus/chain/actors"
|
||||
"github.com/filecoin-project/lotus/chain/actors/builtin/system"
|
||||
"github.com/filecoin-project/lotus/chain/consensus/filcns"
|
||||
"github.com/filecoin-project/lotus/chain/state"
|
||||
@ -51,7 +52,7 @@ func TestLiteMigration(t *testing.T) {
|
||||
|
||||
oldManifestData, err := stmgr.GetManifestData(ctx, oldStateTree)
|
||||
require.NoError(t, err)
|
||||
newManifestCid := makeTestManifest(t, ctxStore)
|
||||
newManifestCid := makeTestManifest(t, ctxStore, actorstypes.Version9)
|
||||
// Use the Cid we generated to get the new manifest instead of loading it from the store, so as to confirm it's in the store
|
||||
var newManifest manifest.Manifest
|
||||
require.NoError(t, ctxStore.Get(ctx, newManifestCid, &newManifest), "error getting new manifest")
|
||||
@ -59,7 +60,7 @@ func TestLiteMigration(t *testing.T) {
|
||||
// populate the entries field of the manifest
|
||||
require.NoError(t, newManifest.Load(ctx, ctxStore), "error loading new manifest")
|
||||
|
||||
newStateRoot, err := filcns.LiteMigration(ctx, bs, newManifestCid, stateRoot, actorstypes.Version8, types.StateTreeVersion4, types.StateTreeVersion4)
|
||||
newStateRoot, err := filcns.LiteMigration(ctx, bs, newManifestCid, stateRoot, actorstypes.Version8, actorstypes.Version9, types.StateTreeVersion4, types.StateTreeVersion4)
|
||||
require.NoError(t, err)
|
||||
|
||||
newStateTree, err := state.LoadStateTree(ctxStore, newStateRoot)
|
||||
@ -90,11 +91,11 @@ func TestLiteMigration(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func makeTestManifest(t *testing.T, ctxStore adt.Store) cid.Cid {
|
||||
func makeTestManifest(t *testing.T, ctxStore adt.Store, av actorstypes.Version) cid.Cid {
|
||||
builder := cid.V1Builder{Codec: cid.Raw, MhType: mh.IDENTITY}
|
||||
|
||||
manifestData := manifest.ManifestData{}
|
||||
for _, name := range []string{"system", "init", "cron", "account", "storagepower", "storageminer", "storagemarket", "paymentchannel", "multisig", "reward", "verifiedregistry"} {
|
||||
for _, name := range actors.GetBuiltinActorsKeys(av) {
|
||||
codeCid, err := builder.Sum([]byte(fmt.Sprintf("fil/8/%s", name)))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
Loading…
Reference in New Issue
Block a user