From 2b686c49bfa68c2ffad33086ae94c537a5f64384 Mon Sep 17 00:00:00 2001 From: Quentin Mc Gaw Date: Tue, 21 Jan 2025 10:30:01 +0100 Subject: [PATCH 1/7] feat(core/types): header copy hooks --- core/types/block.go | 3 +-- core/types/block.libevm.go | 10 ++++++++++ core/types/block.libevm_test.go | 4 ++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/core/types/block.go b/core/types/block.go index 692cf01c076b..0a483686f9ae 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -277,8 +277,7 @@ func NewBlockWithWithdrawals(header *Header, txs []*Transaction, uncles []*Heade return b.WithWithdrawals(withdrawals) } -// CopyHeader creates a deep copy of a block header. -func CopyHeader(h *Header) *Header { +func copyHeader(h *Header) *Header { cpy := *h if cpy.Difficulty = new(big.Int); h.Difficulty != nil { cpy.Difficulty.Set(h.Difficulty) diff --git a/core/types/block.libevm.go b/core/types/block.libevm.go index ca1e6d7e57d9..c3d351489b62 100644 --- a/core/types/block.libevm.go +++ b/core/types/block.libevm.go @@ -32,6 +32,7 @@ type HeaderHooks interface { UnmarshalJSON(*Header, []byte) error //nolint:govet EncodeRLP(*Header, io.Writer) error DecodeRLP(*Header, *rlp.Stream) error + Copy(*Header) *Header } // hooks returns the Header's registered HeaderHooks, if any, otherwise a @@ -108,3 +109,12 @@ func (*NOOPHeaderHooks) DecodeRLP(h *Header, s *rlp.Stream) error { type withoutMethods Header return s.Decode((*withoutMethods)(h)) } + +func (n *NOOPHeaderHooks) Copy(h *Header) *Header { + return copyHeader(h) +} + +// CopyHeader creates a deep copy of a block header. +func CopyHeader(h *Header) *Header { + return h.hooks().Copy(h) +} diff --git a/core/types/block.libevm_test.go b/core/types/block.libevm_test.go index 7f5cfd83c540..48ba5883e122 100644 --- a/core/types/block.libevm_test.go +++ b/core/types/block.libevm_test.go @@ -75,6 +75,10 @@ func (hh *stubHeaderHooks) DecodeRLP(h *Header, s *rlp.Stream) error { return hh.errDecode } +func (hh *stubHeaderHooks) Copy(h *Header) *Header { + return h +} + func TestHeaderHooks(t *testing.T) { TestOnlyClearRegisteredExtras() defer TestOnlyClearRegisteredExtras() From 9c69d612c5f30f5f0f67270fee6b70d4dd2b9f36 Mon Sep 17 00:00:00 2001 From: Quentin Mc Gaw Date: Tue, 21 Jan 2025 17:20:40 +0100 Subject: [PATCH 2/7] Export `copyHeader` as `CopyEthHeader` --- core/types/block.go | 4 +++- core/types/block.libevm.go | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/core/types/block.go b/core/types/block.go index 0a483686f9ae..9d056fc8bc4c 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -277,7 +277,9 @@ func NewBlockWithWithdrawals(header *Header, txs []*Transaction, uncles []*Heade return b.WithWithdrawals(withdrawals) } -func copyHeader(h *Header) *Header { +// CopyEthHeader creates a deep copy of an Ethereum block header. +// Use [CopyHeader] instead if your header has any registered extra. +func CopyEthHeader(h *Header) *Header { cpy := *h if cpy.Difficulty = new(big.Int); h.Difficulty != nil { cpy.Difficulty.Set(h.Difficulty) diff --git a/core/types/block.libevm.go b/core/types/block.libevm.go index c3d351489b62..e029c67d374a 100644 --- a/core/types/block.libevm.go +++ b/core/types/block.libevm.go @@ -111,7 +111,7 @@ func (*NOOPHeaderHooks) DecodeRLP(h *Header, s *rlp.Stream) error { } func (n *NOOPHeaderHooks) Copy(h *Header) *Header { - return copyHeader(h) + return CopyEthHeader(h) } // CopyHeader creates a deep copy of a block header. From 48e2b3c874e5b38ff2dd8212e25196b01ebe1b30 Mon Sep 17 00:00:00 2001 From: Quentin Mc Gaw Date: Fri, 31 Jan 2025 19:45:15 +0100 Subject: [PATCH 3/7] =?UTF-8?q?Move=20to=20a=20PostCopy=20hook=20?= =?UTF-8?q?=F0=9F=8E=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/types/block.go | 6 +++--- core/types/block.libevm.go | 11 ++--------- core/types/block.libevm_test.go | 4 +--- 3 files changed, 6 insertions(+), 15 deletions(-) diff --git a/core/types/block.go b/core/types/block.go index 9d056fc8bc4c..53141a535c5e 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -277,9 +277,8 @@ func NewBlockWithWithdrawals(header *Header, txs []*Transaction, uncles []*Heade return b.WithWithdrawals(withdrawals) } -// CopyEthHeader creates a deep copy of an Ethereum block header. -// Use [CopyHeader] instead if your header has any registered extra. -func CopyEthHeader(h *Header) *Header { +// CopyHeader creates a deep copy of a block header. +func CopyHeader(h *Header) *Header { cpy := *h if cpy.Difficulty = new(big.Int); h.Difficulty != nil { cpy.Difficulty.Set(h.Difficulty) @@ -310,6 +309,7 @@ func CopyEthHeader(h *Header) *Header { cpy.ParentBeaconRoot = new(common.Hash) *cpy.ParentBeaconRoot = *h.ParentBeaconRoot } + h.hooks().PostCopy(&cpy, h) return &cpy } diff --git a/core/types/block.libevm.go b/core/types/block.libevm.go index e029c67d374a..4e6e5f3b0d02 100644 --- a/core/types/block.libevm.go +++ b/core/types/block.libevm.go @@ -32,7 +32,7 @@ type HeaderHooks interface { UnmarshalJSON(*Header, []byte) error //nolint:govet EncodeRLP(*Header, io.Writer) error DecodeRLP(*Header, *rlp.Stream) error - Copy(*Header) *Header + PostCopy(dst, src *Header) } // hooks returns the Header's registered HeaderHooks, if any, otherwise a @@ -110,11 +110,4 @@ func (*NOOPHeaderHooks) DecodeRLP(h *Header, s *rlp.Stream) error { return s.Decode((*withoutMethods)(h)) } -func (n *NOOPHeaderHooks) Copy(h *Header) *Header { - return CopyEthHeader(h) -} - -// CopyHeader creates a deep copy of a block header. -func CopyHeader(h *Header) *Header { - return h.hooks().Copy(h) -} +func (n *NOOPHeaderHooks) PostCopy(dst, src *Header) {} diff --git a/core/types/block.libevm_test.go b/core/types/block.libevm_test.go index 48ba5883e122..e5d32de17ae3 100644 --- a/core/types/block.libevm_test.go +++ b/core/types/block.libevm_test.go @@ -75,9 +75,7 @@ func (hh *stubHeaderHooks) DecodeRLP(h *Header, s *rlp.Stream) error { return hh.errDecode } -func (hh *stubHeaderHooks) Copy(h *Header) *Header { - return h -} +func (hh *stubHeaderHooks) PostCopy(dst, src *Header) {} func TestHeaderHooks(t *testing.T) { TestOnlyClearRegisteredExtras() From b2b28ce5aac82973e3e45762108623b08ef1e4f9 Mon Sep 17 00:00:00 2001 From: Quentin Mc Gaw Date: Fri, 31 Jan 2025 19:50:37 +0100 Subject: [PATCH 4/7] Change `PostCopy(dst, src)` -> `PostCopy(dst)` --- core/types/block.go | 2 +- core/types/block.libevm.go | 4 ++-- core/types/block.libevm_test.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/types/block.go b/core/types/block.go index 53141a535c5e..336275917db0 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -309,7 +309,7 @@ func CopyHeader(h *Header) *Header { cpy.ParentBeaconRoot = new(common.Hash) *cpy.ParentBeaconRoot = *h.ParentBeaconRoot } - h.hooks().PostCopy(&cpy, h) + h.hooks().PostCopy(&cpy) return &cpy } diff --git a/core/types/block.libevm.go b/core/types/block.libevm.go index 4e6e5f3b0d02..9258eefac799 100644 --- a/core/types/block.libevm.go +++ b/core/types/block.libevm.go @@ -32,7 +32,7 @@ type HeaderHooks interface { UnmarshalJSON(*Header, []byte) error //nolint:govet EncodeRLP(*Header, io.Writer) error DecodeRLP(*Header, *rlp.Stream) error - PostCopy(dst, src *Header) + PostCopy(dst *Header) } // hooks returns the Header's registered HeaderHooks, if any, otherwise a @@ -110,4 +110,4 @@ func (*NOOPHeaderHooks) DecodeRLP(h *Header, s *rlp.Stream) error { return s.Decode((*withoutMethods)(h)) } -func (n *NOOPHeaderHooks) PostCopy(dst, src *Header) {} +func (n *NOOPHeaderHooks) PostCopy(dst *Header) {} diff --git a/core/types/block.libevm_test.go b/core/types/block.libevm_test.go index e5d32de17ae3..6412653bb4f0 100644 --- a/core/types/block.libevm_test.go +++ b/core/types/block.libevm_test.go @@ -75,7 +75,7 @@ func (hh *stubHeaderHooks) DecodeRLP(h *Header, s *rlp.Stream) error { return hh.errDecode } -func (hh *stubHeaderHooks) PostCopy(dst, src *Header) {} +func (hh *stubHeaderHooks) PostCopy(dst *Header) {} func TestHeaderHooks(t *testing.T) { TestOnlyClearRegisteredExtras() From 7e5e8327c947bddef0706a13d86c8978c057005f Mon Sep 17 00:00:00 2001 From: Quentin Mc Gaw Date: Mon, 3 Feb 2025 12:51:00 +0100 Subject: [PATCH 5/7] add test case --- core/types/block.libevm_test.go | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/core/types/block.libevm_test.go b/core/types/block.libevm_test.go index 6412653bb4f0..213b2daff4b0 100644 --- a/core/types/block.libevm_test.go +++ b/core/types/block.libevm_test.go @@ -29,6 +29,7 @@ import ( . "github.com/ava-labs/libevm/core/types" "github.com/ava-labs/libevm/crypto" "github.com/ava-labs/libevm/libevm/ethtest" + "github.com/ava-labs/libevm/libevm/pseudo" "github.com/ava-labs/libevm/rlp" ) @@ -36,6 +37,8 @@ type stubHeaderHooks struct { suffix []byte gotRawJSONToUnmarshal, gotRawRLPToDecode []byte setHeaderToOnUnmarshalOrDecode Header + accessor pseudo.Accessor[*Header, *stubHeaderHooks] + copied *stubHeaderHooks errMarshal, errUnmarshal, errEncode, errDecode error } @@ -75,7 +78,9 @@ func (hh *stubHeaderHooks) DecodeRLP(h *Header, s *rlp.Stream) error { return hh.errDecode } -func (hh *stubHeaderHooks) PostCopy(dst *Header) {} +func (hh *stubHeaderHooks) PostCopy(dst *Header) { + hh.accessor.Set(dst, hh.copied) +} func TestHeaderHooks(t *testing.T) { TestOnlyClearRegisteredExtras() @@ -137,6 +142,22 @@ func TestHeaderHooks(t *testing.T) { assert.Equalf(t, &stub.setHeaderToOnUnmarshalOrDecode, hdr, "%T after RLP decoding with hook", hdr) }) + t.Run("PostCopy", func(t *testing.T) { + hdr := new(Header) + stub := &stubHeaderHooks{ + accessor: extras.Header, + copied: &stubHeaderHooks{ + suffix: []byte("copied"), + }, + } + extras.Header.Set(hdr, stub) + cpy := CopyHeader(hdr) + + copiedStub := extras.Header.Get(cpy) + + assert.Equal(t, stub.copied, copiedStub) + }) + t.Run("error_propagation", func(t *testing.T) { errMarshal := errors.New("whoops") errUnmarshal := errors.New("is it broken?") From e2b11fe0fa8747a1f6b23fb7816801bcf38a68a6 Mon Sep 17 00:00:00 2001 From: Quentin McGaw Date: Tue, 4 Feb 2025 08:52:51 +0100 Subject: [PATCH 6/7] Update core/types/block.libevm_test.go Co-authored-by: Arran Schlosberg <519948+ARR4N@users.noreply.github.com> Signed-off-by: Quentin McGaw --- core/types/block.libevm_test.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/core/types/block.libevm_test.go b/core/types/block.libevm_test.go index 213b2daff4b0..81920c5b062c 100644 --- a/core/types/block.libevm_test.go +++ b/core/types/block.libevm_test.go @@ -146,16 +146,14 @@ func TestHeaderHooks(t *testing.T) { hdr := new(Header) stub := &stubHeaderHooks{ accessor: extras.Header, - copied: &stubHeaderHooks{ + toCopy: &stubHeaderHooks{ suffix: []byte("copied"), }, } extras.Header.Set(hdr, stub) - cpy := CopyHeader(hdr) - copiedStub := extras.Header.Get(cpy) - - assert.Equal(t, stub.copied, copiedStub) + got := extras.Header.Get(CopyHeader(hdr)) + assert.Equal(t, stub.toCopy, got) }) t.Run("error_propagation", func(t *testing.T) { From def07f8b84bca7d6c756b8f966c984f9cac092d1 Mon Sep 17 00:00:00 2001 From: Quentin Mc Gaw Date: Tue, 4 Feb 2025 08:52:05 +0100 Subject: [PATCH 7/7] Rename stubHeaderHooks copied -> toCopy --- core/types/block.libevm_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/types/block.libevm_test.go b/core/types/block.libevm_test.go index 81920c5b062c..e89926767323 100644 --- a/core/types/block.libevm_test.go +++ b/core/types/block.libevm_test.go @@ -38,7 +38,7 @@ type stubHeaderHooks struct { gotRawJSONToUnmarshal, gotRawRLPToDecode []byte setHeaderToOnUnmarshalOrDecode Header accessor pseudo.Accessor[*Header, *stubHeaderHooks] - copied *stubHeaderHooks + toCopy *stubHeaderHooks errMarshal, errUnmarshal, errEncode, errDecode error } @@ -79,7 +79,7 @@ func (hh *stubHeaderHooks) DecodeRLP(h *Header, s *rlp.Stream) error { } func (hh *stubHeaderHooks) PostCopy(dst *Header) { - hh.accessor.Set(dst, hh.copied) + hh.accessor.Set(dst, hh.toCopy) } func TestHeaderHooks(t *testing.T) {