diff --git a/rlp/decode.go b/rlp/decode.go
index 0fbca243ee..e75e63d0be 100644
--- a/rlp/decode.go
+++ b/rlp/decode.go
@@ -168,7 +168,7 @@ func makeDecoder(typ reflect.Type, tags rlpstruct.Tags) (dec decoder, err error)
return decodeU256NoPtr, nil
case kind == reflect.Ptr:
return makePtrDecoder(typ, tags)
- case reflect.PointerTo(typ).Implements(decoderInterface):
+ case implementsInterface(reflect.PointerTo(typ), decoderInterface):
return decodeDecoder, nil
case isUint(kind):
return decodeUint, nil
@@ -262,7 +262,7 @@ func decodeU256(s *Stream, val reflect.Value) error {
func makeListDecoder(typ reflect.Type, tag rlpstruct.Tags) (decoder, error) {
etype := typ.Elem()
- if etype.Kind() == reflect.Uint8 && !reflect.PointerTo(etype).Implements(decoderInterface) {
+ if etype.Kind() == reflect.Uint8 && !implementsInterface(reflect.PointerTo(etype), decoderInterface) {
if typ.Kind() == reflect.Array {
return decodeByteArray, nil
}
diff --git a/rlp/encode.go b/rlp/encode.go
index 3645bbfda0..f95d12a85c 100644
--- a/rlp/encode.go
+++ b/rlp/encode.go
@@ -151,7 +151,7 @@ func makeWriter(typ reflect.Type, ts rlpstruct.Tags) (writer, error) {
return writeU256IntNoPtr, nil
case kind == reflect.Ptr:
return makePtrWriter(typ, ts)
- case reflect.PointerTo(typ).Implements(encoderInterface):
+ case implementsInterface(reflect.PointerTo(typ), encoderInterface):
return makeEncoderWriter(typ), nil
case isUint(kind):
return writeUint, nil
@@ -409,7 +409,7 @@ func makePtrWriter(typ reflect.Type, ts rlpstruct.Tags) (writer, error) {
}
func makeEncoderWriter(typ reflect.Type) writer {
- if typ.Implements(encoderInterface) {
+ if implementsInterface(typ, encoderInterface) {
return func(val reflect.Value, w *encBuffer) error {
return val.Interface().(Encoder).EncodeRLP(w)
}
diff --git a/rlp/reflection.go b/rlp/reflection.go
new file mode 100644
index 0000000000..f7f1a507b1
--- /dev/null
+++ b/rlp/reflection.go
@@ -0,0 +1,25 @@
+// Copyright 2025 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it 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 go-ethereum library is distributed in the hope that it 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 .
+
+//go:build !tinygo
+
+package rlp
+
+import "reflect"
+
+func implementsInterface(t reflect.Type, i reflect.Type) bool {
+ return t.Implements(i)
+}
diff --git a/rlp/reflection_tinygo.go b/rlp/reflection_tinygo.go
new file mode 100644
index 0000000000..e9cbe07840
--- /dev/null
+++ b/rlp/reflection_tinygo.go
@@ -0,0 +1,38 @@
+// Copyright 2025 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it 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 go-ethereum library is distributed in the hope that it 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 .
+
+//go:build tinygo
+
+package rlp
+
+import "reflect"
+
+var customEncodedTypes = make(map[reflect.Type]bool)
+
+func implementsInterface(t reflect.Type, i reflect.Type) bool {
+ // reflect implementation of tinygo cannot handle this automatically
+ // at runtime. So we need custom encoded types to be registered manually.
+ if i == decoderInterface || i == encoderInterface {
+ return customEncodedTypes[t]
+ }
+ return false
+}
+
+// RegisterCustomEncodedType manually registers a type as an implementation of
+// Decoder and Encoder interfaces
+func RegisterCustomEncodedType(t reflect.Type) {
+ customEncodedTypes[t] = true
+}
diff --git a/rlp/typecache.go b/rlp/typecache.go
index eebf4cd611..79b50a6b8a 100644
--- a/rlp/typecache.go
+++ b/rlp/typecache.go
@@ -199,8 +199,8 @@ func rtypeToStructType(typ reflect.Type, rec map[reflect.Type]*rlpstruct.Type) *
t := &rlpstruct.Type{
Name: typ.String(),
Kind: k,
- IsEncoder: typ.Implements(encoderInterface),
- IsDecoder: typ.Implements(decoderInterface),
+ IsEncoder: implementsInterface(typ, encoderInterface),
+ IsDecoder: implementsInterface(typ, decoderInterface),
}
rec[typ] = t
if k == reflect.Array || k == reflect.Slice || k == reflect.Ptr {
@@ -234,5 +234,5 @@ func isUint(k reflect.Kind) bool {
}
func isByte(typ reflect.Type) bool {
- return typ.Kind() == reflect.Uint8 && !typ.Implements(encoderInterface)
+ return typ.Kind() == reflect.Uint8 && !implementsInterface(typ, encoderInterface)
}