You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository has been archived by the owner on Oct 7, 2020. It is now read-only.
Hey all - as discussed two weeks ago, I've compiled a bunch of info around getting the data the RPC layer needs out of Tendermint.
Overview
Ethermint needs a way of querying Tendermint blocks and their associated metadata in order to surface Web3-compatible JSON-RPC responses. We've discussed a number of ways to do this in the past, and most recently converged on using Tendermint tags as a way of indexing data for access by the RPC layer. This document proposes a detailed implementation path for that solution. Note that sending transactions and managing account information is deliberately left out-of-scope since these are much larger discussions that do not block the solution proposed herein.
Architecture
We'll need to create some Ethermint-specific tags to support certain JSON-RPC methods, and persist additional data in some cases to support advanced features like bloom filters over logs. Below, see a list of tags we'll need to create:
eth.blockhash: represents the Ethereum-style block hash to which a given transaction or block belongs.
eth.txhash: represents the Ethereum-style transaction hash to which a given transaction belongs.
eth.topics: represents an Ethereum log topic associated with a given transaction.
Below, see the lists of additional metadata we'll need to persist with each block and transaction.
Block Metadata Persistence
logsBloom: A bloom filter of logs emitted in this block.
hash: The Ethereum-style hash of the block.
Transaction Metadata Persistence
blockHash: The Ethereum-style block hash of the transaction's block.
hash: The Ethereum-style hash of the transaction.
Note: Ethereum draws a distinction between transactions and transaction receipts. In Geth, receipts are stored separately from transactions. Thus, this requires the following additional fields to be stored alongside each transaction to facilitate transaction receipt lookups:
logs: An array of logs generated by the transaction.
logsBloom: A bloom filter of the logs emitted in this transaction.
If we don't want to persist the Ethereum-style hashes with the blocks and transactions themselves, we can calculate them on-the-fly in the RPC layer.
Filters and Stateful RPC
Ethereum supports stateful RPC methods via a two-call flow:
The user registers a filter via one of the eth_new*Filter methods, which returns a filter ID.
The user calls eth_getFilter* with the filter ID to get the changes that have occurred since the previous call to eth_getFilter*.
Supporting filters of this kind won't require any changes to Tendermint. Instead, the Ethermint RPC layer will maintain a pointer to the last-filtered block number for each registered filter. When a request to eth_getFilter* is received, then the RPC layer will perform a lookup using the tags outlined above. For example, a filter defined with the following parameters:
would yield the following query to the Tendermint storage engine upon receipt of a getFilterChanges call:
eth.topics CONTAINS 0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b OR (eth.topics CONTAINS 0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b OR eth.topics CONTAINS 0x0000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebccc) AND block.height >= 1 AND block.height <= 2 AND tx.sender = 0x8888f1f195afa192cfee860698584c030f4c9db1
Note: The above query isn't canonical, it's here to illustrate the idea.
I'm concerned about the performance characteristics of running many CONTAINS operations - lots of Ethereum developers set fromBlock to 1 and toBlock to latest, which would precipitate a scan of the entire blockchain to find matching transactions. Furthermore, it only operates on substring matches, so we'd need to parse each returned block in Ethermint and manually perform log-index-based matching to be in full compliance with the JSON-RPC API. Here's the relevant info from the spec:
A note on specifying topic filters:
Topics are order-dependent. A transaction with a log with topics [A, B] will be matched by the following topic filters:
[] "anything"
[A] "A in first position (and anything after)"
[null, B] "anything in first position AND B in second position (and anything after)"
[A, B] "A in first position AND B in second position (and anything after)"
[[A, B], [A, B]] "(A OR B) in first position AND (A OR B) in second position (and anything after)"
Index of RPC Methods
Method
Tags Needed
Notes
web3_clientVersion
N/A
Unrelated to Tendermint.
web3_sha3
N/A
Unrelated to Tendermint.
net_version
N/A
Unrelated to Tendermint.
net_peerCount
N/A
Unrelated to Tendermint.
net_listening
N/A
Unrelated to Tendermint.
eth_protocolVersion
N/A
Unrelated to Tendermint.
eth_syncing
N/A
"The sync status object may need to be different depending on the details of Tendermint's sync protocol. However, the 'synced' result is simply a boolean, and can easily be derived from Tendermint's internal sync state."
eth_coinbase
N/A
"This can be a config. Since there's no mining on Ethermint, this method doesn't have any meaning."
eth_mining
N/A
Will always be false.
eth_hashrate
N/A
Will always be zero.
eth_gasPrice
N/A
"Geth calculates this using its internal 'Gas Price Oracle,' which takes a percentile of the last N blocks. We can do the same."
eth_accounts
N/A
"This can be returned by whatever Ethermint uses as its 'owned account' abstraction. If we want to force users to write their own wallet applications, this can be an empty array."
eth_blockNumber
N/A
"This is the block height, which Tendermint already caches for us."
eth_getBalance
N/A
"This is kept in the state trie, which is a separate discussion."
eth_getStorageAt
N/A
"This is kept in the state trie, which is a separate discussion."
eth_getTransactionCount
N/A
This can be calculated by counting the transactions returned by a query for the transaction's sender.
eth_getBlockTransactionCountByHash
eth.blockhash
This can be calculated by counting the number of transactions returned by a query for a given block hash.
eth_getBlockTransactionCountByNumber
N/A
This can be calculated by counting the number of transactions returned by a query for a given block number.
eth_getUncleCountByBlockHash
N/A
"Will always be zero, since Ethermint does not have the concept of uncles."
eth_getUncleCountByBlockNumber
N/A
"Will always be zero, since Ethermint does not have the concept of uncles."
eth_getCode
N/A
"This is kept in the state trie, which is a separate discussion."
eth_sign
N/A
This is calculated based on your unlocked accounts. Ethermint can do the same.
eth_sendTransaction
N/A
Out-of-scope for this discussion.
eth_sendRawTransaction
N/A
Out-of-scope for this discussion.
eth_call
N/A
Out-of-scope for this discussion.
eth_estimateGas
N/A
Out-of-scope for this discussion.
eth_getBlockByHash
eth.blockhash
"This can be calculated by querying for a given block, then all of its transactions."
eth_getBlockByNumber
N/A
"This can be calculated by querying for a given block, then all of its transactions."
eth_getTransactionByHash
eth.txhash
This can be calculated by querying for a given transaction by its Ethereum-style hash.
eth_getTransactionByBlockHashAndIndex
eth.blockhash
eth_getTransactionbyBlockNumberAndIndex
N/A
eth_getTransactionReceipt
eth.txhash
eth_getUncleByBlockHashAndIndex
N/A
"Will always return null, since Ethermint has no concept of uncles."
eth_getUncleByBlockNumberAndIndex
N/A
"Will always return null, since Ethermint has no concept of uncles."
eth_newFilter
N/A
See note regarding filters.
eth_newBlockFilter
N/A
See note regarding filters.
eth_newPendingTransactionFilter
N/A
See note regarding filters.
eth_uninstallFilter
N/A
See note regarding filters.
eth_getFilterChanges
N/A
See note regarding filters.
eth_getFilterLogs
N/A
See note regarding filters.
eth_getLogs
eth.topics
See note regarding filters.
eth_getWork
N/A
May not be relevant to Ethermint.
eth_submitWork
N/A
Not relevant to Ethermint.
eth_submitHashrate
N/A
Not relevant to Ethermint.
eth_getProof
N/A
"Generated from the state trie, which is a separate discussion."
The text was updated successfully, but these errors were encountered:
Great composition @mslipper! Let us discuss these in detail during our ethermint weekly. Namely, all the outstanding items. We should also discuss logs and receipts in particular.
Hey all - as discussed two weeks ago, I've compiled a bunch of info around getting the data the RPC layer needs out of Tendermint.
Overview
Ethermint needs a way of querying Tendermint blocks and their associated metadata in order to surface Web3-compatible JSON-RPC responses. We've discussed a number of ways to do this in the past, and most recently converged on using Tendermint tags as a way of indexing data for access by the RPC layer. This document proposes a detailed implementation path for that solution. Note that sending transactions and managing account information is deliberately left out-of-scope since these are much larger discussions that do not block the solution proposed herein.
Architecture
We'll need to create some Ethermint-specific tags to support certain JSON-RPC methods, and persist additional data in some cases to support advanced features like bloom filters over logs. Below, see a list of tags we'll need to create:
eth.blockhash
: represents the Ethereum-style block hash to which a given transaction or block belongs.eth.txhash
: represents the Ethereum-style transaction hash to which a given transaction belongs.eth.topics
: represents an Ethereum log topic associated with a given transaction.Below, see the lists of additional metadata we'll need to persist with each block and transaction.
Block Metadata Persistence
logsBloom
: A bloom filter of logs emitted in this block.hash
: The Ethereum-style hash of the block.Transaction Metadata Persistence
blockHash
: The Ethereum-style block hash of the transaction's block.hash
: The Ethereum-style hash of the transaction.Note: Ethereum draws a distinction between transactions and transaction receipts. In Geth, receipts are stored separately from transactions. Thus, this requires the following additional fields to be stored alongside each transaction to facilitate transaction receipt lookups:
logs
: An array of logs generated by the transaction.logsBloom
: A bloom filter of the logs emitted in this transaction.If we don't want to persist the Ethereum-style hashes with the blocks and transactions themselves, we can calculate them on-the-fly in the RPC layer.
Filters and Stateful RPC
Ethereum supports stateful RPC methods via a two-call flow:
eth_new*Filter
methods, which returns a filter ID.eth_getFilter*
with the filter ID to get the changes that have occurred since the previous call toeth_getFilter*
.Supporting filters of this kind won't require any changes to Tendermint. Instead, the Ethermint RPC layer will maintain a pointer to the last-filtered block number for each registered filter. When a request to
eth_getFilter*
is received, then the RPC layer will perform a lookup using the tags outlined above. For example, a filter defined with the following parameters:would yield the following query to the Tendermint storage engine upon receipt of a
getFilterChanges
call:eth.topics CONTAINS 0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b OR (eth.topics CONTAINS 0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b OR eth.topics CONTAINS 0x0000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebccc) AND block.height >= 1 AND block.height <= 2 AND tx.sender = 0x8888f1f195afa192cfee860698584c030f4c9db1
Note: The above query isn't canonical, it's here to illustrate the idea.
I'm concerned about the performance characteristics of running many
CONTAINS
operations - lots of Ethereum developers setfromBlock
to 1 andtoBlock
tolatest
, which would precipitate a scan of the entire blockchain to find matching transactions. Furthermore, it only operates on substring matches, so we'd need to parse each returned block in Ethermint and manually perform log-index-based matching to be in full compliance with the JSON-RPC API. Here's the relevant info from the spec:Index of RPC Methods
The text was updated successfully, but these errors were encountered: