Bls official tests (#268)

* Update fixtures with BLS and SSZ generic

* Stash changes following https://github.com/status-im/nim-serialization/issues/4

* Add Private to Public key conversion

* Add message signing tests

* Add aggregate signatures and public keys

* Add BLS to test suite
This commit is contained in:
Mamy Ratsimbazafy 2019-05-23 09:41:17 +02:00 committed by GitHub
parent 8da71715eb
commit 2a4c4df7c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 138 additions and 26 deletions

View File

@ -21,4 +21,5 @@ import # Unit test
import # Official fixtures import # Official fixtures
# TODO - re-enable # TODO - re-enable
#./official/test_fixture_state #./official/test_fixture_state
./official/test_fixture_shuffling ./official/test_fixture_shuffling,
./official/test_fixture_bls

@ -1 +1 @@
Subproject commit 80c3652796488e62c37087a9bffae60c6b1cefa5 Subproject commit 76fd020646fef404c55837fbc40833b0d0b2ac72

View File

@ -5,7 +5,9 @@ import
# Beacon chain internals # Beacon chain internals
# submodule in nim-beacon-chain/tests/official/fixtures/ # submodule in nim-beacon-chain/tests/official/fixtures/
../../beacon_chain/spec/[datatypes, crypto, digest], ../../beacon_chain/spec/[datatypes, crypto, digest],
../../beacon_chain/ssz ../../beacon_chain/ssz,
# Workarounds
endians # parseHex into uint64
export nimcrypto.toHex export nimcrypto.toHex
@ -75,7 +77,7 @@ type
blocks*: seq[BeaconBlock] blocks*: seq[BeaconBlock]
expected_state*: BeaconState expected_state*: BeaconState
ShufflingTests* = object Tests*[T] = object
title*: string title*: string
summary*: string summary*: string
forks_timeline*: string forks_timeline*: string
@ -83,14 +85,52 @@ type
config*: string config*: string
runner*: string runner*: string
handler*: string handler*: string
test_cases*: seq[ShufflingTestCase] test_cases*: seq[T]
ShufflingTestCase* = object Shuffling* = object
seed*: Eth2Digest seed*: Eth2Digest
count*: uint64 count*: uint64
shuffled*: seq[ValidatorIndex] shuffled*: seq[ValidatorIndex]
Tests* = StateTests or ShufflingTests # # 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 # Default init
@ -110,30 +150,47 @@ proc readValue*[N: static int](r: var JsonReader, a: var array[N, byte]) {.inlin
proc readValue*(r: var JsonReader, a: var ValidatorIndex) {.inline.} = proc readValue*(r: var JsonReader, a: var ValidatorIndex) {.inline.} =
a = r.readValue(uint32) a = r.readValue(uint32)
# TODO: cannot pass a typedesc proc readValue*(r: var JsonReader, a: var Domain) {.inline.} =
# proc parseTests*(jsonPath: string, T: typedesc[Tests]): T = ## Custom deserializer for Domain
# # TODO: due to generic early symbol resolution ## They are uint64 stored in hex values
# # we cannot use a generic proc # Furthermore Nim parseHex doesn't support uint
# # Otherwise we get: # until https://github.com/nim-lang/Nim/pull/11067
# # "Error: undeclared identifier: 'ReaderType'" # (0.20)
# # Templates, even untyped don't work let be_uint = hexToPaddedByteArray[8](r.readValue(string))
# try: bigEndian64(a.addr, be_uint.unsafeAddr)
# result = Json.loadFile(jsonPath, T)
# except SerializationError as err:
# writeStackTrace()
# stderr.write "Json load issue for file \"", jsonPath, "\"\n"
# stderr.write err.formatMsg(jsonPath), "\n"
# quit 1
proc parseTests*(jsonPath: string): ShufflingTests = 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
try: try:
result = Json.loadFile(jsonPath, ShufflingTests) result = Json.loadFile(jsonPath, T)
except SerializationError as err: except SerializationError as err:
writeStackTrace() writeStackTrace()
stderr.write "Json load issue for file \"", jsonPath, "\"\n" stderr.write "Json load issue for file \"", jsonPath, "\"\n"
stderr.write err.formatMsg(jsonPath), "\n" stderr.write err.formatMsg(jsonPath), "\n"
quit 1 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 # Mocking helpers
# https://github.com/ethereum/eth2.0-specs/blob/75f0af45bb0613bb406fc72d10266cee4cfb402a/tests/phase0/helpers.py#L107 # https://github.com/ethereum/eth2.0-specs/blob/75f0af45bb0613bb406fc72d10266cee4cfb402a/tests/phase0/helpers.py#L107

View File

@ -0,0 +1,54 @@
# beacon_chain
# Copyright (c) 2018 Status Research & Development GmbH
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
# Standard libs
ospaths, strutils, json, unittest,
# Third parties
# Beacon chain internals
../../beacon_chain/spec/crypto,
# Test utilities
./fixtures_utils
const TestFolder = currentSourcePath.rsplit(DirSep, 1)[0]
const TestsPath = "fixtures" / "json_tests" / "bls"
var
blsPrivToPubTests: Tests[BLSPrivToPub]
blsSignMsgTests: Tests[BLSSignMsg]
blsAggSigTests: Tests[BLSAggSig]
blsAggPubKeyTests: Tests[BLSAggPubKey]
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")
test "Private to public key conversion":
for t in blsPrivToPubTests.test_cases:
let implResult = t.input.pubkey()
check: implResult == t.output
test "Message signing":
for t in blsSignMsgTests.test_cases:
let implResult = t.input.privkey.bls_sign(
t.input.message,
uint64(t.input.domain)
)
check: implResult == t.output
test "Aggregating signatures":
for t in blsAggSigTests.test_cases:
let implResult = t.input.combine()
check: implResult == t.output
test "Aggregating public keys":
for t in blsAggPubKeyTests.test_cases:
let implResult = t.input.combine()
check: implResult == t.output

View File

@ -18,11 +18,11 @@ import
const TestFolder = currentSourcePath.rsplit(DirSep, 1)[0] const TestFolder = currentSourcePath.rsplit(DirSep, 1)[0]
const TestsPath = "fixtures" / "json_tests" / "shuffling" / "core" / "shuffling_full.json" const TestsPath = "fixtures" / "json_tests" / "shuffling" / "core" / "shuffling_full.json"
var shufflingTests: ShufflingTests var shufflingTests: Tests[Shuffling]
suite "Official - Shuffling tests": suite "Official - Shuffling tests":
test "Parsing the official shuffling tests": test "Parsing the official shuffling tests":
shufflingTests = parseTests(TestFolder / TestsPath) shufflingTests = parseTestsShuffling(TestFolder / TestsPath)
test "Shuffling a sequence of N validators": test "Shuffling a sequence of N validators":
for t in shufflingTests.test_cases: for t in shufflingTests.test_cases:

View File

@ -24,7 +24,7 @@ var stateTests: StateTests
suite "Official - State tests": # Initializing a beacon state from the deposits suite "Official - State tests": # Initializing a beacon state from the deposits
# Source: https://github.com/ethereum/eth2.0-specs/blob/2baa242ac004b0475604c4c4ef4315e14f56c5c7/tests/phase0/test_sanity.py#L55-L460 # Source: https://github.com/ethereum/eth2.0-specs/blob/2baa242ac004b0475604c4c4ef4315e14f56c5c7/tests/phase0/test_sanity.py#L55-L460
test "Parsing the official state tests into Nimbus beacon types": test "Parsing the official state tests into Nimbus beacon types":
stateTests = parseTests(TestFolder / TestsPath, StateTests) # TODO pending typedesc fix in fixture_utils.nim stateTests = parseTests(TestFolder / TestsPath, StateTests)
doAssert $stateTests.test_cases[0].name == "test_empty_block_transition" doAssert $stateTests.test_cases[0].name == "test_empty_block_transition"
test "[For information - Non-blocking] Block root signing": test "[For information - Non-blocking] Block root signing":