Block and Header Validity

Abstract

Like all blockchains, rollups are defined as the chain of valid blocks from the genesis, to the head. Thus, the block and header validity rules define the chain.

Verifying a block/header is done in 3 parts:

  1. Verify correct serialization according to the protobuf spec

  2. Perform basic validation of the types

  3. Perform verification of the new block against the previously accepted block

Basic Validation

Each type contains a .ValidateBasic() method, which verifies that certain basic invariants hold. The ValidateBasic() calls are nested, starting from the Block struct, all the way down to each subfield.

The nested basic validation, and validation checks, are called as follows:

Block.ValidateBasic()
  // Make sure the block's SignedHeader passes basic validation
  SignedHeader.ValidateBasic()
    // Make sure the SignedHeader's Header passes basic validation
    Header.ValidateBasic()
	  verify ProposerAddress not nil
	// Make sure the SignedHeader's signature passes basic validation
	Signature.ValidateBasic()
	  // Ensure that someone signed the block
	  verify len(c.Signatures) not 0
	If sh.Validators is nil, or len(sh.Validators.Validators) is 0, assume based rollup, pass validation, and skip all remaining checks.
	Validators.ValidateBasic()
	  // github.com/rollkit/cometbft/blob/main/types/validator.go#L37
	  verify sh.Validators is not nil, and len(sh.Validators.Validators) != 0
	  // apply basic validation to all Validators
	  for each validator:
	    validator.ValidateBasic()
		  validate not nil
		  validator.PubKey not nil
		  validator.VotingPower >= 0
		  validator.Address == correct size
	  // apply ValidateBasic to the proposer field:
	  sh.Validators.Proposer.ValidateBasic()
		validate not nil
		validator.PubKey not nil
		validator.VotingPower >= 0
		validator.Address == correct size
    Assert that SignedHeader.Validators.Hash() == SignedHeader.AggregatorsHash
	Verify SignedHeader.Signature
  Data.ValidateBasic() // always passes
  // make sure the SignedHeader's DataHash is equal to the hash of the actual data in the block.
  Data.Hash() == SignedHeader.DataHash

Verification Against Previous Block

// code does not match spec: see https://github.com/rollkit/rollkit/issues/1277
Block.Verify()
  SignedHeader.Verify(untrustH *SignedHeader)
    // basic validation removed in #1231, because go-header already validates it
    //untrustH.ValidateBasic()
	Header.Verify(untrustH *SignedHeader)
	  if untrustH.Height == h.Height + 1, then apply the following check:
	    untrstH.AggregatorsHash[:], h.NextAggregatorsHash[:]
	if untrustH.Height > h.Height + 1:
	  soft verification failure	
	// We should know they're adjacent now,
	// verify the link to previous.
	untrustH.LastHeaderHash == h.Header.Hash()
	// Verify LastCommit hash
	untrustH.LastCommitHash == sh.Signature.GetCommitHash(...)
	

Block

Field NameValid StateValidation
SignedHeaderHeader of the block, signed by proposer(See SignedHeader)
DataTransaction data of the blockData.Hash == SignedHeader.DataHash

SignedHeader

Field NameValid StateValidation
HeaderValid header for the blockHeader passes ValidateBasic() and Verify()
Signature1 valid signature from the centralized sequencerSignature passes ValidateBasic(), with additional checks in SignedHeader.ValidateBasic()
ValidatorsArray of Aggregators, must have length exactly 1.Validators passes ValidateBasic()

Note: The AggregatorsHash and NextAggregatorsHash fields have been removed. Rollkit vA should ignore all Valset updates from the ABCI app, and always enforce that the proposer is the centralized sequencer set as the 1 validator in the genesis block.

Field NameValid StateValidation
BaseHeader .
HeightHeight of the previous accepted header, plus 1.checked in the `Verify()`` step
TimeTimestamp of the blockNot validated in Rollkit
ChainIDThe hard-coded ChainID of the chainShould be checked as soon as the header is received
Header .
Versionunused
LastHeaderHashThe hash of the previous accepted blockchecked in the `Verify()`` step
LastCommitHashThe hash of the previous accepted block's commitchecked in the `Verify()`` step
DataHashCorrect hash of the block's Data fieldchecked in the `ValidateBasic()`` step
ConsensusHashunused
AppHashThe correct state root after executing the block's transactions against the accepted statechecked during block execution
LastResultsHashCorrect results from executing transactionschecked during block execution
ProposerAddressAddress of the expected proposerchecked in the Verify() step
SignatureSignature of the expected proposersignature verification occurs in the ValidateBasic() step

ValidatorSet

Field NameValid StateValidation
ValidatorsArray of validators, each must pass Validator.ValidateBasic()Validator.ValidateBasic()
ProposerMust pass Validator.ValidateBasic()Validator.ValidateBasic()