From 77f141947e0ca46822e86d8fbd05fe4991bd443e Mon Sep 17 00:00:00 2001 From: Quentin Mc Gaw Date: Mon, 3 Feb 2025 17:41:52 +0100 Subject: [PATCH 1/5] chore(core/types): add Test_Body_hasOptionalFields to enforce `hasLaterOptionalField` is up to date --- core/types/block.internal.libevm_test.go | 42 ++++++++++++++++++++++++ core/types/block.libevm.go | 6 +++- 2 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 core/types/block.internal.libevm_test.go diff --git a/core/types/block.internal.libevm_test.go b/core/types/block.internal.libevm_test.go new file mode 100644 index 00000000000..bf1ec6d1eb6 --- /dev/null +++ b/core/types/block.internal.libevm_test.go @@ -0,0 +1,42 @@ +package types + +import ( + "reflect" + "slices" + "strings" + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_Body_hasOptionalFields(t *testing.T) { + t.Parallel() + + var body Body + + assert.False(t, body.hasOptionalFields(), "body has no optional field set") + + v := reflect.ValueOf(&body).Elem() + typ := reflect.TypeOf(body) + for i := 0; i < v.NumField(); i++ { + fieldType := typ.Field(i) + rlpTag := fieldType.Tag.Get("rlp") + rlpTagFields := strings.Split(rlpTag, ",") + if !slices.Contains(rlpTagFields, "optional") { + continue + } + + field := v.Field(i) + before := field.Interface() + switch field.Kind() { + case reflect.Slice: + slice := reflect.MakeSlice(field.Type(), 1, 1) + field.Set(slice) + default: + t.Errorf("unexpected field kind %q for field %q", field.Kind(), fieldType.Name) + } + + assert.Truef(t, body.hasOptionalFields(), "body has the optional field %q set", fieldType.Name) + field.Set(reflect.ValueOf(before)) // reset the field + } +} diff --git a/core/types/block.libevm.go b/core/types/block.libevm.go index 094613ee1e3..014411e610b 100644 --- a/core/types/block.libevm.go +++ b/core/types/block.libevm.go @@ -137,7 +137,7 @@ func (b *Body) EncodeRLP(dst io.Writer) error { return err } - hasLaterOptionalField := b.Withdrawals != nil + hasLaterOptionalField := b.hasOptionalFields() if err := b.hooks().AppendRLPFields(w, hasLaterOptionalField); err != nil { return err } @@ -148,6 +148,10 @@ func (b *Body) EncodeRLP(dst io.Writer) error { }) } +func (b *Body) hasOptionalFields() bool { + return b.Withdrawals != nil +} + // DecodeRLP implements the [rlp.Decoder] interface. func (b *Body) DecodeRLP(s *rlp.Stream) error { return s.FromList(func() error { From 1f3f31eae3cd02707c45aa15a7052a366e414598 Mon Sep 17 00:00:00 2001 From: Quentin McGaw Date: Tue, 4 Feb 2025 14:00:12 +0100 Subject: [PATCH 2/5] Simplify rlp tag extraction code Co-authored-by: Arran Schlosberg <519948+ARR4N@users.noreply.github.com> Signed-off-by: Quentin McGaw --- core/types/block.internal.libevm_test.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/core/types/block.internal.libevm_test.go b/core/types/block.internal.libevm_test.go index bf1ec6d1eb6..1076c54601e 100644 --- a/core/types/block.internal.libevm_test.go +++ b/core/types/block.internal.libevm_test.go @@ -20,9 +20,8 @@ func Test_Body_hasOptionalFields(t *testing.T) { typ := reflect.TypeOf(body) for i := 0; i < v.NumField(); i++ { fieldType := typ.Field(i) - rlpTag := fieldType.Tag.Get("rlp") - rlpTagFields := strings.Split(rlpTag, ",") - if !slices.Contains(rlpTagFields, "optional") { + tag := fieldType.Tag.Get("rlp") + if !slices.Contains(strings.Split(tag, ","), "optional") { continue } From 3c70266d1f75d65e93c98b8154f1136d813bb806 Mon Sep 17 00:00:00 2001 From: Quentin Mc Gaw Date: Tue, 4 Feb 2025 14:01:24 +0100 Subject: [PATCH 3/5] Rename `hasOptionalField` -> `hasAnyOptionalFieldSet` --- core/types/block.internal.libevm_test.go | 6 +++--- core/types/block.libevm.go | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/core/types/block.internal.libevm_test.go b/core/types/block.internal.libevm_test.go index 1076c54601e..22ed3f22a07 100644 --- a/core/types/block.internal.libevm_test.go +++ b/core/types/block.internal.libevm_test.go @@ -9,12 +9,12 @@ import ( "github.com/stretchr/testify/assert" ) -func Test_Body_hasOptionalFields(t *testing.T) { +func Test_Body_hasAnyOptionalFieldSet(t *testing.T) { t.Parallel() var body Body - assert.False(t, body.hasOptionalFields(), "body has no optional field set") + assert.False(t, body.hasAnyOptionalFieldSet(), "body has no optional field set") v := reflect.ValueOf(&body).Elem() typ := reflect.TypeOf(body) @@ -35,7 +35,7 @@ func Test_Body_hasOptionalFields(t *testing.T) { t.Errorf("unexpected field kind %q for field %q", field.Kind(), fieldType.Name) } - assert.Truef(t, body.hasOptionalFields(), "body has the optional field %q set", fieldType.Name) + assert.Truef(t, body.hasAnyOptionalFieldSet(), "body has the optional field %q set", fieldType.Name) field.Set(reflect.ValueOf(before)) // reset the field } } diff --git a/core/types/block.libevm.go b/core/types/block.libevm.go index 014411e610b..7cbb797fc39 100644 --- a/core/types/block.libevm.go +++ b/core/types/block.libevm.go @@ -137,7 +137,7 @@ func (b *Body) EncodeRLP(dst io.Writer) error { return err } - hasLaterOptionalField := b.hasOptionalFields() + hasLaterOptionalField := b.hasAnyOptionalFieldSet() if err := b.hooks().AppendRLPFields(w, hasLaterOptionalField); err != nil { return err } @@ -148,7 +148,7 @@ func (b *Body) EncodeRLP(dst io.Writer) error { }) } -func (b *Body) hasOptionalFields() bool { +func (b *Body) hasAnyOptionalFieldSet() bool { return b.Withdrawals != nil } From 92d44f29226706a9512b05b7f2483a8856016142 Mon Sep 17 00:00:00 2001 From: Quentin Mc Gaw Date: Tue, 4 Feb 2025 14:01:42 +0100 Subject: [PATCH 4/5] Rename `Test_Body_hasAnyOptionalFieldSet` -> `TestBody_hasAnyOptionalFieldSet` --- core/types/block.internal.libevm_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/types/block.internal.libevm_test.go b/core/types/block.internal.libevm_test.go index 22ed3f22a07..ac3d302477d 100644 --- a/core/types/block.internal.libevm_test.go +++ b/core/types/block.internal.libevm_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/assert" ) -func Test_Body_hasAnyOptionalFieldSet(t *testing.T) { +func TestBody_hasAnyOptionalFieldSet(t *testing.T) { t.Parallel() var body Body From 24b3aec5c1bfdf4db758d236bba5a2312470d4b1 Mon Sep 17 00:00:00 2001 From: Quentin Mc Gaw Date: Tue, 4 Feb 2025 15:33:21 +0100 Subject: [PATCH 5/5] Call v.Type().Field(i) directly --- core/types/block.internal.libevm_test.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/types/block.internal.libevm_test.go b/core/types/block.internal.libevm_test.go index ac3d302477d..bbcd2ad7658 100644 --- a/core/types/block.internal.libevm_test.go +++ b/core/types/block.internal.libevm_test.go @@ -17,9 +17,8 @@ func TestBody_hasAnyOptionalFieldSet(t *testing.T) { assert.False(t, body.hasAnyOptionalFieldSet(), "body has no optional field set") v := reflect.ValueOf(&body).Elem() - typ := reflect.TypeOf(body) for i := 0; i < v.NumField(); i++ { - fieldType := typ.Field(i) + fieldType := v.Type().Field(i) tag := fieldType.Tag.Get("rlp") if !slices.Contains(strings.Split(tag, ","), "optional") { continue