Skip to content

Commit

Permalink
chain actors: codegen templates for all actors
Browse files Browse the repository at this point in the history
  • Loading branch information
magik6k committed Apr 27, 2021
1 parent 2f0d6b7 commit e17a6c4
Show file tree
Hide file tree
Showing 55 changed files with 2,661 additions and 275 deletions.
130 changes: 94 additions & 36 deletions chain/actors/agen/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,35 @@ import (
"fmt"
"golang.org/x/xerrors"
"io/ioutil"
"os"
"path/filepath"
"text/template"
)

var latestVersion = 4

var versions = []int{0, 2, 3, latestVersion}

var versionImports = map[int]string{
0: "/",
2: "/v2/",
3: "/v3/",
latestVersion: "/v4/",
}

var actors = map[string][]int{
"account": versions,
"cron": versions,
"init": versions,
"market": versions,
"miner": versions,
"multisig": versions,
"paych": versions,
"power": versions,
"reward": versions,
"verifreg": versions,
}

func main() {
if err := run(); err != nil {
fmt.Println(err)
Expand All @@ -17,45 +42,15 @@ func main() {
}

func run() error {
versions := []int{0, 2, 3, 4}

versionImports := map[int]string{
0: "/",
2: "/v2/",
3: "/v3/",
4: "/v4/",
}

actors := map[string][]int{
"account": versions,
}

for act, versions := range actors {
actDir := filepath.Join("chain/actors/builtin", act)

{
af, err := ioutil.ReadFile(filepath.Join(actDir, "state.go.template"))
if err != nil {
return xerrors.Errorf("loading state adapter template: %w", err)
}

for _, version := range versions {
tpl := template.Must(template.New("").Funcs(template.FuncMap{}).Parse(string(af)))

var b bytes.Buffer

err := tpl.Execute(&b, map[string]interface{}{
"v": version,
"import": versionImports[version],
})
if err != nil {
return err
}
if err := generateState(actDir); err != nil {
return err
}

if err := ioutil.WriteFile(filepath.Join(actDir, fmt.Sprintf("v%d.go", version)), b.Bytes(), 0666); err != nil {
return err
}
}
if err := generateMessages(actDir); err != nil {
return err
}

{
Expand All @@ -71,7 +66,8 @@ func run() error {
var b bytes.Buffer

err = tpl.Execute(&b, map[string]interface{}{
"versions": versions,
"versions": versions,
"latestVersion": latestVersion,
})
if err != nil {
return err
Expand All @@ -85,3 +81,65 @@ func run() error {

return nil
}

func generateState(actDir string) error {
af, err := ioutil.ReadFile(filepath.Join(actDir, "state.go.template"))
if err != nil {
if os.IsNotExist(err) {
return nil // skip
}

return xerrors.Errorf("loading state adapter template: %w", err)
}

for _, version := range versions {
tpl := template.Must(template.New("").Funcs(template.FuncMap{}).Parse(string(af)))

var b bytes.Buffer

err := tpl.Execute(&b, map[string]interface{}{
"v": version,
"import": versionImports[version],
})
if err != nil {
return err
}

if err := ioutil.WriteFile(filepath.Join(actDir, fmt.Sprintf("v%d.go", version)), b.Bytes(), 0666); err != nil {
return err
}
}

return nil
}

func generateMessages(actDir string) error {
af, err := ioutil.ReadFile(filepath.Join(actDir, "message.go.template"))
if err != nil {
if os.IsNotExist(err) {
return nil // skip
}

return xerrors.Errorf("loading state adapter template: %w", err)
}

for _, version := range versions {
tpl := template.Must(template.New("").Funcs(template.FuncMap{}).Parse(string(af)))

var b bytes.Buffer

err := tpl.Execute(&b, map[string]interface{}{
"v": version,
"import": versionImports[version],
})
if err != nil {
return err
}

if err := ioutil.WriteFile(filepath.Join(actDir, fmt.Sprintf("message%d.go", version)), b.Bytes(), 0666); err != nil {
return err
}
}

return nil
}
10 changes: 10 additions & 0 deletions chain/actors/builtin/cron/actor.go.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package cron

import (
builtin{{.latestVersion}} "github.com/filecoin-project/specs-actors{{import .latestVersion}}actors/builtin"
)

var (
Address = builtin{{.latestVersion}}.CronActorAddr
Methods = builtin{{.latestVersion}}.MethodsCron
)
56 changes: 56 additions & 0 deletions chain/actors/builtin/init/actor.go.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package init

import (
"golang.org/x/xerrors"

"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
"github.com/filecoin-project/go-state-types/cbor"
"github.com/ipfs/go-cid"

"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/chain/actors/builtin"
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/node/modules/dtypes"
{{range .versions}}
builtin{{.}} "github.com/filecoin-project/specs-actors{{import .}}actors/builtin"{{end}}
)

func init() {
{{range .versions}} builtin.RegisterActorState(builtin{{.}}.InitActorCodeID, func(store adt.Store, root cid.Cid) (cbor.Marshaler, error) {
return load{{.}}(store, root)
})
{{end}}}

var (
Address = builtin{{.latestVersion}}.InitActorAddr
Methods = builtin{{.latestVersion}}.MethodsInit
)

func Load(store adt.Store, act *types.Actor) (State, error) {
switch act.Code {
{{range .versions}} case builtin{{.}}.InitActorCodeID:
return load{{.}}(store, act.Head)
{{end}} }
return nil, xerrors.Errorf("unknown actor code %s", act.Code)
}

type State interface {
cbor.Marshaler

ResolveAddress(address address.Address) (address.Address, bool, error)
MapAddressToNewID(address address.Address) (address.Address, error)
NetworkName() (dtypes.NetworkName, error)

ForEachActor(func(id abi.ActorID, address address.Address) error) error

// Remove exists to support tooling that manipulates state for testing.
// It should not be used in production code, as init actor entries are
// immutable.
Remove(addrs ...address.Address) error

// Sets the network's name. This should only be used on upgrade/fork.
SetNetworkName(name string) error

addressMap() (adt.Map, error)
}
86 changes: 86 additions & 0 deletions chain/actors/builtin/init/state.go.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package init

import (
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/go-state-types/abi"
{{if (ge .v 3)}} builtin{{.v}} "github.com/filecoin-project/specs-actors{{.import}}actors/builtin"
{{end}} "github.com/ipfs/go-cid"
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"

"github.com/filecoin-project/lotus/chain/actors/adt"
"github.com/filecoin-project/lotus/node/modules/dtypes"

init{{.v}} "github.com/filecoin-project/specs-actors{{.import}}actors/builtin/init"
adt{{.v}} "github.com/filecoin-project/specs-actors{{.import}}actors/util/adt"
)

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
}

type state{{.v}} struct {
init{{.v}}.State
store adt.Store
}

func (s *state{{.v}}) ResolveAddress(address address.Address) (address.Address, bool, error) {
return s.State.ResolveAddress(s.store, address)
}

func (s *state{{.v}}) MapAddressToNewID(address address.Address) (address.Address, error) {
return s.State.MapAddressToNewID(s.store, address)
}

func (s *state{{.v}}) ForEachActor(cb func(id abi.ActorID, address address.Address) error) error {
addrs, err := adt{{.v}}.AsMap(s.store, s.State.AddressMap{{if (ge .v 3)}}, builtin{{.v}}.DefaultHamtBitwidth{{end}})
if err != nil {
return err
}
var actorID cbg.CborInt
return addrs.ForEach(&actorID, func(key string) error {
addr, err := address.NewFromBytes([]byte(key))
if err != nil {
return err
}
return cb(abi.ActorID(actorID), addr)
})
}

func (s *state{{.v}}) NetworkName() (dtypes.NetworkName, error) {
return dtypes.NetworkName(s.State.NetworkName), nil
}

func (s *state{{.v}}) SetNetworkName(name string) error {
s.State.NetworkName = name
return nil
}

func (s *state{{.v}}) Remove(addrs ...address.Address) (err error) {
m, err := adt{{.v}}.AsMap(s.store, s.State.AddressMap{{if (ge .v 3)}}, builtin{{.v}}.DefaultHamtBitwidth{{end}})
if err != nil {
return err
}
for _, addr := range addrs {
if err = m.Delete(abi.AddrKey(addr)); err != nil {
return xerrors.Errorf("failed to delete entry for address: %s; err: %w", addr, err)
}
}
amr, err := m.Root()
if err != nil {
return xerrors.Errorf("failed to get address map root: %w", err)
}
s.State.AddressMap = amr
return nil
}

func (s *state{{.v}}) addressMap() (adt.Map, error) {
return adt{{.v}}.AsMap(s.store, s.AddressMap{{if (ge .v 3)}}, builtin{{.v}}.DefaultHamtBitwidth{{end}})
}
Loading

0 comments on commit e17a6c4

Please sign in to comment.