From 1504391d4f98e28722d9cff1751ecd5c28805eee Mon Sep 17 00:00:00 2001 From: Paul O'Leary Date: Fri, 19 May 2023 07:32:30 -0700 Subject: [PATCH 1/3] Change legacy rando geth fork choice to be deterministic, based on block hash. --- core/forkchoice.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/forkchoice.go b/core/forkchoice.go index 7dd1a86307..117b9fab8d 100644 --- a/core/forkchoice.go +++ b/core/forkchoice.go @@ -17,6 +17,7 @@ package core import ( + "bytes" "errors" "math/big" @@ -104,7 +105,7 @@ func (f *ForkChoice) ReorgNeeded(current *types.Header, header *types.Header) (b if f.preserve != nil { currentPreserve, externPreserve = f.preserve(current), f.preserve(header) } - reorg = !currentPreserve && (externPreserve || f.rand.Float64() < 0.5) + reorg = !currentPreserve && (externPreserve || bytes.Compare(current.Hash().Bytes(), header.Hash().Bytes()) < 0) } } return reorg, nil From 347867434d455de9b4609f0e23c1f0e8e8876d30 Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Wed, 18 Oct 2023 18:22:11 +0530 Subject: [PATCH 2/3] core: add forkchoice tests --- core/forkchoice_test.go | 58 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/core/forkchoice_test.go b/core/forkchoice_test.go index 857081e578..196db669ff 100644 --- a/core/forkchoice_test.go +++ b/core/forkchoice_test.go @@ -10,6 +10,8 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/trie" + + "github.com/stretchr/testify/require" ) // chainValidatorFake is a mock for the chain validator service @@ -30,6 +32,62 @@ func newChainReaderFake(getTd func(hash common.Hash, number uint64) *big.Int) *c return &chainReaderFake{getTd: getTd} } +// nolint: tparallel +func TestForkChoice(t *testing.T) { + t.Parallel() + + // Create mocks for forker + getTd := func(hash common.Hash, number uint64) *big.Int { + if number <= 2 { + return big.NewInt(int64(number)) + } + + return big.NewInt(0) + } + mockChainReader := newChainReaderFake(getTd) + mockForker := NewForkChoice(mockChainReader, nil, nil) + + createHeader := func(number int64, extra []byte) *types.Header { + return &types.Header{ + Number: big.NewInt(number), + Extra: extra, + } + } + + // Create headers for different cases + headerA := createHeader(1, []byte("A")) + headerB := createHeader(2, []byte("B")) + headerC := createHeader(3, []byte("C")) + headerD := createHeader(4, []byte("D")) // 0x96b0f70c01f4d2b1ee2df5b0202c099776f24c9375ffc89d94b880007633961b (hash) + headerE := createHeader(4, []byte("E")) // 0xdc0acf54354ff86194baeaab983098a49a40218cffcc77a583726fc06c429685 (hash) + + // Create test cases + testCases := []struct { + name string + current *types.Header + incoming *types.Header + want bool + }{ + {"tdd(incoming) > tdd(current)", headerA, headerB, true}, + {"tdd(current) > tdd(incoming)", headerB, headerA, false}, + {"tdd(current) = tdd(incoming), number(incoming) > number(current)", headerC, headerD, false}, + {"tdd(current) = tdd(incoming), number(current) > number(incoming)", headerD, headerC, true}, + {"tdd(current) = tdd(incoming), number(current) = number(incoming), hash(current) > hash(incoming)", headerE, headerD, false}, + {"tdd(current) = tdd(incoming), number(current) = number(incoming), hash(incoming) > hash(current)", headerD, headerE, true}, + } + _ = testCases + + // nolint: paralleltest + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + res, err := mockForker.ReorgNeeded(tc.current, tc.incoming) + require.Equal(t, tc.want, res, tc.name) + require.NoError(t, err, tc.name) + }) + } +} + func TestPastChainInsert(t *testing.T) { t.Parallel() From 8f67f862dca6c6c1e8c942a8011d7ce258f74421 Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Wed, 18 Oct 2023 18:24:02 +0530 Subject: [PATCH 3/3] fix --- core/forkchoice_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/core/forkchoice_test.go b/core/forkchoice_test.go index 196db669ff..4b4a1343a1 100644 --- a/core/forkchoice_test.go +++ b/core/forkchoice_test.go @@ -61,7 +61,6 @@ func TestForkChoice(t *testing.T) { headerD := createHeader(4, []byte("D")) // 0x96b0f70c01f4d2b1ee2df5b0202c099776f24c9375ffc89d94b880007633961b (hash) headerE := createHeader(4, []byte("E")) // 0xdc0acf54354ff86194baeaab983098a49a40218cffcc77a583726fc06c429685 (hash) - // Create test cases testCases := []struct { name string current *types.Header @@ -75,7 +74,6 @@ func TestForkChoice(t *testing.T) { {"tdd(current) = tdd(incoming), number(current) = number(incoming), hash(current) > hash(incoming)", headerE, headerD, false}, {"tdd(current) = tdd(incoming), number(current) = number(incoming), hash(incoming) > hash(current)", headerD, headerE, true}, } - _ = testCases // nolint: paralleltest for _, tc := range testCases {