Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create State specific JSON api-s #281

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions jsonrpc/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules/

openrpc.json
40 changes: 40 additions & 0 deletions jsonrpc/src/content/params.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,5 +72,45 @@
"schema": {
"$ref": "#/components/schemas/DataRadius"
}
},
"Address": {
"name": "address",
"description": "The address of the account",
"required": true,
"schema": {
"$ref": "#/components/schemas/bytes20"
}
},
"StateRoot": {
"name": "stateRoot",
"description": "The root of the state trie",
"required": true,
"schema": {
"$ref": "#/components/schemas/bytes32"
}
},
"Codehash": {
"name": "codehash",
"description": "The hash of the contract's code.",
"required": true,
"schema": {
"$ref": "#/components/schemas/bytes32"
}
},
"StorageRoot": {
"name": "storageRoot",
"description": "The root of the contract's storage trie",
"required": true,
"schema": {
"$ref": "#/components/schemas/bytes32"
}
},
"StorageSlot": {
"name": "storageSlot",
"description": "The slot in the storage trie",
"required": true,
"schema": {
"$ref": "#/components/schemas/uint256"
}
}
}
71 changes: 71 additions & 0 deletions jsonrpc/src/content/results.json
Original file line number Diff line number Diff line change
Expand Up @@ -217,5 +217,76 @@
"title": "number of peers",
"type": "number"
}
},
"DataRadiusResult": {
"name": "radiusResult",
"description": "The radius of the local node.",
"schema": {
"$ref": "#/components/schemas/DataRadius"
}
},
"AccountStateResult": {
"name": "accountStateResult",
"description": "The state of the account.",
"schema": {
"type": "object",
"required": [
"nonce",
"balance",
"storageRoot",
"codehash",
"proof"
],
"properties": {
"nonce": {
"description": "The account's nonce",
"$ref": "#/components/schemas/uint"
},
"balance": {
"description": "The account's balance",
"$ref": "#/components/schemas/uint256"
},
"storageRoot": {
"description": "The root of the storate trie of the smart contract",
"$ref": "#/components/schemas/bytes32"
},
"codehash": {
"description": "The hash of the smart contract's code",
"$ref": "#/components/schemas/bytes32"
},
"proof": {
"description": "The proof of the account state inclusion",
"$ref": "#/components/schemas/trieProof"
}
}
}
},
"ContractStorageAtResult": {
"name": "contractStorageAtResult",
"description": "The value that is stored in the contract's storage trie.",
"schema": {
"type": "object",
"required": [
"value",
"proof"
],
"properties": {
"value": {
"description": "The value stored in the storage trie, or \"0x0\" if missing",
"$ref": "#/components/schemas/uint256"
},
"proof": {
"description": "The proof of the inclusion",
"$ref": "#/components/schemas/trieProof"
}
}
}
},
"ContractBytecodeResult": {
"name": "contractBytecodeResult",
"description": "The contract's bytecode",
"schema": {
"$ref": "#/components/schemas/hexString"
}
}
}
8 changes: 8 additions & 0 deletions jsonrpc/src/methods/history.json
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,14 @@
"$ref": "#/components/contentDescriptors/TraceRecursiveFindContentResult"
}
},
{
"name": "portal_historyRadius",
"summary": "Returns the radius used by the history network.",
"params": [],
"result": {
"$ref": "#/components/contentDescriptors/DataRadiusResult"
}
},
{
"name": "portal_historyStore",
"summary": "Store history content key with content data",
Expand Down
68 changes: 68 additions & 0 deletions jsonrpc/src/methods/state.json
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,26 @@
"$ref": "#/components/contentDescriptors/RecursiveFindContentResult"
}
},
{
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do I understand correctly that these calls walk down the state to get to a specific account / storage data?
So basically a bunch of different recursiveFindContent calls?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, that's the idea. It is a mid point between recursiveFindContent and eth_ state methods (eth_getBalance, eth_getStorageAt, eth_getTransactionCount, eth_getCode).

Copy link
Collaborator

@kdeme kdeme Mar 19, 2024

Choose a reason for hiding this comment

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

Right. I'm not a big fan of mixing these type of methods in the core Portal json-rpc API. Unless their logic is also required in the core protocol.

It seems they are not so different from the Execution layer JSON-RPC API counterparts, aside from directly requiring the state root versus the block root?

But if that is enough reason to still have them, then I'd say they perhaps should have a separate, more application focused, Portal json-rpc "namespace"? Or for now, atleast they could be made optional in the current Portal JSON-RPC specification (and moved when/if there are more?).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I would say that benefits are slightly better:

  • the Execution api-s actually don't allow block hash. They explicitly support block number or string ("latest", "earliest" or "pending"), and I don't think we support either (I assume we plan to in the long run, so this might not be so big issue)
  • official api for the eth_getStorageAt would have to always iterate over state trie (to find account state) and contract storage trie. The api that I propose splits those tree traversals into separate calls (meaning, if you want to get multiple values from the same contract, you will iterate state trie only once).

I'm fine with creating different namespace and / or making them optional. Maybe we can discuss this on the next team meeting.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Further thinking about it, having a different namespace is not just useful for us in keeping some logic separate, but even more interesting for end users.

Providing just one API which contains also all these lower level calls that are only useful for testing the actual protocol will be overwhelming and not great UX. Separate user focused API does sound better for that.

"name": "portal_stateTraceRecursiveFindContent",
"summary": "Look up a target content key in the network and get tracing data",
"params": [
{
"$ref": "#/components/contentDescriptors/ContentKey"
}
],
"result": {
"$ref": "#/components/contentDescriptors/TraceRecursiveFindContentResult"
}
},
{
"name": "portal_stateRadius",
"summary": "Returns the radius used by the state network.",
"params": [],
"result": {
"$ref": "#/components/contentDescriptors/DataRadiusResult"
}
},
{
"name": "portal_stateStore",
"summary": "Store state content key with content data",
Expand Down Expand Up @@ -180,5 +200,53 @@
"result": {
"$ref": "#/components/contentDescriptors/GossipResult"
}
},
{
"name": "portal_stateRecursiveFindAccountState",
"summary": "Traverses the state trie and returns the AccountState and its proof.",
"params": [
{
"$ref": "#/components/contentDescriptors/StateRoot"
},
{
"$ref": "#/components/contentDescriptors/Address"
}
],
"result": {
"$ref": "#/components/contentDescriptors/AccountStateResult"
}
},
{
"name": "portal_stateRecursiveFindContractStorageAt",
"summary": "Traverses the contract's storage trie and returns value stored at the requested slot.",
"params": [
{
"$ref": "#/components/contentDescriptors/Address"
},
{
"$ref": "#/components/contentDescriptors/StorageRoot"
},
{
"$ref": "#/components/contentDescriptors/StorageSlot"
}
],
"result": {
"$ref": "#/components/contentDescriptors/ContractStorageAtResult"
}
},
{
"name": "portal_stateRecursiveFindContractBytecode",
"summary": "Returns the contracts's bytecode.",
"params": [
{
"$ref": "#/components/contentDescriptors/Address"
},
{
"$ref": "#/components/contentDescriptors/Codehash"
}
],
"result": {
"$ref": "#/components/contentDescriptors/ContractBytecodeResult"
}
}
]
5 changes: 5 additions & 0 deletions jsonrpc/src/schemas/base_types.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@
"type": "string",
"pattern": "^0x[0-9a-f]{32}$"
},
"bytes20": {
"title": "20 hex encoded bytes",
"type": "string",
"pattern": "^0x[0-9a-f]{40}$"
},
"bytes32": {
"title": "32 hex encoded bytes",
"type": "string",
Expand Down
7 changes: 7 additions & 0 deletions jsonrpc/src/schemas/portal.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,12 @@
"title": "UDP port number",
"type": "string",
"pattern": "^([1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$"
},
"trieProof": {
"title": "The proof of a trie node inclusion given as a list of encoded trie nodes, from the root to the target node.",
"type": "array",
"items": {
"$ref": "#/components/schemas/hexString"
}
}
}
Loading