mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-18 02:40:45 +00:00
eth/protocols/eth: fix blockAccessList empty marker (#35286)
This PR addresses an issue in the eth71 `BlockAccessListsMsg` handler, specifically: - if the requested bal is not accessible in the server side, 0x80 (EmptyString) will be returned as the marker - at the client side, old message definition `rlp.RawList[RawBlockAccessList]` assumes all the elements are List - the message with 0x80 (kind = string) won't be decoded correctly - the peer will be disconnected The message definition has been changed to `rlp.RawList[rlp.RawValue]`, which is aligned with the one in SNAP/2 protocol.
This commit is contained in:
parent
aa3d286f54
commit
3006c4411b
4 changed files with 51 additions and 12 deletions
|
|
@ -742,7 +742,7 @@ func testGetBlockAccessLists(t *testing.T, protocol uint) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
hashes []common.Hash
|
hashes []common.Hash
|
||||||
expect rlp.RawList[RawBlockAccessList]
|
expect rlp.RawList[rlp.RawValue]
|
||||||
)
|
)
|
||||||
for i := uint64(0); i <= backend.chain.CurrentBlock().Number.Uint64(); i++ {
|
for i := uint64(0); i <= backend.chain.CurrentBlock().Number.Uint64(); i++ {
|
||||||
block := backend.chain.GetBlockByNumber(i)
|
block := backend.chain.GetBlockByNumber(i)
|
||||||
|
|
@ -771,6 +771,42 @@ func testGetBlockAccessLists(t *testing.T, protocol uint) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestBlockAccessListsUnavailableDecode checks that a BlockAccessLists response
|
||||||
|
// containing the EIP-8159 unavailability marker (RLP empty string).
|
||||||
|
func TestBlockAccessListsUnavailableDecode(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
balRaw := makeTestBAL(t, common.Address{0x11})
|
||||||
|
|
||||||
|
// Assemble a response the way the serving side does, with the middle
|
||||||
|
// entry signaled as unavailable.
|
||||||
|
var list rlp.RawList[rlp.RawValue]
|
||||||
|
list.AppendRaw(balRaw)
|
||||||
|
list.AppendRaw(rlp.EmptyString)
|
||||||
|
list.AppendRaw(balRaw)
|
||||||
|
|
||||||
|
enc, err := rlp.EncodeToBytes(&BlockAccessListPacket{RequestId: 42, List: list})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to encode packet: %v", err)
|
||||||
|
}
|
||||||
|
var packet BlockAccessListPacket
|
||||||
|
if err := rlp.DecodeBytes(enc, &packet); err != nil {
|
||||||
|
t.Fatalf("failed to decode packet: %v", err)
|
||||||
|
}
|
||||||
|
bals, err := packet.List.Items()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to decode BAL entries: %v", err)
|
||||||
|
}
|
||||||
|
if len(bals) != 3 {
|
||||||
|
t.Fatalf("wrong entry count: got %d, want 3", len(bals))
|
||||||
|
}
|
||||||
|
for i, want := range [][]byte{balRaw, rlp.EmptyString, balRaw} {
|
||||||
|
if !bytes.Equal(bals[i], want) {
|
||||||
|
t.Errorf("entry %d mismatch: got %x, want %x", i, bals[i], want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type decoder struct {
|
type decoder struct {
|
||||||
msg []byte
|
msg []byte
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -679,10 +679,10 @@ func handleGetBlockAccessLists(backend Backend, msg Decoder, peer *Peer) error {
|
||||||
|
|
||||||
// serviceGetBlockAccessListsQuery assembles the response to a BAL query.
|
// serviceGetBlockAccessListsQuery assembles the response to a BAL query.
|
||||||
// Unavailable BALs are returned as empty list entries.
|
// Unavailable BALs are returned as empty list entries.
|
||||||
func serviceGetBlockAccessListsQuery(chain *core.BlockChain, query GetBlockAccessListsRequest) rlp.RawList[RawBlockAccessList] {
|
func serviceGetBlockAccessListsQuery(chain *core.BlockChain, query GetBlockAccessListsRequest) rlp.RawList[rlp.RawValue] {
|
||||||
var (
|
var (
|
||||||
bytes int
|
bytes int
|
||||||
bals rlp.RawList[RawBlockAccessList]
|
bals rlp.RawList[rlp.RawValue]
|
||||||
)
|
)
|
||||||
for _, hash := range query {
|
for _, hash := range query {
|
||||||
if bytes >= softResponseLimit || bals.Len() >= maxBALsServe {
|
if bytes >= softResponseLimit || bals.Len() >= maxBALsServe {
|
||||||
|
|
@ -720,7 +720,12 @@ func handleBlockAccessLists(backend Backend, msg Decoder, peer *Peer) error {
|
||||||
metadata := func() interface{} {
|
metadata := func() interface{} {
|
||||||
hashes := make([]common.Hash, len(bals))
|
hashes := make([]common.Hash, len(bals))
|
||||||
for i := range bals {
|
for i := range bals {
|
||||||
hashes[i] = crypto.Keccak256Hash(bals[i].Bytes())
|
// Unavailable BALs (signaled by the empty string) are marked
|
||||||
|
// with the zero hash
|
||||||
|
if bytes.Equal(bals[i], rlp.EmptyString) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
hashes[i] = crypto.Keccak256Hash(bals[i])
|
||||||
}
|
}
|
||||||
return hashes
|
return hashes
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -258,7 +258,7 @@ func (p *Peer) ReplyReceiptsRLP70(id uint64, receipts rlp.RawList[*ReceiptList],
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReplyBlockAccessLists is the response to GetBlockAccessLists (EIP-8159).
|
// ReplyBlockAccessLists is the response to GetBlockAccessLists (EIP-8159).
|
||||||
func (p *Peer) ReplyBlockAccessLists(id uint64, list rlp.RawList[RawBlockAccessList]) error {
|
func (p *Peer) ReplyBlockAccessLists(id uint64, list rlp.RawList[rlp.RawValue]) error {
|
||||||
return p2p.Send(p.rw, BlockAccessListsMsg, &BlockAccessListPacket{
|
return p2p.Send(p.rw, BlockAccessListsMsg, &BlockAccessListPacket{
|
||||||
RequestId: id,
|
RequestId: id,
|
||||||
List: list,
|
List: list,
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/forkid"
|
"github.com/ethereum/go-ethereum/core/forkid"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/types/bal"
|
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -299,15 +298,14 @@ type GetBlockAccessListsPacket struct {
|
||||||
GetBlockAccessListsRequest
|
GetBlockAccessListsRequest
|
||||||
}
|
}
|
||||||
|
|
||||||
type RawBlockAccessList struct {
|
// BlockAccessListResponse holds one raw entry per requested hash. Entries are
|
||||||
rlp.RawList[bal.AccountAccess]
|
// kept as raw values because, per EIP-8159, the RLP empty string signals an
|
||||||
}
|
// unavailable BAL (an empty list is itself a valid BAL).
|
||||||
|
type BlockAccessListResponse []rlp.RawValue
|
||||||
type BlockAccessListResponse []RawBlockAccessList
|
|
||||||
|
|
||||||
type BlockAccessListPacket struct {
|
type BlockAccessListPacket struct {
|
||||||
RequestId uint64
|
RequestId uint64
|
||||||
List rlp.RawList[RawBlockAccessList]
|
List rlp.RawList[rlp.RawValue]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*StatusPacket) Name() string { return "Status" }
|
func (*StatusPacket) Name() string { return "Status" }
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue