github.com/klaytn/klaytn@v1.12.1/accounts/abi/bind/backends/simulated.go (about)

     1  // Modifications Copyright 2018 The klaytn Authors
     2  // Copyright 2015 The go-ethereum Authors
     3  // This file is part of the go-ethereum library.
     4  //
     5  // The go-ethereum library is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Lesser General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // The go-ethereum library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    13  // GNU Lesser General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Lesser General Public License
    16  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    17  //
    18  // This file is derived from accounts/abi/bind/backends/simulated.go (2018/06/04).
    19  // Modified and improved for the klaytn development.
    20  
    21  package backends
    22  
    23  import (
    24  	"context"
    25  	"errors"
    26  	"fmt"
    27  	"math/big"
    28  	"sync"
    29  	"time"
    30  
    31  	"github.com/klaytn/klaytn"
    32  	"github.com/klaytn/klaytn/accounts/abi/bind"
    33  	"github.com/klaytn/klaytn/blockchain"
    34  	"github.com/klaytn/klaytn/blockchain/bloombits"
    35  	"github.com/klaytn/klaytn/blockchain/state"
    36  	"github.com/klaytn/klaytn/blockchain/types"
    37  	"github.com/klaytn/klaytn/blockchain/vm"
    38  	"github.com/klaytn/klaytn/common"
    39  	"github.com/klaytn/klaytn/common/math"
    40  	"github.com/klaytn/klaytn/consensus/gxhash"
    41  	"github.com/klaytn/klaytn/event"
    42  	"github.com/klaytn/klaytn/networks/rpc"
    43  	"github.com/klaytn/klaytn/node/cn/filters"
    44  	"github.com/klaytn/klaytn/params"
    45  	"github.com/klaytn/klaytn/storage/database"
    46  )
    47  
    48  // This nil assignment ensures compile time that SimulatedBackend implements bind.ContractBackend.
    49  var _ bind.ContractBackend = (*SimulatedBackend)(nil)
    50  
    51  var (
    52  	errBlockNumberUnsupported  = errors.New("simulatedBackend cannot access blocks other than the latest block")
    53  	errBlockDoesNotExist       = errors.New("block does not exist in blockchain")
    54  	errTransactionDoesNotExist = errors.New("transaction does not exist")
    55  )
    56  
    57  // SimulatedBackend implements bind.ContractBackend, simulating a blockchain in
    58  // the background. Its main purpose is to allow for easy testing of contract bindings.
    59  // Simulated backend implements the following interfaces:
    60  // ChainReader, ChainStateReader, ContractBackend, ContractCaller, ContractFilterer, ContractTransactor,
    61  // DeployBackend, GasEstimator, GasPricer, LogFilterer, PendingContractCaller, TransactionReader, and TransactionSender
    62  type SimulatedBackend struct {
    63  	database   database.DBManager     // In memory database to store our testing data
    64  	blockchain *blockchain.BlockChain // Klaytn blockchain to handle the consensus
    65  
    66  	mu           sync.Mutex
    67  	pendingBlock *types.Block   // Currently pending block that will be imported on request
    68  	pendingState *state.StateDB // Currently pending state that will be the active on request
    69  
    70  	events *filters.EventSystem // Event system for filtering log events live
    71  
    72  	config *params.ChainConfig
    73  }
    74  
    75  // NewSimulatedBackendWithDatabase creates a new binding backend based on the given database
    76  // and uses a simulated blockchain for testing purposes.
    77  func NewSimulatedBackendWithDatabase(database database.DBManager, alloc blockchain.GenesisAlloc, cfg *params.ChainConfig) *SimulatedBackend {
    78  	genesis := blockchain.Genesis{Config: cfg, Alloc: alloc}
    79  	genesis.MustCommit(database)
    80  	blockchain, _ := blockchain.NewBlockChain(database, nil, genesis.Config, gxhash.NewFaker(), vm.Config{})
    81  
    82  	backend := &SimulatedBackend{
    83  		database:   database,
    84  		blockchain: blockchain,
    85  		config:     genesis.Config,
    86  		events:     filters.NewEventSystem(new(event.TypeMux), &filterBackend{database, blockchain}, false),
    87  	}
    88  	backend.rollback()
    89  	return backend
    90  }
    91  
    92  // NewSimulatedBackendWithGasPrice creates a new binding backend using a simulated blockchain with a given unitPrice.
    93  // for testing purposes.
    94  func NewSimulatedBackendWithGasPrice(alloc blockchain.GenesisAlloc, unitPrice uint64) *SimulatedBackend {
    95  	cfg := params.AllGxhashProtocolChanges.Copy()
    96  	cfg.UnitPrice = unitPrice
    97  	return NewSimulatedBackendWithDatabase(database.NewMemoryDBManager(), alloc, cfg)
    98  }
    99  
   100  // NewSimulatedBackend creates a new binding backend using a simulated blockchain
   101  // for testing purposes.
   102  func NewSimulatedBackend(alloc blockchain.GenesisAlloc) *SimulatedBackend {
   103  	return NewSimulatedBackendWithDatabase(database.NewMemoryDBManager(), alloc, params.AllGxhashProtocolChanges)
   104  }
   105  
   106  // Close terminates the underlying blockchain's update loop.
   107  func (b *SimulatedBackend) Close() error {
   108  	b.blockchain.Stop()
   109  	return nil
   110  }
   111  
   112  // Commit imports all the pending transactions as a single block and starts a
   113  // fresh new state.
   114  func (b *SimulatedBackend) Commit() {
   115  	b.mu.Lock()
   116  	defer b.mu.Unlock()
   117  
   118  	if _, err := b.blockchain.InsertChain([]*types.Block{b.pendingBlock}); err != nil {
   119  		panic(err) // This cannot happen unless the simulator is wrong, fail in that case
   120  	}
   121  	b.rollback()
   122  }
   123  
   124  // Rollback aborts all pending transactions, reverting to the last committed state.
   125  func (b *SimulatedBackend) Rollback() {
   126  	b.mu.Lock()
   127  	defer b.mu.Unlock()
   128  
   129  	b.rollback()
   130  }
   131  
   132  func (b *SimulatedBackend) rollback() {
   133  	blocks, _ := blockchain.GenerateChain(b.config, b.blockchain.CurrentBlock(), gxhash.NewFaker(), b.database, 1, func(int, *blockchain.BlockGen) {})
   134  	stateDB, _ := b.blockchain.State()
   135  
   136  	b.pendingBlock = blocks[0]
   137  	b.pendingState, _ = state.New(b.pendingBlock.Root(), stateDB.Database(), nil, nil)
   138  }
   139  
   140  // stateByBlockNumber retrieves a state by a given blocknumber.
   141  func (b *SimulatedBackend) stateByBlockNumber(ctx context.Context, blockNumber *big.Int) (*state.StateDB, error) {
   142  	if blockNumber == nil || blockNumber.Cmp(b.blockchain.CurrentBlock().Number()) == 0 {
   143  		return b.blockchain.State()
   144  	}
   145  	block, err := b.blockByNumberNoLock(ctx, blockNumber)
   146  	if err != nil {
   147  		return nil, err
   148  	}
   149  	return b.blockchain.StateAt(block.Root())
   150  }
   151  
   152  // CodeAt returns the code associated with a certain account in the blockchain.
   153  func (b *SimulatedBackend) CodeAt(ctx context.Context, contract common.Address, blockNumber *big.Int) ([]byte, error) {
   154  	b.mu.Lock()
   155  	defer b.mu.Unlock()
   156  
   157  	stateDB, err := b.stateByBlockNumber(ctx, blockNumber)
   158  	if err != nil {
   159  		return nil, err
   160  	}
   161  
   162  	return stateDB.GetCode(contract), nil
   163  }
   164  
   165  // BalanceAt returns the peb balance of a certain account in the blockchain.
   166  func (b *SimulatedBackend) BalanceAt(ctx context.Context, contract common.Address, blockNumber *big.Int) (*big.Int, error) {
   167  	b.mu.Lock()
   168  	defer b.mu.Unlock()
   169  
   170  	stateDB, err := b.stateByBlockNumber(ctx, blockNumber)
   171  	if err != nil {
   172  		return nil, err
   173  	}
   174  
   175  	return stateDB.GetBalance(contract), nil
   176  }
   177  
   178  // NonceAt returns the nonce of a certain account in the blockchain.
   179  func (b *SimulatedBackend) NonceAt(ctx context.Context, contract common.Address, blockNumber *big.Int) (uint64, error) {
   180  	b.mu.Lock()
   181  	defer b.mu.Unlock()
   182  
   183  	stateDB, err := b.stateByBlockNumber(ctx, blockNumber)
   184  	if err != nil {
   185  		return 0, err
   186  	}
   187  
   188  	return stateDB.GetNonce(contract), nil
   189  }
   190  
   191  // StorageAt returns the value of key in the storage of an account in the blockchain.
   192  func (b *SimulatedBackend) StorageAt(ctx context.Context, contract common.Address, key common.Hash, blockNumber *big.Int) ([]byte, error) {
   193  	b.mu.Lock()
   194  	defer b.mu.Unlock()
   195  
   196  	stateDB, err := b.stateByBlockNumber(ctx, blockNumber)
   197  	if err != nil {
   198  		return nil, err
   199  	}
   200  
   201  	val := stateDB.GetState(contract, key)
   202  	return val[:], nil
   203  }
   204  
   205  // TransactionReceipt returns the receipt of a transaction.
   206  func (b *SimulatedBackend) TransactionReceipt(_ context.Context, txHash common.Hash) (*types.Receipt, error) {
   207  	b.mu.Lock()
   208  	defer b.mu.Unlock()
   209  
   210  	receipt, _, _, _ := b.database.ReadReceipt(txHash)
   211  	return receipt, nil
   212  }
   213  
   214  // TransactionByHash checks the pool of pending transactions in addition to the
   215  // blockchain. The isPending return value indicates whether the transaction has been
   216  // mined yet. Note that the transaction may not be part of the canonical chain even if
   217  // it's not pending.
   218  func (b *SimulatedBackend) TransactionByHash(ctx context.Context, txHash common.Hash) (*types.Transaction, bool, error) {
   219  	b.mu.Lock()
   220  	defer b.mu.Unlock()
   221  
   222  	tx := b.pendingBlock.Transaction(txHash)
   223  	if tx != nil {
   224  		return tx, true, nil
   225  	}
   226  	tx, _, _, _ = b.database.ReadTxAndLookupInfo(txHash)
   227  	if tx != nil {
   228  		return tx, false, nil
   229  	}
   230  	return nil, false, klaytn.NotFound
   231  }
   232  
   233  // BlockByHash retrieves a block based on the block hash.
   234  func (b *SimulatedBackend) BlockByHash(_ context.Context, hash common.Hash) (*types.Block, error) {
   235  	b.mu.Lock()
   236  	defer b.mu.Unlock()
   237  
   238  	if hash == b.pendingBlock.Hash() {
   239  		return b.pendingBlock, nil
   240  	}
   241  
   242  	block := b.blockchain.GetBlockByHash(hash)
   243  	if block != nil {
   244  		return block, nil
   245  	}
   246  
   247  	return nil, errBlockDoesNotExist
   248  }
   249  
   250  // BlockByNumber retrieves a block from the database by number, caching it
   251  // (associated with its hash) if found.
   252  func (b *SimulatedBackend) BlockByNumber(ctx context.Context, number *big.Int) (*types.Block, error) {
   253  	b.mu.Lock()
   254  	defer b.mu.Unlock()
   255  
   256  	return b.blockByNumberNoLock(ctx, number)
   257  }
   258  
   259  // blockByNumberNoLock retrieves a block from the database by number, caching it
   260  // (associated with its hash) if found without Lock.
   261  func (b *SimulatedBackend) blockByNumberNoLock(_ context.Context, number *big.Int) (*types.Block, error) {
   262  	if number == nil || number.Cmp(b.pendingBlock.Number()) == 0 {
   263  		return b.blockchain.CurrentBlock(), nil
   264  	}
   265  
   266  	block := b.blockchain.GetBlockByNumber(uint64(number.Int64()))
   267  	if block == nil {
   268  		return nil, errBlockDoesNotExist
   269  	}
   270  
   271  	return block, nil
   272  }
   273  
   274  // HeaderByHash returns a block header from the current canonical chain.
   275  func (b *SimulatedBackend) HeaderByHash(_ context.Context, hash common.Hash) (*types.Header, error) {
   276  	b.mu.Lock()
   277  	defer b.mu.Unlock()
   278  
   279  	if hash == b.pendingBlock.Hash() {
   280  		return b.pendingBlock.Header(), nil
   281  	}
   282  
   283  	header := b.blockchain.GetHeaderByHash(hash)
   284  	if header == nil {
   285  		return nil, errBlockDoesNotExist
   286  	}
   287  
   288  	return header, nil
   289  }
   290  
   291  // HeaderByNumber returns a block header from the current canonical chain. If number is
   292  // nil, the latest known header is returned.
   293  func (b *SimulatedBackend) HeaderByNumber(_ context.Context, block *big.Int) (*types.Header, error) {
   294  	b.mu.Lock()
   295  	defer b.mu.Unlock()
   296  
   297  	if block == nil || block.Cmp(b.pendingBlock.Number()) == 0 {
   298  		return b.blockchain.CurrentHeader(), nil
   299  	}
   300  
   301  	return b.blockchain.GetHeaderByNumber(uint64(block.Int64())), nil
   302  }
   303  
   304  // TransactionCount returns the number of transactions in a given block.
   305  func (b *SimulatedBackend) TransactionCount(_ context.Context, blockHash common.Hash) (uint, error) {
   306  	b.mu.Lock()
   307  	defer b.mu.Unlock()
   308  
   309  	if blockHash == b.pendingBlock.Hash() {
   310  		return uint(b.pendingBlock.Transactions().Len()), nil
   311  	}
   312  
   313  	block := b.blockchain.GetBlockByHash(blockHash)
   314  	if block == nil {
   315  		return uint(0), errBlockDoesNotExist
   316  	}
   317  
   318  	return uint(block.Transactions().Len()), nil
   319  }
   320  
   321  // TransactionInBlock returns the transaction for a specific block at a specific index.
   322  func (b *SimulatedBackend) TransactionInBlock(_ context.Context, blockHash common.Hash, index uint) (*types.Transaction, error) {
   323  	b.mu.Lock()
   324  	defer b.mu.Unlock()
   325  
   326  	if blockHash == b.pendingBlock.Hash() {
   327  		transactions := b.pendingBlock.Transactions()
   328  		if uint(len(transactions)) < index+1 {
   329  			return nil, errTransactionDoesNotExist
   330  		}
   331  
   332  		return transactions[index], nil
   333  	}
   334  
   335  	block := b.blockchain.GetBlockByHash(blockHash)
   336  	if block == nil {
   337  		return nil, errBlockDoesNotExist
   338  	}
   339  
   340  	transactions := block.Transactions()
   341  	if uint(len(transactions)) < index+1 {
   342  		return nil, errTransactionDoesNotExist
   343  	}
   344  
   345  	return transactions[index], nil
   346  }
   347  
   348  // PendingCodeAt returns the code associated with an account in the pending state.
   349  func (b *SimulatedBackend) PendingCodeAt(_ context.Context, contract common.Address) ([]byte, error) {
   350  	b.mu.Lock()
   351  	defer b.mu.Unlock()
   352  
   353  	return b.pendingState.GetCode(contract), nil
   354  }
   355  
   356  // CallContract executes a contract call.
   357  func (b *SimulatedBackend) CallContract(ctx context.Context, call klaytn.CallMsg, blockNumber *big.Int) ([]byte, error) {
   358  	b.mu.Lock()
   359  	defer b.mu.Unlock()
   360  
   361  	if blockNumber != nil && blockNumber.Cmp(b.blockchain.CurrentBlock().Number()) != 0 {
   362  		return nil, errBlockNumberUnsupported
   363  	}
   364  	stateDB, err := b.blockchain.State()
   365  	if err != nil {
   366  		return nil, err
   367  	}
   368  	res, err := b.callContract(ctx, call, b.blockchain.CurrentBlock(), stateDB)
   369  	if err != nil {
   370  		return nil, err
   371  	}
   372  	// If the result contains a revert reason, try to unpack and return it.
   373  	if len(res.Revert()) > 0 {
   374  		return nil, blockchain.NewRevertError(res)
   375  	}
   376  	return res.Return(), res.Unwrap()
   377  }
   378  
   379  // PendingCallContract executes a contract call on the pending state.
   380  func (b *SimulatedBackend) PendingCallContract(ctx context.Context, call klaytn.CallMsg) ([]byte, error) {
   381  	b.mu.Lock()
   382  	defer b.mu.Unlock()
   383  	defer b.pendingState.RevertToSnapshot(b.pendingState.Snapshot())
   384  
   385  	res, err := b.callContract(ctx, call, b.pendingBlock, b.pendingState)
   386  	if err != nil {
   387  		return nil, err
   388  	}
   389  	// If the result contains a revert reason, try to unpack and return it.
   390  	if len(res.Revert()) > 0 {
   391  		return nil, blockchain.NewRevertError(res)
   392  	}
   393  	return res.Return(), res.Unwrap()
   394  }
   395  
   396  // PendingNonceAt implements PendingStateReader.PendingNonceAt, retrieving
   397  // the nonce currently pending for the account.
   398  func (b *SimulatedBackend) PendingNonceAt(_ context.Context, account common.Address) (uint64, error) {
   399  	b.mu.Lock()
   400  	defer b.mu.Unlock()
   401  
   402  	return b.pendingState.GetOrNewStateObject(account).Nonce(), nil
   403  }
   404  
   405  // SuggestGasPrice implements ContractTransactor.SuggestGasPrice. Since the simulated
   406  // chain doesn't have miners, we just return a gas price of 1 for any call.
   407  func (b *SimulatedBackend) SuggestGasPrice(_ context.Context) (*big.Int, error) {
   408  	return new(big.Int).SetUint64(b.config.UnitPrice), nil
   409  }
   410  
   411  // EstimateGas executes the requested code against the latest block/state and
   412  // returns the used amount of gas.
   413  func (b *SimulatedBackend) EstimateGas(ctx context.Context, call klaytn.CallMsg) (uint64, error) {
   414  	b.mu.Lock()
   415  	defer b.mu.Unlock()
   416  
   417  	balance := b.pendingState.GetBalance(call.From) // from can't be nil
   418  
   419  	// Create a helper to check if a gas allowance results in an executable transaction
   420  	executable := func(gas uint64) (bool, *blockchain.ExecutionResult, error) {
   421  		call.Gas = gas
   422  
   423  		currentState, err := b.blockchain.State()
   424  		if err != nil {
   425  			return true, nil, nil
   426  		}
   427  		res, err := b.callContract(ctx, call, b.blockchain.CurrentBlock(), currentState)
   428  		if err != nil {
   429  			if errors.Is(err, blockchain.ErrIntrinsicGas) {
   430  				return true, nil, nil // Special case, raise gas limit
   431  			}
   432  			return true, nil, err // Bail out
   433  		}
   434  		return res.Failed(), res, nil
   435  	}
   436  
   437  	estimated, err := blockchain.DoEstimateGas(ctx, call.Gas, 0, call.Value, call.GasPrice, balance, executable)
   438  	if err != nil {
   439  		return 0, err
   440  	} else {
   441  		return uint64(estimated), nil
   442  	}
   443  }
   444  
   445  // callContract implements common code between normal and pending contract calls.
   446  // state is modified during execution, make sure to copy it if necessary.
   447  func (b *SimulatedBackend) callContract(_ context.Context, call klaytn.CallMsg, block *types.Block, stateDB *state.StateDB) (*blockchain.ExecutionResult, error) {
   448  	// Ensure message is initialized properly.
   449  	if call.GasPrice == nil {
   450  		call.GasPrice = big.NewInt(1)
   451  	}
   452  	if call.Gas == 0 {
   453  		call.Gas = 50000000
   454  	}
   455  	if call.Value == nil {
   456  		call.Value = new(big.Int)
   457  	}
   458  	// Set infinite balance to the fake caller account.
   459  	from := stateDB.GetOrNewStateObject(call.From)
   460  	from.SetBalance(math.MaxBig256)
   461  	// Execute the call.
   462  	nonce := from.Nonce()
   463  	intrinsicGas, _ := types.IntrinsicGas(call.Data, nil, call.To == nil, b.config.Rules(block.Number()))
   464  
   465  	var accessList types.AccessList
   466  	if call.AccessList != nil {
   467  		accessList = *call.AccessList
   468  	}
   469  	msg := types.NewMessage(call.From, call.To, nonce, call.Value, call.Gas, call.GasPrice, call.Data, true, intrinsicGas, accessList)
   470  
   471  	txContext := blockchain.NewEVMTxContext(msg, block.Header())
   472  	blockContext := blockchain.NewEVMBlockContext(block.Header(), b.blockchain, nil)
   473  	// Create a new environment which holds all relevant information
   474  	// about the transaction and calling mechanisms.
   475  	vmenv := vm.NewEVM(blockContext, txContext, stateDB, b.config, &vm.Config{})
   476  
   477  	return blockchain.NewStateTransition(vmenv, msg).TransitionDb()
   478  }
   479  
   480  // SendTransaction updates the pending block to include the given transaction.
   481  // It panics if the transaction is invalid.
   482  func (b *SimulatedBackend) SendTransaction(_ context.Context, tx *types.Transaction) error {
   483  	b.mu.Lock()
   484  	defer b.mu.Unlock()
   485  
   486  	// Check transaction validity
   487  	block := b.blockchain.CurrentBlock()
   488  	signer := types.MakeSigner(b.blockchain.Config(), block.Number())
   489  	sender, err := types.Sender(signer, tx)
   490  	if err != nil {
   491  		panic(fmt.Errorf("invalid transaction: %v", err))
   492  	}
   493  	nonce := b.pendingState.GetNonce(sender)
   494  	if tx.Nonce() != nonce {
   495  		panic(fmt.Errorf("invalid transaction nonce: got %d, want %d", tx.Nonce(), nonce))
   496  	}
   497  
   498  	// Include tx in chain.
   499  	blocks, _ := blockchain.GenerateChain(b.config, block, gxhash.NewFaker(), b.database, 1, func(number int, block *blockchain.BlockGen) {
   500  		for _, tx := range b.pendingBlock.Transactions() {
   501  			block.AddTxWithChain(b.blockchain, tx)
   502  		}
   503  		block.AddTxWithChain(b.blockchain, tx)
   504  	})
   505  	stateDB, _ := b.blockchain.State()
   506  
   507  	b.pendingBlock = blocks[0]
   508  	b.pendingState, _ = state.New(b.pendingBlock.Root(), stateDB.Database(), nil, nil)
   509  	return nil
   510  }
   511  
   512  // FilterLogs executes a log filter operation, blocking during execution and
   513  // returning all the results in one batch.
   514  //
   515  // TODO(karalabe): Deprecate when the subscription one can return past data too.
   516  func (b *SimulatedBackend) FilterLogs(ctx context.Context, query klaytn.FilterQuery) ([]types.Log, error) {
   517  	// Initialize unset filter boundaries to run from genesis to chain head
   518  	from := int64(0)
   519  	if query.FromBlock != nil {
   520  		from = query.FromBlock.Int64()
   521  	}
   522  	to := int64(-1)
   523  	if query.ToBlock != nil {
   524  		to = query.ToBlock.Int64()
   525  	}
   526  	// Construct and execute the filter
   527  	filter := filters.NewRangeFilter(&filterBackend{b.database, b.blockchain}, from, to, query.Addresses, query.Topics)
   528  
   529  	// Run the filter and return all the logs
   530  	logs, err := filter.Logs(ctx)
   531  	if err != nil {
   532  		return nil, err
   533  	}
   534  	res := make([]types.Log, len(logs))
   535  	for i, nLog := range logs {
   536  		res[i] = *nLog
   537  	}
   538  	return res, nil
   539  }
   540  
   541  // ChainID can return the chain ID of the chain.
   542  func (b *SimulatedBackend) ChainID(ctx context.Context) (*big.Int, error) {
   543  	return b.blockchain.Config().ChainID, nil
   544  }
   545  
   546  // SubscribeFilterLogs creates a background log filtering operation, returning a
   547  // subscription immediately, which can be used to stream the found events.
   548  func (b *SimulatedBackend) SubscribeFilterLogs(_ context.Context, query klaytn.FilterQuery, ch chan<- types.Log) (klaytn.Subscription, error) {
   549  	// Subscribe to contract events
   550  	sink := make(chan []*types.Log)
   551  
   552  	sub, err := b.events.SubscribeLogs(query, sink)
   553  	if err != nil {
   554  		return nil, err
   555  	}
   556  	// Since we're getting logs in batches, we need to flatten them into a plain stream
   557  	return event.NewSubscription(func(quit <-chan struct{}) error {
   558  		defer sub.Unsubscribe()
   559  		for {
   560  			select {
   561  			case logs := <-sink:
   562  				for _, nlog := range logs {
   563  					select {
   564  					case ch <- *nlog:
   565  					case err := <-sub.Err():
   566  						return err
   567  					case <-quit:
   568  						return nil
   569  					}
   570  				}
   571  			case err := <-sub.Err():
   572  				return err
   573  			case <-quit:
   574  				return nil
   575  			}
   576  		}
   577  	}), nil
   578  }
   579  
   580  // CurrentBlockNumber returns a current block number.
   581  func (b *SimulatedBackend) CurrentBlockNumber(ctx context.Context) (uint64, error) {
   582  	return b.blockchain.CurrentBlock().NumberU64(), nil
   583  }
   584  
   585  // SubscribeNewHead returns an event subscription for a new header
   586  func (b *SimulatedBackend) SubscribeNewHead(_ context.Context, ch chan<- *types.Header) (klaytn.Subscription, error) {
   587  	// subscribe to a new head
   588  	sink := make(chan *types.Header)
   589  	sub := b.events.SubscribeNewHeads(sink)
   590  
   591  	return event.NewSubscription(func(quit <-chan struct{}) error {
   592  		defer sub.Unsubscribe()
   593  		for {
   594  			select {
   595  			case head := <-sink:
   596  				select {
   597  				case ch <- head:
   598  				case err := <-sub.Err():
   599  					return err
   600  				case <-quit:
   601  					return nil
   602  				}
   603  			case err := <-sub.Err():
   604  				return err
   605  			case <-quit:
   606  				return nil
   607  			}
   608  		}
   609  	}), nil
   610  }
   611  
   612  // AdjustTime adds a time shift to the simulated clock.
   613  // It can only be called on empty blocks.
   614  func (b *SimulatedBackend) AdjustTime(adjustment time.Duration) error {
   615  	b.mu.Lock()
   616  	defer b.mu.Unlock()
   617  
   618  	if len(b.pendingBlock.Transactions()) != 0 {
   619  		return errors.New("Could not adjust time on non-empty block")
   620  	}
   621  
   622  	blocks, _ := blockchain.GenerateChain(b.config, b.blockchain.CurrentBlock(), gxhash.NewFaker(), b.database, 1, func(number int, block *blockchain.BlockGen) {
   623  		block.OffsetTime(int64(adjustment.Seconds()))
   624  	})
   625  	stateDB, _ := b.blockchain.State()
   626  
   627  	b.pendingBlock = blocks[0]
   628  	b.pendingState, _ = state.New(b.pendingBlock.Root(), stateDB.Database(), nil, nil)
   629  
   630  	return nil
   631  }
   632  
   633  // Blockchain returns the underlying blockchain.
   634  func (b *SimulatedBackend) BlockChain() *blockchain.BlockChain {
   635  	return b.blockchain
   636  }
   637  
   638  func (b *SimulatedBackend) PendingBlock() *types.Block {
   639  	return b.pendingBlock
   640  }
   641  
   642  // filterBackend implements filters.Backend to support filtering for logs without
   643  // taking bloom-bits acceleration structures into account.
   644  type filterBackend struct {
   645  	db database.DBManager
   646  	bc *blockchain.BlockChain
   647  }
   648  
   649  func (fb *filterBackend) ChainDB() database.DBManager { return fb.db }
   650  func (fb *filterBackend) EventMux() *event.TypeMux    { panic("not supported") }
   651  
   652  func (fb *filterBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
   653  	return fb.bc.GetHeaderByHash(hash), nil
   654  }
   655  
   656  func (fb *filterBackend) HeaderByNumber(_ context.Context, block rpc.BlockNumber) (*types.Header, error) {
   657  	if block == rpc.LatestBlockNumber {
   658  		return fb.bc.CurrentHeader(), nil
   659  	}
   660  	return fb.bc.GetHeaderByNumber(uint64(block.Int64())), nil
   661  }
   662  
   663  func (fb *filterBackend) GetBlockReceipts(_ context.Context, hash common.Hash) types.Receipts {
   664  	return fb.bc.GetReceiptsByBlockHash(hash)
   665  }
   666  
   667  func (fb *filterBackend) GetLogs(_ context.Context, hash common.Hash) ([][]*types.Log, error) {
   668  	return fb.bc.GetLogsByHash(hash), nil
   669  }
   670  
   671  func (fb *filterBackend) SubscribeNewTxsEvent(_ chan<- blockchain.NewTxsEvent) event.Subscription {
   672  	return nullSubscription()
   673  }
   674  
   675  func (fb *filterBackend) SubscribeChainEvent(ch chan<- blockchain.ChainEvent) event.Subscription {
   676  	return fb.bc.SubscribeChainEvent(ch)
   677  }
   678  
   679  func (fb *filterBackend) SubscribeRemovedLogsEvent(ch chan<- blockchain.RemovedLogsEvent) event.Subscription {
   680  	return fb.bc.SubscribeRemovedLogsEvent(ch)
   681  }
   682  
   683  func (fb *filterBackend) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription {
   684  	return fb.bc.SubscribeLogsEvent(ch)
   685  }
   686  
   687  func (fb *filterBackend) SubscribePendingLogsEvent(_ chan<- []*types.Log) event.Subscription {
   688  	return nullSubscription()
   689  }
   690  
   691  func (fb *filterBackend) BloomStatus() (uint64, uint64) { return 4096, 0 }
   692  
   693  func (fb *filterBackend) ServiceFilter(_ context.Context, _ *bloombits.MatcherSession) {
   694  	panic("not supported")
   695  }
   696  
   697  func (fb *filterBackend) ChainConfig() *params.ChainConfig {
   698  	return fb.bc.Config()
   699  }
   700  
   701  func nullSubscription() event.Subscription {
   702  	return event.NewSubscription(func(quit <-chan struct{}) error {
   703  		<-quit
   704  		return nil
   705  	})
   706  }