Skip to content

Commit

Permalink
123
Browse files Browse the repository at this point in the history
  • Loading branch information
zsfelfoldi committed May 5, 2024
1 parent 3769f6d commit 8d158db
Show file tree
Hide file tree
Showing 5 changed files with 357 additions and 27 deletions.
11 changes: 11 additions & 0 deletions beacon/types/exec_header.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,14 @@ func (eh *ExecutionHeader) ParentHash() common.Hash {
panic(fmt.Errorf("unsupported ExecutionPayloadHeader type %T", obj))
}
}

func (eh *ExecutionHeader) StateRoot() common.Hash {
switch obj := eh.obj.(type) {
case *capella.ExecutionPayloadHeader:
return common.Hash(obj.StateRoot)
case *deneb.ExecutionPayloadHeader:
return common.Hash(obj.StateRoot)
default:
panic(fmt.Errorf("unsupported ExecutionPayloadHeader type %T", obj))
}
}
16 changes: 15 additions & 1 deletion cmd/bltest/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@
package main

import (
"context"
"fmt"
"io"
"os"

"github.com/ethereum/go-ethereum/beacon/config"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient/lightclient"
"github.com/ethereum/go-ethereum/internal/flags"
"github.com/ethereum/go-ethereum/log"
Expand Down Expand Up @@ -91,8 +93,20 @@ func sync(ctx *cli.Context) error {
client := lightclient.NewClient(config.MakeLightClientConfig(ctx), nil, rpcClient)
client.Start()

headCh := make(chan *types.Header, 1)
client.SubscribeNewHead(context.Background(), headCh)

// run until stopped
<-ctx.Done()
loop:
for {
select {
case head := <-headCh:
log.Info("New head received", "number", head.Number, "hash", head.Hash())
case <-ctx.Done():
break loop
}
}

client.Stop()
return nil
}
35 changes: 35 additions & 0 deletions ethclient/lightclient/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,41 @@ func (c *canonicalChain) getFinality() *btypes.ExecutionHeader {
return c.finality
}

func (c *canonicalChain) resolveBlockNumber(number *big.Int) (uint64, *btypes.ExecutionHeader, error) {
if !number.IsInt64() {
return 0, nil, errors.New("Invalid block number")
}
num := number.Int64()
if num < 0 {
switch rpc.BlockNumber(num) {
case rpc.SafeBlockNumber, rpc.FinalizedBlockNumber:
if header := c.getFinality(); header != nil {
return header.BlockNumber(), header, nil
}
return 0, nil, errors.New("Finalized block unknown")
case rpc.LatestBlockNumber, rpc.PendingBlockNumber:
if header := c.getHead(); header != nil {
return header.BlockNumber(), header, nil
}
return 0, nil, errors.New("Head block unknown")
default:
return 0, nil, errors.New("Invalid block number")
}
}
return uint64(num), nil, nil
}

func (c *canonicalChain) blockNumberToHash(ctx context.Context, number *big.Int) (common.Hash, error) {
num, header, err := c.resolveBlockNumber(number)
if err != nil {
return common.Hash{}, err
}
if header != nil {
return header.BlockHash(), nil
}
return c.getHash(ctx, num)
}

type blocksAndHeaders struct {
lock sync.Mutex
client *rpc.Client
Expand Down
59 changes: 33 additions & 26 deletions ethclient/lightclient/lightclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ type Client struct {
scheduler *request.Scheduler
canonicalChain *canonicalChain
blocksAndHeaders *blocksAndHeaders
state *lightState
headSubLock ssync.Mutex
headSubs map[*headSub]struct{}
cancelHeadFetch func()
Expand All @@ -60,6 +61,7 @@ func NewClient(config config.LightClientConfig, db ethdb.Database, rpcClient *rp
}
canonicalChain := newCanonicalChain(headTracker, blocksAndHeaders, client.newHead)
client.canonicalChain = canonicalChain
client.state = newLightState(rpcClient, canonicalChain, blocksAndHeaders)

checkpointInit := sync.NewCheckpointInit(committeeChain, config.Checkpoint)
forwardSync := sync.NewForwardUpdateSync(committeeChain)
Expand All @@ -85,32 +87,8 @@ func (c *Client) BlockByHash(ctx context.Context, hash common.Hash) (*types.Bloc
return c.blocksAndHeaders.getBlock(ctx, hash)
}

func (c *Client) numberToHash(ctx context.Context, number *big.Int) (common.Hash, error) {
if !number.IsInt64() {
return common.Hash{}, errors.New("Invalid block number")
}
num := number.Int64()
if num < 0 {
switch rpc.BlockNumber(num) {
case rpc.SafeBlockNumber, rpc.FinalizedBlockNumber:
if header := c.canonicalChain.getFinality(); header != nil {
return header.BlockHash(), nil
}
return common.Hash{}, errors.New("Finalized block unknown")
case rpc.LatestBlockNumber, rpc.PendingBlockNumber:
if header := c.canonicalChain.getHead(); header != nil {
return header.BlockHash(), nil
}
return common.Hash{}, errors.New("Head block unknown")
default:
return common.Hash{}, errors.New("Invalid block number")
}
}
return c.canonicalChain.getHash(ctx, uint64(num))
}

func (c *Client) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) {
hash, err := c.numberToHash(ctx, number)
hash, err := c.canonicalChain.blockNumberToHash(ctx, number)
if err != nil {
return nil, err
}
Expand All @@ -122,7 +100,7 @@ func (c *Client) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Hea
}

func (c *Client) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) {
hash, err := c.numberToHash(ctx, number)
hash, err := c.canonicalChain.blockNumberToHash(ctx, number)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -205,3 +183,32 @@ func (h *headSub) Unsubscribe() {
func (h *headSub) Err() <-chan error {
return h.errCh
}

func (c *Client) BalanceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (*big.Int, error) {
proof, _, err := c.state.getProof(ctx, blockNumber, account, nil, false)
if err != nil {
return nil, err
}
return proof.Balance, nil
}

func (c *Client) StorageAt(ctx context.Context, account common.Address, key common.Hash, blockNumber *big.Int) ([]byte, error) {
proof, _, err := c.state.getProof(ctx, blockNumber, account, []string{key.Hex()}, false) //TODO hashed key?
if err != nil {
return nil, err
}
return stValueBytes(proof.StorageProof[0].Value)
}

func (c *Client) CodeAt(ctx context.Context, account common.Address, blockNumber *big.Int) ([]byte, error) {
_, code, err := c.state.getProof(ctx, blockNumber, account, nil, true)
return code, err
}

func (c *Client) NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error) {
proof, _, err := c.state.getProof(ctx, blockNumber, account, nil, false)
if err != nil {
return 0, err
}
return proof.Nonce, nil
}

0 comments on commit 8d158db

Please sign in to comment.