Skip to content

Commit 880f139

Browse files
committed
beacon/engine, eth/catalyst: return block access lists in payload bodies v2
1 parent e7314c8 commit 880f139

3 files changed

Lines changed: 99 additions & 12 deletions

File tree

beacon/engine/types.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,12 @@ type ExecutionPayloadBody struct {
415415
Withdrawals []*types.Withdrawal `json:"withdrawals"`
416416
}
417417

418+
// ExecutionPayloadBodyV2 extends ExecutionPayloadBody with the block access list.
419+
type ExecutionPayloadBodyV2 struct {
420+
ExecutionPayloadBody
421+
BlockAccessList *bal.BlockAccessList `json:"blockAccessList"`
422+
}
423+
418424
// Client identifiers to support ClientVersionV1.
419425
const (
420426
ClientCode = "GE"

eth/catalyst/api.go

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1176,30 +1176,30 @@ func (api *ConsensusAPI) GetPayloadBodiesByHashV1(hashes []common.Hash) []*engin
11761176
return bodies
11771177
}
11781178

1179-
// GetPayloadBodiesByHashV2 implements engine_getPayloadBodiesByHashV1 which allows for retrieval of a list
1179+
// GetPayloadBodiesByHashV2 implements engine_getPayloadBodiesByHashV2 which allows for retrieval of a list
11801180
// of block bodies by the engine api.
1181-
func (api *ConsensusAPI) GetPayloadBodiesByHashV2(hashes []common.Hash) []*engine.ExecutionPayloadBody {
1182-
bodies := make([]*engine.ExecutionPayloadBody, len(hashes))
1181+
func (api *ConsensusAPI) GetPayloadBodiesByHashV2(hashes []common.Hash) []*engine.ExecutionPayloadBodyV2 {
1182+
bodies := make([]*engine.ExecutionPayloadBodyV2, len(hashes))
11831183
for i, hash := range hashes {
11841184
block := api.eth.BlockChain().GetBlockByHash(hash)
1185-
bodies[i] = getBody(block)
1185+
bodies[i] = getBodyV2(block)
11861186
}
11871187
return bodies
11881188
}
11891189

11901190
// GetPayloadBodiesByRangeV1 implements engine_getPayloadBodiesByRangeV1 which allows for retrieval of a range
11911191
// of block bodies by the engine api.
11921192
func (api *ConsensusAPI) GetPayloadBodiesByRangeV1(start, count hexutil.Uint64) ([]*engine.ExecutionPayloadBody, error) {
1193-
return api.getBodiesByRange(start, count)
1193+
return getBodiesByRange(api, start, count, getBody)
11941194
}
11951195

1196-
// GetPayloadBodiesByRangeV2 implements engine_getPayloadBodiesByRangeV1 which allows for retrieval of a range
1196+
// GetPayloadBodiesByRangeV2 implements engine_getPayloadBodiesByRangeV2 which allows for retrieval of a range
11971197
// of block bodies by the engine api.
1198-
func (api *ConsensusAPI) GetPayloadBodiesByRangeV2(start, count hexutil.Uint64) ([]*engine.ExecutionPayloadBody, error) {
1199-
return api.getBodiesByRange(start, count)
1198+
func (api *ConsensusAPI) GetPayloadBodiesByRangeV2(start, count hexutil.Uint64) ([]*engine.ExecutionPayloadBodyV2, error) {
1199+
return getBodiesByRange(api, start, count, getBodyV2)
12001200
}
12011201

1202-
func (api *ConsensusAPI) getBodiesByRange(start, count hexutil.Uint64) ([]*engine.ExecutionPayloadBody, error) {
1202+
func getBodiesByRange[T any](api *ConsensusAPI, start, count hexutil.Uint64, getBody func(*types.Block) *T) ([]*T, error) {
12031203
if start == 0 || count == 0 {
12041204
return nil, engine.InvalidParams.With(fmt.Errorf("invalid start or count, start: %v count: %v", start, count))
12051205
}
@@ -1212,7 +1212,7 @@ func (api *ConsensusAPI) getBodiesByRange(start, count hexutil.Uint64) ([]*engin
12121212
if last > current {
12131213
last = current
12141214
}
1215-
bodies := make([]*engine.ExecutionPayloadBody, 0, uint64(count))
1215+
bodies := make([]*T, 0, uint64(count))
12161216
for i := uint64(start); i <= last; i++ {
12171217
block := api.eth.BlockChain().GetBlockByNumber(i)
12181218
bodies = append(bodies, getBody(block))
@@ -1241,6 +1241,17 @@ func getBody(block *types.Block) *engine.ExecutionPayloadBody {
12411241
return &result
12421242
}
12431243

1244+
func getBodyV2(block *types.Block) *engine.ExecutionPayloadBodyV2 {
1245+
body := getBody(block)
1246+
if body == nil {
1247+
return nil
1248+
}
1249+
return &engine.ExecutionPayloadBodyV2{
1250+
ExecutionPayloadBody: *body,
1251+
BlockAccessList: block.AccessList(),
1252+
}
1253+
}
1254+
12441255
// convertRequests converts a hex requests slice to plain [][]byte.
12451256
func convertRequests(hex []hexutil.Bytes) [][]byte {
12461257
if hex == nil {

eth/catalyst/api_test.go

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import (
3939
"github.com/ethereum/go-ethereum/consensus/ethash"
4040
"github.com/ethereum/go-ethereum/core"
4141
"github.com/ethereum/go-ethereum/core/types"
42+
"github.com/ethereum/go-ethereum/core/types/bal"
4243
"github.com/ethereum/go-ethereum/crypto"
4344
"github.com/ethereum/go-ethereum/crypto/kzg4844"
4445
"github.com/ethereum/go-ethereum/eth"
@@ -1366,7 +1367,7 @@ func TestGetBlockBodiesByHash(t *testing.T) {
13661367
for k, test := range tests {
13671368
result := api.GetPayloadBodiesByHashV2(test.hashes)
13681369
for i, r := range result {
1369-
if err := checkEqualBody(test.results[i], r); err != nil {
1370+
if err := checkEqualBodyV2(test.results[i], r); err != nil {
13701371
t.Fatalf("test %v: invalid response: %v\nexpected %+v\ngot %+v", k, err, test.results[i], r)
13711372
}
13721373
}
@@ -1444,7 +1445,7 @@ func TestGetBlockBodiesByRange(t *testing.T) {
14441445
}
14451446
if len(result) == len(test.results) {
14461447
for i, r := range result {
1447-
if err := checkEqualBody(test.results[i], r); err != nil {
1448+
if err := checkEqualBodyV2(test.results[i], r); err != nil {
14481449
t.Fatalf("test %d: invalid response: %v\nexpected %+v\ngot %+v", k, err, test.results[i], r)
14491450
}
14501451
}
@@ -1520,6 +1521,75 @@ func checkEqualBody(a *types.Body, b *engine.ExecutionPayloadBody) error {
15201521
return nil
15211522
}
15221523

1524+
func checkEqualBodyV2(a *types.Body, b *engine.ExecutionPayloadBodyV2) error {
1525+
if b == nil {
1526+
return checkEqualBody(a, nil)
1527+
}
1528+
return checkEqualBody(a, &b.ExecutionPayloadBody)
1529+
}
1530+
1531+
func TestGetPayloadBodyV2BlockAccessList(t *testing.T) {
1532+
empty := bal.BlockAccessList{}
1533+
emptyHash := empty.Hash()
1534+
tests := []struct {
1535+
name string
1536+
header *types.Header
1537+
accessList *bal.BlockAccessList
1538+
want string
1539+
}{
1540+
{
1541+
name: "retained empty BAL",
1542+
header: &types.Header{BlockAccessListHash: &emptyHash},
1543+
accessList: &empty,
1544+
want: "[]",
1545+
},
1546+
{
1547+
name: "pruned BAL",
1548+
header: &types.Header{BlockAccessListHash: &emptyHash},
1549+
want: "null",
1550+
},
1551+
{
1552+
name: "pre-Amsterdam block",
1553+
header: new(types.Header),
1554+
want: "null",
1555+
},
1556+
}
1557+
for _, test := range tests {
1558+
t.Run(test.name, func(t *testing.T) {
1559+
block := types.NewBlockWithHeader(test.header).WithAccessListUnsafe(test.accessList)
1560+
body := getBodyV2(block)
1561+
encoded, err := json.Marshal(body)
1562+
if err != nil {
1563+
t.Fatal(err)
1564+
}
1565+
var fields map[string]json.RawMessage
1566+
if err := json.Unmarshal(encoded, &fields); err != nil {
1567+
t.Fatal(err)
1568+
}
1569+
if got := string(fields["blockAccessList"]); got != test.want {
1570+
t.Fatalf("unexpected blockAccessList: got %s, want %s", got, test.want)
1571+
}
1572+
})
1573+
}
1574+
}
1575+
1576+
func TestGetPayloadBodyV1OmitsBlockAccessList(t *testing.T) {
1577+
empty := bal.BlockAccessList{}
1578+
emptyHash := empty.Hash()
1579+
block := types.NewBlockWithHeader(&types.Header{BlockAccessListHash: &emptyHash}).WithAccessListUnsafe(&empty)
1580+
encoded, err := json.Marshal(getBody(block))
1581+
if err != nil {
1582+
t.Fatal(err)
1583+
}
1584+
var fields map[string]json.RawMessage
1585+
if err := json.Unmarshal(encoded, &fields); err != nil {
1586+
t.Fatal(err)
1587+
}
1588+
if _, ok := fields["blockAccessList"]; ok {
1589+
t.Fatal("V1 payload body contains blockAccessList")
1590+
}
1591+
}
1592+
15231593
func TestBlockToPayloadWithBlobs(t *testing.T) {
15241594
header := types.Header{}
15251595
var txs []*types.Transaction

0 commit comments

Comments
 (0)