Merge pull request #1575 from ethereum/broken-gens

Fix broken test generators
This commit is contained in:
Danny Ryan 2020-01-23 10:36:53 -07:00 committed by GitHub
commit ec00f6d9ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 135 additions and 100 deletions

View File

@ -20,6 +20,7 @@ def hash(x):
F2Q_COEFF_LEN = 48 F2Q_COEFF_LEN = 48
G2_COMPRESSED_Z_LEN = 48 G2_COMPRESSED_Z_LEN = 48
DST = bls.G2ProofOfPossession.DST
def int_to_hex(n: int, byte_length: int = None) -> str: def int_to_hex(n: int, byte_length: int = None) -> str:
@ -29,6 +30,13 @@ def int_to_hex(n: int, byte_length: int = None) -> str:
return encode_hex(byte_value) return encode_hex(byte_value)
def int_to_bytes(n: int, byte_length: int = None) -> bytes:
byte_value = int_to_big_endian(n)
if byte_length:
byte_value = byte_value.rjust(byte_length, b'\x00')
return byte_value
def hex_to_int(x: str) -> int: def hex_to_int(x: str) -> int:
return int(x, 16) return int(x, 16)
@ -57,116 +65,144 @@ PRIVKEYS = [
] ]
def hash_message(msg: bytes, def case01_sign():
domain: bytes) -> Tuple[Tuple[str, str], Tuple[str, str], Tuple[str, str]]: for privkey in PRIVKEYS:
""" for message in MESSAGES:
Hash message sig = bls.G2ProofOfPossession.Sign(privkey, message)
Input: full_name = f'{int_to_hex(privkey)}_{encode_hex(message)}'
- Message as bytes32 yield f'sign_case_{(hash(bytes(full_name, "utf-8"))[:8]).hex()}', {
- domain as bytes8
Output:
- Message hash as a G2 point
"""
return [
[
int_to_hex(fq2.coeffs[0], F2Q_COEFF_LEN),
int_to_hex(fq2.coeffs[1], F2Q_COEFF_LEN),
]
for fq2 in bls.utils.hash_to_G2(msg, domain)
]
def hash_message_compressed(msg: bytes, domain: bytes) -> Tuple[str, str]:
"""
Hash message
Input:
- Message as bytes32
- domain as bytes8
Output:
- Message hash as a compressed G2 point
"""
z1, z2 = bls.utils.compress_G2(bls.utils.hash_to_G2(msg, domain))
return [int_to_hex(z1, G2_COMPRESSED_Z_LEN), int_to_hex(z2, G2_COMPRESSED_Z_LEN)]
def case01_message_hash_G2_uncompressed():
for msg in MESSAGES:
for domain in DOMAINS:
yield f'uncom_g2_hash_{encode_hex(msg)}_{encode_hex(domain)}', {
'input': { 'input': {
'message': encode_hex(msg), 'privkey': int_to_hex(privkey),
'domain': encode_hex(domain), 'message': encode_hex(message),
}, },
'output': hash_message(msg, domain) 'output': encode_hex(sig)
} }
def case02_message_hash_G2_compressed(): def case02_verify():
for msg in MESSAGES: for i, privkey in enumerate(PRIVKEYS):
for domain in DOMAINS: for message in MESSAGES:
yield f'com_g2_hash_{encode_hex(msg)}_{encode_hex(domain)}', { # Valid signature
signature = bls.G2ProofOfPossession.Sign(privkey, message)
pubkey = bls.G2ProofOfPossession.PrivToPub(privkey)
full_name = f'{encode_hex(pubkey)}_{encode_hex(message)}_valid'
yield f'verify_case_{(hash(bytes(full_name, "utf-8"))[:8]).hex()}', {
'input': { 'input': {
'message': encode_hex(msg), 'pubkey': encode_hex(pubkey),
'domain': encode_hex(domain), 'message': encode_hex(message),
'signature': encode_hex(signature),
}, },
'output': hash_message_compressed(msg, domain) 'output': True,
}
# Invalid signatures -- wrong pubkey
wrong_pubkey = bls.G2ProofOfPossession.PrivToPub(PRIVKEYS[(i + 1) % len(PRIVKEYS)])
full_name = f'{encode_hex(wrong_pubkey)}_{encode_hex(message)}_wrong_pubkey'
yield f'verify_case_{(hash(bytes(full_name, "utf-8"))[:8]).hex()}', {
'input': {
'pubkey': encode_hex(wrong_pubkey),
'message': encode_hex(message),
'signature': encode_hex(signature),
},
'output': False,
}
# Invalid signature -- tampered with signature
tampered_signature = signature[:-4] + b'\xFF\xFF\xFF\xFF'
full_name = f'{encode_hex(pubkey)}_{encode_hex(message)}_tampered_signature'
yield f'verify_case_{(hash(bytes(full_name, "utf-8"))[:8]).hex()}', {
'input': {
'pubkey': encode_hex(pubkey),
'message': encode_hex(message),
'signature': encode_hex(tampered_signature),
},
'output': False,
} }
def case03_private_to_public_key(): def case03_aggregate():
pubkeys = [bls.privtopub(privkey) for privkey in PRIVKEYS] for message in MESSAGES:
pubkeys_serial = ['0x' + pubkey.hex() for pubkey in pubkeys] sigs = [bls.G2ProofOfPossession.Sign(privkey, message) for privkey in PRIVKEYS]
for privkey, pubkey_serial in zip(PRIVKEYS, pubkeys_serial): yield f'aggregate_{encode_hex(message)}', {
yield f'priv_to_pub_{int_to_hex(privkey)}', { 'input': [encode_hex(sig) for sig in sigs],
'input': int_to_hex(privkey), 'output': encode_hex(bls.G2ProofOfPossession.Aggregate(sigs)),
'output': pubkey_serial,
} }
def case04_sign_messages(): def case04_fast_aggregate_verify():
for privkey in PRIVKEYS: for i, message in enumerate(MESSAGES):
for message in MESSAGES: privkeys = PRIVKEYS[:i + 1]
for domain in DOMAINS: sigs = [bls.G2ProofOfPossession.Sign(privkey, message) for privkey in privkeys]
sig = bls.sign(message, privkey, domain) aggregate_signature = bls.G2ProofOfPossession.Aggregate(sigs)
full_name = f'{int_to_hex(privkey)}_{encode_hex(message)}_{encode_hex(domain)}' pubkeys = [bls.G2ProofOfPossession.PrivToPub(privkey) for privkey in privkeys]
yield f'sign_msg_case_{(hash(bytes(full_name, "utf-8"))[:8]).hex()}', { pubkeys_serial = [encode_hex(pubkey) for pubkey in pubkeys]
'input': {
'privkey': int_to_hex(privkey), # Valid signature
'message': encode_hex(message), full_name = f'{pubkeys_serial}_{encode_hex(message)}_valid'
'domain': encode_hex(domain), yield f'fast_aggregate_verify_{(hash(bytes(full_name, "utf-8"))[:8]).hex()}', {
}, 'input': {
'output': encode_hex(sig) 'pubkeys': pubkeys_serial,
} 'message': encode_hex(message),
'signature': encode_hex(aggregate_signature),
},
'output': True,
}
# Invalid signature -- extra pubkey
pubkeys_extra = pubkeys + [bls.G2ProofOfPossession.PrivToPub(PRIVKEYS[-1])]
pubkeys_extra_serial = [encode_hex(pubkey) for pubkey in pubkeys]
full_name = f'{pubkeys_extra_serial}_{encode_hex(message)}_extra_pubkey'
yield f'fast_aggregate_verify_{(hash(bytes(full_name, "utf-8"))[:8]).hex()}', {
'input': {
'pubkeys': pubkeys_extra_serial,
'message': encode_hex(message),
'signature': encode_hex(aggregate_signature),
},
'output': False,
}
# Invalid signature -- tampered with signature
tampered_signature = aggregate_signature[:-4] + b'\xff\xff\xff\xff'
full_name = f'{pubkeys_serial}_{encode_hex(message)}_tampered_signature'
yield f'fast_aggregate_verify_{(hash(bytes(full_name, "utf-8"))[:8]).hex()}', {
'input': {
'pubkeys': pubkeys_serial,
'message': encode_hex(message),
'signature': encode_hex(tampered_signature),
},
'output': False,
}
# TODO: case05_verify_messages: Verify messages signed in case04 def case05_aggregate_verify():
# It takes too long, empty for now pairs = []
sigs = []
for privkey, message in zip(PRIVKEYS, MESSAGES):
sig = bls.G2ProofOfPossession.Sign(privkey, message)
pubkey = bls.G2ProofOfPossession.PrivToPub(privkey)
pairs.append({
'pubkey': encode_hex(pubkey),
'message': encode_hex(message),
})
sigs.append(sig)
aggregate_signature = bls.G2ProofOfPossession.Aggregate(sigs)
def case06_aggregate_sigs(): yield f'fast_aggregate_verify_valid', {
for domain in DOMAINS: 'input': {
for message in MESSAGES: 'pairs': pairs,
sigs = [bls.sign(message, privkey, domain) for privkey in PRIVKEYS] 'signature': encode_hex(aggregate_signature),
yield f'agg_sigs_{encode_hex(message)}_{encode_hex(domain)}', { },
'input': [encode_hex(sig) for sig in sigs], 'output': True,
'output': encode_hex(bls.aggregate_signatures(sigs)),
}
def case07_aggregate_pubkeys():
pubkeys = [bls.privtopub(privkey) for privkey in PRIVKEYS]
pubkeys_serial = [encode_hex(pubkey) for pubkey in pubkeys]
yield f'agg_pub_keys', {
'input': pubkeys_serial,
'output': encode_hex(bls.aggregate_pubkeys(pubkeys)),
} }
tampered_signature = aggregate_signature[:4] + b'\xff\xff\xff\xff'
# TODO yield f'fast_aggregate_verify_tampered_signature', {
# Aggregate verify 'input': {
'pairs': pairs,
# TODO 'signature': encode_hex(tampered_signature),
# Proof-of-possession },
'output': False,
}
def create_provider(handler_name: str, def create_provider(handler_name: str,
@ -195,10 +231,9 @@ def create_provider(handler_name: str,
if __name__ == "__main__": if __name__ == "__main__":
gen_runner.run_generator("bls", [ gen_runner.run_generator("bls", [
create_provider('msg_hash_uncompressed', case01_message_hash_G2_uncompressed), create_provider('sign', case01_sign),
create_provider('msg_hash_compressed', case02_message_hash_G2_compressed), create_provider('verify', case02_verify),
create_provider('priv_to_pub', case03_private_to_public_key), create_provider('aggregate', case03_aggregate),
create_provider('sign_msg', case04_sign_messages), create_provider('fast_aggregate_verify', case04_fast_aggregate_verify),
create_provider('aggregate_sigs', case06_aggregate_sigs), create_provider('aggregate_verify', case05_aggregate_verify),
create_provider('aggregate_pubkeys', case07_aggregate_pubkeys),
]) ])

View File

@ -1,6 +1,6 @@
from ssz_test_case import invalid_test_case, valid_test_case from ssz_test_case import invalid_test_case, valid_test_case
from eth2spec.utils.ssz.ssz_typing import SSZType, Container, byte, uint8, uint16, \ from eth2spec.utils.ssz.ssz_typing import SSZType, Container, byte, uint8, uint16, \
uint32, uint64, List, Bytes, Vector, Bitvector, Bitlist uint32, uint64, List, ByteList, Vector, Bitvector, Bitlist
from eth2spec.utils.ssz.ssz_impl import serialize from eth2spec.utils.ssz.ssz_impl import serialize
from random import Random from random import Random
from typing import Dict, Tuple, Sequence, Callable from typing import Dict, Tuple, Sequence, Callable
@ -32,7 +32,7 @@ class ComplexTestStruct(Container):
A: uint16 A: uint16
B: List[uint16, 128] B: List[uint16, 128]
C: uint8 C: uint8
D: Bytes[256] D: ByteList[256]
E: VarTestStruct E: VarTestStruct
F: Vector[FixedTestStruct, 4] F: Vector[FixedTestStruct, 4]
G: Vector[VarTestStruct, 2] G: Vector[VarTestStruct, 2]