# EPF6 - Week 12 & 13 Updates
## tl;dr
- Merged two PRs ([#15637](https://github.com/OffchainLabs/prysm/pull/15637), [#15668](https://github.com/OffchainLabs/prysm/pull/15668)) for handling various-sized types like `List`.
- Nice to get some valuable reviews from my mentors.
- Reviewed Nando's PR ([#15676](https://github.com/OffchainLabs/prysm/pull/15676)).
## Details
In Week 12, I couldn't spend much time on SSZ-QL because of working on upcoming PQ devnet for [leanEthereum](https://github.com/leanEthereum/leanSpec).
However, I achieved lots of progress in this week (Week 13), merging two big PRs consequently. Also, I'm super glad that my colleague Nando submitted his first PR to Prysm and also merged one in this week!
### Handling various-sized SSZ types (e.g., `List`)
{%preview https://github.com/OffchainLabs/prysm/pull/15637 %}
In [my last update](https://hackmd.io/@junsong/SJrYqcz9xg#Subsequent-PRs-are-on-the-track%E2%80%A6), I explained about the concept "Population", which makes the user set the length of `List` dynamically. This would be super useful in terms of performance, as frequently used containers like `BeaconState` can be cached with empty fields and later populated by an actual `BeaconState` instance before querying the data.
Nando suggested populating the actual value when analyzing the object, and his [PR](https://github.com/OffchainLabs/prysm/pull/15676) fixes this issue.
### Parsing SSZ tags for Multi-dimension Cases
{%preview https://github.com/OffchainLabs/prysm/pull/15668 %}
This PR dealt with three things:
1. Add `elementInfo` for `Vector` type (so that we can store and print it out.)
2. Print `sszInfo` prettier, following the notation of [`consensus-specs`](https://github.com/ethereum/consensus-specs) repository.
3. **Parsing SSZ tags for multi-dimension cases.**
`Print()` function now returns the beautiful string chunks that shows the overall structure with its size information:
```
VariableTestContainer (Variable-size / fixed size: 104, total size: 412)
├─ leading_field (offset: 0) Bytes32 (Fixed-size / size: 32)
├─ field_list_uint64 (offset: 104) List[uint64, 2048] (Variable-size / length: 5, size: 40)
├─ field_list_container (offset: 144) List[FixedNestedContainer, 128] (Variable-size / length: 3, size: 120)
├─ field_list_bytes32 (offset: 264) List[Bytes32, 100] (Variable-size / length: 3, size: 96)
├─ nested (offset: 360) VariableNestedContainer (Variable-size / fixed size: 12, total size: 52)
│ ├─ value1 (offset: 0) uint64 (Fixed-size / size: 8)
│ └─ field_list_uint64 (offset: 12) List[uint64, 100] (Variable-size / length: 5, size: 40)
└─ trailing_field (offset: 48) Bytes56 (Fixed-size / size: 56)
```
Multi-dimensional tags are often used especially for holding 2D byte arrays. For example, `Transactions` field in `ExecutionPayloadDeneb` has a tag like `ssz-max:"1048576,1073741824" ssz-size:"?,?"`. Each transaction is serialized as a byte array, and multiple transactions are just a 2D byte array in the consensus layer.
This PR introduces `SSZDimension` which is hugely inspired from the [one](https://github.com/OffchainLabs/fastssz/blob/518c4ce735160cbd555d22c08ef86a0bef8bf27b/sszgen/tag_parser.go#L165-L169) of `OffchainLabs/fastssz`.
```go
// SSZDimension holds parsed SSZ tag information for current dimension.
// Mutually exclusive fields indicate whether the dimension is a vector or a list.
type SSZDimension struct {
vectorLength *uint64
listLimit *uint64
}
```
At first, I was trying to accept any arbitrary (and crazy) SSZ tags, so my implementation didn't consider mutually exclusiveness:
```go
// SSZDimension holds parsed SSZ tag information for current dimension.
//
// NOTE: This struct stores raw string without parsing to uint64,
// as it might have a wildcard ('?') indicating variable size.
type SSZDimension struct {
SizeValue string // Current dimension for ssz-size
MaxValue string // Current dimension for ssz-max
HasSize bool
HasMax bool
}
```
This implementation added a slight complexity for determining the dimension as a `List` or `Vector`:
```go=
// IsList returns true if this dimension represents a list.
// `ssz-size` can be a wildcard ('?') indicating variable size.
func (info *SSZDimension) IsList() bool {
return info.HasMax && (!info.HasSize || info.SizeValue == "" || info.SizeValue == "?")
}
```

But Radek pointed out that the code must be clean and simple. `SSZDimension` shouldn't be both `List` and `Vector` in the same time, so in the parsing phase, it makes much sense return an error when validation fails.
Suggestion from my mentors and colleague (Nando) is always helpful to find the points that I've overlooked while I'm coding something. Nice experience!
### What's next
- `Bitlist` and `Bitvector`: There are some places that use those SSZ types in `BeaconState`, and I need some clever ways to determine whether a type is either `List` or `Bitlist`.