nimbus-eth2/tests/test_eip7594_helpers.nim

130 lines
4.0 KiB
Nim

# beacon_chain
# Copyright (c) 2018-2024 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.}
# Uncategorized helper functions from the spec
import
unittest2,
random,
std/[algorithm, macros, tables, sysrand],
stew/results,
stint,
kzg4844/[kzg_abi, kzg_ex],
ssz_serialization/proofs,
chronicles,
../beacon_chain/spec/beacon_time,
eth/p2p/discoveryv5/[node],
./consensus_spec/[os_ops, fixtures_utils],
../beacon_chain/spec/[helpers, eip7594_helpers],
../beacon_chain/spec/datatypes/[eip7594, deneb]
from std/sequtils import anyIt, mapIt, toSeq
from std/strutils import rsplit
block:
template sourceDir: string = currentSourcePath.rsplit(DirSep, 1)[0]
doAssert Kzg.loadTrustedSetup(
sourceDir &
"/../vendor/nim-kzg4844/kzg4844/csources/src/trusted_setup.txt", 0).isOk
const MAX_TOP_BYTE = 114
proc createSampleKzgBlobs(n: int): seq[KzgBlob] =
var blob: array[BYTES_PER_BLOB, byte]
var blobs: seq[KzgBlob]
for i in 0..<n:
discard urandom(blob)
for i in 0..<BYTES_PER_BLOB.int:
if blob[i] > MAX_TOP_BYTE and i %% kzg_abi.BYTES_PER_FIELD_ELEMENT == 0:
blob[i] = MAX_TOP_BYTE
blobs.add(KzgBlob(bytes: blob))
blobs
proc chunks[T](lst: seq[T], n: int): seq[seq[T]] =
## Helper that splits a list into N sized chunks.
result = @[]
for i in countup(0, len(lst) - 1, n):
result.add(lst[i..min(i + n - 1, len(lst) - 1)])
suite "EIP-7594 Unit Tests":
test "EIP-7594: Compute Extended Matrix":
proc testComputeExtendedMatrix() =
let
blob_count = 2
input_blobs = createSampleKzgBlobs(blob_count)
extended_matrix = compute_extended_matrix(input_blobs)
doAssert extended_matrix.get.len == kzg_abi.CELLS_PER_EXT_BLOB * blob_count
let
chunkSize = kzg_abi.CELLS_PER_EXT_BLOB
rows = chunks(extended_matrix.get, kzg_abi.CELLS_PER_EXT_BLOB)
for row in rows:
doAssert len(row) == kzg_abi.CELLS_PER_EXT_BLOB
testComputeExtendedMatrix()
test "EIP:7594: Recover Matrix":
proc testRecoverMatrix() =
var rng = initRand(5566)
# Number of samples we shall be recovering
const N_SAMPLES = kzg_abi.CELLS_PER_EXT_BLOB div 2
# Compute an extended matrix with 2 blobs for this test
let
blob_count = 2
blobs = createSampleKzgBlobs(blob_count)
extended_matrix = compute_extended_matrix(blobs)
# Construct a matrix with some entries missing
var partial_matrix: seq[MatrixEntry]
for blob_entries in chunks(extended_matrix.get, kzg_abi.CELLS_PER_EXT_BLOB):
var blb_entry = blob_entries
rng.shuffle(blb_entry)
partial_matrix.add(blob_entries[0..N_SAMPLES-1])
# Given the partial matrix, recover the missing entries
let recovered_matrix = recover_matrix(partial_matrix, blob_count)
# Ensure that the recovered matrix matches the original matrix
doAssert recovered_matrix == extended_matrix, "Both matrices don't match!"
testRecoverMatrix()
suite "EIP-7594 Sampling Tests":
test "EIP7594: Extended Sample Count":
proc testExtendedSampleCount() =
let samplesPerSlot = 16
const tests = [
(0, 16),
(1, 20),
(2, 24),
(3, 27),
(4, 29),
(5, 32),
(6, 35),
(7, 37),
(8, 40),
(9, 42),
(10, 44),
(11, 47),
(12, 49),
(13, 51),
(14, 53),
(15, 55),
(16, 57),
(17, 59),
(18, 61),
(19, 63),
(20, 65)
]
for (allowed_failures, extendedSampleCount) in tests:
check: get_extended_sample_count(samplesPerSlot, allowed_failures) == extendedSampleCount
testExtendedSampleCount()