nimbus-eth2/tests/test_eth2_ssz_serialization.nim
Etan Kissling a94ba8cbb5
Add test to compare SSZ bounds against Teku impl (#6836)
* Add test to compare SSZ bounds against Teku impl

Ensure that our SSZ bounds are computed the same way as in Teku by
comparing the bounds for `deneb.SignedBeaconBlock`.

* Lint

* Make platform agnostic regarding how Git checks out newlines
2025-01-10 22:55:42 +00:00

111 lines
4.0 KiB
Nim

# beacon_chain
# Copyright (c) 2018-2025 Status Research & Development GmbH
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.
{.push raises: [].}
{.used.}
import
std/strutils,
unittest2,
../beacon_chain/spec/datatypes/[phase0, altair, bellatrix, deneb],
../beacon_chain/spec/eth2_ssz_serialization,
./consensus_spec/os_ops
static:
doAssert isFixedSize(Slot) == true
type
Specific = object
f1: Slot
f2: Epoch
Primitive = object # Same as above, but using primitive fields
f1: uint64
f2: uint64
suite "Specific field types":
test "roundtrip":
let encoded = SSZ.encode(Specific(f1: Slot(1), f2: Epoch(2)))
check SSZ.decode(encoded, Primitive) == Primitive(f1: 1, f2: 2)
test "root update":
template testit(T: type) =
var t: T
t.root = hash_tree_root(t.message)
let encoded = SSZ.encode(t)
let decoded = SSZ.decode(encoded, T)
check:
t.message == decoded.message
t.root == decoded.root
t = default(type t)
readSszBytes(encoded, t, false)
check:
t.root.isZero
testit(phase0.SignedBeaconBlock)
testit(phase0.TrustedSignedBeaconBlock)
testit(altair.SignedBeaconBlock)
testit(altair.TrustedSignedBeaconBlock)
suite "Size bounds":
test "SignedBeaconBlockDeneb":
# https://gist.github.com/tbenr/a0ae19fe7496106886ec1f3cc097c208
template sourceDir: string = currentSourcePath.rsplit(DirSep, 1)[0]
let expected = os_ops.readFile(
sourceDir/"test_files"/"SszLengthBounds_SignedBeaconBlockDeneb.txt")
var
res = ""
loc = @["SignedBeaconBlockDeneb"]
func record(T: typedesc) =
when T is SomeSig|ValidatorPubKey:
res.add loc.join(".") & "[" & $T.blob.len & "]: SszLengthBounds" &
"{min=" & $T.minSize & ", max=" & $T.maxSize & "}\n"
loc[^1].add "[element]"
byte.record()
elif T is ExecutionAddress|BloomLogs:
res.add loc.join(".") & "[" & $T.data.len & "]: SszLengthBounds" &
"{min=" & $T.minSize & ", max=" & $T.maxSize & "}\n"
loc[^1].add "[element]"
byte.record()
elif T is KzgCommitment:
res.add loc.join(".") & "[" & $T.bytes.len & "]: SszLengthBounds" &
"{min=" & $T.minSize & ", max=" & $T.maxSize & "}\n"
loc[^1].add "[element]"
byte.record()
elif T is array|HashArray:
res.add loc.join(".") & "[" & $T.len & "]: SszLengthBounds" &
"{min=" & $T.minSize & ", max=" & $T.maxSize & "}\n"
loc[^1].add "[element]"
ElemType(T).record()
elif T is List|HashList:
res.add loc.join(".") & "(" & $T.maxLen & "): SszLengthBounds" &
"{min=" & $T.minSize & ", max=" & $T.maxSize & "}\n"
loc[^1].add "(element)"
ElemType(T).record()
elif T is BitArray:
res.add loc.join(".") & "[" & $T.bits & "]: SszLengthBounds" &
"{min=" & $T.minSize & ", max=" & $T.maxSize & "}\n"
res.add loc.join(".") & "[element]: SszLengthBounds" &
"{min=0(+1 bits), max=0(+1 bits)}\n"
elif T is BitList:
res.add loc.join(".") & "(" & $T.maxLen & "): SszLengthBounds" &
"{min=" & $T.minSize & ", max=" & $T.maxSize & "}\n"
res.add loc.join(".") & "(element): SszLengthBounds" &
"{min=0(+1 bits), max=0(+1 bits)}\n"
else:
res.add loc.join(".") & ": SszLengthBounds" &
"{min=" & $T.minSize & ", max=" & $T.maxSize & "}\n"
when T is object and T isnot Eth2Digest|UInt256:
T.enumAllSerializedFields():
loc.add fieldName
record(FieldType)
discard loc.pop()
record deneb.SignedBeaconBlock
check res.splitLines() == expected.splitLines()