Convenience IPLD types

The types described below are not referenced directly from within the canonical Ethereum merkle tree. Instead, these types can be constructed and verified from underlying canonical Ethereum IPLD structures using the algorithms described here. These types are introduced to improve the convenience and performance of accessing and working with the Ethereum objects for certain purposes.

Transaction Trace IPLD

Transaction traces contain the EVM context, input, and output for each individual OPCODE operation performed during the application of a transaction on a certain state. These objects can be generated or verified by applying the referenced transactions on top of the referenced state.

# TxTrace contains the EVM context, input, and output for each OPCODE in a transaction that was applied to a specific state
type TxTrace struct {
   # List of CIDs linking to the transactions that were used to generate this trace by applying them onto the state referenced below
   # If this trace was produced by the first transaction in a block then this list will contain only that one transaction
   # and this trace was produced by applying it directly to the referenced state
   # Otherwise, the trace is the output of the last transaction in the list applied to the state produced by
   # sequentially applying the proceeding txs to the referenced state
   TxCIDs [&Transaction]
   # CID link to the root node of the state trie that the above transaction set was applied on top of to produce this trace
   StateRootCID &StateTrieNode
   Result Bytes
   Frames [Frame]
   Gas Uint
   Failed Bool
}

# Frame represents the EVM context, input, and output for a specific OPCODE during a transaction trace
type Frame struct {
    Op     OpCode
    From   Address
    To     Address
    Input  Bytes
    Output Bytes
    Gas    Uint
    Cost   Uint
    Value  BigInt
}

Provided a Header multihash/CID and a transaction index, we can generate a TxTrace by

  1. Fetching and decoding the Header IPLD.
  2. Stepping down into the transaction trie referenced in the header.
    1. Collecting the transaction at the provided index and all transactions with indexes lower than the provided index.
    2. KECCAK_256 hashing each transaction.
    3. Convert hashes to CIDs using the KECCAK_256 multihash and EthTx codec.
    4. Order these CIDs in a list by transaction index.
  3. Collect the StateRootCID from within this Header.
  4. Use ipfs-ethdb with state root linked in the Header to instantiate an EVM on top of the ipld state of this block.
  5. Apply each of the transactions on top of this state using the ipfs-ethdb based EVM.
  6. For the final transaction applied, collect the trace output from the EVM.
  7. Assemble the trace output, the Transaction CIDs, and the root StateTrieNode CID into the TxTrace object.

Block IPLD

Block IPLD represents an entire block (header + body) in the Ethereum blockchain, it contains direct content hash references to the sets of transactions and receipts for that block in order to avoid the need to traverse the transaction and receipt tries to collect these sets (as is required when starting from a canonical Header block). These objects can be generated or verified by following the links within the contained Header to collect the Transactions and Receipts from the referenced transaction and receipt tries.

# Block represents an entire block in the Ethereum blockchain.
type Block struct {
   # CID link to the header at this block
   # This CID is composed of the KECCAK_256 multihash of the RLP encoded header and the EthHeader codec (0x90)
   # Note that the header contains references to the uncles and tx, receipt, and state tries at this height
   Header       &Header
   # CID link to the list of transactions at this block
   # This CID is composed of the KECCAK_256 multihash of the RLP encoded list of transactions and the EthTxList codec (tbd)
   Transactions &Transactions
   # CID link to the list of receipts at this block
   # This CID is composed of the KECCAK_256 multihash of the RLP encoded list of receipts and the EthTxReceiptList codec (tbd)
   Receipts     &Receipts
}

Provided a Header multihash/CID, we can generate a Block IPLD by

  1. Fetching and decoding the Header IPLD.
  2. Stepping down into the transaction trie referenced in the header.
    1. Collecting each transaction stored at the leaf nodes in the trie.
    2. KECCAK_256 hashing each transaction.
    3. Order these hashes in a list by transaction index.
    4. KECCAK_256 hash the RLP encoded list.
    5. Convert to CID using the KECCAK_256 multihash and EthTxHashList codec.
  3. Stepping down into the receipt trie referenced in the header.
    1. Collecting each receipt stored at the leaf nodes in the trie.
    2. KECCAK_256 hashing each receipt.
    3. Order these hashes in a list by receipt index.
    4. KECCAK_256 hash the RLP encoded list.
    5. Convert to CID using the KECCAK_256 multihash and EthTxReceiptHashList codec.
  4. Assemble the Header CID, Transactions CID, and Receipts CID into the Block object.

Transactions IPLD

This is the IPLD schema for the ordered list of all transactions for a given block.

# Transactions contains a list of all of the Ethereum transactions at this block
type Transactions [&Transaction]

Receipts IPLD

This is the IPLD schema for the ordered list of all receipts for a given block.

# Receipts contains a list of all of the receipts at this block
type Receipts [Receipt]

Genesis IPLD

This is the IPLD schema for the configuration settings and genesis allocations to produce a specific genesis block and begin an Ethereum blockchain. It also includes a reference to the genesis block Header it produces. This is a single IPLD block at the base of an entire Ethereum chain.

# GenesisInfo specifies the header fields, state of a genesis block, and hard fork switch-over blocks through the chain configuration.
# NOTE: we need a new multicodec type for the Genesis object
type GenesisInfo struct {
   # CID link to the genesis header this genesis info produces
   # This CID is composed of the KECCAK_256 multihash of the linked RLP encoded header and the EthHeader codec (0x90)
   GensisHeader &Header
   
   Config     ChainConfig
   Nonce      Uint
   Timestamp  Uint
   ExtraData  Bytes
   GasLimit   Unit
   Difficulty BigInt
   Mixhash    Hash
   Coinbase   Address
   Alloc      GenesisAlloc
   
   # These fields are used for consensus tests. Please don't use them
   # in actual genesis blocks.
   Number     Uint
   GasUsed    Uint
   ParentHash Hash
}

# GenesisAlloc is a map that specifies the initial state that is part of the genesis block.
type GenesisAlloc {Address:GenesisAccount}

# GenesisAccount is an account in the state of the genesis block.
type GenesisAccount struct {
    Code       Bytes
    Storage    {Hash:Hash}
    Balance    BigInt
    Nonce      Uint
    PrivateKey Bytes
}

# ChainConfig is the core config which determines the blockchain settings.
# ChainConfig is stored in the database on a per block basis.
# This means that any network, identified by its genesis block, can have its own set of configuration options.
# The ChainConfig referenced in GenesisInfo is used to produce the genesis block but is not necessarily used for later blocks down the chain.
type ChainConfig struct {
    ChainID BigInt
    HomesteadBlock BigInt
    DAOForkBlock   BigInt
    DAOForkSupport Bool
    EIP150Block BigInt
    EIP150Hash  Hash
    EIP155Block BigInt
    EIP158Block BigInt
    ByzantiumBlock      BigInt
    ConstantinopleBlock BigInt
    PetersburgBlock     BigInt
    IstanbulBlock       BigInt
    MuirGlacierBlock    BigInt
    YoloV2Block BigInt
    EWASMBlock  BigInt
	
    # Various consensus engines
    Ethash EthashConfig
    Clique CliqueConfig
}

# EthashConfig is the consensus engine config for proof-of-work based sealing.
# At this time there are no configuration options for the Ethash engine.
type EthashConfig struct {} representation tuple

# CliqueConfig is the consensus engine config for proof-of-authority based sealing.
type CliqueConfig struct {
    Period Uint
    Epoch Uint
}