This could occur as a result of database corruption or database update
race, where transaction → (blockHash, blockNum, txIndex) lookup succeeds
but the body for blockHash is not (yet) in the database.
Follow the same strategy for header versioning, except put everything
into the same "./core/types" package – for now. Adaptation of the
existing code outside the package to come next.
For now, follow header version (v0 or v1). Later header/block versions
should become independent: Blocks should have their own epoch-based
versioning schedule, and it should be possible to bump header version
without bump block version, and vice versa.
block.Header is now a lightweight wrapper around an embedded
HeaderInterface value, which is implemented by both v0 and v1 headers.
It inherits all methods from the wrapped HeaderInterface, except it
overrides EncodeRLP, DecodeRLP, and Hash to handle tagged-RLP
encoding/decoding. (block.HeaderRegistry is the tagged RLP registry for
versioned headers.)
A ripple effect is that header instance creation now requires knowledge
of epoch. This logic is handled by blockfactory. blockfactory.Factory
is the interface, implemented by blockfactory.factory type. It uses a
chain config to pull in the right epoch for the right type.
As a convenience, blockfactory.NewTestHeader creates a new test-purpose
headers. Use this in contexts where the implied chain config is
TestChainConfig or the chain config does not matter.
Miscellaneous changes:
- block.HeaderFieldSetter now lives in its own file.
- The functionality of block.NewHeaderWith has been replaced by the
(*block.Header).With method.
The accompanying unit tests for (*block.Header).EncodeRLP and
(*block.Header).DecodeRLP() are the cross-sectional unit tests for the
functionality added by this. They make sure that v0 header is
encoded/decoded without tagged RLP envelope (compatibility mode), and v1
header is encoded/decoded with one. See comments of the RLP byte
sequence for differences.