Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move BLS extensions to new file in Altair #2438

Merged
merged 4 commits into from
Jun 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 24 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ def floorlog2(x: int) -> uint64:
'''


OPTIMIZED_BLS_AGGREGATE_PUBKEYS = '''
def eth2_aggregate_pubkeys(pubkeys: Sequence[BLSPubkey]) -> BLSPubkey:
return bls.AggregatePKs(pubkeys)
'''


class ProtocolDefinition(NamedTuple):
# just function definitions currently. May expand with configuration vars in future.
functions: Dict[str, str]
Expand Down Expand Up @@ -305,6 +311,11 @@ def invariant_checks(cls) -> str:
"""
raise NotImplementedError()

@classmethod
@abstractmethod
def implement_optimizations(cls, functions: Dict[str, str]) -> Dict[str, str]:
raise NotImplementedError()

@classmethod
@abstractmethod
def build_spec(cls, preset_name: str,
Expand Down Expand Up @@ -429,6 +440,10 @@ def hardcoded_custom_type_dep_constants(cls) -> Dict[str, str]:
def invariant_checks(cls) -> str:
return ''

@classmethod
def implement_optimizations(cls, functions: Dict[str, str]) -> Dict[str, str]:
return functions

@classmethod
def build_spec(cls, preset_name: str,
source_files: Sequence[Path], preset_files: Sequence[Path], config_file: Path) -> str:
Expand Down Expand Up @@ -482,6 +497,11 @@ def invariant_checks(cls) -> str:
TIMELY_HEAD_WEIGHT + TIMELY_SOURCE_WEIGHT + TIMELY_TARGET_WEIGHT + SYNC_REWARD_WEIGHT + PROPOSER_WEIGHT
) == WEIGHT_DENOMINATOR'''

@classmethod
def implement_optimizations(cls, functions: Dict[str, str]) -> Dict[str, str]:
if "eth2_aggregate_pubkeys" in functions:
functions["eth2_aggregate_pubkeys"] = OPTIMIZED_BLS_AGGREGATE_PUBKEYS.strip()
return super().implement_optimizations(functions)

#
# MergeSpecBuilder
Expand Down Expand Up @@ -588,7 +608,8 @@ def format_protocol(protocol_name: str, protocol_def: ProtocolDefinition) -> str
for k in list(spec_object.functions):
if "ceillog2" in k or "floorlog2" in k:
del spec_object.functions[k]
functions_spec = '\n\n\n'.join(spec_object.functions.values())
functions = builder.implement_optimizations(spec_object.functions)
functions_spec = '\n\n\n'.join(functions.values())

# Access global dict of config vars for runtime configurables
for name in spec_object.config_vars.keys():
Expand Down Expand Up @@ -831,7 +852,7 @@ def initialize_options(self):
self.out_dir = 'pyspec_output'
self.build_targets = """
minimal:presets/minimal:configs/minimal.yaml
mainnet:presets/mainnet:configs/mainnet.yaml
mainnet:presets/mainnet:configs/mainnet.yaml
"""

def finalize_options(self):
Expand All @@ -853,6 +874,7 @@ def finalize_options(self):
specs/phase0/validator.md
specs/phase0/weak-subjectivity.md
specs/altair/beacon-chain.md
specs/altair/bls.md
specs/altair/fork.md
specs/altair/validator.md
specs/altair/p2p-interface.md
Expand Down
22 changes: 6 additions & 16 deletions specs/altair/beacon-chain.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@
- [`SyncAggregate`](#syncaggregate)
- [`SyncCommittee`](#synccommittee)
- [Helper functions](#helper-functions)
- [`Predicates`](#predicates)
- [`eth2_fast_aggregate_verify`](#eth2_fast_aggregate_verify)
- [Crypto](#crypto)
- [Misc](#misc-1)
- [`add_flag`](#add_flag)
- [`has_flag`](#has_flag)
Expand Down Expand Up @@ -107,7 +106,6 @@ Altair is the first beacon chain hard fork. Its main features are:

| Name | Value |
| - | - |
| `G2_POINT_AT_INFINITY` | `BLSSignature(b'\xc0' + b'\x00' * 95)` |
| `PARTICIPATION_FLAG_WEIGHTS` | `[TIMELY_SOURCE_WEIGHT, TIMELY_TARGET_WEIGHT, TIMELY_HEAD_WEIGHT]` |

## Preset
Expand Down Expand Up @@ -221,19 +219,11 @@ class SyncCommittee(Container):

## Helper functions

### `Predicates`
### Crypto

#### `eth2_fast_aggregate_verify`

```python
def eth2_fast_aggregate_verify(pubkeys: Sequence[BLSPubkey], message: Bytes32, signature: BLSSignature) -> bool:
"""
Wrapper to ``bls.FastAggregateVerify`` accepting the ``G2_POINT_AT_INFINITY`` signature when ``pubkeys`` is empty.
"""
if len(pubkeys) == 0 and signature == G2_POINT_AT_INFINITY:
return True
return bls.FastAggregateVerify(pubkeys, message, signature)
```
Refer to the definitions in the [phase 0 document regarding BLS signatures](../phase0/beacon-chain.md#bls-signatures)
and the extensions defined in the [Altair BLS document](./bls.md). This specification assumes knowledge of
the functionality described in those documents.

### Misc

Expand Down Expand Up @@ -310,7 +300,7 @@ def get_next_sync_committee(state: BeaconState) -> SyncCommittee:
"""
indices = get_next_sync_committee_indices(state)
pubkeys = [state.validators[index].pubkey for index in indices]
aggregate_pubkey = bls.AggregatePKs(pubkeys)
aggregate_pubkey = eth2_aggregate_pubkeys(pubkeys)
return SyncCommittee(pubkeys=pubkeys, aggregate_pubkey=aggregate_pubkey)
```

Expand Down
65 changes: 65 additions & 0 deletions specs/altair/bls.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Ethereum 2.0 Altair BLS extensions

## Table of contents

<!-- TOC -->
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->

- [Introduction](#introduction)
- [Constants](#constants)
- [Extensions](#extensions)
- [`eth2_aggregate_pubkeys`](#eth2_aggregate_pubkeys)
- [`eth2_fast_aggregate_verify`](#eth2_fast_aggregate_verify)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->
<!-- /TOC -->

## Introduction

A number of extensions are defined to handle BLS signatures in the Altair upgrade.

Knowledge of the [phase 0 specification](../phase0/beacon-chain.md) is assumed, including type definitions.

## Constants

| Name | Value |
| - | - |
| `G2_POINT_AT_INFINITY` | `BLSSignature(b'\xc0' + b'\x00' * 95)` |

## Extensions

### `eth2_aggregate_pubkeys`

An additional function `AggregatePKs` is defined to extend the
[IETF BLS signature draft standard v4](https://tools.ietf.org/html/draft-irtf-cfrg-bls-signature-04)
spec referenced in the phase 0 document.

```python
def eth2_aggregate_pubkeys(pubkeys: Sequence[BLSPubkey]) -> BLSPubkey:
"""
Return the aggregate public key for the public keys in ``pubkeys``.

NOTE: the ``+`` operation should be interpreted as elliptic curve point addition, which takes as input
elliptic curve points that must be decoded from the input ``BLSPubkey``s.
This implementation is for demonstrative purposes only and ignores encoding/decoding concerns.
Refer to the BLS signature draft standard for more information.
"""
assert len(pubkeys) > 0
result = copy(pubkeys[0])
for pubkey in pubkeys[1:]:
result += pubkey
return result
```

### `eth2_fast_aggregate_verify`

```python
def eth2_fast_aggregate_verify(pubkeys: Sequence[BLSPubkey], message: Bytes32, signature: BLSSignature) -> bool:
"""
Wrapper to ``bls.FastAggregateVerify`` accepting the ``G2_POINT_AT_INFINITY`` signature when ``pubkeys`` is empty.
"""
if len(pubkeys) == 0 and signature == G2_POINT_AT_INFINITY:
return True
return bls.FastAggregateVerify(pubkeys, message, signature)
```