The yellow paper says:

Transaction Receipt. In order to encode information about a transaction concerning which it may be useful to form a zero-knowledge proof, or index and search, we encode a receipt of each transaction containing certain in- formation from its execution.

Why isn't this information stored in the transaction itself? that way one can save one more field in the block header. So what was the design philosophy behind that?

  • 2
    IMHO It should be possible but you will end up with another set of problems because transaction wil now include part of the world state (the logs generated depend on the state).
    – Ismael
    Sep 11, 2018 at 17:49
  • It could be another storage structure which points both to the transaction storage trie and receipt storage trie and you just need to store the hash of this new structure in the transaction. Nonetheless I think your answer that "it is possible" is the correct answer and if you write your comment your comment in answer format, I'll accept it.
    – Syed
    Sep 17, 2018 at 19:01
  • Honestly I don't know if it is possible, the problems can be difficult or impossible to solve.
    – Ismael
    Sep 18, 2018 at 15:00

1 Answer 1


Because transactions are identified by their hashes. Transaction hash is calculated on all the fields of the transaction. After transaction is signed, you can't modify it without changing the hash, and if you do that before it is mined, the network takes it as a different transaction.

When a transaction creates a contract, the contract address is stored in the Receipt. How would you add this data to the transaction struct without changing its hash? You couldn't. The only way to seal the result of the transaction is to create another struct and store it there. This is what Receipts are, its the output of the transaction, a very different concept, while Transaction data being the input.

In short, the decision to design things this way was correct.

BTW, transactions are not stored in the block header, transactions are stored in a separate trie. Only the hash of all transactions of the block is kept in the header.

  • Given the world state, isn't the data generated as result of running the transaction (the contract, etc) canonical (otherwise how can all validators validate it)? If so then you can just define transaction_and_receipt_hash = Kec(transaction_hash | receipt_hash), and have that in the trie. I agree you might argue that the current way is cleaner but it is also possible to combine them and you end up saving one field (combining transactionRoot and ReceiptRoot) in block header which is critical for a light client.
    – Syed
    Sep 12, 2018 at 7:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.