You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
TL;DR - SSZ tests are not exhaustive for dynamic lists with many elements in them.
Context
Our Go-SSZ library is currently up-to-date with v0.8 and passing all latest spec tests, both minimal and mainnet. However, we encountered something quite interesting in slot/block sanity tests when it came to SSZ. Our hash tree root for the beacon state in all the slot/block sanity tests was failing and returning a different root than what the spec wants. We were confused as we were indeed passing all types of spec tests. We noticed, however, that the SSZ spec tests do not cover cases where dynamic lists have a lot of elements (the slot sanity tests had 512 validators in the registry of the state).
We found a discrepancy between Python and Go in mixInLength when converting the length of an object into a 256-bit number. In Python, following code returns:
It turns out we had to use a different method of putting the length into a buffer than binary.PutUvarint, however, we expected SSZ spec tests to have covered these cases. It turns out that if there were a single SSZ spec test case that had lists with lengths as big as the ones in the sanity tests, we could have caught this bug earlier.
The text was updated successfully, but these errors were encountered:
Yes, the SSZ spec doesn't include Var-ints. Var-ints are simply not the same as uint256, they encode numbers in 7 bits per byte, with the last bit signifying an extended number (reading the next 7 bits from the next byte). It's used in a few places in Eth1, but nowhere in Eth 2 (yes, bitlists are encoded similar, but not the same), so I am quite surprised that you even encode it like that.
But fair enough, we can put higher list sizes in some spec tests. Good for the extension of the ssz-generic test suite later.
Hi @protolambda totally - we shouldn't have been encoding it that way but it was just a bit tricky that no SSZ spec tests failed due to that. Our wrong approach/bug could have been caught through better coverage from the spec tests, however.
It was an off-by-28 😅 And coverage didn't catch it, as branch/line coverage is the same for different lengths mix ins. Current limit is at 100 items to put in a dynamic list, but your bug only triggered after 127 (more than 7 bits). Sure is a fun one.
TL;DR - SSZ tests are not exhaustive for dynamic lists with many elements in them.
Context
Our Go-SSZ library is currently up-to-date with v0.8 and passing all latest spec tests, both minimal and mainnet. However, we encountered something quite interesting in slot/block sanity tests when it came to SSZ. Our hash tree root for the beacon state in all the slot/block sanity tests was failing and returning a different root than what the spec wants. We were confused as we were indeed passing all types of spec tests. We noticed, however, that the SSZ spec tests do not cover cases where dynamic lists have a lot of elements (the slot sanity tests had 512 validators in the registry of the state).
We found a discrepancy between Python and Go in mixInLength when converting the length of an object into a 256-bit number. In Python, following code returns:
The same code in Go, however, returns:
It turns out we had to use a different method of putting the length into a buffer than
binary.PutUvarint
, however, we expected SSZ spec tests to have covered these cases. It turns out that if there were a single SSZ spec test case that had lists with lengths as big as the ones in the sanity tests, we could have caught this bug earlier.The text was updated successfully, but these errors were encountered: