mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-04 20:21:15 +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 (
|
||||
hashes []common.Hash
|
||||
expect rlp.RawList[RawBlockAccessList]
|
||||
expect rlp.RawList[rlp.RawValue]
|
||||
)
|
||||
for i := uint64(0); i <= backend.chain.CurrentBlock().Number.Uint64(); 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 {
|
||||
msg []byte
|
||||
}
|
||||
|
|
|
|||
|
|
@ -679,10 +679,10 @@ func handleGetBlockAccessLists(backend Backend, msg Decoder, peer *Peer) error {
|
|||
|
||||
// serviceGetBlockAccessListsQuery assembles the response to a BAL query.
|
||||
// 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 (
|
||||
bytes int
|
||||
bals rlp.RawList[RawBlockAccessList]
|
||||
bals rlp.RawList[rlp.RawValue]
|
||||
)
|
||||
for _, hash := range query {
|
||||
if bytes >= softResponseLimit || bals.Len() >= maxBALsServe {
|
||||
|
|
@ -720,7 +720,12 @@ func handleBlockAccessLists(backend Backend, msg Decoder, peer *Peer) error {
|
|||
metadata := func() interface{} {
|
||||
hashes := make([]common.Hash, len(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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -258,7 +258,7 @@ func (p *Peer) ReplyReceiptsRLP70(id uint64, receipts rlp.RawList[*ReceiptList],
|
|||
}
|
||||
|
||||
// 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{
|
||||
RequestId: id,
|
||||
List: list,
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ import (
|
|||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/forkid"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/core/types/bal"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
)
|
||||
|
||||
|
|
@ -299,15 +298,14 @@ type GetBlockAccessListsPacket struct {
|
|||
GetBlockAccessListsRequest
|
||||
}
|
||||
|
||||
type RawBlockAccessList struct {
|
||||
rlp.RawList[bal.AccountAccess]
|
||||
}
|
||||
|
||||
type BlockAccessListResponse []RawBlockAccessList
|
||||
// BlockAccessListResponse holds one raw entry per requested hash. Entries are
|
||||
// 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 BlockAccessListPacket struct {
|
||||
RequestId uint64
|
||||
List rlp.RawList[RawBlockAccessList]
|
||||
List rlp.RawList[rlp.RawValue]
|
||||
}
|
||||
|
||||
func (*StatusPacket) Name() string { return "Status" }
|
||||
|
|
|
|||
Loading…
Reference in a new issue