EIP-7916 - SSZ ProgressiveList

Created 2025-03-24
Status Draft
Category Core
Type Standards Track
Authors

Abstract

This EIP introduces a new Merkle tree shape for Simple Serialize (SSZ) types that results in fewer hashes when only a small number of leaves is used. The new tree shape grows progressively with increased leaf count and no longer has a bounded capacity. It also offers forward compatibility: a given chunk index is always assigned the same stable generalized index (gindex) regardless of leaf count.

New types are defined to use the progressive Merkle tree shape: ProgressiveList[type] and ProgressiveBitlist. These new types represent lists of arbitrary length with stable merkleization, reducing hashing overhead for small lists and avoiding arbitrary capacity limits.

Motivation

Current SSZ List[type, N] types require a predefined capacity N, which leads to several issues:

The progressive Merkle tree shape addresses these by:

Specification

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 and RFC 8174.

Progressive Merkle tree

The SSZ Merkleization specification) is extended with a helper function:

This results in a 0-terminated sequence of binary subtrees with increasing leaf count. The deepest subtree is padded with zeroed chunks (virtually for memory efficiency).

        root
         /\
        /  \
       /\   1: chunks[0 ..< 1]
      /  \
     /\   4: chunks[1 ..< 5]
    /  \
   /\  16: chunks[5 ..< 21]
  /  \
 0   64: chunks[21 ..< 85]
Depth Added chunks Total chunks Total capacity (bytes)
0 0 0 0
1 1 1 32
2 4 5 160
3 16 21 672
4 64 85 2'720
5 256 341 10'912
6 1'024 1'365 43'680
7 4'096 5'461 174'752
8 16'384 21'845 699'040
9 65'536 87'381 2'796'192
10 262'144 349'525 11'184'800
11 1'048'576 1'398'101 44'739'232
12 4'194'304 5'592'405 178'956'960
13 16'777'216 22'369'621 715'827'872
14 67'108'864 89'478'485 2'863'311'520
15 268'435'456 357'913'941 11'453'246'112

ProgressiveList[type] and ProgressiveBitlist

Two new SSZ composite types) are defined:

The new types are considered "variable-size".

For convenience we alias:

The default value is defined as:

Type Default Value
ProgressiveList[type] []
ProgressiveBitlist []

Serialization

Serialization, deserialization, and JSON mapping of ProgressiveBitlist are identical to Bitlist[N].

Serialization, deserialization, and JSON mapping of ProgressiveList[type] are identical to List[type, N].

Merkleization

The Merkleization definitions are extended.

Rationale

Why a recursive structure?

Why not dynamic depth?

Dynamic-depth Merkleization destabilizes gindices:

Mixing in successor subtrees ensures predictable gindices and proof sizes.

Why not fixed-capacity lists?

List[type, N]:

ProgressiveList[type] offers a scalable, efficient alternative.

Why are initial leaf count and scaling factors not exposed parameters?

Backwards Compatibility

The new SSZ types coexist with existing types without conflict and share their serialization logic.

Test Cases

See EIP assets.

Reference Implementation

See EIP assets, based on protolambda/remerkleable.

Security Considerations

Copyright

Copyright and related rights waived via CC0.