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 }