github.com/kisexp/xdchain@v0.0.0-20211206025815-490d6b732aa7/eth/api_backend.go (about)

     1  // Copyright 2015 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package eth
    18  
    19  import (
    20  	"context"
    21  	"errors"
    22  	"fmt"
    23  	"math/big"
    24  	"time"
    25  
    26  	"github.com/kisexp/xdchain/accounts"
    27  	"github.com/kisexp/xdchain/common"
    28  	"github.com/kisexp/xdchain/consensus"
    29  	"github.com/kisexp/xdchain/core"
    30  	"github.com/kisexp/xdchain/core/bloombits"
    31  	"github.com/kisexp/xdchain/core/mps"
    32  	"github.com/kisexp/xdchain/core/rawdb"
    33  	"github.com/kisexp/xdchain/core/state"
    34  	"github.com/kisexp/xdchain/core/types"
    35  	"github.com/kisexp/xdchain/core/vm"
    36  	"github.com/kisexp/xdchain/eth/downloader"
    37  	"github.com/kisexp/xdchain/eth/gasprice"
    38  	"github.com/kisexp/xdchain/ethdb"
    39  	"github.com/kisexp/xdchain/event"
    40  	"github.com/kisexp/xdchain/miner"
    41  	"github.com/kisexp/xdchain/params"
    42  	pcore "github.com/kisexp/xdchain/permission/core"
    43  	"github.com/kisexp/xdchain/rpc"
    44  	"github.com/jpmorganchase/quorum-security-plugin-sdk-go/proto"
    45  )
    46  
    47  // EthAPIBackend implements ethapi.Backend for full nodes
    48  type EthAPIBackend struct {
    49  	extRPCEnabled bool
    50  	eth           *Ethereum
    51  	gpo           *gasprice.Oracle
    52  
    53  	// Quorum
    54  	//
    55  	// hex node id from node public key
    56  	hexNodeId string
    57  
    58  	// timeout value for call
    59  	evmCallTimeOut time.Duration
    60  }
    61  
    62  // ChainConfig returns the active chain configuration.
    63  func (b *EthAPIBackend) ChainConfig() *params.ChainConfig {
    64  	return b.eth.blockchain.Config()
    65  }
    66  
    67  // PSMR returns the private state metadata resolver.
    68  func (b *EthAPIBackend) PSMR() mps.PrivateStateMetadataResolver {
    69  	return b.eth.blockchain.PrivateStateManager()
    70  }
    71  
    72  func (b *EthAPIBackend) CurrentBlock() *types.Block {
    73  	return b.eth.blockchain.CurrentBlock()
    74  }
    75  
    76  func (b *EthAPIBackend) SetHead(number uint64) {
    77  	b.eth.protocolManager.downloader.Cancel()
    78  	b.eth.blockchain.SetHead(number)
    79  }
    80  
    81  func (b *EthAPIBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) {
    82  	// Pending block is only known by the miner
    83  	if number == rpc.PendingBlockNumber {
    84  		block := b.eth.miner.PendingBlock()
    85  		return block.Header(), nil
    86  	}
    87  	// Otherwise resolve and return the block
    88  	if number == rpc.LatestBlockNumber {
    89  		return b.eth.blockchain.CurrentBlock().Header(), nil
    90  	}
    91  	return b.eth.blockchain.GetHeaderByNumber(uint64(number)), nil
    92  }
    93  
    94  func (b *EthAPIBackend) HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Header, error) {
    95  	if blockNr, ok := blockNrOrHash.Number(); ok {
    96  		return b.HeaderByNumber(ctx, blockNr)
    97  	}
    98  	if hash, ok := blockNrOrHash.Hash(); ok {
    99  		header := b.eth.blockchain.GetHeaderByHash(hash)
   100  		if header == nil {
   101  			return nil, errors.New("header for hash not found")
   102  		}
   103  		if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash {
   104  			return nil, errors.New("hash is not currently canonical")
   105  		}
   106  		return header, nil
   107  	}
   108  	return nil, errors.New("invalid arguments; neither block nor hash specified")
   109  }
   110  
   111  func (b *EthAPIBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
   112  	return b.eth.blockchain.GetHeaderByHash(hash), nil
   113  }
   114  
   115  func (b *EthAPIBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) {
   116  	// Pending block is only known by the miner
   117  	if number == rpc.PendingBlockNumber {
   118  		if b.eth.protocolManager.raftMode {
   119  			// Use latest instead.
   120  			return b.eth.blockchain.CurrentBlock(), nil
   121  		}
   122  		block := b.eth.miner.PendingBlock()
   123  		return block, nil
   124  	}
   125  	// Otherwise resolve and return the block
   126  	if number == rpc.LatestBlockNumber {
   127  		return b.eth.blockchain.CurrentBlock(), nil
   128  	}
   129  	return b.eth.blockchain.GetBlockByNumber(uint64(number)), nil
   130  }
   131  
   132  func (b *EthAPIBackend) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) {
   133  	return b.eth.blockchain.GetBlockByHash(hash), nil
   134  }
   135  
   136  func (b *EthAPIBackend) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) {
   137  	if blockNr, ok := blockNrOrHash.Number(); ok {
   138  		return b.BlockByNumber(ctx, blockNr)
   139  	}
   140  	if hash, ok := blockNrOrHash.Hash(); ok {
   141  		header := b.eth.blockchain.GetHeaderByHash(hash)
   142  		if header == nil {
   143  			return nil, errors.New("header for hash not found")
   144  		}
   145  		if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash {
   146  			return nil, errors.New("hash is not currently canonical")
   147  		}
   148  		block := b.eth.blockchain.GetBlock(hash, header.Number.Uint64())
   149  		if block == nil {
   150  			return nil, errors.New("header found, but block body is missing")
   151  		}
   152  		return block, nil
   153  	}
   154  	return nil, errors.New("invalid arguments; neither block nor hash specified")
   155  }
   156  
   157  func (b *EthAPIBackend) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (vm.MinimalApiState, *types.Header, error) {
   158  	psm, err := b.PSMR().ResolveForUserContext(ctx)
   159  	if err != nil {
   160  		return nil, nil, err
   161  	}
   162  	// Pending state is only known by the miner
   163  	if number == rpc.PendingBlockNumber {
   164  		// Quorum
   165  		if b.eth.protocolManager.raftMode {
   166  			// Use latest instead.
   167  			header, err := b.HeaderByNumber(ctx, rpc.LatestBlockNumber)
   168  			if header == nil || err != nil {
   169  				return nil, nil, err
   170  			}
   171  			publicState, privateState, err := b.eth.BlockChain().StateAtPSI(header.Root, psm.ID)
   172  			return EthAPIState{publicState, privateState}, header, err
   173  		}
   174  		block, publicState, privateState := b.eth.miner.Pending(psm.ID)
   175  		return EthAPIState{publicState, privateState}, block.Header(), nil
   176  	}
   177  	// Otherwise resolve the block number and return its state
   178  	header, err := b.HeaderByNumber(ctx, number)
   179  	if err != nil {
   180  		return nil, nil, err
   181  	}
   182  	if header == nil {
   183  		return nil, nil, errors.New("header not found")
   184  	}
   185  	stateDb, privateState, err := b.eth.BlockChain().StateAtPSI(header.Root, psm.ID)
   186  	return EthAPIState{stateDb, privateState}, header, err
   187  
   188  }
   189  
   190  func (b *EthAPIBackend) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (vm.MinimalApiState, *types.Header, error) {
   191  	if blockNr, ok := blockNrOrHash.Number(); ok {
   192  		return b.StateAndHeaderByNumber(ctx, blockNr)
   193  	}
   194  	if hash, ok := blockNrOrHash.Hash(); ok {
   195  		header, err := b.HeaderByHash(ctx, hash)
   196  		if err != nil {
   197  			return nil, nil, err
   198  		}
   199  		if header == nil {
   200  			return nil, nil, errors.New("header for hash not found")
   201  		}
   202  		if blockNrOrHash.RequireCanonical && b.eth.blockchain.GetCanonicalHash(header.Number.Uint64()) != hash {
   203  			return nil, nil, errors.New("hash is not currently canonical")
   204  		}
   205  		psm, err := b.PSMR().ResolveForUserContext(ctx)
   206  		if err != nil {
   207  			return nil, nil, err
   208  		}
   209  		stateDb, privateState, err := b.eth.BlockChain().StateAtPSI(header.Root, psm.ID)
   210  		return EthAPIState{stateDb, privateState}, header, err
   211  
   212  	}
   213  	return nil, nil, errors.New("invalid arguments; neither block nor hash specified")
   214  }
   215  
   216  // Modified for Quorum:
   217  // - If MPS is enabled then the list of receipts returned will contain all public receipts, plus the private receipts for this PSI.
   218  // - if MPS is not enabled, then list will contain all public and private receipts
   219  // Note that for a privacy marker transactions, the private receipts will remain under PSReceipts
   220  func (b *EthAPIBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) {
   221  	receipts := b.eth.blockchain.GetReceiptsByHash(hash)
   222  	psm, err := b.PSMR().ResolveForUserContext(ctx)
   223  	if err != nil {
   224  		return nil, err
   225  	}
   226  
   227  	psiReceipts := make([]*types.Receipt, len(receipts))
   228  	for i := 0; i < len(receipts); i++ {
   229  		psiReceipts[i] = receipts[i]
   230  		if receipts[i].PSReceipts != nil {
   231  			psReceipt, found := receipts[i].PSReceipts[psm.ID]
   232  			// if PSReceipt found and this is not a privacy marker transaction receipt, then pull out the PSI receipt
   233  			if found && receipts[i].TxHash == psReceipt.TxHash {
   234  				psiReceipts[i] = psReceipt
   235  			}
   236  		}
   237  	}
   238  
   239  	return psiReceipts, nil
   240  }
   241  
   242  func (b *EthAPIBackend) GetLogs(ctx context.Context, hash common.Hash) ([][]*types.Log, error) {
   243  	receipts, err := b.GetReceipts(ctx, hash)
   244  	if err != nil {
   245  		return nil, err
   246  	}
   247  	if receipts == nil {
   248  		return nil, nil
   249  	}
   250  	privateReceipts, err := b.eth.blockchain.GetPMTPrivateReceiptsByHash(ctx, hash)
   251  	if err != nil {
   252  		return nil, err
   253  	}
   254  
   255  	logs := make([][]*types.Log, len(receipts)+len(privateReceipts))
   256  	for i, receipt := range receipts {
   257  		logs[i] = receipt.Logs
   258  	}
   259  	for i, receipt := range privateReceipts {
   260  		logs[len(receipts)+i] = receipt.Logs
   261  	}
   262  	return logs, nil
   263  }
   264  
   265  func (b *EthAPIBackend) GetTd(ctx context.Context, hash common.Hash) *big.Int {
   266  	return b.eth.blockchain.GetTdByHash(hash)
   267  }
   268  
   269  func (b *EthAPIBackend) GetEVM(ctx context.Context, msg core.Message, state vm.MinimalApiState, header *types.Header) (*vm.EVM, func() error, error) {
   270  	statedb := state.(EthAPIState)
   271  	vmError := func() error { return nil }
   272  
   273  	txContext := core.NewEVMTxContext(msg)
   274  	context := core.NewEVMBlockContext(header, b.eth.BlockChain(), nil)
   275  
   276  	// Set the private state to public state if contract address is not present in the private state
   277  	to := common.Address{}
   278  	if msg.To() != nil {
   279  		to = *msg.To()
   280  	}
   281  
   282  	privateState := statedb.privateState
   283  	if !privateState.Exist(to) {
   284  		privateState = statedb.state
   285  	}
   286  
   287  	return vm.NewEVM(context, txContext, statedb.state, privateState, b.eth.blockchain.Config(), *b.eth.blockchain.GetVMConfig()), vmError, nil
   288  }
   289  
   290  func (b *EthAPIBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription {
   291  	return b.eth.BlockChain().SubscribeRemovedLogsEvent(ch)
   292  }
   293  
   294  func (b *EthAPIBackend) SubscribePendingLogsEvent(ch chan<- []*types.Log) event.Subscription {
   295  	return b.eth.SubscribePendingLogs(ch) // Quorum
   296  }
   297  
   298  func (b *EthAPIBackend) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription {
   299  	return b.eth.BlockChain().SubscribeChainEvent(ch)
   300  }
   301  
   302  func (b *EthAPIBackend) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription {
   303  	return b.eth.BlockChain().SubscribeChainHeadEvent(ch)
   304  }
   305  
   306  func (b *EthAPIBackend) SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription {
   307  	return b.eth.BlockChain().SubscribeChainSideEvent(ch)
   308  }
   309  
   310  func (b *EthAPIBackend) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription {
   311  	return b.eth.BlockChain().SubscribeLogsEvent(ch)
   312  }
   313  
   314  func (b *EthAPIBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error {
   315  	// validation for node need to happen here and cannot be done as a part of
   316  	// validateTx in tx_pool.go as tx_pool validation will happen in every node
   317  	if b.hexNodeId != "" && !pcore.ValidateNodeForTxn(b.hexNodeId, signedTx.From()) {
   318  		return errors.New("cannot send transaction from this node")
   319  	}
   320  	return b.eth.txPool.AddLocal(signedTx)
   321  }
   322  
   323  func (b *EthAPIBackend) GetPoolTransactions() (types.Transactions, error) {
   324  	pending, err := b.eth.txPool.Pending()
   325  	if err != nil {
   326  		return nil, err
   327  	}
   328  	var txs types.Transactions
   329  	for _, batch := range pending {
   330  		txs = append(txs, batch...)
   331  	}
   332  	return txs, nil
   333  }
   334  
   335  func (b *EthAPIBackend) GetPoolTransaction(hash common.Hash) *types.Transaction {
   336  	return b.eth.txPool.Get(hash)
   337  }
   338  
   339  func (b *EthAPIBackend) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) {
   340  	tx, blockHash, blockNumber, index := rawdb.ReadTransaction(b.eth.ChainDb(), txHash)
   341  	return tx, blockHash, blockNumber, index, nil
   342  }
   343  
   344  func (b *EthAPIBackend) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) {
   345  	return b.eth.txPool.Nonce(addr), nil
   346  }
   347  
   348  func (b *EthAPIBackend) Stats() (pending int, queued int) {
   349  	return b.eth.txPool.Stats()
   350  }
   351  
   352  func (b *EthAPIBackend) TxPoolContent() (map[common.Address]types.Transactions, map[common.Address]types.Transactions) {
   353  	return b.eth.TxPool().Content()
   354  }
   355  
   356  func (b *EthAPIBackend) TxPool() *core.TxPool {
   357  	return b.eth.TxPool()
   358  }
   359  
   360  func (b *EthAPIBackend) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription {
   361  	return b.eth.TxPool().SubscribeNewTxsEvent(ch)
   362  }
   363  
   364  func (b *EthAPIBackend) Downloader() *downloader.Downloader {
   365  	return b.eth.Downloader()
   366  }
   367  
   368  func (b *EthAPIBackend) ProtocolVersion() int {
   369  	return b.eth.EthVersion()
   370  }
   371  
   372  func (b *EthAPIBackend) SuggestPrice(ctx context.Context) (*big.Int, error) {
   373  	if b.ChainConfig().IsQuorum {
   374  		return big.NewInt(0), nil
   375  	} else {
   376  		return b.gpo.SuggestPrice(ctx)
   377  	}
   378  }
   379  
   380  func (b *EthAPIBackend) ChainDb() ethdb.Database {
   381  	return b.eth.ChainDb()
   382  }
   383  
   384  func (b *EthAPIBackend) EventMux() *event.TypeMux {
   385  	return b.eth.EventMux()
   386  }
   387  
   388  func (b *EthAPIBackend) AccountManager() *accounts.Manager {
   389  	return b.eth.AccountManager()
   390  }
   391  
   392  func (b *EthAPIBackend) ExtRPCEnabled() bool {
   393  	return b.extRPCEnabled
   394  }
   395  
   396  func (b *EthAPIBackend) CallTimeOut() time.Duration {
   397  	return b.evmCallTimeOut
   398  }
   399  
   400  func (b *EthAPIBackend) RPCGasCap() uint64 {
   401  	return b.eth.config.RPCGasCap
   402  }
   403  
   404  func (b *EthAPIBackend) RPCTxFeeCap() float64 {
   405  	return b.eth.config.RPCTxFeeCap
   406  }
   407  
   408  func (b *EthAPIBackend) BloomStatus() (uint64, uint64) {
   409  	sections, _, _ := b.eth.bloomIndexer.Sections()
   410  	return params.BloomBitsBlocks, sections
   411  }
   412  
   413  func (b *EthAPIBackend) ServiceFilter(ctx context.Context, session *bloombits.MatcherSession) {
   414  	for i := 0; i < bloomFilterThreads; i++ {
   415  		go session.Multiplex(bloomRetrievalBatch, bloomRetrievalWait, b.eth.bloomRequests)
   416  	}
   417  }
   418  
   419  func (b *EthAPIBackend) Engine() consensus.Engine {
   420  	return b.eth.engine
   421  }
   422  
   423  func (b *EthAPIBackend) CurrentHeader() *types.Header {
   424  	return b.eth.blockchain.CurrentHeader()
   425  }
   426  
   427  func (b *EthAPIBackend) Miner() *miner.Miner {
   428  	return b.eth.Miner()
   429  }
   430  
   431  func (b *EthAPIBackend) StartMining(threads int) error {
   432  	return b.eth.StartMining(threads)
   433  }
   434  
   435  // The validation of pre-requisite for multitenancy is done when EthService
   436  // is being created. So it's safe to use the config value here.
   437  func (b *EthAPIBackend) SupportsMultitenancy(rpcCtx context.Context) (*proto.PreAuthenticatedAuthenticationToken, bool) {
   438  	authToken := rpc.PreauthenticatedTokenFromContext(rpcCtx)
   439  	if authToken != nil && b.eth.config.MultiTenantEnabled() {
   440  		return authToken, true
   441  	}
   442  	return nil, false
   443  }
   444  
   445  func (b *EthAPIBackend) AccountExtraDataStateGetterByNumber(ctx context.Context, number rpc.BlockNumber) (vm.AccountExtraDataStateGetter, error) {
   446  	s, _, err := b.StateAndHeaderByNumber(ctx, number)
   447  	return s, err
   448  }
   449  
   450  func (b *EthAPIBackend) IsPrivacyMarkerTransactionCreationEnabled() bool {
   451  	return b.eth.config.QuorumChainConfig.PrivacyMarkerEnabled() && b.ChainConfig().IsPrivacyPrecompile(b.eth.blockchain.CurrentBlock().Number())
   452  }
   453  
   454  // used by Quorum
   455  type EthAPIState struct {
   456  	state, privateState *state.StateDB
   457  }
   458  
   459  func (s EthAPIState) GetBalance(addr common.Address) *big.Int {
   460  	if s.privateState.Exist(addr) {
   461  		return s.privateState.GetBalance(addr)
   462  	}
   463  	return s.state.GetBalance(addr)
   464  }
   465  
   466  func (s EthAPIState) GetCode(addr common.Address) []byte {
   467  	if s.privateState.Exist(addr) {
   468  		return s.privateState.GetCode(addr)
   469  	}
   470  	return s.state.GetCode(addr)
   471  }
   472  
   473  func (s EthAPIState) SetNonce(addr common.Address, nonce uint64) {
   474  	if s.privateState.Exist(addr) {
   475  		s.privateState.SetNonce(addr, nonce)
   476  	} else {
   477  		s.state.SetNonce(addr, nonce)
   478  	}
   479  }
   480  
   481  func (s EthAPIState) SetCode(addr common.Address, code []byte) {
   482  	if s.privateState.Exist(addr) {
   483  		s.privateState.SetCode(addr, code)
   484  	} else {
   485  		s.state.SetCode(addr, code)
   486  	}
   487  }
   488  
   489  func (s EthAPIState) SetBalance(addr common.Address, balance *big.Int) {
   490  	if s.privateState.Exist(addr) {
   491  		s.privateState.SetBalance(addr, balance)
   492  	} else {
   493  		s.state.SetBalance(addr, balance)
   494  	}
   495  }
   496  
   497  func (s EthAPIState) SetStorage(addr common.Address, storage map[common.Hash]common.Hash) {
   498  	if s.privateState.Exist(addr) {
   499  		s.privateState.SetStorage(addr, storage)
   500  	} else {
   501  		s.state.SetStorage(addr, storage)
   502  	}
   503  }
   504  
   505  func (s EthAPIState) SetState(a common.Address, key common.Hash, value common.Hash) {
   506  	if s.privateState.Exist(a) {
   507  		s.privateState.SetState(a, key, value)
   508  	} else {
   509  		s.state.SetState(a, key, value)
   510  	}
   511  }
   512  
   513  func (s EthAPIState) GetState(a common.Address, b common.Hash) common.Hash {
   514  	if s.privateState.Exist(a) {
   515  		return s.privateState.GetState(a, b)
   516  	}
   517  	return s.state.GetState(a, b)
   518  }
   519  
   520  func (s EthAPIState) GetNonce(addr common.Address) uint64 {
   521  	if s.privateState.Exist(addr) {
   522  		return s.privateState.GetNonce(addr)
   523  	}
   524  	return s.state.GetNonce(addr)
   525  }
   526  
   527  func (s EthAPIState) GetPrivacyMetadata(addr common.Address) (*state.PrivacyMetadata, error) {
   528  	if s.privateState.Exist(addr) {
   529  		return s.privateState.GetPrivacyMetadata(addr)
   530  	}
   531  	return nil, fmt.Errorf("%x: %w", addr, common.ErrNotPrivateContract)
   532  }
   533  
   534  func (s EthAPIState) GetManagedParties(addr common.Address) ([]string, error) {
   535  	if s.privateState.Exist(addr) {
   536  		return s.privateState.GetManagedParties(addr)
   537  	}
   538  	return nil, fmt.Errorf("%x: %w", addr, common.ErrNotPrivateContract)
   539  }
   540  
   541  func (s EthAPIState) GetRLPEncodedStateObject(addr common.Address) ([]byte, error) {
   542  	getFunc := s.state.GetRLPEncodedStateObject
   543  	if s.privateState.Exist(addr) {
   544  		getFunc = s.privateState.GetRLPEncodedStateObject
   545  	}
   546  	return getFunc(addr)
   547  }
   548  
   549  func (s EthAPIState) GetProof(addr common.Address) ([][]byte, error) {
   550  	if s.privateState.Exist(addr) {
   551  		return s.privateState.GetProof(addr)
   552  	}
   553  	return s.state.GetProof(addr)
   554  }
   555  
   556  func (s EthAPIState) GetStorageProof(addr common.Address, h common.Hash) ([][]byte, error) {
   557  	if s.privateState.Exist(addr) {
   558  		return s.privateState.GetStorageProof(addr, h)
   559  	}
   560  	return s.state.GetStorageProof(addr, h)
   561  }
   562  
   563  func (s EthAPIState) StorageTrie(addr common.Address) state.Trie {
   564  	if s.privateState.Exist(addr) {
   565  		return s.privateState.StorageTrie(addr)
   566  	}
   567  	return s.state.StorageTrie(addr)
   568  }
   569  
   570  func (s EthAPIState) Error() error {
   571  	if s.privateState.Error() != nil {
   572  		return s.privateState.Error()
   573  	}
   574  	return s.state.Error()
   575  }
   576  
   577  func (s EthAPIState) GetCodeHash(addr common.Address) common.Hash {
   578  	if s.privateState.Exist(addr) {
   579  		return s.privateState.GetCodeHash(addr)
   580  	}
   581  	return s.state.GetCodeHash(addr)
   582  }
   583  
   584  //func (s MinimalApiState) Error