hash-tree-root tests

This commit is contained in:
protolambda 2019-06-25 02:35:55 +02:00
parent 9fb5806764
commit a5b7564c5b
No known key found for this signature in database
GPG Key ID: EC89FDBB2B4C7623

View File

@ -1,8 +1,10 @@
from typing import Iterable
from .ssz_impl import serialize, hash_tree_root from .ssz_impl import serialize, hash_tree_root
from .ssz_typing import ( from .ssz_typing import (
Bit, Bool, Container, List, Vector, Bytes, BytesN, Bit, Bool, Container, List, Vector, Bytes, BytesN,
uint8, uint16, uint32, uint64, byte uint8, uint16, uint32, uint64, uint256, byte
) )
from ..hash_function import hash as bytes_hash
import pytest import pytest
@ -46,37 +48,117 @@ sig_test_data = [0 for i in range(96)]
for k, v in {0: 1, 32: 2, 64: 3, 95: 0xff}.items(): for k, v in {0: 1, 32: 2, 64: 3, 95: 0xff}.items():
sig_test_data[k] = v sig_test_data[k] = v
def chunk(hex: str) -> str:
return (hex + ("00" * 32))[:64] # just pad on the right, to 32 bytes (64 hex chars)
def h(a: str, b: str) -> str:
return bytes_hash(bytes.fromhex(a) + bytes.fromhex(b)).hex()
# zero hashes, as strings, for
zero_hashes = [chunk("")]
for layer in range(1, 32):
zero_hashes.append(h(zero_hashes[layer - 1], zero_hashes[layer - 1]))
def merge(a: str, branch: Iterable[str]) -> str:
"""
Merge (out on left, branch on right) leaf a with branch items, branch is from bottom to top.
"""
out = a
for b in branch:
out = h(out, b)
return out
test_data = [ test_data = [
("bit F", Bit(False), "00"), ("bit F", Bit(False), "00", chunk("00")),
("bit T", Bit(True), "01"), ("bit T", Bit(True), "01", chunk("01")),
("bool F", Bool(False), "00"), ("bool F", Bool(False), "00", chunk("00")),
("bool T", Bool(True), "01"), ("bool T", Bool(True), "01", chunk("01")),
("uint8 00", uint8(0x00), "00"), ("uint8 00", uint8(0x00), "00", chunk("00")),
("uint8 01", uint8(0x01), "01"), ("uint8 01", uint8(0x01), "01", chunk("01")),
("uint8 ab", uint8(0xab), "ab"), ("uint8 ab", uint8(0xab), "ab", chunk("ab")),
("byte 00", byte(0x00), "00"), ("byte 00", byte(0x00), "00", chunk("00")),
("byte 01", byte(0x01), "01"), ("byte 01", byte(0x01), "01", chunk("01")),
("byte ab", byte(0xab), "ab"), ("byte ab", byte(0xab), "ab", chunk("ab")),
("uint16 0000", uint16(0x0000), "0000"), ("uint16 0000", uint16(0x0000), "0000", chunk("0000")),
("uint16 abcd", uint16(0xabcd), "cdab"), ("uint16 abcd", uint16(0xabcd), "cdab", chunk("cdab")),
("uint32 00000000", uint32(0x00000000), "00000000"), ("uint32 00000000", uint32(0x00000000), "00000000", chunk("00000000")),
("uint32 01234567", uint32(0x01234567), "67452301"), ("uint32 01234567", uint32(0x01234567), "67452301", chunk("67452301")),
("small (4567, 0123)", SmallTestStruct(A=0x4567, B=0x0123), "67452301"), ("small (4567, 0123)", SmallTestStruct(A=0x4567, B=0x0123), "67452301", h(chunk("6745"), chunk("2301"))),
("small [4567, 0123]::2", Vector[uint16, 2](uint16(0x4567), uint16(0x0123)), "67452301"), ("small [4567, 0123]::2", Vector[uint16, 2](uint16(0x4567), uint16(0x0123)), "67452301", chunk("67452301")),
("uint32 01234567", uint32(0x01234567), "67452301"), ("uint32 01234567", uint32(0x01234567), "67452301", chunk("67452301")),
("uint64 0000000000000000", uint64(0x00000000), "0000000000000000"), ("uint64 0000000000000000", uint64(0x00000000), "0000000000000000", chunk("0000000000000000")),
("uint64 0123456789abcdef", uint64(0x0123456789abcdef), "efcdab8967452301"), ("uint64 0123456789abcdef", uint64(0x0123456789abcdef), "efcdab8967452301", chunk("efcdab8967452301")),
("sig", BytesN[96](*sig_test_data), ("sig", BytesN[96](*sig_test_data),
"0100000000000000000000000000000000000000000000000000000000000000" "0100000000000000000000000000000000000000000000000000000000000000"
"0200000000000000000000000000000000000000000000000000000000000000" "0200000000000000000000000000000000000000000000000000000000000000"
"03000000000000000000000000000000000000000000000000000000000000ff"), "03000000000000000000000000000000000000000000000000000000000000ff",
("emptyTestStruct", EmptyTestStruct(), ""), h(h(chunk("01"), chunk("02")),
("singleFieldTestStruct", SingleFieldTestStruct(A=0xab), "ab"), h("03000000000000000000000000000000000000000000000000000000000000ff", chunk("")))),
("fixedTestStruct", FixedTestStruct(A=0xab, B=0xaabbccdd00112233, C=0x12345678), "ab33221100ddccbbaa78563412"), ("emptyTestStruct", EmptyTestStruct(), "", chunk("")),
("varTestStruct nil", VarTestStruct(A=0xabcd, C=0xff), "cdab07000000ff"), ("singleFieldTestStruct", SingleFieldTestStruct(A=0xab), "ab", chunk("ab")),
("varTestStruct empty", VarTestStruct(A=0xabcd, B=List[uint16, 1024](), C=0xff), "cdab07000000ff"), ("uint16 list", List[uint16, 32](uint16(0xaabb), uint16(0xc0ad), uint16(0xeeff)), "bbaaadc0ffee",
h(h(chunk("bbaaadc0ffee"), chunk("")), chunk("03000000")) # max length: 32 * 2 = 64 bytes = 2 chunks
),
("uint32 list", List[uint32, 128](uint32(0xaabb), uint32(0xc0ad), uint32(0xeeff)), "bbaa0000adc00000ffee0000",
# max length: 128 * 4 = 512 bytes = 16 chunks
h(merge(chunk("bbaa0000adc00000ffee0000"), zero_hashes[0:4]), chunk("03000000"))
),
("uint256 list", List[uint256, 32](uint256(0xaabb), uint256(0xc0ad), uint256(0xeeff)),
"bbaa000000000000000000000000000000000000000000000000000000000000"
"adc0000000000000000000000000000000000000000000000000000000000000"
"ffee000000000000000000000000000000000000000000000000000000000000",
h(merge(h(h(chunk("bbaa"), chunk("adc0")), h(chunk("ffee"), chunk(""))), zero_hashes[2:5]), chunk("03000000"))
),
("uint256 list long", List[uint256, 128](i for i in range(1, 20)),
"".join([i.to_bytes(length=32, byteorder='little').hex() for i in range(1, 20)]),
h(merge(
h(
h(
h(
h(h(chunk("01"), chunk("02")), h(chunk("03"), chunk("04"))),
h(h(chunk("05"), chunk("06")), h(chunk("07"), chunk("08"))),
),
h(
h(h(chunk("09"), chunk("0a")), h(chunk("0b"), chunk("0c"))),
h(h(chunk("0d"), chunk("0e")), h(chunk("0f"), chunk("10"))),
)
),
h(
h(
h(h(chunk("11"), chunk("12")), h(chunk("13"), chunk(""))),
zero_hashes[2]
),
zero_hashes[3]
)
),
zero_hashes[5:7]), chunk("13000000")) # 128 chunks = 7 deep
),
("fixedTestStruct", FixedTestStruct(A=0xab, B=0xaabbccdd00112233, C=0x12345678), "ab33221100ddccbbaa78563412",
h(h(chunk("ab"), chunk("33221100ddccbbaa")), h(chunk("78563412"), chunk("")))),
("varTestStruct nil", VarTestStruct(A=0xabcd, C=0xff), "cdab07000000ff",
h(h(chunk("cdab"), h(zero_hashes[6], chunk("00000000"))), h(chunk("ff"), chunk("")))),
("varTestStruct empty", VarTestStruct(A=0xabcd, B=List[uint16, 1024](), C=0xff), "cdab07000000ff",
h(h(chunk("cdab"), h(zero_hashes[6], chunk("00000000"))), h(chunk("ff"), chunk("")))), # log2(1024*2/32)= 6 deep
("varTestStruct some", VarTestStruct(A=0xabcd, B=List[uint16, 1024](1, 2, 3), C=0xff), ("varTestStruct some", VarTestStruct(A=0xabcd, B=List[uint16, 1024](1, 2, 3), C=0xff),
"cdab07000000ff010002000300"), "cdab07000000ff010002000300",
h(
h(
chunk("cdab"),
h(
merge(
chunk("010002000300"),
zero_hashes[0:6]
),
chunk("03000000") # length mix in
)
),
h(chunk("ff"), chunk(""))
)),
("complexTestStruct", ("complexTestStruct",
ComplexTestStruct( ComplexTestStruct(
A=0xaabb, A=0xaabb,
@ -90,8 +172,8 @@ test_data = [
FixedTestStruct(A=0xee, B=0x4444444444444444, C=0x00112233), FixedTestStruct(A=0xee, B=0x4444444444444444, C=0x00112233),
FixedTestStruct(A=0xff, B=0x5555555555555555, C=0x44556677)), FixedTestStruct(A=0xff, B=0x5555555555555555, C=0x44556677)),
G=Vector[VarTestStruct, 2]( G=Vector[VarTestStruct, 2](
VarTestStruct(A=0xabcd, B=List[uint16, 1024](1, 2, 3), C=0xff), VarTestStruct(A=0xdead, B=List[uint16, 1024](1, 2, 3), C=0x11),
VarTestStruct(A=0xabcd, B=List[uint16, 1024](1, 2, 3), C=0xff)), VarTestStruct(A=0xbeef, B=List[uint16, 1024](4, 5, 6), C=0x22)),
), ),
"bbaa" "bbaa"
"47000000" # offset of B, []uint16 "47000000" # offset of B, []uint16
@ -107,17 +189,53 @@ test_data = [
"666f6f626172" # foobar "666f6f626172" # foobar
"cdab07000000ff010002000300" # contents of E "cdab07000000ff010002000300" # contents of E
"08000000" "15000000" # [start G]: local offsets of [2]varTestStruct "08000000" "15000000" # [start G]: local offsets of [2]varTestStruct
"cdab07000000ff010002000300" "adde0700000011010002000300"
"cdab07000000ff010002000300", "efbe0700000022040005000600",
) h(
h(
h( # A and B
chunk("bbaa"),
h(merge(chunk("22114433"), zero_hashes[0:3]), chunk("02000000")) # 2*128/32 = 8 chunks
),
h( # C and D
chunk("ff"),
h(merge(chunk("666f6f626172"), zero_hashes[0:3]), chunk("06000000")) # 256/32 = 8 chunks
)
),
h(
h( # E and F
h(h(chunk("cdab"), h(merge(chunk("010002000300"), zero_hashes[0:6]), chunk("03000000"))),
h(chunk("ff"), chunk(""))),
h(
h(
h(h(chunk("cc"), chunk("4242424242424242")), h(chunk("37133713"), chunk(""))),
h(h(chunk("dd"), chunk("3333333333333333")), h(chunk("cdabcdab"), chunk(""))),
),
h(
h(h(chunk("ee"), chunk("4444444444444444")), h(chunk("33221100"), chunk(""))),
h(h(chunk("ff"), chunk("5555555555555555")), h(chunk("77665544"), chunk(""))),
),
)
),
h( # G and padding
h(
h(h(chunk("adde"), h(merge(chunk("010002000300"), zero_hashes[0:6]), chunk("03000000"))),
h(chunk("11"), chunk(""))),
h(h(chunk("efbe"), h(merge(chunk("040005000600"), zero_hashes[0:6]), chunk("03000000"))),
h(chunk("22"), chunk(""))),
),
chunk("")
)
)
))
] ]
@pytest.mark.parametrize("name, value, serialized", test_data) @pytest.mark.parametrize("name, value, serialized, _", test_data)
def test_serialize(name, value, serialized): def test_serialize(name, value, serialized, _):
assert serialize(value) == bytes.fromhex(serialized) assert serialize(value) == bytes.fromhex(serialized)
@pytest.mark.parametrize("name, value, _", test_data) @pytest.mark.parametrize("name, value, _, root", test_data)
def test_hash_tree_root(name, value, _): def test_hash_tree_root(name, value, _, root):
hash_tree_root(value) assert hash_tree_root(value) == bytes.fromhex(root)