diff --git a/eth/taiko_api_backend.go b/eth/taiko_api_backend.go index 49e8580b664f..404e88ae21c8 100644 --- a/eth/taiko_api_backend.go +++ b/eth/taiko_api_backend.go @@ -89,3 +89,26 @@ func (s *TaikoAPIBackend) TxPoolContent( maxTransactionsLists, ) } + +// Get L2ParentHashes retrieves the preceding 256 parent hashes given a block number. +func (s *TaikoAPIBackend) GetL2ParentHashes(blockID uint64) ([]common.Hash, error) { + var hashes []common.Hash + headers, err := s.GetL2ParentHeaders(blockID) + if err != nil { + return nil, err + } + + for _, x := range headers { + hashes = append(hashes, x.Hash()) + } + return hashes, nil +} + +// Get L2ParentBlocks retrieves the preceding 256 parent blocks given a block number. +func (s *TaikoAPIBackend) GetL2ParentHeaders(blockID uint64) ([]*types.Header, error) { + var headers []*types.Header + for i := blockID; i != 0 && (blockID-i) < 256; i-- { + headers = append(headers, s.eth.blockchain.GetHeaderByNumber(blockID-i)) + } + return headers, nil +} diff --git a/ethclient/taiko_api.go b/ethclient/taiko_api.go index 9637608d062f..dd3372b121c2 100644 --- a/ethclient/taiko_api.go +++ b/ethclient/taiko_api.go @@ -4,6 +4,7 @@ import ( "context" "math/big" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/rawdb" ) @@ -29,3 +30,23 @@ func (ec *Client) L1OriginByID(ctx context.Context, blockID *big.Int) (*rawdb.L1 return res, nil } + +func (ec *Client) GetL2ParentHashes(ctx context.Context, blockID uint64) ([]common.Hash, error) { + var res []common.Hash + + if err := ec.c.CallContext(ctx, &res, "taiko_getL2ParentHashes", blockID); err != nil { + return nil, err + } + + return res, nil +} + +func (ec *Client) GetL2ParentHeaders(ctx context.Context, blockID uint64) ([]map[string]interface{}, error) { + var res []map[string]interface{} + + if err := ec.c.CallContext(ctx, &res, "taiko_getL2ParentHeaders", blockID); err != nil { + return nil, err + } + + return res, nil +} diff --git a/ethclient/taiko_api_test.go b/ethclient/taiko_api_test.go index 7a7cfc7dcd4c..76b86b3263cd 100644 --- a/ethclient/taiko_api_test.go +++ b/ethclient/taiko_api_test.go @@ -104,6 +104,55 @@ func TestL1OriginByID(t *testing.T) { require.Equal(t, testL1Origin, l1OriginFound) } +func TestGetL2ParentHashes(t *testing.T) { + ec, blocks, _ := newTaikoAPITestClient(t) + + hashes, err := ec.GetL2ParentHashes(context.Background(), common.Big3.Uint64()) + require.Nil(t, err) + + log.Info("hashes", "a", hashes) + require.Equal(t, 3, len(hashes)) + require.Equal(t, blocks[0].Hash(), hashes[0]) + require.Equal(t, blocks[1].Hash(), hashes[1]) + require.Equal(t, blocks[2].Hash(), hashes[2]) + + hashes, err = ec.GetL2ParentHashes(context.Background(), common.Big2.Uint64()) + require.Nil(t, err) + + require.Equal(t, 2, len(hashes)) + require.Equal(t, blocks[0].Hash(), hashes[0]) + require.Equal(t, blocks[1].Hash(), hashes[1]) + + hashes, err = ec.GetL2ParentHashes(context.Background(), common.Big0.Uint64()) + require.Nil(t, err) + + require.Equal(t, 0, len(hashes)) +} + +func TestGetL2ParentBlocks(t *testing.T) { + ec, blocks, _ := newTaikoAPITestClient(t) + + res, err := ec.GetL2ParentHeaders(context.Background(), common.Big3.Uint64()) + require.Nil(t, err) + + require.Equal(t, 3, len(res)) + require.Equal(t, res[0]["hash"], blocks[0].Hash().String()) + require.Equal(t, res[1]["hash"], blocks[1].Hash().String()) + require.Equal(t, res[2]["hash"], blocks[2].Hash().String()) + + res, err = ec.GetL2ParentHeaders(context.Background(), common.Big2.Uint64()) + require.Nil(t, err) + + require.Equal(t, 2, len(res)) + require.Equal(t, res[0]["hash"], blocks[0].Hash().String()) + require.Equal(t, res[1]["hash"], blocks[1].Hash().String()) + + res, err = ec.GetL2ParentHeaders(context.Background(), common.Big0.Uint64()) + require.Nil(t, err) + + require.Equal(t, 0, len(res)) +} + // randomHash generates a random blob of data and returns it as a hash. func randomHash() common.Hash { var hash common.Hash