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 }