Skip to content

Commit

Permalink
[Tests] SSZ unsigned integer + test suite genericity (#284)
Browse files Browse the repository at this point in the history
* Generics over tests (status-im/nim-serialization#4, status-im/nim-serialization#5, nim-lang/Nim#11225)

* Skeleton of SSZ uint tests

* Check all primitive uint types

* Add deserialization test. "wrong length" skipped due to #280

* Move test types to their specific test files

* Stint also sometimes throws an AssertionError for invalid ranges

* Add debug path for Access denied issue in Appveyor 64-bit (https://ci.appveyor.com/project/nimbus/nim-beacon-chain/builds/25278666/job/fs8q0bcluvj2gdor#L866)

* indent the Appveyor debug info
  • Loading branch information
mratsim authored and tersec committed Jun 17, 2019
1 parent e9180c4 commit 0926ebf
Show file tree
Hide file tree
Showing 6 changed files with 216 additions and 122 deletions.
3 changes: 2 additions & 1 deletion tests/all_tests.nim
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ import # Official fixtures
# TODO - re-enable
#./official/test_fixture_state
./official/test_fixture_shuffling,
./official/test_fixture_bls
./official/test_fixture_bls,
./official/test_fixture_ssz_uint
110 changes: 12 additions & 98 deletions tests/official/fixtures_utils.nim
Original file line number Diff line number Diff line change
@@ -1,26 +1,20 @@
import
# Status libs
blscurve, nimcrypto, byteutils,
byteutils,
eth/common, serialization, json_serialization,
# Beacon chain internals
# submodule in nim-beacon-chain/tests/official/fixtures/
../../beacon_chain/spec/[datatypes, crypto, digest],
../../beacon_chain/ssz,
# Workarounds
endians # parseHex into uint64
../../beacon_chain/spec/datatypes

export nimcrypto.toHex
export # Workaround:
# - https://github.com/status-im/nim-serialization/issues/4
# - https://github.com/status-im/nim-serialization/issues/5
# - https://github.com/nim-lang/Nim/issues/11225
serialization.readValue

type
# TODO: use ref object to avoid allocating
# so much on the stack - pending https://github.com/status-im/nim-json-serialization/issues/3
StateTests* = object
title*: string
summary*: string
test_suite*: string
fork*: string
test_cases*: seq[StateTestCase]


TestConstants* = object
# TODO - 0.5.1 constants
SHARD_COUNT*: int
Expand Down Expand Up @@ -69,14 +63,6 @@ type
DOMAIN_VOLUNTARY_EXIT*: SignatureDomain
DOMAIN_TRANSFER*: SignatureDomain

StateTestCase* = object
name*: string
config*: TestConstants
verify_signatures*: bool
initial_state*: BeaconState
blocks*: seq[BeaconBlock]
expected_state*: BeaconState

Tests*[T] = object
title*: string
summary*: string
Expand All @@ -87,51 +73,6 @@ type
handler*: string
test_cases*: seq[T]

Shuffling* = object
seed*: Eth2Digest
count*: uint64
shuffled*: seq[ValidatorIndex]

# # TODO - but already tested in nim-blscurve
# BLSUncompressedG2 = object
# input*: tuple[
# message: seq[byte],
# domain: array[1, byte]
# ]
# output*: ECP2_BLS381

# # TODO - but already tested in nim-blscurve
# BLSCompressedG2 = object
# input*: tuple[
# message: seq[byte],
# domain: array[1, byte]
# ]
# output*: ECP2_BLS381

Domain = distinct uint64
## Domains have custom hex serialization

BLSPrivToPub* = object
input*: ValidatorPrivKey
output*: ValidatorPubKey

BLSSignMsgInput = object
privkey*: ValidatorPrivKey
message*: seq[byte]
domain*: Domain

BLSSignMsg* = object
input*: BLSSignMsgInput
output*: Signature

BLSAggSig* = object
input*: seq[Signature]
output*: Signature

BLSAggPubKey* = object
input*: seq[ValidatorPubKey]
output*: ValidatorPubKey

# #######################
# Default init
proc default*(T: typedesc): T = discard
Expand All @@ -150,47 +91,20 @@ proc readValue*[N: static int](r: var JsonReader, a: var array[N, byte]) {.inlin
proc readValue*(r: var JsonReader, a: var ValidatorIndex) {.inline.} =
a = r.readValue(uint32)

proc readValue*(r: var JsonReader, a: var Domain) {.inline.} =
## Custom deserializer for Domain
## They are uint64 stored in hex values
# Furthermore Nim parseHex doesn't support uint
# until https://github.com/nim-lang/Nim/pull/11067
# (0.20)
let be_uint = hexToPaddedByteArray[8](r.readValue(string))
bigEndian64(a.addr, be_uint.unsafeAddr)

proc readValue*(r: var JsonReader, a: var seq[byte]) {.inline.} =
## Custom deserializer for seq[byte]
a = hexToSeqByte(r.readValue(string))

template parseTestsImpl(T: untyped) {.dirty.} =
# TODO: workaround typedesc/generics
# being broken with nim-serialization
# - https://github.com/status-im/nim-serialization/issues/4
# - https://github.com/status-im/nim-serialization/issues/5
proc parseTests*(jsonPath: string, T: typedesc): Tests[T] =
try:
result = Json.loadFile(jsonPath, T)
debugEcho " [Debug] Loading file: \"", jsonPath, '\"'
result = Json.loadFile(jsonPath, Tests[T])
except SerializationError as err:
writeStackTrace()
stderr.write "Json load issue for file \"", jsonPath, "\"\n"
stderr.write err.formatMsg(jsonPath), "\n"
quit 1

proc parseTestsShuffling*(jsonPath: string): Tests[Shuffling] =
parseTestsImpl(Tests[Shuffling])

proc parseTestsBLSPrivToPub*(jsonPath: string): Tests[BLSPrivToPub] =
parseTestsImpl(Tests[BLSPrivToPub])

proc parseTestsBLSSignMsg*(jsonPath: string): Tests[BLSSignMsg] =
parseTestsImpl(Tests[BLSSignMsg])

proc parseTestsBLSAggSig*(jsonPath: string): Tests[BLSAggSig] =
parseTestsImpl(Tests[BLSAggSig])

proc parseTestsBLSAggPubKey*(jsonPath: string): Tests[BLSAggPubKey] =
parseTestsImpl(Tests[BLSAggPubKey])

# #######################
# Mocking helpers
# https://github.com/ethereum/eth2.0-specs/blob/75f0af45bb0613bb406fc72d10266cee4cfb402a/tests/phase0/helpers.py#L107
Expand All @@ -216,4 +130,4 @@ proc build_empty_block_for_next_slot*(state: BeaconState): BeaconBlock =
# prev_root,
# BeaconBlockBody()
# )
{.error: "Not implemented".}
{.error: "Not implemented".}
65 changes: 58 additions & 7 deletions tests/official/test_fixture_bls.nim
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,67 @@

import
# Standard libs
ospaths, strutils, json, unittest,
# Third parties

ospaths, strutils, unittest, endians,
# Status libs
blscurve, byteutils,
# Beacon chain internals
../../beacon_chain/spec/crypto,
# Test utilities
./fixtures_utils

type
# # TODO - but already tested in nim-blscurve
# BLSUncompressedG2 = object
# input*: tuple[
# message: seq[byte],
# domain: array[1, byte]
# ]
# output*: ECP2_BLS381

# # TODO - but already tested in nim-blscurve
# BLSCompressedG2 = object
# input*: tuple[
# message: seq[byte],
# domain: array[1, byte]
# ]
# output*: ECP2_BLS381

Domain = distinct uint64
## Domains have custom hex serialization

BLSPrivToPub* = object
input*: ValidatorPrivKey
output*: ValidatorPubKey

BLSSignMsgInput = object
privkey*: ValidatorPrivKey
message*: seq[byte]
domain*: Domain

BLSSignMsg* = object
input*: BLSSignMsgInput
output*: Signature

BLSAggSig* = object
input*: seq[Signature]
output*: Signature

BLSAggPubKey* = object
input*: seq[ValidatorPubKey]
output*: ValidatorPubKey

proc readValue*(r: var JsonReader, a: var Domain) {.inline.} =
## Custom deserializer for Domain
## They are uint64 stored in hex values
# Furthermore Nim parseHex doesn't support uint
# until https://github.com/nim-lang/Nim/pull/11067
# (0.20)
let be_uint = hexToPaddedByteArray[8](r.readValue(string))
bigEndian64(a.addr, be_uint.unsafeAddr)

const TestFolder = currentSourcePath.rsplit(DirSep, 1)[0]
const TestsPath = "fixtures" / "json_tests" / "bls"

var
blsPrivToPubTests: Tests[BLSPrivToPub]
blsSignMsgTests: Tests[BLSSignMsg]
Expand All @@ -25,10 +76,10 @@ var

suite "Official - BLS tests":
test "Parsing the official BLS tests":
blsPrivToPubTests = parseTestsBLSPrivToPub(TestFolder / TestsPath / "priv_to_pub" / "priv_to_pub.json")
blsSignMsgTests = parseTestsBLSSignMsg(TestFolder / TestsPath / "sign_msg" / "sign_msg.json")
blsAggSigTests = parseTestsBLSAggSig(TestFolder / TestsPath / "aggregate_sigs" / "aggregate_sigs.json")
blsAggPubKeyTests = parseTestsBLSAggPubKey(TestFolder / TestsPath / "aggregate_pubkeys" / "aggregate_pubkeys.json")
blsPrivToPubTests = parseTests(TestFolder / TestsPath / "priv_to_pub" / "priv_to_pub.json", BLSPrivToPub)
blsSignMsgTests = parseTests(TestFolder / TestsPath / "sign_msg" / "sign_msg.json", BLSSignMsg)
blsAggSigTests = parseTests(TestFolder / TestsPath / "aggregate_sigs" / "aggregate_sigs.json", BLSAggSig)
blsAggPubKeyTests = parseTests(TestFolder / TestsPath / "aggregate_pubkeys" / "aggregate_pubkeys.json", BLSAggPubKey)

test "Private to public key conversion":
for t in blsPrivToPubTests.test_cases:
Expand Down
14 changes: 9 additions & 5 deletions tests/official/test_fixture_shuffling.nim
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,19 @@

import
# Standard library
ospaths, strutils, json, unittest,
# Third parties

ospaths, strutils, unittest,
# Beacon chain internals
../../beacon_chain/spec/[datatypes, validator],
../../beacon_chain/spec/[datatypes, validator, digest],
# Test utilities
../testutil,
./fixtures_utils

type
Shuffling* = object
seed*: Eth2Digest
count*: uint64
shuffled*: seq[ValidatorIndex]

const TestFolder = currentSourcePath.rsplit(DirSep, 1)[0]

when const_preset == "mainnet":
Expand All @@ -27,7 +31,7 @@ var shufflingTests: Tests[Shuffling]

suite "Official - Shuffling tests [Preset: " & preset():
test "Parsing the official shuffling tests [Preset: " & preset():
shufflingTests = parseTestsShuffling(TestFolder / TestsPath)
shufflingTests = parseTests(TestFolder / TestsPath, Shuffling)

test "Shuffling a sequence of N validators" & preset():
for t in shufflingTests.test_cases:
Expand Down
Loading

0 comments on commit 0926ebf

Please sign in to comment.