@ -18,6 +18,7 @@ package ethapi
import (
import (
"context"
"context"
"encoding/hex"
"errors"
"errors"
"fmt"
"fmt"
"math/big"
"math/big"
@ -674,15 +675,19 @@ func (s *BlockChainAPI) GetProof(ctx context.Context, address common.Address, st
}
}
// create the proof for the storageKeys
// create the proof for the storageKeys
for i , key := range storageKeys {
for i , hexKey := range storageKeys {
key , err := decodeHash ( hexKey )
if err != nil {
return nil , err
}
if storageTrie != nil {
if storageTrie != nil {
proof , storageError := state . GetStorageProof ( address , common . HexToHash ( key ) )
proof , storageError := state . GetStorageProof ( address , key )
if storageError != nil {
if storageError != nil {
return nil , storageError
return nil , storageError
}
}
storageProof [ i ] = StorageResult { k ey, ( * hexutil . Big ) ( state . GetState ( address , common . HexToHash ( key ) ) . Big ( ) ) , toHexSlice ( proof ) }
storageProof [ i ] = StorageResult { hexK ey, ( * hexutil . Big ) ( state . GetState ( address , key ) . Big ( ) ) , toHexSlice ( proof ) }
} else {
} else {
storageProof [ i ] = StorageResult { k ey, & hexutil . Big { } , [ ] string { } }
storageProof [ i ] = StorageResult { hexK ey, & hexutil . Big { } , [ ] string { } }
}
}
}
}
@ -703,6 +708,22 @@ func (s *BlockChainAPI) GetProof(ctx context.Context, address common.Address, st
} , state . Error ( )
} , state . Error ( )
}
}
// decodeHash parses a hex-encoded 32-byte hash. The input may optionally
// be prefixed by 0x and can have an byte length up to 32.
func decodeHash ( s string ) ( common . Hash , error ) {
if strings . HasPrefix ( s , "0x" ) || strings . HasPrefix ( s , "0X" ) {
s = s [ 2 : ]
}
b , err := hex . DecodeString ( s )
if err != nil {
return common . Hash { } , fmt . Errorf ( "hex string invalid" )
}
if len ( b ) > 32 {
return common . Hash { } , fmt . Errorf ( "hex string too long, want at most 32 bytes" )
}
return common . BytesToHash ( b ) , nil
}
// GetHeaderByNumber returns the requested canonical block header.
// GetHeaderByNumber returns the requested canonical block header.
// * When blockNr is -1 the chain head is returned.
// * When blockNr is -1 the chain head is returned.
// * When blockNr is -2 the pending chain head is returned.
// * When blockNr is -2 the pending chain head is returned.
@ -821,12 +842,16 @@ func (s *BlockChainAPI) GetCode(ctx context.Context, address common.Address, blo
// GetStorageAt returns the storage from the state at the given address, key and
// GetStorageAt returns the storage from the state at the given address, key and
// block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta block
// block number. The rpc.LatestBlockNumber and rpc.PendingBlockNumber meta block
// numbers are also allowed.
// numbers are also allowed.
func ( s * BlockChainAPI ) GetStorageAt ( ctx context . Context , address common . Address , k ey string , blockNrOrHash rpc . BlockNumberOrHash ) ( hexutil . Bytes , error ) {
func ( s * BlockChainAPI ) GetStorageAt ( ctx context . Context , address common . Address , hexK ey string , blockNrOrHash rpc . BlockNumberOrHash ) ( hexutil . Bytes , error ) {
state , _ , err := s . b . StateAndHeaderByNumberOrHash ( ctx , blockNrOrHash )
state , _ , err := s . b . StateAndHeaderByNumberOrHash ( ctx , blockNrOrHash )
if state == nil || err != nil {
if state == nil || err != nil {
return nil , err
return nil , err
}
}
res := state . GetState ( address , common . HexToHash ( key ) )
key , err := decodeHash ( hexKey )
if err != nil {
return nil , fmt . Errorf ( "unable to decode storage key: %s" , err )
}
res := state . GetState ( address , key )
return res [ : ] , state . Error ( )
return res [ : ] , state . Error ( )
}
}