From 41ca149429790fed7464410581c59b38d9b8d2ec Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Mon, 24 May 2021 11:51:08 -0700 Subject: [PATCH 1/4] Explicitly define `bls.AggregatePKs` --- setup.py | 19 +++++++++++++++++-- specs/altair/beacon-chain.md | 30 +++++++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index 8095e3b7f4..d840c34371 100644 --- a/setup.py +++ b/setup.py @@ -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] @@ -305,6 +311,10 @@ def invariant_checks(cls) -> str: """ raise NotImplementedError() + @classmethod + def implement_optimizations(cls, functions: Dict[str, str]) -> Dict[str, str]: + return functions + @classmethod @abstractmethod def build_spec(cls, preset_name: str, @@ -482,6 +492,10 @@ 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: + return {**functions, **{"eth2_aggregate_pubkeys": OPTIMIZED_BLS_AGGREGATE_PUBKEYS.strip()}} # # MergeSpecBuilder @@ -588,7 +602,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(): @@ -831,7 +846,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): diff --git a/specs/altair/beacon-chain.md b/specs/altair/beacon-chain.md index 7412a8490c..cd877161cb 100644 --- a/specs/altair/beacon-chain.md +++ b/specs/altair/beacon-chain.md @@ -26,6 +26,8 @@ - [`SyncAggregate`](#syncaggregate) - [`SyncCommittee`](#synccommittee) - [Helper functions](#helper-functions) + - [Crypto](#crypto) + - [BLS public keys](#bls-public-keys) - [`Predicates`](#predicates) - [`eth2_fast_aggregate_verify`](#eth2_fast_aggregate_verify) - [Misc](#misc-1) @@ -221,6 +223,32 @@ class SyncCommittee(Container): ## Helper functions + +### Crypto + +#### BLS public keys + +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 +``` + ### `Predicates` #### `eth2_fast_aggregate_verify` @@ -310,7 +338,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) ``` From 4d5bc83af429433a8ddd061ae27beca64f761f40 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Thu, 27 May 2021 11:59:02 -0700 Subject: [PATCH 2/4] Re-org files --- specs/altair/beacon-chain.md | 44 ++---------------------- specs/altair/bls.md | 65 ++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 41 deletions(-) create mode 100644 specs/altair/bls.md diff --git a/specs/altair/beacon-chain.md b/specs/altair/beacon-chain.md index cd877161cb..2ac1d18891 100644 --- a/specs/altair/beacon-chain.md +++ b/specs/altair/beacon-chain.md @@ -27,9 +27,6 @@ - [`SyncCommittee`](#synccommittee) - [Helper functions](#helper-functions) - [Crypto](#crypto) - - [BLS public keys](#bls-public-keys) - - [`Predicates`](#predicates) - - [`eth2_fast_aggregate_verify`](#eth2_fast_aggregate_verify) - [Misc](#misc-1) - [`add_flag`](#add_flag) - [`has_flag`](#has_flag) @@ -109,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 @@ -223,45 +219,11 @@ class SyncCommittee(Container): ## Helper functions - ### Crypto -#### BLS public keys - -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 -``` - -### `Predicates` - -#### `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 diff --git a/specs/altair/bls.md b/specs/altair/bls.md new file mode 100644 index 0000000000..5292360561 --- /dev/null +++ b/specs/altair/bls.md @@ -0,0 +1,65 @@ +# Ethereum 2.0 Altair BLS extensions + +## Table of contents + + + + + +- [Introduction](#introduction) +- [Constants](#constants) +- [Extensions](#extensions) + - [`eth2_aggregate_pubkeys`](#eth2_aggregate_pubkeys) + - [`eth2_fast_aggregate_verify`](#eth2_fast_aggregate_verify) + + + + +## 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) +``` From 7a14e93c655da9c00669af9cbb37efef4326cea8 Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Thu, 27 May 2021 12:02:44 -0700 Subject: [PATCH 3/4] PR feedback --- setup.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index d840c34371..5384b1a704 100644 --- a/setup.py +++ b/setup.py @@ -312,8 +312,9 @@ def invariant_checks(cls) -> str: raise NotImplementedError() @classmethod + @abstractmethod def implement_optimizations(cls, functions: Dict[str, str]) -> Dict[str, str]: - return functions + raise NotImplementedError() @classmethod @abstractmethod @@ -439,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: From 6ecbc5e357a39b830ed71d8e5848c6bee1b1de9b Mon Sep 17 00:00:00 2001 From: Alex Stokes Date: Thu, 27 May 2021 12:21:04 -0700 Subject: [PATCH 4/4] Add new file to spec infra --- setup.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 5384b1a704..81a07f20f6 100644 --- a/setup.py +++ b/setup.py @@ -500,7 +500,8 @@ def invariant_checks(cls) -> str: @classmethod def implement_optimizations(cls, functions: Dict[str, str]) -> Dict[str, str]: if "eth2_aggregate_pubkeys" in functions: - return {**functions, **{"eth2_aggregate_pubkeys": OPTIMIZED_BLS_AGGREGATE_PUBKEYS.strip()}} + functions["eth2_aggregate_pubkeys"] = OPTIMIZED_BLS_AGGREGATE_PUBKEYS.strip() + return super().implement_optimizations(functions) # # MergeSpecBuilder @@ -873,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