mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-17 10:20:44 +00:00
beacon/engine, eth/catalyst: return block access lists in payload bodies v2 (#35347)
This commit is contained in:
parent
e7314c8a13
commit
b34a925e9e
3 changed files with 99 additions and 12 deletions
|
|
@ -415,6 +415,12 @@ type ExecutionPayloadBody struct {
|
||||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExecutionPayloadBodyV2 extends ExecutionPayloadBody with the block access list.
|
||||||
|
type ExecutionPayloadBodyV2 struct {
|
||||||
|
ExecutionPayloadBody
|
||||||
|
BlockAccessList *bal.BlockAccessList `json:"blockAccessList"`
|
||||||
|
}
|
||||||
|
|
||||||
// Client identifiers to support ClientVersionV1.
|
// Client identifiers to support ClientVersionV1.
|
||||||
const (
|
const (
|
||||||
ClientCode = "GE"
|
ClientCode = "GE"
|
||||||
|
|
|
||||||
|
|
@ -1176,13 +1176,13 @@ func (api *ConsensusAPI) GetPayloadBodiesByHashV1(hashes []common.Hash) []*engin
|
||||||
return bodies
|
return bodies
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPayloadBodiesByHashV2 implements engine_getPayloadBodiesByHashV1 which allows for retrieval of a list
|
// GetPayloadBodiesByHashV2 implements engine_getPayloadBodiesByHashV2 which allows for retrieval of a list
|
||||||
// of block bodies by the engine api.
|
// of block bodies by the engine api.
|
||||||
func (api *ConsensusAPI) GetPayloadBodiesByHashV2(hashes []common.Hash) []*engine.ExecutionPayloadBody {
|
func (api *ConsensusAPI) GetPayloadBodiesByHashV2(hashes []common.Hash) []*engine.ExecutionPayloadBodyV2 {
|
||||||
bodies := make([]*engine.ExecutionPayloadBody, len(hashes))
|
bodies := make([]*engine.ExecutionPayloadBodyV2, len(hashes))
|
||||||
for i, hash := range hashes {
|
for i, hash := range hashes {
|
||||||
block := api.eth.BlockChain().GetBlockByHash(hash)
|
block := api.eth.BlockChain().GetBlockByHash(hash)
|
||||||
bodies[i] = getBody(block)
|
bodies[i] = getBodyV2(block)
|
||||||
}
|
}
|
||||||
return bodies
|
return bodies
|
||||||
}
|
}
|
||||||
|
|
@ -1190,16 +1190,16 @@ func (api *ConsensusAPI) GetPayloadBodiesByHashV2(hashes []common.Hash) []*engin
|
||||||
// GetPayloadBodiesByRangeV1 implements engine_getPayloadBodiesByRangeV1 which allows for retrieval of a range
|
// GetPayloadBodiesByRangeV1 implements engine_getPayloadBodiesByRangeV1 which allows for retrieval of a range
|
||||||
// of block bodies by the engine api.
|
// of block bodies by the engine api.
|
||||||
func (api *ConsensusAPI) GetPayloadBodiesByRangeV1(start, count hexutil.Uint64) ([]*engine.ExecutionPayloadBody, error) {
|
func (api *ConsensusAPI) GetPayloadBodiesByRangeV1(start, count hexutil.Uint64) ([]*engine.ExecutionPayloadBody, error) {
|
||||||
return api.getBodiesByRange(start, count)
|
return getBodiesByRange(api, start, count, getBody)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPayloadBodiesByRangeV2 implements engine_getPayloadBodiesByRangeV1 which allows for retrieval of a range
|
// GetPayloadBodiesByRangeV2 implements engine_getPayloadBodiesByRangeV2 which allows for retrieval of a range
|
||||||
// of block bodies by the engine api.
|
// of block bodies by the engine api.
|
||||||
func (api *ConsensusAPI) GetPayloadBodiesByRangeV2(start, count hexutil.Uint64) ([]*engine.ExecutionPayloadBody, error) {
|
func (api *ConsensusAPI) GetPayloadBodiesByRangeV2(start, count hexutil.Uint64) ([]*engine.ExecutionPayloadBodyV2, error) {
|
||||||
return api.getBodiesByRange(start, count)
|
return getBodiesByRange(api, start, count, getBodyV2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *ConsensusAPI) getBodiesByRange(start, count hexutil.Uint64) ([]*engine.ExecutionPayloadBody, error) {
|
func getBodiesByRange[T any](api *ConsensusAPI, start, count hexutil.Uint64, getBody func(*types.Block) *T) ([]*T, error) {
|
||||||
if start == 0 || count == 0 {
|
if start == 0 || count == 0 {
|
||||||
return nil, engine.InvalidParams.With(fmt.Errorf("invalid start or count, start: %v count: %v", start, count))
|
return nil, engine.InvalidParams.With(fmt.Errorf("invalid start or count, start: %v count: %v", start, count))
|
||||||
}
|
}
|
||||||
|
|
@ -1212,7 +1212,7 @@ func (api *ConsensusAPI) getBodiesByRange(start, count hexutil.Uint64) ([]*engin
|
||||||
if last > current {
|
if last > current {
|
||||||
last = current
|
last = current
|
||||||
}
|
}
|
||||||
bodies := make([]*engine.ExecutionPayloadBody, 0, uint64(count))
|
bodies := make([]*T, 0, uint64(count))
|
||||||
for i := uint64(start); i <= last; i++ {
|
for i := uint64(start); i <= last; i++ {
|
||||||
block := api.eth.BlockChain().GetBlockByNumber(i)
|
block := api.eth.BlockChain().GetBlockByNumber(i)
|
||||||
bodies = append(bodies, getBody(block))
|
bodies = append(bodies, getBody(block))
|
||||||
|
|
@ -1241,6 +1241,17 @@ func getBody(block *types.Block) *engine.ExecutionPayloadBody {
|
||||||
return &result
|
return &result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getBodyV2(block *types.Block) *engine.ExecutionPayloadBodyV2 {
|
||||||
|
body := getBody(block)
|
||||||
|
if body == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &engine.ExecutionPayloadBodyV2{
|
||||||
|
ExecutionPayloadBody: *body,
|
||||||
|
BlockAccessList: block.AccessList(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// convertRequests converts a hex requests slice to plain [][]byte.
|
// convertRequests converts a hex requests slice to plain [][]byte.
|
||||||
func convertRequests(hex []hexutil.Bytes) [][]byte {
|
func convertRequests(hex []hexutil.Bytes) [][]byte {
|
||||||
if hex == nil {
|
if hex == nil {
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/consensus/ethash"
|
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"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/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/crypto/kzg4844"
|
"github.com/ethereum/go-ethereum/crypto/kzg4844"
|
||||||
"github.com/ethereum/go-ethereum/eth"
|
"github.com/ethereum/go-ethereum/eth"
|
||||||
|
|
@ -1366,7 +1367,7 @@ func TestGetBlockBodiesByHash(t *testing.T) {
|
||||||
for k, test := range tests {
|
for k, test := range tests {
|
||||||
result := api.GetPayloadBodiesByHashV2(test.hashes)
|
result := api.GetPayloadBodiesByHashV2(test.hashes)
|
||||||
for i, r := range result {
|
for i, r := range result {
|
||||||
if err := checkEqualBody(test.results[i], r); err != nil {
|
if err := checkEqualBodyV2(test.results[i], r); err != nil {
|
||||||
t.Fatalf("test %v: invalid response: %v\nexpected %+v\ngot %+v", k, err, test.results[i], r)
|
t.Fatalf("test %v: invalid response: %v\nexpected %+v\ngot %+v", k, err, test.results[i], r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1444,7 +1445,7 @@ func TestGetBlockBodiesByRange(t *testing.T) {
|
||||||
}
|
}
|
||||||
if len(result) == len(test.results) {
|
if len(result) == len(test.results) {
|
||||||
for i, r := range result {
|
for i, r := range result {
|
||||||
if err := checkEqualBody(test.results[i], r); err != nil {
|
if err := checkEqualBodyV2(test.results[i], r); err != nil {
|
||||||
t.Fatalf("test %d: invalid response: %v\nexpected %+v\ngot %+v", k, err, test.results[i], r)
|
t.Fatalf("test %d: invalid response: %v\nexpected %+v\ngot %+v", k, err, test.results[i], r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1520,6 +1521,75 @@ func checkEqualBody(a *types.Body, b *engine.ExecutionPayloadBody) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func checkEqualBodyV2(a *types.Body, b *engine.ExecutionPayloadBodyV2) error {
|
||||||
|
if b == nil {
|
||||||
|
return checkEqualBody(a, nil)
|
||||||
|
}
|
||||||
|
return checkEqualBody(a, &b.ExecutionPayloadBody)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetPayloadBodyV2BlockAccessList(t *testing.T) {
|
||||||
|
empty := bal.BlockAccessList{}
|
||||||
|
emptyHash := empty.Hash()
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
header *types.Header
|
||||||
|
accessList *bal.BlockAccessList
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "retained empty BAL",
|
||||||
|
header: &types.Header{BlockAccessListHash: &emptyHash},
|
||||||
|
accessList: &empty,
|
||||||
|
want: "[]",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "pruned BAL",
|
||||||
|
header: &types.Header{BlockAccessListHash: &emptyHash},
|
||||||
|
want: "null",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "pre-Amsterdam block",
|
||||||
|
header: new(types.Header),
|
||||||
|
want: "null",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
block := types.NewBlockWithHeader(test.header).WithAccessListUnsafe(test.accessList)
|
||||||
|
body := getBodyV2(block)
|
||||||
|
encoded, err := json.Marshal(body)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
var fields map[string]json.RawMessage
|
||||||
|
if err := json.Unmarshal(encoded, &fields); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if got := string(fields["blockAccessList"]); got != test.want {
|
||||||
|
t.Fatalf("unexpected blockAccessList: got %s, want %s", got, test.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetPayloadBodyV1OmitsBlockAccessList(t *testing.T) {
|
||||||
|
empty := bal.BlockAccessList{}
|
||||||
|
emptyHash := empty.Hash()
|
||||||
|
block := types.NewBlockWithHeader(&types.Header{BlockAccessListHash: &emptyHash}).WithAccessListUnsafe(&empty)
|
||||||
|
encoded, err := json.Marshal(getBody(block))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
var fields map[string]json.RawMessage
|
||||||
|
if err := json.Unmarshal(encoded, &fields); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if _, ok := fields["blockAccessList"]; ok {
|
||||||
|
t.Fatal("V1 payload body contains blockAccessList")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestBlockToPayloadWithBlobs(t *testing.T) {
|
func TestBlockToPayloadWithBlobs(t *testing.T) {
|
||||||
header := types.Header{}
|
header := types.Header{}
|
||||||
var txs []*types.Transaction
|
var txs []*types.Transaction
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue