github.com/ethersphere/bee/v2@v2.2.0/pkg/transaction/backendsimulation/backend.go (about) 1 // Copyright 2021 The Swarm Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package backendsimulation 6 7 import ( 8 "context" 9 "errors" 10 "math/big" 11 12 "github.com/ethereum/go-ethereum" 13 "github.com/ethereum/go-ethereum/common" 14 "github.com/ethereum/go-ethereum/core/types" 15 "github.com/ethersphere/bee/v2/pkg/transaction" 16 ) 17 18 type AccountAtKey struct { 19 BlockNumber uint64 20 Account common.Address 21 } 22 23 type simulatedBackend struct { 24 blockNumber uint64 25 26 receipts map[common.Hash]*types.Receipt 27 noncesAt map[AccountAtKey]uint64 28 29 blocks []Block 30 step uint64 31 } 32 33 type Block struct { 34 Number uint64 35 Receipts map[common.Hash]*types.Receipt 36 NoncesAt map[AccountAtKey]uint64 37 } 38 39 type Option interface { 40 apply(*simulatedBackend) 41 } 42 43 type optionFunc func(*simulatedBackend) 44 45 func (f optionFunc) apply(r *simulatedBackend) { f(r) } 46 47 func WithBlocks(blocks ...Block) Option { 48 return optionFunc(func(sb *simulatedBackend) { 49 sb.blocks = blocks 50 }) 51 } 52 53 func New(options ...Option) transaction.Backend { 54 m := &simulatedBackend{ 55 receipts: make(map[common.Hash]*types.Receipt), 56 noncesAt: make(map[AccountAtKey]uint64), 57 58 blockNumber: 0, 59 } 60 for _, opt := range options { 61 opt.apply(m) 62 } 63 64 return m 65 } 66 67 func (m *simulatedBackend) advanceBlock() { 68 if m.step >= uint64(len(m.blocks)) { 69 return 70 } 71 block := m.blocks[m.step] 72 m.step++ 73 74 m.blockNumber = block.Number 75 76 if block.Receipts != nil { 77 for hash, receipt := range block.Receipts { 78 m.receipts[hash] = receipt 79 } 80 } 81 82 if block.NoncesAt != nil { 83 for addr, nonce := range block.NoncesAt { 84 m.noncesAt[addr] = nonce 85 } 86 } 87 } 88 89 func (m *simulatedBackend) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) { 90 return nil, errors.New("not implemented") 91 } 92 93 func (m *simulatedBackend) CodeAt(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error) { 94 return nil, errors.New("not implemented") 95 } 96 97 func (*simulatedBackend) CallContract(ctx context.Context, call ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) { 98 return nil, errors.New("not implemented") 99 } 100 101 func (*simulatedBackend) PendingCodeAt(ctx context.Context, account common.Address) ([]byte, error) { 102 return nil, errors.New("not implemented") 103 } 104 105 func (m *simulatedBackend) PendingNonceAt(ctx context.Context, account common.Address) (uint64, error) { 106 return 0, errors.New("not implemented") 107 } 108 109 func (m *simulatedBackend) SuggestGasPrice(ctx context.Context) (*big.Int, error) { 110 return nil, errors.New("not implemented") 111 } 112 113 func (m *simulatedBackend) EstimateGas(ctx context.Context, call ethereum.CallMsg) (gas uint64, err error) { 114 return 0, errors.New("not implemented") 115 } 116 117 func (m *simulatedBackend) SendTransaction(ctx context.Context, tx *types.Transaction) error { 118 return errors.New("not implemented") 119 } 120 121 func (*simulatedBackend) FilterLogs(ctx context.Context, query ethereum.FilterQuery) ([]types.Log, error) { 122 return nil, errors.New("not implemented") 123 } 124 125 func (*simulatedBackend) SubscribeFilterLogs(ctx context.Context, query ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error) { 126 return nil, errors.New("not implemented") 127 } 128 129 func (m *simulatedBackend) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) { 130 receipt, ok := m.receipts[txHash] 131 if ok { 132 return receipt, nil 133 } else { 134 return nil, ethereum.NotFound 135 } 136 } 137 138 func (m *simulatedBackend) TransactionByHash(ctx context.Context, hash common.Hash) (tx *types.Transaction, isPending bool, err error) { 139 return nil, false, errors.New("not implemented") 140 } 141 142 func (m *simulatedBackend) BlockNumber(ctx context.Context) (uint64, error) { 143 m.advanceBlock() 144 return m.blockNumber, nil 145 } 146 147 func (m *simulatedBackend) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) { 148 return nil, errors.New("not implemented") 149 } 150 151 func (m *simulatedBackend) BalanceAt(ctx context.Context, address common.Address, block *big.Int) (*big.Int, error) { 152 return nil, errors.New("not implemented") 153 } 154 func (m *simulatedBackend) NonceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (uint64, error) { 155 nonce, ok := m.noncesAt[AccountAtKey{Account: account, BlockNumber: blockNumber.Uint64()}] 156 if ok { 157 return nonce, nil 158 } else { 159 return 0, nil 160 } 161 } 162 163 func (m *simulatedBackend) SuggestGasTipCap(ctx context.Context) (*big.Int, error) { 164 return nil, errors.New("not implemented") 165 } 166 167 func (m *simulatedBackend) ChainID(ctx context.Context) (*big.Int, error) { 168 return nil, errors.New("not implemented") 169 } 170 171 func (m *simulatedBackend) Close() { 172 }