Substate database is used as the Off-The-Chain testing module in the applications for recording or replaying transactions. The Replayer can execute any transaction in complete isolation by loading the substate of the transaction and executing the transaction.
Database contains a minimal subset of the World-State Trie to faithfully replay transactions in isolation. The subset contains all the entries represented as a flat key-value store (and is not stored as a slow Merkle Patricia Trie) for executing a transaction.
There are 5 data structures stored in a substate DB:
SubstateAccount
: account information (nonce, balance, code, storage)WorldState
: mapping of account address andSubstateAccount
SubstateEnv
: information from block headers (block gasLimit, number, timestamp, hashes)SubstateMessage
: message for transaction executionSubstateResult
: result of transaction execution
5 values are required to replay transactions and validate results:
PreState
: world-state that is read during transaction executionEnv
: block information required for transaction executionMessage
: array with exactly 1 transactionPostState
: alloc that is generated by transaction executionResult
: execution result and receipt array with exactly 1 receipt
The first 2 bytes of a key in a substate DB represent different data types as follows:
1s
: Substate, a key is"1s"+N+T
with transaction indexT
at blockN
.T
andN
are encoded in a big-endian 64-bit binary.1c
: EVM bytecode, a key is"1c"+codeHash
wherecodeHash
is Keccak256 hash of the bytecode.
Ethereum substate recorder/replayer based on the paper:
Yeonsoo Kim, Seongho Jeong, Kamil Jezek, Bernd Burgstaller, and Bernhard Scholz: An Off-The-Chain Execution Environment for Scalable Testing and Profiling of Smart Contracts, USENIX ATC'21
You can find all executables including geth
and our substate-cli
in build/bin/
directory.