|
| 1 | +# Block and Header Validity |
| 2 | + |
| 3 | +## Abstract |
| 4 | + |
| 5 | +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. |
| 6 | + |
| 7 | +Verifying a block / header is done in 3 parts: |
| 8 | + |
| 9 | +1. Verify correct serialization according to the protobuf spec |
| 10 | + |
| 11 | +2. Perform basic validation of the types |
| 12 | + |
| 13 | +3. Perform verification of the new block against the previous accepted block |
| 14 | + |
| 15 | +## Basic Validation |
| 16 | + |
| 17 | +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. |
| 18 | + |
| 19 | +The nested basic validation, and validation checks, are called as follows: |
| 20 | + |
| 21 | +```go |
| 22 | +Block.ValidateBasic() |
| 23 | + // Make sure the block's SignedHeader passes basic validation |
| 24 | + SignedHeader.ValidateBasic() |
| 25 | + // Make sure the SignedHeader's Header passes basic validation |
| 26 | + Header.ValidateBasic() |
| 27 | + verify ProposerAddress not nil |
| 28 | + // Make sure the SignedHeader's Commit passes basic validation |
| 29 | + Commit.ValidateBasic() |
| 30 | + // Ensure that someone signed the block |
| 31 | + verify len(c.Signatures) not 0 |
| 32 | + If sh.Validators is nil, or len(sh.Validators.Validators) is 0, assume based rollup, pass validation, and skip all remaining checks. |
| 33 | + Validators.ValidateBasic() |
| 34 | + // github.com/rollkit/cometbft/blob/main/types/validator.go#L37 |
| 35 | + verify sh.Validators is not nil, and len(sh.Validators.Validators) != 0 |
| 36 | + // apply basic validation to all Validators |
| 37 | + for each validator: |
| 38 | + validator.ValidateBasic() |
| 39 | + validate not nil |
| 40 | + validator.PubKey not nil |
| 41 | + validator.VotingPower >= 0 |
| 42 | + validator.Address == correct size |
| 43 | + // apply ValidateBasic to the proposer field: |
| 44 | + sh.Validators.Proposer.ValidateBasic() |
| 45 | + validate not nil |
| 46 | + validator.PubKey not nil |
| 47 | + validator.VotingPower >= 0 |
| 48 | + validator.Address == correct size |
| 49 | + Assert that SignedHeader.Validators.Hash() == SignedHeader.AggregatorsHash |
| 50 | + Assert that len(SignedHeader.Commit.Signatures) == 1 (Exactly one signer check) |
| 51 | + Verify the 1 signature |
| 52 | + Data.ValidateBasic() // always passes |
| 53 | + // make sure the SignedHeader's DataHash is equal to the hash of the actual data in the block. |
| 54 | + Data.Hash() == SignedHeader.DataHash |
| 55 | +``` |
| 56 | + |
| 57 | +## Verification Against Previous Block |
| 58 | + |
| 59 | +```go |
| 60 | +// code does not match spec: see https://github.com/rollkit/rollkit/issues/1277 |
| 61 | +Block.Verify() |
| 62 | + SignedHeader.Verify(untrustH *SignedHeader) |
| 63 | + // basic validation removed in #1231, because go-header already validates it |
| 64 | + //untrustH.ValidateBasic() |
| 65 | + Header.Verify(untrustH *SignedHeader) |
| 66 | + if untrustH.Height == h.Height + 1, then apply the following check: |
| 67 | + untrstH.AggregatorsHash[:], h.NextAggregatorsHash[:] |
| 68 | + if untrustH.Height > h.Height + 1: |
| 69 | + soft verification failure |
| 70 | + // We should know they're adjacent now, |
| 71 | + // verify the link to previous. |
| 72 | + untrustH.LastHeaderHash == h.Header.Hash() |
| 73 | + // Verify LastCommit hash |
| 74 | + untrustH.LastCommitHash == sh.Commit.GetCommitHash(...) |
| 75 | + |
| 76 | +``` |
| 77 | + |
| 78 | +## [Block](https://github.com/rollkit/rollkit/blob/main/types/block.go#L26) |
| 79 | + |
| 80 | +| **Field Name** | **Valid State** | **Validation** | |
| 81 | +|----------------|-----------------------------------------|------------------------------------| |
| 82 | +| SignedHeader | Header of the block, signed by proposer | (See SignedHeader) | |
| 83 | +| Data | Transaction data of the block | Data.Hash == SignedHeader.DataHash | |
| 84 | + |
| 85 | +## [SignedHeader](https://github.com/rollkit/rollkit/blob/main/types/signed_header.go#L16) |
| 86 | + |
| 87 | +| **Field Name** | **Valid State** | **Validation** | |
| 88 | +|----------------|--------------------------------------------------------------------------|---------------------------------------------------------------------------------------------| |
| 89 | +| Header | Valid header for the block | `Header` passes `ValidateBasic()` and `Verify()` | |
| 90 | +| Commit | 1 valid signature from the expected proposer | `Commit` passes `ValidateBasic()`, with additional checks in `SignedHeader.ValidateBasic()` | |
| 91 | +| Validators | Array of Aggregators, should be length 1 (or zero for based rollup case) | `Validators` passes `ValidateBasic()` | |
| 92 | + |
| 93 | +## [Header](https://github.com/rollkit/rollkit/blob/main/types/header.go#L25) |
| 94 | + |
| 95 | +| **Field Name** | **Valid State** | **Validation** | |
| 96 | +|---------------------|--------------------------------------------------------------------------------------------|---------------------------------------| |
| 97 | +| **BaseHeader** . | | | |
| 98 | +| Height | Height of the previous accepted header, plus 1. | checked in the `Verify()`` step | |
| 99 | +| Time | Timestamp of the block | Not validated in Rollkit | |
| 100 | +| ChainID | The hard-coded ChainID of the chain | Should be checked as soon as the header is received | |
| 101 | +| **Header** . | | | |
| 102 | +| Version | unused | | |
| 103 | +| LastHeaderHash | The hash of the previous accepted block | checked in the `Verify()`` step | |
| 104 | +| LastCommitHash | The hash of the previous accepted block's commit | checked in the `Verify()`` step | |
| 105 | +| DataHash | Correct hash of the block's Data field | checked in the `ValidateBasic()`` step | |
| 106 | +| ConsensusHash | unused | | |
| 107 | +| AppHash | The correct state root after executing the block's transactions against the accepted state | checked during block execution | |
| 108 | +| LastResultsHash | Correct results from executing transactions | checked during block execution | |
| 109 | +| ProposerAddress | Address of the expected proposer | checked in the `Verify()` step | |
| 110 | +| AggregatorsHash | Matches the NextAggregatorsHash of the previous accepted block | checked in the `Verify()` step | |
| 111 | +| NextAggregatorsHash | Set during block execution, according to the ABCI app | checked during block execution | |
| 112 | + |
| 113 | +## [Commit](https://github.com/rollkit/rollkit/blob/main/types/block.go#L48) |
| 114 | + |
| 115 | +| **Field Name** | **Valid State** | **Validation** | |
| 116 | +|----------------|---------------------------------------------------------|----------------------------| |
| 117 | +| Signatures | Array containing a signature from the expected proposer | checked in `ValidateBasic()`, signature verification occurs in `SignedHeader.ValidateBasic()` | |
| 118 | + |
| 119 | +## [ValidatorSet](https://github.com/cometbft/cometbft/blob/main/types/validator_set.go#L51) |
| 120 | + |
| 121 | +| **Field Name** | **Valid State** | **Validation** | |
| 122 | +|--------------|-----------------------------------------------------------------|-----------------------------| |
| 123 | +| Validators | Array of validators, each must pass `Validator.ValidateBasic()` | `Validator.ValidateBasic()` | |
| 124 | +| Proposer | Must pass `Validator.ValidateBasic()` | `Validator.ValidateBasic()` | |
0 commit comments