Update to IETF BLS draft-irtf-cfrg-bls-signature-02

This commit is contained in:
Hsiao-Wei Wang 2020-05-09 11:48:48 +08:00
parent 3a71c6d9bd
commit cdd0ed0f7b
No known key found for this signature in database
GPG Key ID: 95B070122902DEA4
7 changed files with 19 additions and 16 deletions

View File

@ -603,13 +603,13 @@ def bytes_to_int(data: bytes) -> uint64:
#### BLS Signatures #### BLS Signatures
Eth2 makes use of BLS signatures as specified in the [IETF draft BLS specification](https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-00). Specifically, eth2 uses the `BLS_SIG_BLS12381G2-SHA256-SSWU-RO-_POP_` ciphersuite which implements the following interfaces: Eth2 makes use of BLS signatures as specified in the [IETF draft BLS specification](https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-02). Specifically, eth2 uses the `BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_` ciphersuite which implements the following interfaces:
- `def Sign(SK: int, message: Bytes) -> BLSSignature` - `def Sign(SK: int, message: Bytes) -> BLSSignature`
- `def Verify(PK: BLSPubkey, message: Bytes, signature: BLSSignature) -> bool` - `def Verify(PK: BLSPubkey, message: Bytes, signature: BLSSignature) -> bool`
- `def Aggregate(signatures: Sequence[BLSSignature]) -> BLSSignature` - `def Aggregate(signatures: Sequence[BLSSignature]) -> BLSSignature`
- `def FastAggregateVerify(PKs: Sequence[BLSPubkey], message: Bytes, signature: BLSSignature) -> bool` - `def FastAggregateVerify(PKs: Sequence[BLSPubkey], message: Bytes, signature: BLSSignature) -> bool`
- `def AggregateVerify(pairs: Sequence[PK: BLSPubkey, message: Bytes], signature: BLSSignature) -> bool` - `def AggregateVerify(PKs: Sequence[BLSPubkey], message: Sequence[Bytes], signature: BLSSignature) -> bool`
Within these specifications, BLS signatures are treated as a module for notational clarity, thus to verify a signature `bls.Verify(...)` is used. Within these specifications, BLS signatures are treated as a module for notational clarity, thus to verify a signature `bls.Verify(...)` is used.

View File

@ -596,7 +596,7 @@ def is_valid_indexed_attestation(state: BeaconState, indexed_attestation: Indexe
all_signing_roots.append(compute_signing_root(attestation_wrapper, domain)) all_signing_roots.append(compute_signing_root(attestation_wrapper, domain))
else: else:
assert not cbit assert not cbit
return bls.AggregateVerify(zip(all_pubkeys, all_signing_roots), signature=attestation.signature) return bls.AggregateVerify(all_pubkeys, all_signing_roots, signature=attestation.signature)
``` ```
#### `is_shard_attestation` #### `is_shard_attestation`
@ -764,7 +764,7 @@ def apply_shard_transition(state: BeaconState, shard: Shard, transition: ShardTr
for header in headers for header in headers
] ]
# Verify combined proposer signature # Verify combined proposer signature
assert bls.AggregateVerify(zip(pubkeys, signing_roots), signature=transition.proposer_signature_aggregate) assert bls.AggregateVerify(pubkeys, signing_roots, signature=transition.proposer_signature_aggregate)
# Save updated state # Save updated state
state.shard_states[shard] = transition.shard_states[len(transition.shard_states) - 1] state.shard_states[shard] = transition.shard_states[len(transition.shard_states) - 1]

View File

@ -300,7 +300,7 @@ def process_early_derived_secret_reveal(state: BeaconState, reveal: EarlyDerived
domain = get_domain(state, DOMAIN_RANDAO, reveal.epoch) domain = get_domain(state, DOMAIN_RANDAO, reveal.epoch)
signing_roots = [compute_signing_root(root, domain) for root in [hash_tree_root(reveal.epoch), reveal.mask]] signing_roots = [compute_signing_root(root, domain) for root in [hash_tree_root(reveal.epoch), reveal.mask]]
assert bls.AggregateVerify(zip(pubkeys, signing_roots), reveal.reveal) assert bls.AggregateVerify(pubkeys, signing_roots, reveal.reveal)
if reveal.epoch >= get_current_epoch(state) + CUSTODY_PERIOD_TO_RANDAO_PADDING: if reveal.epoch >= get_current_epoch(state) + CUSTODY_PERIOD_TO_RANDAO_PADDING:
# Full slashing when the secret was revealed so early it may be a valid custody # Full slashing when the secret was revealed so early it may be a valid custody

View File

@ -280,7 +280,10 @@ def get_shard_transition(beacon_state: BeaconState,
if proposal.signature != BLSSignature(): if proposal.signature != BLSSignature():
proposer_signatures.append(proposal.signature) proposer_signatures.append(proposal.signature)
proposer_signature_aggregate = bls.Aggregate(proposer_signatures) if len(proposer_signatures) > 0:
proposer_signature_aggregate = bls.Aggregate(proposer_signatures)
else:
proposer_signature_aggregate = BLSSignature()
return ShardTransition( return ShardTransition(
start_slot=start_slot, start_slot=start_slot,

View File

@ -2,5 +2,5 @@ from py_ecc.bls import G2ProofOfPossession as bls
from eth2spec.phase0 import spec from eth2spec.phase0 import spec
privkeys = [i + 1 for i in range(spec.SLOTS_PER_EPOCH * 256)] privkeys = [i + 1 for i in range(spec.SLOTS_PER_EPOCH * 256)]
pubkeys = [bls.PrivToPub(privkey) for privkey in privkeys] pubkeys = [bls.SkToPk(privkey) for privkey in privkeys]
pubkey_to_privkey = {pubkey: privkey for privkey, pubkey in zip(privkeys, pubkeys)} pubkey_to_privkey = {pubkey: privkey for privkey, pubkey in zip(privkeys, pubkeys)}

View File

@ -29,13 +29,13 @@ def Verify(PK, message, signature):
@only_with_bls(alt_return=True) @only_with_bls(alt_return=True)
def AggregateVerify(pairs, signature): def AggregateVerify(pubkeys, messages, signature):
return bls.AggregateVerify(pairs, signature) return bls.AggregateVerify(pubkeys, messages, signature)
@only_with_bls(alt_return=True) @only_with_bls(alt_return=True)
def FastAggregateVerify(PKs, message, signature): def FastAggregateVerify(pubkeys, message, signature):
return bls.FastAggregateVerify(PKs, message, signature) return bls.FastAggregateVerify(pubkeys, message, signature)
@only_with_bls(alt_return=STUB_SIGNATURE) @only_with_bls(alt_return=STUB_SIGNATURE)

View File

@ -69,7 +69,7 @@ def case02_verify():
for message in MESSAGES: for message in MESSAGES:
# Valid signature # Valid signature
signature = bls.G2ProofOfPossession.Sign(privkey, message) signature = bls.G2ProofOfPossession.Sign(privkey, message)
pubkey = bls.G2ProofOfPossession.PrivToPub(privkey) pubkey = bls.G2ProofOfPossession.SkToPk(privkey)
identifier = f'{encode_hex(pubkey)}_{encode_hex(message)}' identifier = f'{encode_hex(pubkey)}_{encode_hex(message)}'
yield f'verify_valid_case_{(hash(bytes(identifier, "utf-8"))[:8]).hex()}', { yield f'verify_valid_case_{(hash(bytes(identifier, "utf-8"))[:8]).hex()}', {
'input': { 'input': {
@ -81,7 +81,7 @@ def case02_verify():
} }
# Invalid signatures -- wrong pubkey # Invalid signatures -- wrong pubkey
wrong_pubkey = bls.G2ProofOfPossession.PrivToPub(PRIVKEYS[(i + 1) % len(PRIVKEYS)]) wrong_pubkey = bls.G2ProofOfPossession.SkToPk(PRIVKEYS[(i + 1) % len(PRIVKEYS)])
identifier = f'{encode_hex(wrong_pubkey)}_{encode_hex(message)}' identifier = f'{encode_hex(wrong_pubkey)}_{encode_hex(message)}'
yield f'verify_wrong_pubkey_case_{(hash(bytes(identifier, "utf-8"))[:8]).hex()}', { yield f'verify_wrong_pubkey_case_{(hash(bytes(identifier, "utf-8"))[:8]).hex()}', {
'input': { 'input': {
@ -119,7 +119,7 @@ def case04_fast_aggregate_verify():
privkeys = PRIVKEYS[:i + 1] privkeys = PRIVKEYS[:i + 1]
sigs = [bls.G2ProofOfPossession.Sign(privkey, message) for privkey in privkeys] sigs = [bls.G2ProofOfPossession.Sign(privkey, message) for privkey in privkeys]
aggregate_signature = bls.G2ProofOfPossession.Aggregate(sigs) aggregate_signature = bls.G2ProofOfPossession.Aggregate(sigs)
pubkeys = [bls.G2ProofOfPossession.PrivToPub(privkey) for privkey in privkeys] pubkeys = [bls.G2ProofOfPossession.SkToPk(privkey) for privkey in privkeys]
pubkeys_serial = [encode_hex(pubkey) for pubkey in pubkeys] pubkeys_serial = [encode_hex(pubkey) for pubkey in pubkeys]
# Valid signature # Valid signature
@ -134,7 +134,7 @@ def case04_fast_aggregate_verify():
} }
# Invalid signature -- extra pubkey # Invalid signature -- extra pubkey
pubkeys_extra = pubkeys + [bls.G2ProofOfPossession.PrivToPub(PRIVKEYS[-1])] pubkeys_extra = pubkeys + [bls.G2ProofOfPossession.SkToPk(PRIVKEYS[-1])]
pubkeys_extra_serial = [encode_hex(pubkey) for pubkey in pubkeys_extra] pubkeys_extra_serial = [encode_hex(pubkey) for pubkey in pubkeys_extra]
identifier = f'{pubkeys_extra_serial}_{encode_hex(message)}' identifier = f'{pubkeys_extra_serial}_{encode_hex(message)}'
yield f'fast_aggregate_verify_extra_pubkey_{(hash(bytes(identifier, "utf-8"))[:8]).hex()}', { yield f'fast_aggregate_verify_extra_pubkey_{(hash(bytes(identifier, "utf-8"))[:8]).hex()}', {
@ -164,7 +164,7 @@ def case05_aggregate_verify():
sigs = [] sigs = []
for privkey, message in zip(PRIVKEYS, MESSAGES): for privkey, message in zip(PRIVKEYS, MESSAGES):
sig = bls.G2ProofOfPossession.Sign(privkey, message) sig = bls.G2ProofOfPossession.Sign(privkey, message)
pubkey = bls.G2ProofOfPossession.PrivToPub(privkey) pubkey = bls.G2ProofOfPossession.SkToPk(privkey)
pairs.append({ pairs.append({
'pubkey': encode_hex(pubkey), 'pubkey': encode_hex(pubkey),
'message': encode_hex(message), 'message': encode_hex(message),