github.com/ari-anchor/sei-tendermint@v0.0.0-20230519144642-dc826b7b56bb/docs/architecture/adr-020-block-size.md (about)

     1  # ADR 020: Limiting txs size inside a block
     2  
     3  ## Changelog
     4  
     5  13-08-2018: Initial Draft
     6  15-08-2018: Second version after Dev's comments
     7  28-08-2018: Third version after Ethan's comments
     8  30-08-2018: AminoOverheadForBlock => MaxAminoOverheadForBlock
     9  31-08-2018: Bounding evidence and chain ID
    10  13-01-2019: Add section on MaxBytes vs MaxDataBytes
    11  
    12  ## Context
    13  
    14  We currently use MaxTxs to reap txs from the mempool when proposing a block,
    15  but enforce MaxBytes when unmarshaling a block, so we could easily propose a
    16  block thats too large to be valid.
    17  
    18  We should just remove MaxTxs all together and stick with MaxBytes, and have a
    19  `mempool.ReapMaxBytes`.
    20  
    21  But we can't just reap BlockSize.MaxBytes, since MaxBytes is for the entire block,
    22  not for the txs inside the block. There's extra amino overhead + the actual
    23  headers on top of the actual transactions + evidence + last commit.
    24  We could also consider using a MaxDataBytes instead of or in addition to MaxBytes.
    25  
    26  ## MaxBytes vs MaxDataBytes
    27  
    28  The [PR #3045](https://github.com/tendermint/tendermint/pull/3045) suggested
    29  additional clarity/justification was necessary here, wither respect to the use
    30  of MaxDataBytes in addition to, or instead of, MaxBytes.
    31  
    32  MaxBytes provides a clear limit on the total size of a block that requires no
    33  additional calculation if you want to use it to bound resource usage, and there
    34  has been considerable discussions about optimizing tendermint around 1MB blocks.
    35  Regardless, we need some maximum on the size of a block so we can avoid
    36  unmarshaling blocks that are too big during the consensus, and it seems more
    37  straightforward to provide a single fixed number for this rather than a
    38  computation of "MaxDataBytes + everything else you need to make room for
    39  (signatures, evidence, header)". MaxBytes provides a simple bound so we can
    40  always say "blocks are less than X MB".
    41  
    42  Having both MaxBytes and MaxDataBytes feels like unnecessary complexity. It's
    43  not particularly surprising for MaxBytes to imply the maximum size of the
    44  entire block (not just txs), one just has to know that a block includes header,
    45  txs, evidence, votes. For more fine grained control over the txs included in the
    46  block, there is the MaxGas. In practice, the MaxGas may be expected to do most of
    47  the tx throttling, and the MaxBytes to just serve as an upper bound on the total
    48  size. Applications can use MaxGas as a MaxDataBytes by just taking the gas for
    49  every tx to be its size in bytes.
    50  
    51  ## Proposed solution
    52  
    53  Therefore, we should
    54  
    55  1) Get rid of MaxTxs.
    56  2) Rename MaxTxsBytes to MaxBytes.
    57  
    58  When we need to ReapMaxBytes from the mempool, we calculate the upper bound as follows:
    59  
    60  ```
    61  ExactLastCommitBytes = {number of validators currently enabled} * {MaxVoteBytes}
    62  MaxEvidenceBytesPerBlock = MaxBytes / 10
    63  ExactEvidenceBytes = cs.evpool.PendingEvidence(MaxEvidenceBytesPerBlock) * MaxEvidenceBytes
    64  
    65  mempool.ReapMaxBytes(MaxBytes - MaxAminoOverheadForBlock - ExactLastCommitBytes - ExactEvidenceBytes - MaxHeaderBytes)
    66  ```
    67  
    68  where MaxVoteBytes, MaxEvidenceBytes, MaxHeaderBytes and MaxAminoOverheadForBlock
    69  are constants defined inside the `types` package:
    70  
    71  - MaxVoteBytes - 170 bytes
    72  - MaxEvidenceBytes - 364 bytes
    73  - MaxHeaderBytes - 476 bytes (~276 bytes hashes + 200 bytes - 50 UTF-8 encoded
    74    symbols of chain ID 4 bytes each in the worst case + amino overhead)
    75  - MaxAminoOverheadForBlock - 8 bytes (assuming MaxHeaderBytes includes amino
    76    overhead for encoding header, MaxVoteBytes - for encoding vote, etc.)
    77  
    78  ChainID needs to bound to 50 symbols max.
    79  
    80  When reaping evidence, we use MaxBytes to calculate the upper bound (e.g. 1/10)
    81  to save some space for transactions.
    82  
    83  NOTE while reaping the `max int` bytes in mempool, we should account that every
    84  transaction will take `len(tx)+aminoOverhead`, where aminoOverhead=1-4 bytes.
    85  
    86  We should write a test that fails if the underlying structs got changed, but
    87  MaxXXX stayed the same.
    88  
    89  ## Status
    90  
    91  Implemented
    92  
    93  ## Consequences
    94  
    95  ### Positive
    96  
    97  * one way to limit the size of a block
    98  * less variables to configure
    99  
   100  ### Negative
   101  
   102  * constants that need to be adjusted if the underlying structs got changed
   103  
   104  ### Neutral