Skip to content

Commit

Permalink
refactor: generate internal Header.encodeRLP() for override (#86)
Browse files Browse the repository at this point in the history
## Why this should be merged

This is a precursor to being able to override `types.Header` RLP
{en,de}coding. As there is already a `Header.EncodeRLP()` method we
either have to modify the generated code or rename the generated
method—this PR does the latter.

## How this works

The `rlpgen -internal_methods` flag changes the generated methods from
`EncodeRLP()` and `DecodeRLP()` to `encodeRLP()` and `decodeRLP()`,
respectively. A new CI job checks that generated code is up to date. We
can then implement our own `Header.EncodeRLP()` that either overrides or
falls back on the original.

It appears that `core/gen_genesis.go` was out of date but only because
of formatting.

## How this was tested

I deliberately excluded the change to `core/types/gen_header_rlp.go` to
confirm that the new workflow
[detects](https://github.com/ava-labs/libevm/actions/runs/12259667481/job/34202386378?pr=86#step:5:92)
the change and fails. The actual change can be inspected via the code
diff.
  • Loading branch information
ARR4N authored Dec 11, 2024
1 parent 380aa31 commit aa183c5
Show file tree
Hide file tree
Showing 8 changed files with 119 additions and 32 deletions.
17 changes: 17 additions & 0 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,20 @@ jobs:
- name: Run non-flaky tests concurrently
run: |
go test -short $(go list ./... | grep -Pv "${FLAKY_REGEX}");
go_generate:
env:
EXCLUDE_REGEX: 'ava-labs/libevm/(accounts/usbwallet/trezor)$'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: 1.21.4

- name: Run `go generate`
run: go list ./... | grep -Pv "${EXCLUDE_REGEX}" | xargs go generate;

- name: git diff
run: git diff --exit-code
56 changes: 28 additions & 28 deletions core/gen_genesis.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion core/types/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ 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 -out gen_header_rlp.go
//go:generate go run ../../rlp/rlpgen -type Header -internal_methods -out gen_header_rlp.go

// Header represents a block header in the Ethereum blockchain.
type Header struct {
Expand Down
29 changes: 29 additions & 0 deletions core/types/block.libevm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// 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
// <http://www.gnu.org/licenses/>.

package types

import (
"io"

"github.com/ava-labs/libevm/rlp"
)

func (h *Header) EncodeRLP(w io.Writer) error {
return h.encodeRLP(w)
}

var _ rlp.Encoder = (*Header)(nil)
2 changes: 1 addition & 1 deletion core/types/gen_header_rlp.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 7 additions & 2 deletions rlp/rlpgen/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ type buildContext struct {
rawValueType *types.Named

typeToStructCache map[types.Type]*rlpstruct.Type

internalMethods bool
}

func newBuildContext(packageRLP *types.Package) *buildContext {
Expand Down Expand Up @@ -98,6 +100,8 @@ type genContext struct {
inPackage *types.Package
imports map[string]struct{}
tempCounter int

internalMethods bool
}

func newGenContext(inPackage *types.Package) *genContext {
Expand Down Expand Up @@ -736,7 +740,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) DecodeRLP(dec *rlp.Stream) error {\n", typ)
fmt.Fprintf(&b, "func (obj *%s) %s(dec *rlp.Stream) error {\n", typ, ctx.decoderMethod())
fmt.Fprint(&b, code)
fmt.Fprintf(&b, " *obj = %s\n", result)
fmt.Fprintf(&b, " return nil\n")
Expand All @@ -751,7 +755,7 @@ func generateEncoder(ctx *genContext, typ string, op op) []byte {
ctx.addImport(pathOfPackageRLP)

var b bytes.Buffer
fmt.Fprintf(&b, "func (obj *%s) EncodeRLP(_w io.Writer) error {\n", typ)
fmt.Fprintf(&b, "func (obj *%s) %s(_w io.Writer) error {\n", typ, ctx.encoderMethod())
fmt.Fprintf(&b, " w := rlp.NewEncoderBuffer(_w)\n")
fmt.Fprint(&b, op.genWrite(ctx, "obj"))
fmt.Fprintf(&b, " return w.Flush()\n")
Expand All @@ -773,6 +777,7 @@ 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)
}
Expand Down
31 changes: 31 additions & 0 deletions rlp/rlpgen/gen.libevm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// 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
// <http://www.gnu.org/licenses/>.

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"
}
5 changes: 5 additions & 0 deletions rlp/rlpgen/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ 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()

Expand All @@ -44,6 +45,7 @@ func main() {
Type: *typename,
GenerateEncoder: *genEncoder,
GenerateDecoder: *genDecoder,
InternalMethods: *internal,
}
code, err := cfg.process()
if err != nil {
Expand All @@ -67,6 +69,8 @@ type Config struct {

GenerateEncoder bool
GenerateDecoder bool

InternalMethods bool
}

// process generates the Go code.
Expand Down Expand Up @@ -101,6 +105,7 @@ 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)
Expand Down

0 comments on commit aa183c5

Please sign in to comment.