aboutsummaryrefslogtreecommitdiffstats
path: root/internal
diff options
context:
space:
mode:
Diffstat (limited to 'internal')
-rw-r--r--internal/ethapi/api.go66
1 files changed, 66 insertions, 0 deletions
diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go
index 196be43e0..0c751c328 100644
--- a/internal/ethapi/api.go
+++ b/internal/ethapi/api.go
@@ -508,6 +508,72 @@ func (s *PublicBlockChainAPI) GetBalance(ctx context.Context, address common.Add
return (*hexutil.Big)(state.GetBalance(address)), state.Error()
}
+// Result structs for GetProof
+type AccountResult struct {
+ Address common.Address `json:"address"`
+ AccountProof []string `json:"accountProof"`
+ Balance *hexutil.Big `json:"balance"`
+ CodeHash common.Hash `json:"codeHash"`
+ Nonce hexutil.Uint64 `json:"nonce"`
+ StorageHash common.Hash `json:"storageHash"`
+ StorageProof []StorageResult `json:"storageProof"`
+}
+type StorageResult struct {
+ Key string `json:"key"`
+ Value *hexutil.Big `json:"value"`
+ Proof []string `json:"proof"`
+}
+
+// GetProof returns the Merkle-proof for a given account and optionally some storage keys.
+func (s *PublicBlockChainAPI) GetProof(ctx context.Context, address common.Address, storageKeys []string, blockNr rpc.BlockNumber) (*AccountResult, error) {
+ state, _, err := s.b.StateAndHeaderByNumber(ctx, blockNr)
+ if state == nil || err != nil {
+ return nil, err
+ }
+
+ storageTrie := state.StorageTrie(address)
+ storageHash := types.EmptyRootHash
+ codeHash := state.GetCodeHash(address)
+ storageProof := make([]StorageResult, len(storageKeys))
+
+ // if we have a storageTrie, (which means the account exists), we can update the storagehash
+ if storageTrie != nil {
+ storageHash = storageTrie.Hash()
+ } else {
+ // no storageTrie means the account does not exist, so the codeHash is the hash of an empty bytearray.
+ codeHash = crypto.Keccak256Hash(nil)
+ }
+
+ // create the proof for the storageKeys
+ for i, key := range storageKeys {
+ if storageTrie != nil {
+ proof, storageError := state.GetStorageProof(address, common.HexToHash(key))
+ if storageError != nil {
+ return nil, storageError
+ }
+ storageProof[i] = StorageResult{key, (*hexutil.Big)(state.GetState(address, common.HexToHash(key)).Big()), common.ToHexArray(proof)}
+ } else {
+ storageProof[i] = StorageResult{key, &hexutil.Big{}, []string{}}
+ }
+ }
+
+ // create the accountProof
+ accountProof, proofErr := state.GetProof(address)
+ if proofErr != nil {
+ return nil, proofErr
+ }
+
+ return &AccountResult{
+ Address: address,
+ AccountProof: common.ToHexArray(accountProof),
+ Balance: (*hexutil.Big)(state.GetBalance(address)),
+ CodeHash: codeHash,
+ Nonce: hexutil.Uint64(state.GetNonce(address)),
+ StorageHash: storageHash,
+ StorageProof: storageProof,
+ }, state.Error()
+}
+
// GetBlockByNumber returns the requested block. When blockNr is -1 the chain head is returned. When fullTx is true all
// transactions in the block are returned in full detail, otherwise only the transaction hash is returned.
func (s *PublicBlockChainAPI) GetBlockByNumber(ctx context.Context, blockNr rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) {