Client/StateManager: storageRangeAt() RPC call / EVMStateManager Interface Extension#2922
Conversation
Codecov Report
Additional details and impacted files
Flags with carried forward coverage won't be shown. Click here to find out more. |
| [validators.transaction()], | ||
| [validators.blockOption], | ||
| ]) | ||
| this.storageRangeAt = middleware(this.storageRangeAt.bind(this), 5, [[validators.hex]]) |
There was a problem hiding this comment.
the validators here will only validate the first arg, reading from comments need 5 validators
| /** | ||
| * Returns a limited set of storage keys belonging to an account. | ||
| * @param params An array of 5 parameters: | ||
| * 1. The hash of the block that contains the requested account storage. |
There was a problem hiding this comment.
| * 1. The hash of the block that contains the requested account storage. | |
| * 1. The hash of the block at which to get storage from the state. |
just making it less ambiguous
| * Returns a limited set of storage keys belonging to an account. | ||
| * @param params An array of 5 parameters: | ||
| * 1. The hash of the block that contains the requested account storage. | ||
| * 2. The number index of the requested transaction within the block. |
There was a problem hiding this comment.
| * 2. The number index of the requested transaction within the block. | |
| * 2. The transaction index of the requested block post which to get the storage. |
| * 1. The hash of the block that contains the requested account storage. | ||
| * 2. The number index of the requested transaction within the block. | ||
| * 3. The address of the account. | ||
| * 4. The smallest (hashed) storage key that will be returned. To include the entire range, pass '0x00'. |
There was a problem hiding this comment.
| * 4. The smallest (hashed) storage key that will be returned. To include the entire range, pass '0x00'. | |
| * 4. The starting (hashed) key from which storage will be returned. To include the entire range, pass '0x00'. |
| * 2. The number index of the requested transaction within the block. | ||
| * 3. The address of the account. | ||
| * 4. The smallest (hashed) storage key that will be returned. To include the entire range, pass '0x00'. | ||
| * 5. The maximum number of storage values that will be returned. |
There was a problem hiding this comment.
| * 5. The maximum number of storage values that will be returned. | |
| * 5. The maximum number of storage values that could be returned. |
|
|
||
| let block: Block | ||
| try { | ||
| block = await this.service.chain.getBlock(blockHashBytes) |
There was a problem hiding this comment.
| block = await this.service.chain.getBlock(blockHashBytes) | |
| block = await this.chain.getBlock(blockHashBytes) |
this.chain is available
| } | ||
| } | ||
|
|
||
| if (txIndex + 1 > block.transactions.length) { |
There was a problem hiding this comment.
| if (txIndex + 1 > block.transactions.length) { | |
| if (txIndex >= block.transactions.length) { |
more comprehensible about the check
| } | ||
|
|
||
| try { | ||
| const block = await this.service.chain.getBlock(hexToBytes(blockHash)) |
There was a problem hiding this comment.
isn't the block already read above (in params check) also this.chain can be directly refereed
| try { | ||
| address = Address.fromString(account) | ||
| blockHashBytes = hexToBytes(blockHash) | ||
| startKeyBytes = hexToBytes(startKey) |
There was a problem hiding this comment.
startKey could be directly converted to bigint using a hexToBig... helper , and if limit is also coming as hex encoded it needs to be converted to number/bigint as well as per the requirement
There was a problem hiding this comment.
There does not appear to exist a hexToBigInt() helper. I have however moved the function calls to the same line.
There was a problem hiding this comment.
if the hex is '0x' prefixed, you can just use the BigInt constructor like: BigInt('0xabcde')
| * @returns A {@link StorageRange} object that will contain at most `limit` entries in its `storage` field. | ||
| * The object will also contain `nextKey`, the next (hashed) storage key after the range included in `storage`. | ||
| */ | ||
| async storageRangeAt(params: [string, number, string, string, number]) { |
There was a problem hiding this comment.
| async storageRangeAt(params: [string, number, string, string, number]) { | |
| async storageRangeAt(params: [string, string, string, string, string]) { |
most like it will come as a hex encoded number ... not sure about that but do check and update/confirm
There was a problem hiding this comment.
The reference implementation does use int for both of these.
|
Thanks a lot for this PR! 🙏🙂❤️ |
|
It appears that parameters |
If you are open to do maybe add a very simple /**
* bool validator to check if type is boolean
* @param params parameters of method
* @param index index of parameter
*/
get bool() {
return (params: any[], index: number) => {
if (typeof params[index] !== 'boolean') {
return {
code: INVALID_PARAMS,
message: `invalid argument ${index}: argument is not boolean`,
}
}
}
} |
| [validators.transaction()], | ||
| [validators.blockOption], | ||
| ]) | ||
| // TODO: txIndex and limit are currently not input validated. |
There was a problem hiding this comment.
do we need new validator types for these?
| context.createdAddressNoStorage = thirdResult.createdAddress!! | ||
| }) | ||
|
|
||
| it<TestSetup>('Should return the correct (number of) key value pairs.', async ({ |
There was a problem hiding this comment.
What does the <TestSetup> type parameter do? is it just a label, or does it change the it function?
There was a problem hiding this comment.
It is a typesafe way of passing variables from beforeEach() to tests (see here). For legibility, I had already annotated the TestSetup interface.
| throw new Error('Missing VM.') | ||
| } | ||
|
|
||
| if (txIndex < 0) { |
There was a problem hiding this comment.
if we don't already have a validator for index parameters, it could be worth adding one. especially if there are other methods are doing this themselves
| return await vmCopy.stateManager.dumpStorageRange( | ||
| // Validator already verified that `account` and `startKey` are properly formatted. | ||
| Address.fromString(account), | ||
| bytesToBigInt(hexToBytes(startKey)), |
There was a problem hiding this comment.
| bytesToBigInt(hexToBytes(startKey)), | |
| BigInt(startKey), |
Are there methods that use signed integers (negative numbers)? "index" will always be unsigned, so it might be better to add |
ScottyPoi
left a comment
There was a problem hiding this comment.
Looks great! Thanks for including all the tests, and for adding the validator! super helpful 👍
|
Congrats, your important contribution to this open-source project has earned you a GitPOAP! GitPOAP: 2023 EthereumJS Contributor: Head to gitpoap.io & connect your GitHub account to mint! Learn more about GitPOAPs here. |
|
@KoningR Hi there, thanks again for this great work! 🤩 We'll directly that this into the upcoming releases (so: today)! |

This PR implements
debug_storageRangeAt()as discussed in ethereum/go-ethereum#14350. An implementation is only provided forDefaultStateManager, not forEthersStateManager. Additionally, hashed key preimages are alwaysnullbecause there does not seem to be a good way to retrieve them currently.