@ -655,43 +655,62 @@ type StorageResult struct {
Proof [ ] string ` json:"proof" `
}
// proofList implements ethdb.KeyValueWriter and collects the proofs as
// hex-strings for delivery to rpc-caller.
type proofList [ ] string
func ( n * proofList ) Put ( key [ ] byte , value [ ] byte ) error {
* n = append ( * n , hexutil . Encode ( value ) )
return nil
}
func ( n * proofList ) Delete ( key [ ] byte ) error {
panic ( "not supported" )
}
// GetProof returns the Merkle-proof for a given account and optionally some storage keys.
func ( s * BlockChainAPI ) GetProof ( ctx context . Context , address common . Address , storageKeys [ ] string , blockNrOrHash rpc . BlockNumberOrHash ) ( * AccountResult , error ) {
var (
keys = make ( [ ] common . Hash , len ( storageKeys ) )
storageProof = make ( [ ] StorageResult , len ( storageKeys ) )
storageTrie state . Trie
storageHash = types . EmptyRootHash
codeHash = types . EmptyCodeHash
)
// Greedily deserialize all keys. This prevents state access on invalid input
for i , hexKey := range storageKeys {
if key , err := decodeHash ( hexKey ) ; err != nil {
return nil , err
} else {
keys [ i ] = key
}
}
state , _ , err := s . b . StateAndHeaderByNumberOrHash ( ctx , blockNrOrHash )
if state == nil || err != nil {
return nil , err
}
storageTrie , err := state . StorageTrie ( address )
if err != nil {
if storageTrie , err = state . StorageTrie ( address ) ; err != nil {
return nil , err
}
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 we have a storageTrie, the account exists and we must update
// the storage root hash and the code hash.
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 )
codeHash = state . GetCodeHash ( address )
}
// create the proof for the storageKeys
for i , hexKey := range storageK eys {
key , err := decodeHash ( hexKey )
if err != nil {
return nil , err
for i , key := range k eys {
if storageTrie == nil {
storageProof [ i ] = StorageResult { storageKeys [ i ] , & hexutil . Big { } , [ ] string { } }
continue
}
if storageTrie != nil {
proof , storageError := state . GetStorageProof ( address , key )
if storageError != nil {
return nil , storageError
}
storageProof [ i ] = StorageResult { hexKey , ( * hexutil . Big ) ( state . GetState ( address , key ) . Big ( ) ) , toHexSlice ( proof ) }
} else {
storageProof [ i ] = StorageResult { hexKey , & hexutil . Big { } , [ ] string { } }
var proof proofList
if err := storageTrie . Prove ( crypto . Keccak256 ( key . Bytes ( ) ) , 0 , & proof ) ; err != nil {
return nil , err
}
storageProof [ i ] = StorageResult { storageKeys [ i ] ,
( * hexutil . Big ) ( state . GetState ( address , key ) . Big ( ) ) ,
proof }
}
// create the accountProof