Reading the docs, something confused me :
Although older blocks are discarded, full nodes retain all of the block headers from the genesis block to the most recent block to validate that the state is correct. Because the full node has access to all of the block headers, it can be used to rebuild the state of the entire blockchain by executing all of the blocks from the genesis block. Thus it requires much more computation to retrieve information about some previous state, and an archive should generally be used instead.
I find this hard to understand as my understanding is that you need the actual transactions to perform state transitions. The block header does not contain the extrinsic in and of themselves, but only the cryptographic digest of the state and extrinsic root. IOW, nothing outside this trait definition :
pub trait Header
type Number;
type Hash;
type Hashing: Hash<Output = Self::Hash>;
fn new(
number: Self::Number,
extrinsics_root: Self::Hash,
state_root: Self::Hash,
parent_hash: Self::Hash,
digest: Digest
) -> Self;
fn number(&self) -> &Self::Number;
fn set_number(&mut self, number: Self::Number);
fn extrinsics_root(&self) -> &Self::Hash;
fn set_extrinsics_root(&mut self, root: Self::Hash);
fn state_root(&self) -> &Self::Hash;
fn set_state_root(&mut self, root: Self::Hash);
fn parent_hash(&self) -> &Self::Hash;
fn set_parent_hash(&mut self, hash: Self::Hash);
fn digest(&self) -> &Digest;
fn digest_mut(&mut self) -> &mut Digest;
fn hash(&self) -> Self::Hash { ... }
}
Q: How then is it possible to
rebuild the state of the entire blockchain by executing all of the blocks from the genesis block.
?