diff --git a/core/types/block.go b/core/types/block.go index 5272d4c2297d..9cf53db28a46 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -60,7 +60,8 @@ func (n *BlockNonce) UnmarshalText(input []byte) error { } //go:generate go run github.com/fjl/gencodec -type Header -field-override headerMarshaling -out gen_header_json.go -//go:generate go run ../../rlp/rlpgen -type Header -internal_methods -out gen_header_rlp.go +//go:generate go run ../../rlp/rlpgen -type Header -out gen_header_rlp.go +//go:generate go run ../../libevm/cmd/internalise -file gen_header_rlp.go Header.EncodeRLP // Header represents a block header in the Ethereum blockchain. type Header struct { diff --git a/libevm/cmd/internalise/main.go b/libevm/cmd/internalise/main.go new file mode 100644 index 000000000000..5bb1b928ce97 --- /dev/null +++ b/libevm/cmd/internalise/main.go @@ -0,0 +1,117 @@ +// Copyright 2024 the libevm authors. +// +// The libevm additions to go-ethereum are free software: you can redistribute +// them and/or modify them under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, +// or (at your option) any later version. +// +// The libevm additions are distributed in the hope that they will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser +// General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see +// . + +// The internalise command modifies Go files in place, making exported methods +// internal. +// +// Usage: +// +// internalise -file . [. [...]] +// +// For example, with file foo.go containing declarations: +// +// func (f *Foo) Bar() { ... } +// +// func (Foo) Baz() { ... } +// +// running +// +// internalise -file foo.go Foo.Bar Foo.Baz +// +// results in +// +// func (f *Foo) bar() { ... } +// +// func (Foo) baz() { ... } +package main + +import ( + "flag" + "fmt" + "go/ast" + "go/format" + "go/parser" + "go/token" + "os" + "strings" +) + +func main() { + file := flag.String("file", "", "File to modify") + flag.Parse() + + if err := run(*file, flag.Args()...); err != nil { + fmt.Fprint(os.Stderr, err) + os.Exit(1) + } +} + +func run(fileName string, args ...string) error { + methods := make(map[string]map[string]struct{}) + for _, a := range args { + a = strings.TrimPrefix(strings.TrimSpace(a), "*") + parts := strings.Split(a, ".") + if len(parts) != 2 { + return fmt.Errorf("invalid method identifier %q", a) + } + typ, fn := parts[0], parts[1] + if _, ok := methods[typ]; !ok { + methods[typ] = make(map[string]struct{}) + } + methods[typ][fn] = struct{}{} + } + + fset := token.NewFileSet() + mode := parser.SkipObjectResolution | parser.ParseComments + parsed, err := parser.ParseFile(fset, fileName, nil, mode) + if err != nil { + return fmt.Errorf("parser.ParseFile(%q): %v", fileName, err) + } + + for _, d := range parsed.Decls { + fn, ok := d.(*ast.FuncDecl) + if !ok || fn.Recv.NumFields() != 1 { + continue + } + + var typ string + switch t := fn.Recv.List[0].Type.(type) { + case *ast.Ident: + typ = t.Name + case *ast.StarExpr: + typ = t.X.(*ast.Ident).Name //nolint:forcetypeassert // Invariant of valid Go method + } + + name := &fn.Name.Name + if _, ok := methods[typ][*name]; !ok { + continue + } + if n := []rune(*name); n[0] >= 'A' && n[0] <= 'Z' { + n[0] += 'a' - 'A' + *name = string(n) + } + } + + // Since we're not creating, the zero perm/mode is ignored. + f, err := os.OpenFile(fileName, os.O_TRUNC|os.O_WRONLY, 0) //nolint:gosec // Variable file is under our direct control in go:generate + if err != nil { + return fmt.Errorf("os.OpenFile(%q, [write-only, truncate]): %v", fileName, err) + } + if err := format.Node(f, fset, parsed); err != nil { + return fmt.Errorf("format.Node(%T): %v", parsed, err) + } + return f.Close() +} diff --git a/rlp/rlpgen/gen.go b/rlp/rlpgen/gen.go index e641a0564f7e..150797c7aa57 100644 --- a/rlp/rlpgen/gen.go +++ b/rlp/rlpgen/gen.go @@ -35,8 +35,6 @@ type buildContext struct { rawValueType *types.Named typeToStructCache map[types.Type]*rlpstruct.Type - - internalMethods bool } func newBuildContext(packageRLP *types.Package) *buildContext { @@ -100,8 +98,6 @@ type genContext struct { inPackage *types.Package imports map[string]struct{} tempCounter int - - internalMethods bool } func newGenContext(inPackage *types.Package) *genContext { @@ -740,7 +736,7 @@ func generateDecoder(ctx *genContext, typ string, op op) []byte { result, code := op.genDecode(ctx) var b bytes.Buffer - fmt.Fprintf(&b, "func (obj *%s) %s(dec *rlp.Stream) error {\n", typ, ctx.decoderMethod()) + fmt.Fprintf(&b, "func (obj *%s) DecodeRLP(dec *rlp.Stream) error {\n", typ) fmt.Fprint(&b, code) fmt.Fprintf(&b, " *obj = %s\n", result) fmt.Fprintf(&b, " return nil\n") @@ -755,7 +751,7 @@ func generateEncoder(ctx *genContext, typ string, op op) []byte { ctx.addImport(pathOfPackageRLP) var b bytes.Buffer - fmt.Fprintf(&b, "func (obj *%s) %s(_w io.Writer) error {\n", typ, ctx.encoderMethod()) + fmt.Fprintf(&b, "func (obj *%s) EncodeRLP(_w io.Writer) error {\n", typ) fmt.Fprintf(&b, " w := rlp.NewEncoderBuffer(_w)\n") fmt.Fprint(&b, op.genWrite(ctx, "obj")) fmt.Fprintf(&b, " return w.Flush()\n") @@ -777,7 +773,6 @@ func (bctx *buildContext) generate(typ *types.Named, encoder, decoder bool) ([]b encSource []byte decSource []byte ) - ctx.internalMethods = bctx.internalMethods if encoder { encSource = generateEncoder(ctx, typ.Obj().Name(), op) } diff --git a/rlp/rlpgen/gen.libevm.go b/rlp/rlpgen/gen.libevm.go deleted file mode 100644 index 63b52c4e1af3..000000000000 --- a/rlp/rlpgen/gen.libevm.go +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2024 the libevm authors. -// -// The libevm additions to go-ethereum are free software: you can redistribute -// them and/or modify them under the terms of the GNU Lesser General Public License -// as published by the Free Software Foundation, either version 3 of the License, -// or (at your option) any later version. -// -// The libevm additions are distributed in the hope that they will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser -// General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see -// . - -package main - -func (ctx *genContext) encoderMethod() string { - if ctx.internalMethods { - return "encodeRLP" - } - return "EncodeRLP" -} - -func (ctx *genContext) decoderMethod() string { - if ctx.internalMethods { - return "decodeRLP" - } - return "DecodeRLP" -} diff --git a/rlp/rlpgen/main.go b/rlp/rlpgen/main.go index e9ac5cd0e650..3e9310458afe 100644 --- a/rlp/rlpgen/main.go +++ b/rlp/rlpgen/main.go @@ -36,7 +36,6 @@ func main() { genEncoder = flag.Bool("encoder", true, "generate EncodeRLP?") genDecoder = flag.Bool("decoder", false, "generate DecodeRLP?") typename = flag.String("type", "", "type to generate methods for") - internal = flag.Bool("internal_methods", false, "generate internal (lower-case) method names") ) flag.Parse() @@ -45,7 +44,6 @@ func main() { Type: *typename, GenerateEncoder: *genEncoder, GenerateDecoder: *genDecoder, - InternalMethods: *internal, } code, err := cfg.process() if err != nil { @@ -69,8 +67,6 @@ type Config struct { GenerateEncoder bool GenerateDecoder bool - - InternalMethods bool } // process generates the Go code. @@ -105,7 +101,6 @@ func (cfg *Config) process() (code []byte, err error) { } } bctx := newBuildContext(packageRLP) - bctx.internalMethods = cfg.InternalMethods // Find the type and generate. typ, err := lookupStructType(pkg.Scope(), cfg.Type)