Skip to content

eth/protocols/eth: drop protocol version eth/68#33511

Merged
fjl merged 17 commits intoethereum:masterfrom
healthykim:deprecate-eth68
Feb 28, 2026
Merged

eth/protocols/eth: drop protocol version eth/68#33511
fjl merged 17 commits intoethereum:masterfrom
healthykim:deprecate-eth68

Conversation

@healthykim
Copy link
Copy Markdown
Contributor

@healthykim healthykim commented Jan 2, 2026

This PR drops support for eth68.

@rjl493456442
Copy link
Copy Markdown
Member

We should ask other client teams if they have shipped eth69 before the Osaka fork. It's safer to deprecate eth68 if the majority of clients have eth69 available.

@healthykim
Copy link
Copy Markdown
Contributor Author

We should ask other client teams if they have shipped eth69 before the Osaka fork. It's safer to deprecate eth68 if the majority of clients have eth69 available.

When I checked the hive tests, all clients except Erigon were able to be connected using StatusPacket69 and process BlockRangeUpdatePacket messages. For Erigon we can ask, but I think we can at least say that most clients have implemented eth/69.

@healthykim healthykim marked this pull request as ready for review January 6, 2026 08:01
@fjl fjl self-assigned this Jan 6, 2026
@fjl fjl added this to the 1.17.1 milestone Jan 15, 2026
@healthykim
Copy link
Copy Markdown
Contributor Author

Commit 2fa04e1 is built on top of 7f09355 and removes receiptListBuffer. The benchmark below compares the two branches. The benchmark was generated by AI.

rlp.EncoderBuffer was shared previously, but it was allocated on the heap. After changing it to be allocated on demand, it is being allocated on the stack. Since the bloom buffer should be reused, I left it but replaced as a local variable.

goos: darwin
goarch: arm64
pkg: github.com/ethereum/go-ethereum/eth/protocols/eth
                                     │ /tmp/old_final.txt │         /tmp/new_final.txt         │
                                     │       sec/op       │   sec/op     vs base               │
HandleReceipts/blocks=1/rcpt=200-8           832.1µ ±  1%   827.0µ ± 0%       ~ (p=0.086 n=20)
HandleReceipts/blocks=16/rcpt=200-8          12.69m ±  0%   12.60m ± 0%  -0.72% (p=0.000 n=20)
HandleReceipts/blocks=64/rcpt=200-8          49.89m ±  0%   49.80m ± 0%  -0.18% (p=0.002 n=20)
HandleReceipts/blocks=128/rcpt=200-8        100.14m ±  1%   99.41m ± 0%  -0.73% (p=0.008 n=20)
HandleReceipts/blocks=256/rcpt=200-8         202.6m ± 11%   198.9m ± 1%  -1.80% (p=0.001 n=20)
geomean                                      25.45m         25.25m       -0.81%

                                     │ /tmp/old_final.txt │         /tmp/new_final.txt          │
                                     │        B/op        │     B/op      vs base               │
HandleReceipts/blocks=1/rcpt=200-8           392.8Ki ± 0%   392.5Ki ± 0%  -0.08% (p=0.024 n=20)
HandleReceipts/blocks=16/rcpt=200-8          3.660Mi ± 0%   3.661Mi ± 0%       ~ (p=0.565 n=20)
HandleReceipts/blocks=64/rcpt=200-8          14.10Mi ± 0%   14.10Mi ± 0%       ~ (p=0.841 n=20)
HandleReceipts/blocks=128/rcpt=200-8         27.99Mi ± 0%   27.99Mi ± 0%       ~ (p=0.134 n=20)
HandleReceipts/blocks=256/rcpt=200-8         55.74Mi ± 0%   55.74Mi ± 0%       ~ (p=0.298 n=20)
geomean                                      7.905Mi        7.904Mi       -0.01%

                                     │ /tmp/old_final.txt │         /tmp/new_final.txt         │
                                     │     allocs/op      │  allocs/op   vs base               │
HandleReceipts/blocks=1/rcpt=200-8             886.0 ± 0%    886.0 ± 0%       ~ (p=0.182 n=20)
HandleReceipts/blocks=16/rcpt=200-8           13.42k ± 0%   13.40k ± 0%  -0.12% (p=0.000 n=20)
HandleReceipts/blocks=64/rcpt=200-8           53.47k ± 0%   53.41k ± 0%  -0.12% (p=0.000 n=20)
HandleReceipts/blocks=128/rcpt=200-8          106.8k ± 0%   106.7k ± 0%  -0.12% (p=0.000 n=20)
HandleReceipts/blocks=256/rcpt=200-8          213.4k ± 0%   213.2k ± 0%  -0.12% (p=0.000 n=20)
geomean                                       27.05k        27.03k       -0.09%

with buffer (old)

func makeTestReceipts(n int) []*types.Receipt {
	receipts := make([]*types.Receipt, n)
	for i := range receipts {
		r := &types.Receipt{
			Type:              types.DynamicFeeTxType,
			Status:            types.ReceiptStatusSuccessful,
			CumulativeGasUsed: uint64(21000 * (i + 1)),
			Logs: []*types.Log{
				{
					Address: common.Address{byte(i % 256)},
					Topics:  []common.Hash{{byte(i)}, {byte(i + 1)}},
					Data:    []byte{1, 2, 3, 4},
				},
				{
					Address: common.Address{byte((i + 1) % 256)},
					Topics:  []common.Hash{{byte(i + 2)}},
					Data:    []byte{5, 6, 7, 8, 9, 10},
				},
			},
		}
		r.Bloom = types.CreateBloom(r)
		receipts[i] = r
	}
	return receipts
}

func BenchmarkHandleReceipts(b *testing.B) {
	for _, tc := range []struct {
		blocks           int
		receiptsPerBlock int
	}{
		{1, 200},
		{16, 200},
		{64, 200},
		{128, 200},
		{256, 200},
	} {
		name := fmt.Sprintf("blocks=%d/rcpt=%d", tc.blocks, tc.receiptsPerBlock)
		b.Run(name, func(b *testing.B) {
			lists := make([]*ReceiptList, tc.blocks)
			for i := range lists {
				lists[i] = NewReceiptList(makeTestReceipts(tc.receiptsPerBlock))
			}
			rawList, err := rlp.EncodeToRawList(lists)
			if err != nil {
				b.Fatal(err)
			}
			pkt := ReceiptsPacket{RequestId: 1, List: rawList}
			encoded, err := rlp.EncodeToBytes(&pkt)
			if err != nil {
				b.Fatal(err)
			}

			b.ReportAllocs()
			b.ResetTimer()
			for i := 0; i < b.N; i++ {
				var res ReceiptsPacket
				if err := rlp.DecodeBytes(encoded, &res); err != nil {
					b.Fatal(err)
				}
				receiptLists, err := res.List.Items()
				if err != nil {
					b.Fatal(err)
				}
				buffers := new(receiptListBuffers)
				for j := range receiptLists {
					receiptLists[j].setBuffers(buffers)
				}
				hasher := trie.NewStackTrie(nil)
				for j := range receiptLists {
					types.DeriveSha(receiptLists[j].Derivable(), hasher)
				}
				for j := range receiptLists {
					if _, err := receiptLists[j].EncodeForStorage(); err != nil {
						b.Fatal(err)
					}
				}
			}
		})
	}
}

without buffer (new)

func makeTestReceipts(n int) []*types.Receipt {
	receipts := make([]*types.Receipt, n)
	for i := range receipts {
		r := &types.Receipt{
			Type:              types.DynamicFeeTxType,
			Status:            types.ReceiptStatusSuccessful,
			CumulativeGasUsed: uint64(21000 * (i + 1)),
			Logs: []*types.Log{
				{
					Address: common.Address{byte(i % 256)},
					Topics:  []common.Hash{{byte(i)}, {byte(i + 1)}},
					Data:    []byte{1, 2, 3, 4},
				},
				{
					Address: common.Address{byte((i + 1) % 256)},
					Topics:  []common.Hash{{byte(i + 2)}},
					Data:    []byte{5, 6, 7, 8, 9, 10},
				},
			},
		}
		r.Bloom = types.CreateBloom(r)
		receipts[i] = r
	}
	return receipts
}

func BenchmarkHandleReceipts(b *testing.B) {
	for _, tc := range []struct {
		blocks           int
		receiptsPerBlock int
	}{
		{1, 200},
		{16, 200},
		{64, 200},
		{128, 200},
		{256, 200},
	} {
		name := fmt.Sprintf("blocks=%d/rcpt=%d", tc.blocks, tc.receiptsPerBlock)
		b.Run(name, func(b *testing.B) {
			lists := make([]*ReceiptList, tc.blocks)
			for i := range lists {
				lists[i] = NewReceiptList(makeTestReceipts(tc.receiptsPerBlock))
			}
			rawList, err := rlp.EncodeToRawList(lists)
			if err != nil {
				b.Fatal(err)
			}
			pkt := ReceiptsPacket{RequestId: 1, List: rawList}
			encoded, err := rlp.EncodeToBytes(&pkt)
			if err != nil {
				b.Fatal(err)
			}

			b.ReportAllocs()
			b.ResetTimer()
			for i := 0; i < b.N; i++ {
				var res ReceiptsPacket
				if err := rlp.DecodeBytes(encoded, &res); err != nil {
					b.Fatal(err)
				}
				receiptLists, err := res.List.Items()
				if err != nil {
					b.Fatal(err)
				}
				hasher := trie.NewStackTrie(nil)
				var bloomBuf [6]byte
				writeReceipt := writeReceiptForHash(&bloomBuf)
				for j := range receiptLists {
					receipts := newDerivableRawList(&receiptLists[j].items, writeReceipt)
					types.DeriveSha(receipts, hasher)
				}
				for j := range receiptLists {
					if _, err := receiptLists[j].EncodeForStorage(); err != nil {
						b.Fatal(err)
					}
				}
			}
		})
	}
}


}
}

// Tests that synchronisations behave well in multi-version protocol environments
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed this because the purpose of this test was checking how sync behaves with peers which have different protocol versions. However, the test was only using one peer, and it was now labeled as "peer 68" but used eth/69. Best to just remove it.

@fjl fjl changed the title cmd/devp2p, eth: drop eth/68 eth/protocols/eth: drop protocol version eth/68 Feb 28, 2026
fjl
fjl previously approved these changes Feb 28, 2026
@fjl fjl merged commit 723aae2 into ethereum:master Feb 28, 2026
7 of 8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants