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