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:
parent
8da71715eb
commit
2a4c4df7c3
|
@ -21,4 +21,5 @@ import # Unit test
|
|||
import # Official fixtures
|
||||
# TODO - re-enable
|
||||
#./official/test_fixture_state
|
||||
./official/test_fixture_shuffling
|
||||
./official/test_fixture_shuffling,
|
||||
./official/test_fixture_bls
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 80c3652796488e62c37087a9bffae60c6b1cefa5
|
||||
Subproject commit 76fd020646fef404c55837fbc40833b0d0b2ac72
|
|
@ -5,7 +5,9 @@ import
|
|||
# Beacon chain internals
|
||||
# submodule in nim-beacon-chain/tests/official/fixtures/
|
||||
../../beacon_chain/spec/[datatypes, crypto, digest],
|
||||
../../beacon_chain/ssz
|
||||
../../beacon_chain/ssz,
|
||||
# Workarounds
|
||||
endians # parseHex into uint64
|
||||
|
||||
export nimcrypto.toHex
|
||||
|
||||
|
@ -75,7 +77,7 @@ type
|
|||
blocks*: seq[BeaconBlock]
|
||||
expected_state*: BeaconState
|
||||
|
||||
ShufflingTests* = object
|
||||
Tests*[T] = object
|
||||
title*: string
|
||||
summary*: string
|
||||
forks_timeline*: string
|
||||
|
@ -83,14 +85,52 @@ type
|
|||
config*: string
|
||||
runner*: string
|
||||
handler*: string
|
||||
test_cases*: seq[ShufflingTestCase]
|
||||
test_cases*: seq[T]
|
||||
|
||||
ShufflingTestCase* = object
|
||||
Shuffling* = object
|
||||
seed*: Eth2Digest
|
||||
count*: uint64
|
||||
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
|
||||
|
@ -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.} =
|
||||
a = r.readValue(uint32)
|
||||
|
||||
# TODO: cannot pass a typedesc
|
||||
# proc parseTests*(jsonPath: string, T: typedesc[Tests]): T =
|
||||
# # TODO: due to generic early symbol resolution
|
||||
# # we cannot use a generic proc
|
||||
# # Otherwise we get:
|
||||
# # "Error: undeclared identifier: 'ReaderType'"
|
||||
# # Templates, even untyped don't work
|
||||
# try:
|
||||
# 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 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 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:
|
||||
result = Json.loadFile(jsonPath, ShufflingTests)
|
||||
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 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
|
||||
|
|
|
@ -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
|
|
@ -18,11 +18,11 @@ import
|
|||
const TestFolder = currentSourcePath.rsplit(DirSep, 1)[0]
|
||||
const TestsPath = "fixtures" / "json_tests" / "shuffling" / "core" / "shuffling_full.json"
|
||||
|
||||
var shufflingTests: ShufflingTests
|
||||
var shufflingTests: Tests[Shuffling]
|
||||
|
||||
suite "Official - Shuffling tests":
|
||||
test "Parsing the official shuffling tests":
|
||||
shufflingTests = parseTests(TestFolder / TestsPath)
|
||||
shufflingTests = parseTestsShuffling(TestFolder / TestsPath)
|
||||
|
||||
test "Shuffling a sequence of N validators":
|
||||
for t in shufflingTests.test_cases:
|
||||
|
|
|
@ -24,7 +24,7 @@ var stateTests: StateTests
|
|||
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
|
||||
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"
|
||||
|
||||
test "[For information - Non-blocking] Block root signing":
|
||||
|
|
Loading…
Reference in New Issue