mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-18 02:40:45 +00:00
refactor: generate internal Header.encodeRLP() for override (#86)
## 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.
This commit is contained in:
parent
380aa319f9
commit
aa183c52be
8 changed files with 119 additions and 32 deletions
17
.github/workflows/go.yml
vendored
17
.github/workflows/go.yml
vendored
|
|
@ -24,3 +24,20 @@ jobs:
|
||||||
- name: Run non-flaky tests concurrently
|
- name: Run non-flaky tests concurrently
|
||||||
run: |
|
run: |
|
||||||
go test -short $(go list ./... | grep -Pv "${FLAKY_REGEX}");
|
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
|
||||||
|
|
|
||||||
|
|
@ -19,21 +19,21 @@ var _ = (*genesisSpecMarshaling)(nil)
|
||||||
// MarshalJSON marshals as JSON.
|
// MarshalJSON marshals as JSON.
|
||||||
func (g Genesis) MarshalJSON() ([]byte, error) {
|
func (g Genesis) MarshalJSON() ([]byte, error) {
|
||||||
type Genesis struct {
|
type Genesis struct {
|
||||||
Config *params.ChainConfig `json:"config"`
|
Config *params.ChainConfig `json:"config"`
|
||||||
Nonce math.HexOrDecimal64 `json:"nonce"`
|
Nonce math.HexOrDecimal64 `json:"nonce"`
|
||||||
Timestamp math.HexOrDecimal64 `json:"timestamp"`
|
Timestamp math.HexOrDecimal64 `json:"timestamp"`
|
||||||
ExtraData hexutil.Bytes `json:"extraData"`
|
ExtraData hexutil.Bytes `json:"extraData"`
|
||||||
GasLimit math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"`
|
GasLimit math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"`
|
||||||
Difficulty *math.HexOrDecimal256 `json:"difficulty" gencodec:"required"`
|
Difficulty *math.HexOrDecimal256 `json:"difficulty" gencodec:"required"`
|
||||||
Mixhash common.Hash `json:"mixHash"`
|
Mixhash common.Hash `json:"mixHash"`
|
||||||
Coinbase common.Address `json:"coinbase"`
|
Coinbase common.Address `json:"coinbase"`
|
||||||
Alloc map[common.UnprefixedAddress]types.Account `json:"alloc" gencodec:"required"`
|
Alloc map[common.UnprefixedAddress]types.Account `json:"alloc" gencodec:"required"`
|
||||||
Number math.HexOrDecimal64 `json:"number"`
|
Number math.HexOrDecimal64 `json:"number"`
|
||||||
GasUsed math.HexOrDecimal64 `json:"gasUsed"`
|
GasUsed math.HexOrDecimal64 `json:"gasUsed"`
|
||||||
ParentHash common.Hash `json:"parentHash"`
|
ParentHash common.Hash `json:"parentHash"`
|
||||||
BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas"`
|
BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas"`
|
||||||
ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas"`
|
ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas"`
|
||||||
BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed"`
|
BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed"`
|
||||||
}
|
}
|
||||||
var enc Genesis
|
var enc Genesis
|
||||||
enc.Config = g.Config
|
enc.Config = g.Config
|
||||||
|
|
@ -62,21 +62,21 @@ func (g Genesis) MarshalJSON() ([]byte, error) {
|
||||||
// UnmarshalJSON unmarshals from JSON.
|
// UnmarshalJSON unmarshals from JSON.
|
||||||
func (g *Genesis) UnmarshalJSON(input []byte) error {
|
func (g *Genesis) UnmarshalJSON(input []byte) error {
|
||||||
type Genesis struct {
|
type Genesis struct {
|
||||||
Config *params.ChainConfig `json:"config"`
|
Config *params.ChainConfig `json:"config"`
|
||||||
Nonce *math.HexOrDecimal64 `json:"nonce"`
|
Nonce *math.HexOrDecimal64 `json:"nonce"`
|
||||||
Timestamp *math.HexOrDecimal64 `json:"timestamp"`
|
Timestamp *math.HexOrDecimal64 `json:"timestamp"`
|
||||||
ExtraData *hexutil.Bytes `json:"extraData"`
|
ExtraData *hexutil.Bytes `json:"extraData"`
|
||||||
GasLimit *math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"`
|
GasLimit *math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"`
|
||||||
Difficulty *math.HexOrDecimal256 `json:"difficulty" gencodec:"required"`
|
Difficulty *math.HexOrDecimal256 `json:"difficulty" gencodec:"required"`
|
||||||
Mixhash *common.Hash `json:"mixHash"`
|
Mixhash *common.Hash `json:"mixHash"`
|
||||||
Coinbase *common.Address `json:"coinbase"`
|
Coinbase *common.Address `json:"coinbase"`
|
||||||
Alloc map[common.UnprefixedAddress]types.Account `json:"alloc" gencodec:"required"`
|
Alloc map[common.UnprefixedAddress]types.Account `json:"alloc" gencodec:"required"`
|
||||||
Number *math.HexOrDecimal64 `json:"number"`
|
Number *math.HexOrDecimal64 `json:"number"`
|
||||||
GasUsed *math.HexOrDecimal64 `json:"gasUsed"`
|
GasUsed *math.HexOrDecimal64 `json:"gasUsed"`
|
||||||
ParentHash *common.Hash `json:"parentHash"`
|
ParentHash *common.Hash `json:"parentHash"`
|
||||||
BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas"`
|
BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas"`
|
||||||
ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas"`
|
ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas"`
|
||||||
BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed"`
|
BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed"`
|
||||||
}
|
}
|
||||||
var dec Genesis
|
var dec Genesis
|
||||||
if err := json.Unmarshal(input, &dec); err != nil {
|
if err := json.Unmarshal(input, &dec); err != nil {
|
||||||
|
|
|
||||||
|
|
@ -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 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.
|
// Header represents a block header in the Ethereum blockchain.
|
||||||
type Header struct {
|
type Header struct {
|
||||||
|
|
|
||||||
29
core/types/block.libevm.go
Normal file
29
core/types/block.libevm.go
Normal file
|
|
@ -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)
|
||||||
|
|
@ -5,7 +5,7 @@ package types
|
||||||
import "github.com/ava-labs/libevm/rlp"
|
import "github.com/ava-labs/libevm/rlp"
|
||||||
import "io"
|
import "io"
|
||||||
|
|
||||||
func (obj *Header) EncodeRLP(_w io.Writer) error {
|
func (obj *Header) encodeRLP(_w io.Writer) error {
|
||||||
w := rlp.NewEncoderBuffer(_w)
|
w := rlp.NewEncoderBuffer(_w)
|
||||||
_tmp0 := w.List()
|
_tmp0 := w.List()
|
||||||
w.WriteBytes(obj.ParentHash[:])
|
w.WriteBytes(obj.ParentHash[:])
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,8 @@ type buildContext struct {
|
||||||
rawValueType *types.Named
|
rawValueType *types.Named
|
||||||
|
|
||||||
typeToStructCache map[types.Type]*rlpstruct.Type
|
typeToStructCache map[types.Type]*rlpstruct.Type
|
||||||
|
|
||||||
|
internalMethods bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func newBuildContext(packageRLP *types.Package) *buildContext {
|
func newBuildContext(packageRLP *types.Package) *buildContext {
|
||||||
|
|
@ -98,6 +100,8 @@ type genContext struct {
|
||||||
inPackage *types.Package
|
inPackage *types.Package
|
||||||
imports map[string]struct{}
|
imports map[string]struct{}
|
||||||
tempCounter int
|
tempCounter int
|
||||||
|
|
||||||
|
internalMethods bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func newGenContext(inPackage *types.Package) *genContext {
|
func newGenContext(inPackage *types.Package) *genContext {
|
||||||
|
|
@ -736,7 +740,7 @@ func generateDecoder(ctx *genContext, typ string, op op) []byte {
|
||||||
|
|
||||||
result, code := op.genDecode(ctx)
|
result, code := op.genDecode(ctx)
|
||||||
var b bytes.Buffer
|
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.Fprint(&b, code)
|
||||||
fmt.Fprintf(&b, " *obj = %s\n", result)
|
fmt.Fprintf(&b, " *obj = %s\n", result)
|
||||||
fmt.Fprintf(&b, " return nil\n")
|
fmt.Fprintf(&b, " return nil\n")
|
||||||
|
|
@ -751,7 +755,7 @@ func generateEncoder(ctx *genContext, typ string, op op) []byte {
|
||||||
ctx.addImport(pathOfPackageRLP)
|
ctx.addImport(pathOfPackageRLP)
|
||||||
|
|
||||||
var b bytes.Buffer
|
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.Fprintf(&b, " w := rlp.NewEncoderBuffer(_w)\n")
|
||||||
fmt.Fprint(&b, op.genWrite(ctx, "obj"))
|
fmt.Fprint(&b, op.genWrite(ctx, "obj"))
|
||||||
fmt.Fprintf(&b, " return w.Flush()\n")
|
fmt.Fprintf(&b, " return w.Flush()\n")
|
||||||
|
|
@ -773,6 +777,7 @@ func (bctx *buildContext) generate(typ *types.Named, encoder, decoder bool) ([]b
|
||||||
encSource []byte
|
encSource []byte
|
||||||
decSource []byte
|
decSource []byte
|
||||||
)
|
)
|
||||||
|
ctx.internalMethods = bctx.internalMethods
|
||||||
if encoder {
|
if encoder {
|
||||||
encSource = generateEncoder(ctx, typ.Obj().Name(), op)
|
encSource = generateEncoder(ctx, typ.Obj().Name(), op)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
31
rlp/rlpgen/gen.libevm.go
Normal file
31
rlp/rlpgen/gen.libevm.go
Normal file
|
|
@ -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"
|
||||||
|
}
|
||||||
|
|
@ -36,6 +36,7 @@ func main() {
|
||||||
genEncoder = flag.Bool("encoder", true, "generate EncodeRLP?")
|
genEncoder = flag.Bool("encoder", true, "generate EncodeRLP?")
|
||||||
genDecoder = flag.Bool("decoder", false, "generate DecodeRLP?")
|
genDecoder = flag.Bool("decoder", false, "generate DecodeRLP?")
|
||||||
typename = flag.String("type", "", "type to generate methods for")
|
typename = flag.String("type", "", "type to generate methods for")
|
||||||
|
internal = flag.Bool("internal_methods", false, "generate internal (lower-case) method names")
|
||||||
)
|
)
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
|
|
@ -44,6 +45,7 @@ func main() {
|
||||||
Type: *typename,
|
Type: *typename,
|
||||||
GenerateEncoder: *genEncoder,
|
GenerateEncoder: *genEncoder,
|
||||||
GenerateDecoder: *genDecoder,
|
GenerateDecoder: *genDecoder,
|
||||||
|
InternalMethods: *internal,
|
||||||
}
|
}
|
||||||
code, err := cfg.process()
|
code, err := cfg.process()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -67,6 +69,8 @@ type Config struct {
|
||||||
|
|
||||||
GenerateEncoder bool
|
GenerateEncoder bool
|
||||||
GenerateDecoder bool
|
GenerateDecoder bool
|
||||||
|
|
||||||
|
InternalMethods bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// process generates the Go code.
|
// process generates the Go code.
|
||||||
|
|
@ -101,6 +105,7 @@ func (cfg *Config) process() (code []byte, err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bctx := newBuildContext(packageRLP)
|
bctx := newBuildContext(packageRLP)
|
||||||
|
bctx.internalMethods = cfg.InternalMethods
|
||||||
|
|
||||||
// Find the type and generate.
|
// Find the type and generate.
|
||||||
typ, err := lookupStructType(pkg.Scope(), cfg.Type)
|
typ, err := lookupStructType(pkg.Scope(), cfg.Type)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue