Add merkleization tests (#378)

* Add merkleization tests

* Fix typo in build file

* add test prefix
This commit is contained in:
KonradStaniec 2021-07-21 09:24:07 +02:00 committed by GitHub
parent 44fee391f4
commit 20ad6504b7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 83 additions and 2 deletions

View File

@ -66,6 +66,9 @@ task test_trie, "Run trie tests":
task test_db, "Run db tests": task test_db, "Run db tests":
runTest("tests/db/all_tests") runTest("tests/db/all_tests")
task test_ssz, "Run ssz tests":
runTest("tests/ssz/test_merkleization")
task test, "Run all tests": task test, "Run all tests":
for filename in [ for filename in [
"test_bloom", "test_bloom",
@ -78,6 +81,7 @@ task test, "Run all tests":
test_p2p_task() test_p2p_task()
test_trie_task() test_trie_task()
test_db_task() test_db_task()
test_ssz_task()
task test_discv5_full, "Run discovery v5 and its dependencies tests": task test_discv5_full, "Run discovery v5 and its dependencies tests":
test_keys_task() test_keys_task()

View File

@ -363,9 +363,11 @@ template createMerkleizer*(totalElements: static Limit): SszMerkleizerImpl =
const treeHeight = binaryTreeHeight totalElements const treeHeight = binaryTreeHeight totalElements
var combinedChunks {.noInit.}: array[treeHeight, Digest] var combinedChunks {.noInit.}: array[treeHeight, Digest]
let topIndex = treeHeight - 1
SszMerkleizerImpl( SszMerkleizerImpl(
combinedChunks: cast[ptr UncheckedArray[Digest]](addr combinedChunks), combinedChunks: cast[ptr UncheckedArray[Digest]](addr combinedChunks),
topIndex: treeHeight - 1, topIndex: if (topIndex < 0): 0 else: topIndex,
totalChunks: 0) totalChunks: 0)
func getFinalHash*(merkleizer: SszMerkleizerImpl): Digest = func getFinalHash*(merkleizer: SszMerkleizerImpl): Digest =

View File

@ -0,0 +1,75 @@
import
sequtils, unittest,
nimcrypto/[hash, sha2], stew/endians2,
../eth/ssz/merkleization
proc h(a, b: seq[byte]): seq[byte] =
var h: sha256
h.init()
h.update(a & b)
h.finish().data.toSeq()
proc e(v: uint32): seq[byte] =
let elem: uint8 = 255
newSeqWith(28, elem) & v.toBytesLe().toSeq()
proc z(i: int): seq[byte] =
zerohashes[i].data.toSeq()
type TestData[limit: static int64] = object
count: uint32
expectedRoot: seq[byte]
# only happy cases as our merkleizer will happy accept more chunks than limit
# cases from - https://github.com/ethereum/eth2.0-specs/blob/dev/tests/core/pyspec/eth2spec/utils/test_merkle_minimal.py
let cases = (
TestData[0](count: 0, expectedRoot: z(0)),
TestData[1](count: 0, expectedRoot: z(0)),
TestData[1](count: 1, expectedRoot: e(0)),
TestData[2](count: 0, expectedRoot: h(z(0), z(0))),
TestData[2](count: 1, expectedRoot: h(e(0), z(0))),
TestData[2](count: 2, expectedRoot: h(e(0), e(1))),
TestData[4](count: 0, expectedRoot: h(h(z(0), z(0)), z(1))),
TestData[4](count: 1, expectedRoot: h(h(e(0), z(0)), z(1))),
TestData[4](count: 2, expectedRoot: h(h(e(0), e(1)), z(1))),
TestData[4](count: 3, expectedRoot: h(h(e(0), e(1)), h(e(2), z(0)))),
TestData[4](count: 4, expectedRoot: h(h(e(0), e(1)), h(e(2), e(3)))),
TestData[8](count: 0, expectedRoot: h(h(h(z(0), z(0)), z(1)), z(2))),
TestData[8](count: 1, expectedRoot: h(h(h(e(0), z(0)), z(1)), z(2))),
TestData[8](count: 2, expectedRoot: h(h(h(e(0), e(1)), z(1)), z(2))),
TestData[8](count: 3, expectedRoot: h(h(h(e(0), e(1)), h(e(2), z(0))), z(2))),
TestData[8](count: 4, expectedRoot: h(h(h(e(0), e(1)), h(e(2), e(3))), z(2))),
TestData[8](count: 5, expectedRoot: h(h(h(e(0), e(1)), h(e(2), e(3))), h(h(e(4), z(0)), z(1)))),
TestData[8](count: 6, expectedRoot: h(h(h(e(0), e(1)), h(e(2), e(3))), h(h(e(4), e(5)), h(z(0), z(0))))),
TestData[8](count: 7, expectedRoot: h(h(h(e(0), e(1)), h(e(2), e(3))), h(h(e(4), e(5)), h(e(6), z(0))))),
TestData[8](count: 8, expectedRoot: h(h(h(e(0), e(1)), h(e(2), e(3))), h(h(e(4), e(5)), h(e(6), e(7))))),
TestData[16](count: 0, expectedRoot: h(h(h(h(z(0), z(0)), z(1)), z(2)), z(3))),
TestData[16](count: 1, expectedRoot: h(h(h(h(e(0), z(0)), z(1)), z(2)), z(3))),
TestData[16](count: 2, expectedRoot: h(h(h(h(e(0), e(1)), z(1)), z(2)), z(3))),
TestData[16](count: 3, expectedRoot: h(h(h(h(e(0), e(1)), h(e(2), z(0))), z(2)), z(3))),
TestData[16](count: 4, expectedRoot: h(h(h(h(e(0), e(1)), h(e(2), e(3))), z(2)), z(3))),
TestData[16](count: 5, expectedRoot: h(h(h(h(e(0), e(1)), h(e(2), e(3))), h(h(e(4), z(0)), z(1))), z(3))),
TestData[16](count: 6, expectedRoot: h(h(h(h(e(0), e(1)), h(e(2), e(3))), h(h(e(4), e(5)), h(z(0), z(0)))), z(3))),
TestData[16](count: 7, expectedRoot: h(h(h(h(e(0), e(1)), h(e(2), e(3))), h(h(e(4), e(5)), h(e(6), z(0)))), z(3))),
TestData[16](count: 8, expectedRoot: h(h(h(h(e(0), e(1)), h(e(2), e(3))), h(h(e(4), e(5)), h(e(6), e(7)))), z(3))),
TestData[16](count: 9, expectedRoot: h(h(h(h(e(0), e(1)), h(e(2), e(3))), h(h(e(4), e(5)), h(e(6), e(7)))), h(h(h(e(8), z(0)), z(1)), z(2))))
)
suite "Merkleization":
test "calculate correct root from provided chunks":
for testCase in cases.fields:
var merk = createMerkleizer(testCase.limit)
var i: uint32 = 0
while i < testCase.count:
let elem = e(i)
merk.addChunk(elem)
i = i + 1
let calculatedRoot = merk.getFinalhash()
check calculatedRoot.data.toSeq() == testCase.expectedRoot