github.com/Night-mk/quorum@v21.1.0+incompatible/extension/state_fetcher.go (about)

     1  package extension
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"fmt"
     7  
     8  	"github.com/ethereum/go-ethereum/common"
     9  	"github.com/ethereum/go-ethereum/core/state"
    10  	"github.com/ethereum/go-ethereum/core/types"
    11  	"github.com/ethereum/go-ethereum/core/vm"
    12  	"github.com/ethereum/go-ethereum/extension/extensionContracts"
    13  	"github.com/ethereum/go-ethereum/multitenancy"
    14  	"github.com/ethereum/go-ethereum/rpc"
    15  )
    16  
    17  // ChainAccessor provides methods to fetch state and blocks from the local blockchain
    18  type ChainAccessor interface {
    19  	multitenancy.ContextAware
    20  	// GetBlockByHash retrieves a block from the local chain.
    21  	GetBlockByHash(common.Hash) *types.Block
    22  	StateAt(root common.Hash) (*state.StateDB, *state.StateDB, error)
    23  	State() (*state.StateDB, *state.StateDB, error)
    24  	CurrentBlock() *types.Block
    25  }
    26  
    27  // Only extract required methods from ethService.APIBackend
    28  type APIBackendHelper interface {
    29  	multitenancy.AuthorizationProvider
    30  	AccountExtraDataStateGetterByNumber(ctx context.Context, number rpc.BlockNumber) (vm.AccountExtraDataStateGetter, error)
    31  	CurrentBlock() *types.Block
    32  }
    33  
    34  // StateFetcher manages retrieving state from the database and returning it in
    35  // a usable form by the extension API.
    36  type StateFetcher struct {
    37  	chainAccessor ChainAccessor
    38  }
    39  
    40  // Creates a new StateFetcher from the ethereum service
    41  func NewStateFetcher(chainAccessor ChainAccessor) *StateFetcher {
    42  	return &StateFetcher{
    43  		chainAccessor: chainAccessor,
    44  	}
    45  }
    46  
    47  // returns the current block hash
    48  func (fetcher *StateFetcher) getCurrentBlockHash() common.Hash {
    49  	return fetcher.chainAccessor.CurrentBlock().Hash()
    50  }
    51  
    52  // GetAddressStateFromBlock is a public method that combines the other
    53  // functions of a StateFetcher, retrieving the state of an address at a given
    54  // block, represented in JSON.
    55  func (fetcher *StateFetcher) GetAddressStateFromBlock(blockHash common.Hash, addressToFetch common.Address) ([]byte, error) {
    56  	privateState, err := fetcher.privateState(blockHash)
    57  	if err != nil {
    58  		return nil, err
    59  	}
    60  	stateData, err := fetcher.addressStateAsJson(privateState, addressToFetch)
    61  	if err != nil {
    62  		return nil, err
    63  	}
    64  	return stateData, nil
    65  }
    66  
    67  // privateState returns the private state database for a given block hash.
    68  func (fetcher *StateFetcher) privateState(blockHash common.Hash) (*state.StateDB, error) {
    69  	block := fetcher.chainAccessor.GetBlockByHash(blockHash)
    70  	_, privateState, err := fetcher.chainAccessor.StateAt(block.Root())
    71  
    72  	return privateState, err
    73  }
    74  
    75  // addressStateAsJson returns the state of an address, including the balance,
    76  // nonce, code and state data as a JSON map.
    77  func (fetcher *StateFetcher) addressStateAsJson(privateState *state.StateDB, addressToShare common.Address) ([]byte, error) {
    78  	keepAddresses := make(map[string]extensionContracts.AccountWithMetadata)
    79  
    80  	if account, found := privateState.DumpAddress(addressToShare); found {
    81  		keepAddresses[addressToShare.Hex()] = extensionContracts.AccountWithMetadata{
    82  			State: account,
    83  		}
    84  	} else {
    85  		return nil, fmt.Errorf("error in contract state fetch")
    86  	}
    87  	//types can be marshalled, so errors can't occur
    88  	out, _ := json.Marshal(&keepAddresses)
    89  	return out, nil
    90  }
    91  
    92  // returns the privacy metadata
    93  func (fetcher *StateFetcher) GetPrivacyMetaData(blockHash common.Hash, address common.Address) (*state.PrivacyMetadata, error) {
    94  	privateState, err := fetcher.privateState(blockHash)
    95  	if err != nil {
    96  		return nil, err
    97  	}
    98  
    99  	privacyMetaData, err := privateState.GetPrivacyMetadata(address)
   100  	if err != nil {
   101  		return nil, err
   102  	}
   103  
   104  	return privacyMetaData, nil
   105  }
   106  
   107  // returns the privacy metadata
   108  func (fetcher *StateFetcher) GetStorageRoot(blockHash common.Hash, address common.Address) (common.Hash, error) {
   109  	privateState, err := fetcher.privateState(blockHash)
   110  	if err != nil {
   111  		return common.Hash{}, err
   112  	}
   113  
   114  	storageRoot, err := privateState.GetStorageRoot(address)
   115  	if err != nil {
   116  		return common.Hash{}, err
   117  	}
   118  
   119  	return storageRoot, nil
   120  }