Skip to content

graphql: fix block.account and account.storage resolvers (#11662)#20389

Merged
lupin012 merged 3 commits into
mainfrom
lupin012/fix_account_at_bn_using_grapnel
Apr 8, 2026
Merged

graphql: fix block.account and account.storage resolvers (#11662)#20389
lupin012 merged 3 commits into
mainfrom
lupin012/fix_account_at_bn_using_grapnel

Conversation

@lupin012

@lupin012 lupin012 commented Apr 7, 2026

Copy link
Copy Markdown
Contributor

Implement the missing GraphQL resolvers for Block.account(address) and Account.storage(slot), which previously returned null causing "the requested element is null which the schema does not allow".

  • Add GetAccountInfo and GetAccountStorage to GraphQLAPI interface and GraphQLAPIImpl, reading balance/nonce/code/storage from state at the requested block
  • Wire Block.account and Account.storage as proper resolvers in generated.go (IsResolver: true) instead of returning nil struct fields
  • Implement blockResolver.Account() and accountResolver.Storage() in schema.resolvers.go; propagate block number via Account.BlockNum for use by the storage resolver
  • Fix convertDataToStringP in helpers.go to handle accounts.Address type, which caused unhandled/string log spam for transaction from fields
  • Add --graphql flag to startRpcDaemon.sh (required to enable the endpoint)

closes #11662

Implement the missing GraphQL resolvers for Block.account(address) and
Account.storage(slot), which previously returned null causing
"the requested element is null which the schema does not allow".

- Add GetAccountInfo and GetAccountStorage to GraphQLAPI interface and
  GraphQLAPIImpl, reading balance/nonce/code/storage from state at the
  requested block
- Wire Block.account and Account.storage as proper resolvers in
  generated.go (IsResolver: true) instead of returning nil struct fields
- Implement blockResolver.Account() and accountResolver.Storage() in
  schema.resolvers.go; propagate block number via Account.BlockNum for
  use by the storage resolver
- Fix convertDataToStringP in helpers.go to handle accounts.Address
  type, which caused unhandled/string log spam for transaction from fields
- Add --graphql flag to startRpcDaemon.sh (required to enable the endpoint)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@lupin012 lupin012 force-pushed the lupin012/fix_account_at_bn_using_grapnel branch from dcfb55f to e92a02d Compare April 7, 2026 20:05
After rebasing on main (gqlgen v0.17.83 → v0.17.89), the
executableSchema field was renamed from resolvers to Resolvers.
Update the two new resolver dispatch calls accordingly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes GraphQL schema violations by implementing missing resolvers for Block.account(address) and Account.storage(slot) so queries no longer return null for non-nullable schema fields, and adds JSON-RPC backing methods to read account/state data at a given block.

Changes:

  • Extend the JSON-RPC GraphQL API with GetAccountInfo and GetAccountStorage and implement them via state reads at a resolved block number.
  • Switch Block.account and Account.storage to real gqlgen resolvers (instead of struct-field fallbacks) and implement the resolver methods.
  • Update helper conversion to handle accounts.Address values without falling into the “unhandled/string” path.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
rpc/jsonrpc/graphql_api.go Adds state-backed account info & storage read methods used by GraphQL resolvers.
cmd/rpcdaemon/graphql/graph/schema.resolvers.go Implements Block.account and Account.storage resolver logic and passes block number through.
cmd/rpcdaemon/graphql/graph/model/models_gen.go Adds an internal BlockNum field to Account for resolver use.
cmd/rpcdaemon/graphql/graph/helpers.go Extends convertDataToStringP to stringify accounts.Address.
cmd/rpcdaemon/graphql/graph/generated.go Regenerated gqlgen output wiring account/storage as resolvers.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread rpc/jsonrpc/graphql_api.go Outdated
Comment thread rpc/jsonrpc/graphql_api.go Outdated
Comment thread rpc/jsonrpc/graphql_api.go
Comment thread cmd/rpcdaemon/graphql/graph/schema.resolvers.go
Comment thread cmd/rpcdaemon/graphql/graph/schema.resolvers.go
Comment thread cmd/rpcdaemon/graphql/graph/model/models_gen.go Outdated
- Add WithTemporalOverlay in GetAccountInfo and GetAccountStorage to
  handle background commits correctly
- Validate storage slot before opening DB transaction (fail-fast, and
  consistent with GetStorageAt in eth_accounts.go)
- Validate address with IsHexAddress in blockResolver.Account
- Propagate BlockNum to all Account stubs (Miner, tx From/To, log
  Account) so storage(slot) queries target the correct block
- Move Account model out of generated models_gen.go into account.go and
  bind it in gqlgen.yml so BlockNum survives regeneration
- Add NewAccountAtBlock constructor to encapsulate BlockNum assignment
- Add unit tests for slot and address validation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@lupin012 lupin012 marked this pull request as ready for review April 8, 2026 06:44
@AskAlexSharov AskAlexSharov requested a review from Copilot April 8, 2026 06:45

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +203 to +210
func (api *GraphQLAPIImpl) GetAccountStorage(ctx context.Context, address common.Address, slot string, blockNumber rpc.BlockNumber) (string, error) {
slotBytes, decErr := hexutil.FromHexWithValidation(slot)
if decErr != nil {
return zeroStorageHash, &rpc.InvalidParamsError{Message: "unable to decode storage slot: " + hexutil.ErrHexStringInvalid.Error()}
}
if len(slotBytes) > 32 {
return zeroStorageHash, &rpc.InvalidParamsError{Message: hexutil.ErrTooBigHexString.Error()}
}

Copilot AI Apr 8, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GetAccountStorage slot validation currently uses hexutil.FromHexWithValidation, which will accept inputs without a 0x prefix and will also accept odd-length hex by left-padding a nibble. This can make malformed Bytes32 inputs silently resolve to an unintended slot key, which is at odds with the GraphQL schema docs for Bytes32 (0x-prefixed 32-byte hex). Consider explicitly validating the raw slot string format (0x prefix + even number of nibbles, and max 32 bytes) and using the underlying decode error message (decErr) in the InvalidParamsError to make failures actionable.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The lenient behavior is intentional and consistent with GetStorageAt in eth_accounts.go, which uses the same hexutil.FromHexWithValidation and explicitly documents the choice:

// Validation for index i.e. storage slot is non-standard: it can be interpreted
// as QUANTITY (stricter) or as DATA (like Hive tests do).
// Waiting for a spec, we choose the latter because it's more general,
// but we check that the length is not greater than 64 hex-digits.

@lupin012 lupin012 added this pull request to the merge queue Apr 8, 2026
Merged via the queue into main with commit 52547d3 Apr 8, 2026
67 checks passed
@lupin012 lupin012 deleted the lupin012/fix_account_at_bn_using_grapnel branch April 8, 2026 23:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fail to request account info given block number using grapnel

3 participants