Skip to content

Commit

Permalink
Revert "internal/ethapi: quantity-encode storage keys in eth_getProof…
Browse files Browse the repository at this point in the history
… response (ethereum#27309)"

This reverts commit ff8659c.
  • Loading branch information
devopsbo3 committed Nov 10, 2023
1 parent 4c01cd8 commit 4a55d90
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 64 deletions.
36 changes: 1 addition & 35 deletions ethclient/gethclient/gethclient_test.go
Expand Up @@ -105,9 +105,6 @@ func TestGethClient(t *testing.T) {
{
"TestGetProof",
func(t *testing.T) { testGetProof(t, client) },
}, {
"TestGetProofCanonicalizeKeys",
func(t *testing.T) { testGetProofCanonicalizeKeys(t, client) },
}, {
"TestGCStats",
func(t *testing.T) { testGCStats(t, client) },
Expand Down Expand Up @@ -221,7 +218,6 @@ func testGetProof(t *testing.T, client *rpc.Client) {
if result.Balance.Cmp(balance) != 0 {
t.Fatalf("invalid balance, want: %v got: %v", balance, result.Balance)
}

// test storage
if len(result.StorageProof) != 1 {
t.Fatalf("invalid storage proof, want 1 proof, got %v proof(s)", len(result.StorageProof))
Expand All @@ -232,37 +228,7 @@ func testGetProof(t *testing.T, client *rpc.Client) {
t.Fatalf("invalid storage proof value, want: %v, got: %v", slotValue, proof.Value.Bytes())
}
if proof.Key != testSlot.String() {
t.Fatalf("invalid storage proof key, want: %q, got: %q", testSlot.String(), proof.Key)
}
}

func testGetProofCanonicalizeKeys(t *testing.T, client *rpc.Client) {
ec := New(client)

// Tests with non-canon input for storage keys.
// Here we check that the storage key is canonicalized.
result, err := ec.GetProof(context.Background(), testAddr, []string{"0x0dEadbeef"}, nil)
if err != nil {
t.Fatal(err)
}
if result.StorageProof[0].Key != "0xdeadbeef" {
t.Fatalf("wrong storage key encoding in proof: %q", result.StorageProof[0].Key)
}
if result, err = ec.GetProof(context.Background(), testAddr, []string{"0x000deadbeef"}, nil); err != nil {
t.Fatal(err)
}
if result.StorageProof[0].Key != "0xdeadbeef" {
t.Fatalf("wrong storage key encoding in proof: %q", result.StorageProof[0].Key)
}

// If the requested storage key is 32 bytes long, it will be returned as is.
hashSizedKey := "0x00000000000000000000000000000000000000000000000000000000deadbeef"
result, err = ec.GetProof(context.Background(), testAddr, []string{hashSizedKey}, nil)
if err != nil {
t.Fatal(err)
}
if result.StorageProof[0].Key != hashSizedKey {
t.Fatalf("wrong storage key encoding in proof: %q", result.StorageProof[0].Key)
t.Fatalf("invalid storage proof key, want: %v, got: %v", testSlot.String(), proof.Key)
}
}

Expand Down
45 changes: 16 additions & 29 deletions internal/ethapi/api.go
Expand Up @@ -672,61 +672,48 @@ func (n *proofList) Delete(key []byte) error {
func (s *BlockChainAPI) GetProof(ctx context.Context, address common.Address, storageKeys []string, blockNrOrHash rpc.BlockNumberOrHash) (*AccountResult, error) {
var (
keys = make([]common.Hash, len(storageKeys))
keyLengths = make([]int, len(storageKeys))
storageProof = make([]StorageResult, len(storageKeys))
storageTrie state.Trie
storageHash = types.EmptyRootHash
codeHash = types.EmptyCodeHash
)
// Deserialize all keys. This prevents state access on invalid input.
// Greedily deserialize all keys. This prevents state access on invalid input
for i, hexKey := range storageKeys {
var err error
keys[i], keyLengths[i], err = decodeHash(hexKey)
if err != nil {
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
}
if storageTrie, err = state.StorageTrie(address); err != nil {
return nil, err
}

// If we have a storageTrie, the account exists and we must update
// 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()
codeHash = state.GetCodeHash(address)
}
// Create the proofs for the storageKeys.
// create the proof for the storageKeys
for i, key := range keys {
// Output key encoding is a bit special: if the input was a 32-byte hash, it is
// returned as such. Otherwise, we apply the QUANTITY encoding mandated by the
// JSON-RPC spec for getProof. This behavior exists to preserve backwards
// compatibility with older client versions.
var outputKey string
if keyLengths[i] != 32 {
outputKey = hexutil.EncodeBig(key.Big())
} else {
outputKey = hexutil.Encode(key[:])
}

if storageTrie == nil {
storageProof[i] = StorageResult{outputKey, &hexutil.Big{}, []string{}}
storageProof[i] = StorageResult{storageKeys[i], &hexutil.Big{}, []string{}}
continue
}
var proof proofList
if err := storageTrie.Prove(crypto.Keccak256(key.Bytes()), &proof); err != nil {
return nil, err
}
value := (*hexutil.Big)(state.GetState(address, key).Big())
storageProof[i] = StorageResult{outputKey, value, proof}
storageProof[i] = StorageResult{storageKeys[i],
(*hexutil.Big)(state.GetState(address, key).Big()),
proof}
}

// Create the accountProof.
// create the accountProof
accountProof, proofErr := state.GetProof(address)
if proofErr != nil {
return nil, proofErr
Expand All @@ -745,7 +732,7 @@ func (s *BlockChainAPI) GetProof(ctx context.Context, address common.Address, st

// decodeHash parses a hex-encoded 32-byte hash. The input may optionally
// be prefixed by 0x and can have a byte length up to 32.
func decodeHash(s string) (h common.Hash, inputLength int, err error) {
func decodeHash(s string) (common.Hash, error) {
if strings.HasPrefix(s, "0x") || strings.HasPrefix(s, "0X") {
s = s[2:]
}
Expand All @@ -754,12 +741,12 @@ func decodeHash(s string) (h common.Hash, inputLength int, err error) {
}
b, err := hex.DecodeString(s)
if err != nil {
return common.Hash{}, 0, errors.New("hex string invalid")
return common.Hash{}, errors.New("hex string invalid")
}
if len(b) > 32 {
return common.Hash{}, len(b), errors.New("hex string too long, want at most 32 bytes")
return common.Hash{}, errors.New("hex string too long, want at most 32 bytes")
}
return common.BytesToHash(b), len(b), nil
return common.BytesToHash(b), nil
}

// GetHeaderByNumber returns the requested canonical block header.
Expand Down Expand Up @@ -889,7 +876,7 @@ func (s *BlockChainAPI) GetStorageAt(ctx context.Context, address common.Address
if state == nil || err != nil {
return nil, err
}
key, _, err := decodeHash(hexKey)
key, err := decodeHash(hexKey)
if err != nil {
return nil, fmt.Errorf("unable to decode storage key: %s", err)
}
Expand Down

0 comments on commit 4a55d90

Please sign in to comment.