github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/powchain/testing/mock_powchain.go (about)

     1  // Package testing provides useful mocks for an eth1 powchain
     2  // service as needed by unit tests for the beacon node.
     3  package testing
     4  
     5  import (
     6  	"context"
     7  	"fmt"
     8  	"math/big"
     9  	"time"
    10  
    11  	"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
    12  	"github.com/ethereum/go-ethereum/common"
    13  	"github.com/ethereum/go-ethereum/common/hexutil"
    14  	gethTypes "github.com/ethereum/go-ethereum/core/types"
    15  	"github.com/ethereum/go-ethereum/rpc"
    16  	"github.com/prysmaticlabs/prysm/beacon-chain/powchain/types"
    17  	iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
    18  	ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
    19  	"github.com/prysmaticlabs/prysm/shared/bytesutil"
    20  	"github.com/prysmaticlabs/prysm/shared/event"
    21  	"github.com/prysmaticlabs/prysm/shared/trieutil"
    22  )
    23  
    24  // POWChain defines a properly functioning mock for the powchain service.
    25  type POWChain struct {
    26  	ChainFeed         *event.Feed
    27  	LatestBlockNumber *big.Int
    28  	HashesByHeight    map[int][]byte
    29  	TimesByHeight     map[int]uint64
    30  	BlockNumberByTime map[uint64]*big.Int
    31  	Eth1Data          *ethpb.Eth1Data
    32  	GenesisEth1Block  *big.Int
    33  	GenesisState      iface.BeaconState
    34  }
    35  
    36  // GenesisTime represents a static past date - JAN 01 2000.
    37  var GenesisTime = time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC).Unix()
    38  
    39  // NewPOWChain creates a new mock chain with empty block info.
    40  func NewPOWChain() *POWChain {
    41  	return &POWChain{
    42  		HashesByHeight:    make(map[int][]byte),
    43  		TimesByHeight:     make(map[int]uint64),
    44  		BlockNumberByTime: make(map[uint64]*big.Int),
    45  	}
    46  }
    47  
    48  // Eth2GenesisPowchainInfo --
    49  func (m *POWChain) Eth2GenesisPowchainInfo() (uint64, *big.Int) {
    50  	blk := m.GenesisEth1Block
    51  	if blk == nil {
    52  		blk = big.NewInt(GenesisTime)
    53  	}
    54  	return uint64(GenesisTime), blk
    55  }
    56  
    57  // DepositTrie --
    58  func (m *POWChain) DepositTrie() *trieutil.SparseMerkleTrie {
    59  	return &trieutil.SparseMerkleTrie{}
    60  }
    61  
    62  // BlockExists --
    63  func (m *POWChain) BlockExists(_ context.Context, hash common.Hash) (bool, *big.Int, error) {
    64  	// Reverse the map of heights by hash.
    65  	heightsByHash := make(map[[32]byte]int, len(m.HashesByHeight))
    66  	for k, v := range m.HashesByHeight {
    67  		h := bytesutil.ToBytes32(v)
    68  		heightsByHash[h] = k
    69  	}
    70  	val, ok := heightsByHash[hash]
    71  	if !ok {
    72  		return false, nil, fmt.Errorf("could not fetch height for hash: %#x", hash)
    73  	}
    74  	return true, big.NewInt(int64(val)), nil
    75  }
    76  
    77  // BlockHashByHeight --
    78  func (m *POWChain) BlockHashByHeight(_ context.Context, height *big.Int) (common.Hash, error) {
    79  	k := int(height.Int64())
    80  	val, ok := m.HashesByHeight[k]
    81  	if !ok {
    82  		return [32]byte{}, fmt.Errorf("could not fetch hash for height: %v", height)
    83  	}
    84  	return bytesutil.ToBytes32(val), nil
    85  }
    86  
    87  // BlockTimeByHeight --
    88  func (m *POWChain) BlockTimeByHeight(_ context.Context, height *big.Int) (uint64, error) {
    89  	h := int(height.Int64())
    90  	return m.TimesByHeight[h], nil
    91  }
    92  
    93  // BlockByTimestamp --
    94  func (m *POWChain) BlockByTimestamp(_ context.Context, time uint64) (*types.HeaderInfo, error) {
    95  	var chosenTime uint64
    96  	var chosenNumber *big.Int
    97  	for t, num := range m.BlockNumberByTime {
    98  		if t > chosenTime && t <= time {
    99  			chosenNumber = num
   100  			chosenTime = t
   101  		}
   102  	}
   103  	return &types.HeaderInfo{Number: chosenNumber, Time: chosenTime}, nil
   104  }
   105  
   106  // DepositRoot --
   107  func (m *POWChain) DepositRoot() [32]byte {
   108  	root := []byte("depositroot")
   109  	return bytesutil.ToBytes32(root)
   110  }
   111  
   112  // ChainStartDeposits --
   113  func (m *POWChain) ChainStartDeposits() []*ethpb.Deposit {
   114  	return []*ethpb.Deposit{}
   115  }
   116  
   117  // ChainStartEth1Data --
   118  func (m *POWChain) ChainStartEth1Data() *ethpb.Eth1Data {
   119  	return m.Eth1Data
   120  }
   121  
   122  // PreGenesisState --
   123  func (m *POWChain) PreGenesisState() iface.BeaconState {
   124  	return m.GenesisState
   125  }
   126  
   127  // ClearPreGenesisData --
   128  func (m *POWChain) ClearPreGenesisData() {
   129  	// no-op
   130  }
   131  
   132  // IsConnectedToETH1 --
   133  func (m *POWChain) IsConnectedToETH1() bool {
   134  	return true
   135  }
   136  
   137  // RPCClient defines the mock rpc client.
   138  type RPCClient struct {
   139  	Backend *backends.SimulatedBackend
   140  }
   141  
   142  // BatchCall --
   143  func (r *RPCClient) BatchCall(b []rpc.BatchElem) error {
   144  	if r.Backend == nil {
   145  		return nil
   146  	}
   147  
   148  	for _, e := range b {
   149  		num, err := hexutil.DecodeBig(e.Args[0].(string))
   150  		if err != nil {
   151  			return err
   152  		}
   153  		h, err := r.Backend.HeaderByNumber(context.Background(), num)
   154  		if err != nil {
   155  			return err
   156  		}
   157  		*e.Result.(*gethTypes.Header) = *h
   158  
   159  	}
   160  	return nil
   161  }
   162  
   163  // InsertBlock adds provided block info into the chain.
   164  func (m *POWChain) InsertBlock(height int, time uint64, hash []byte) *POWChain {
   165  	m.HashesByHeight[height] = hash
   166  	m.TimesByHeight[height] = time
   167  	m.BlockNumberByTime[time] = big.NewInt(int64(height))
   168  	return m
   169  }
   170  
   171  // BlockExistsWithCache --
   172  func (m *POWChain) BlockExistsWithCache(ctx context.Context, hash common.Hash) (bool, *big.Int, error) {
   173  	return m.BlockExists(ctx, hash)
   174  }