Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions rlp/rlpgen/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -687,6 +687,12 @@ func (bctx *buildContext) makeOp(name *types.Named, typ types.Type, tags rlpstru
if bctx.isDecoder(typ) {
return nil, fmt.Errorf("type %v implements rlp.Decoder with non-pointer receiver", typ)
}
// libevm: named types are reduced to their underlying basic type in this loop.
// We're handling named types here by passing the named type as the main type.
// See [named.libevm.go] for more details.
if hasBasicUnderlying(typ) {
return bctx.makeNamedBasicOp(typ)
}
// TODO: same check for encoder?
return bctx.makeOp(typ, typ.Underlying(), tags)
case *types.Pointer:
Expand Down
2 changes: 1 addition & 1 deletion rlp/rlpgen/gen_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func init() {
}
}

var tests = []string{"uints", "nil", "rawvalue", "optional", "bigint", "uint256", "alias"}
var tests = []string{"uints", "nil", "rawvalue", "optional", "bigint", "uint256", "alias", "named.libevm"}

func TestOutput(t *testing.T) {
for _, test := range tests {
Expand Down
55 changes: 55 additions & 0 deletions rlp/rlpgen/named.libevm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright 2025 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

import (
"fmt"
"go/types"
)

// makeNamedBasicOp is a convenience wrapper for basicOp.
// It returns a basicOp with the named type as the main type instead of the underlying basic type.
func (bctx *buildContext) makeNamedBasicOp(named *types.Named) (op, error) {
underlying := named.Underlying()
basic, ok := underlying.(*types.Basic)
if !ok {
return nil, fmt.Errorf("expected basic type, got %T", underlying)
}

// We use basic op because it actually supports necessary conversions (through writeNeedsConversion and decodeNeedsConversion)
// for named types.
// The only problem with that is it does not support the named type as the main type.
// So we use the named type as the main type instead of the underlying basic type.
baseOp, err := bctx.makeBasicOp(basic)
if err != nil {
return nil, err
}

op, ok := baseOp.(basicOp)
if !ok {
return nil, fmt.Errorf("expected basicOp, got %T", baseOp)
}
op.typ = named

return op, nil
}

// hasBasicUnderlying checks whether `named` has an underlying basic type.
func hasBasicUnderlying(named *types.Named) bool {
_, ok := named.Underlying().(*types.Basic)
return ok
}
15 changes: 15 additions & 0 deletions rlp/rlpgen/testdata/named.libevm.in.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// -*- mode: go -*-

package test

type (
BoolT bool
Uint64T uint64
StringT string
)

type Test struct {
BoolNewT BoolT
Uint64NewT Uint64T
StringNewT StringT
}
49 changes: 49 additions & 0 deletions rlp/rlpgen/testdata/named.libevm.out.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package test

import "github.com/ava-labs/libevm/rlp"
import "io"

func (obj *Test) EncodeRLP(_w io.Writer) error {
w := rlp.NewEncoderBuffer(_w)
_tmp0 := w.List()
w.WriteBool(bool(obj.BoolNewT))
w.WriteUint64(uint64(obj.Uint64NewT))
w.WriteString(string(obj.StringNewT))
w.ListEnd(_tmp0)
return w.Flush()
}

func (obj *Test) DecodeRLP(dec *rlp.Stream) error {
var _tmp0 Test
{
if _, err := dec.List(); err != nil {
return err
}
// BoolNewT:
_tmp1, err := dec.Bool()
if err != nil {
return err
}
_tmp2 := BoolT(_tmp1)
_tmp0.BoolNewT = _tmp2
// Uint64NewT:
_tmp3, err := dec.Uint64()
if err != nil {
return err
}
_tmp4 := Uint64T(_tmp3)
_tmp0.Uint64NewT = _tmp4
// StringNewT:
_tmp5, err := dec.String()
if err != nil {
return err
}
_tmp6 := StringT(_tmp5)
_tmp0.StringNewT = _tmp6
if err := dec.ListEnd(); err != nil {
return err
}
}
*obj = _tmp0
return nil
}
Loading