Merge pull request #1532 from ethereum/carl_new_new_bls
Yet another attempt at adopting IETF BLS Standards
This commit is contained in:
commit
38f947b0c7
|
@ -35,26 +35,26 @@ commands:
|
|||
description: "Restore the cache with pyspec keys"
|
||||
steps:
|
||||
- restore_cached_venv:
|
||||
venv_name: v4-pyspec
|
||||
venv_name: v5-pyspec
|
||||
reqs_checksum: cache-{{ checksum "test_libs/pyspec/requirements.txt" }}-{{ checksum "test_libs/pyspec/requirements-testing.txt" }}
|
||||
save_pyspec_cached_venv:
|
||||
description: Save a venv into a cache with pyspec keys"
|
||||
steps:
|
||||
- save_cached_venv:
|
||||
venv_name: v4-pyspec
|
||||
venv_name: v5-pyspec
|
||||
reqs_checksum: cache-{{ checksum "test_libs/pyspec/requirements.txt" }}-{{ checksum "test_libs/pyspec/requirements-testing.txt" }}
|
||||
venv_path: ./test_libs/pyspec/venv
|
||||
restore_deposit_contract_cached_venv:
|
||||
description: "Restore the cache with deposit_contract keys"
|
||||
steps:
|
||||
- restore_cached_venv:
|
||||
venv_name: v7-deposit-contract
|
||||
venv_name: v8-deposit-contract
|
||||
reqs_checksum: cache-{{ checksum "test_libs/pyspec/requirements.txt" }}-{{ checksum "deposit_contract/requirements-testing.txt" }}
|
||||
save_deposit_contract_cached_venv:
|
||||
description: Save a venv into a cache with deposit_contract keys"
|
||||
steps:
|
||||
- save_cached_venv:
|
||||
venv_name: v7-deposit-contract
|
||||
venv_name: v8-deposit-contract
|
||||
reqs_checksum: cache-{{ checksum "test_libs/pyspec/requirements.txt" }}-{{ checksum "deposit_contract/requirements-testing.txt" }}
|
||||
venv_path: ./deposit_contract/venv
|
||||
jobs:
|
||||
|
|
|
@ -11,7 +11,7 @@ from typing import (
|
|||
|
||||
|
||||
PHASE0_IMPORTS = '''from typing import (
|
||||
Any, Dict, Set, Sequence, Tuple, Optional
|
||||
Any, Dict, Set, Sequence, Tuple, Optional, TypeVar
|
||||
)
|
||||
|
||||
from dataclasses import (
|
||||
|
@ -21,20 +21,17 @@ from dataclasses import (
|
|||
|
||||
from eth2spec.utils.ssz.ssz_impl import hash_tree_root
|
||||
from eth2spec.utils.ssz.ssz_typing import (
|
||||
boolean, Container, List, Vector, uint64,
|
||||
boolean, Container, List, Vector, uint64, SSZType,
|
||||
Bytes1, Bytes4, Bytes8, Bytes32, Bytes48, Bytes96, Bitlist, Bitvector,
|
||||
)
|
||||
from eth2spec.utils.bls import (
|
||||
bls_aggregate_signatures,
|
||||
bls_aggregate_pubkeys,
|
||||
bls_verify,
|
||||
bls_sign,
|
||||
)
|
||||
from eth2spec.utils import bls
|
||||
|
||||
from eth2spec.utils.hash_function import hash
|
||||
|
||||
SSZObject = TypeVar('SSZObject', bound=SSZType)
|
||||
'''
|
||||
PHASE1_IMPORTS = '''from typing import (
|
||||
Any, Dict, Set, Sequence, MutableSequence, NewType, Tuple, Union,
|
||||
Any, Dict, Set, Sequence, MutableSequence, NewType, Tuple, Union, TypeVar
|
||||
)
|
||||
from math import (
|
||||
log2,
|
||||
|
@ -55,18 +52,14 @@ from eth2spec.utils.ssz.ssz_typing import (
|
|||
Bytes1, Bytes4, Bytes8, Bytes32, Bytes48, Bytes96,
|
||||
uint64, bit, boolean, byte,
|
||||
)
|
||||
from eth2spec.utils.bls import (
|
||||
bls_aggregate_pubkeys,
|
||||
bls_verify,
|
||||
bls_verify_multiple,
|
||||
bls_signature_to_G2,
|
||||
)
|
||||
from eth2spec.utils import bls
|
||||
|
||||
from eth2spec.utils.hash_function import hash
|
||||
|
||||
|
||||
SSZVariableName = str
|
||||
GeneralizedIndex = NewType('GeneralizedIndex', int)
|
||||
SSZObject = TypeVar('SSZObject', bound=SSZType)
|
||||
'''
|
||||
SUNDRY_CONSTANTS_FUNCTIONS = '''
|
||||
def ceillog2(x: uint64) -> int:
|
||||
|
|
|
@ -1,148 +0,0 @@
|
|||
# BLS signature verification
|
||||
|
||||
**Notice**: This document is a placeholder to facilitate the emergence of cross-client testnets. Substantive changes are postponed until [BLS standardisation](https://github.com/cfrg/draft-irtf-cfrg-bls-signature) is finalized.
|
||||
|
||||
**Warning**: The constructions in this document should not be considered secure. In particular, the `hash_to_G2` function is known to be unsecure.
|
||||
|
||||
## 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 -->
|
||||
|
||||
|
||||
- [Curve parameters](#curve-parameters)
|
||||
- [Point representations](#point-representations)
|
||||
- [G1 points](#g1-points)
|
||||
- [G2 points](#g2-points)
|
||||
- [Helpers](#helpers)
|
||||
- [`hash_to_G2`](#hash_to_g2)
|
||||
- [`modular_squareroot`](#modular_squareroot)
|
||||
- [Aggregation operations](#aggregation-operations)
|
||||
- [`bls_aggregate_pubkeys`](#bls_aggregate_pubkeys)
|
||||
- [`bls_aggregate_signatures`](#bls_aggregate_signatures)
|
||||
- [Signature verification](#signature-verification)
|
||||
- [`bls_verify`](#bls_verify)
|
||||
- [`bls_verify_multiple`](#bls_verify_multiple)
|
||||
|
||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||
<!-- /TOC -->
|
||||
|
||||
## Curve parameters
|
||||
|
||||
The BLS12-381 curve parameters are defined [here](https://z.cash/blog/new-snark-curve).
|
||||
|
||||
## Point representations
|
||||
|
||||
We represent points in the groups G1 and G2 following [zkcrypto/pairing](https://github.com/zkcrypto/pairing/tree/master/src/bls12_381). We denote by `q` the field modulus and by `i` the imaginary unit.
|
||||
|
||||
### G1 points
|
||||
|
||||
A point in G1 is represented as a 384-bit integer `z` decomposed as a 381-bit integer `x` and three 1-bit flags in the top bits:
|
||||
|
||||
* `x = z % 2**381`
|
||||
* `a_flag = (z % 2**382) // 2**381`
|
||||
* `b_flag = (z % 2**383) // 2**382`
|
||||
* `c_flag = (z % 2**384) // 2**383`
|
||||
|
||||
Respecting bit ordering, `z` is decomposed as `(c_flag, b_flag, a_flag, x)`.
|
||||
|
||||
We require:
|
||||
|
||||
* `x < q`
|
||||
* `c_flag == 1`
|
||||
* if `b_flag == 1` then `a_flag == x == 0` and `z` represents the point at infinity
|
||||
* if `b_flag == 0` then `z` represents the point `(x, y)` where `y` is the valid coordinate such that `(y * 2) // q == a_flag`
|
||||
|
||||
### G2 points
|
||||
|
||||
A point in G2 is represented as a pair of 384-bit integers `(z1, z2)`. We decompose `z1` as above into `x1`, `a_flag1`, `b_flag1`, `c_flag1` and `z2` into `x2`, `a_flag2`, `b_flag2`, `c_flag2`.
|
||||
|
||||
We require:
|
||||
|
||||
* `x1 < q` and `x2 < q`
|
||||
* `a_flag2 == b_flag2 == c_flag2 == 0`
|
||||
* `c_flag1 == 1`
|
||||
* if `b_flag1 == 1` then `a_flag1 == x1 == x2 == 0` and `(z1, z2)` represents the point at infinity
|
||||
* if `b_flag1 == 0` then `(z1, z2)` represents the point `(x1 * i + x2, y)` where `y` is the valid coordinate such that the imaginary part `y_im` of `y` satisfies `(y_im * 2) // q == a_flag1`
|
||||
|
||||
## Helpers
|
||||
|
||||
### `hash_to_G2`
|
||||
|
||||
```python
|
||||
G2_cofactor = 305502333931268344200999753193121504214466019254188142667664032982267604182971884026507427359259977847832272839041616661285803823378372096355777062779109
|
||||
q = 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787
|
||||
|
||||
def hash_to_G2(message_hash: Bytes32, domain: Bytes8) -> Tuple[uint384, uint384]:
|
||||
# Initial candidate x coordinate
|
||||
x_re = int.from_bytes(hash(message_hash + domain + b'\x01'), 'big')
|
||||
x_im = int.from_bytes(hash(message_hash + domain + b'\x02'), 'big')
|
||||
x_coordinate = Fq2([x_re, x_im]) # x = x_re + i * x_im
|
||||
|
||||
# Test candidate y coordinates until a one is found
|
||||
while 1:
|
||||
y_coordinate_squared = x_coordinate ** 3 + Fq2([4, 4]) # The curve is y^2 = x^3 + 4(i + 1)
|
||||
y_coordinate = modular_squareroot(y_coordinate_squared)
|
||||
if y_coordinate is not None: # Check if quadratic residue found
|
||||
return multiply_in_G2((x_coordinate, y_coordinate), G2_cofactor)
|
||||
x_coordinate += Fq2([1, 0]) # Add 1 and try again
|
||||
```
|
||||
|
||||
### `modular_squareroot`
|
||||
|
||||
`modular_squareroot(x)` returns a solution `y` to `y**2 % q == x`, and `None` if none exists. If there are two solutions, the one with higher imaginary component is favored; if both solutions have equal imaginary component, the one with higher real component is favored (note that this is equivalent to saying that the single solution with either imaginary component > p/2 or imaginary component zero and real component > p/2 is favored).
|
||||
|
||||
The following is a sample implementation; implementers are free to implement modular square roots as they wish. Note that `x2 = -x1` is an _additive modular inverse_ so real and imaginary coefficients remain in `[0 .. q-1]`. `coerce_to_int(element: Fq) -> int` is a function that takes Fq element `element` (i.e. integers `mod q`) and converts it to a regular integer.
|
||||
|
||||
```python
|
||||
Fq2_order = q ** 2 - 1
|
||||
eighth_roots_of_unity = [Fq2([1,1]) ** ((Fq2_order * k) // 8) for k in range(8)]
|
||||
|
||||
def modular_squareroot(value: Fq2) -> Fq2:
|
||||
candidate_squareroot = value ** ((Fq2_order + 8) // 16)
|
||||
check = candidate_squareroot ** 2 / value
|
||||
if check in eighth_roots_of_unity[::2]:
|
||||
x1 = candidate_squareroot / eighth_roots_of_unity[eighth_roots_of_unity.index(check) // 2]
|
||||
x2 = -x1
|
||||
x1_re, x1_im = coerce_to_int(x1.coeffs[0]), coerce_to_int(x1.coeffs[1])
|
||||
x2_re, x2_im = coerce_to_int(x2.coeffs[0]), coerce_to_int(x2.coeffs[1])
|
||||
return x1 if (x1_im > x2_im or (x1_im == x2_im and x1_re > x2_re)) else x2
|
||||
return None
|
||||
```
|
||||
|
||||
## Aggregation operations
|
||||
|
||||
### `bls_aggregate_pubkeys`
|
||||
|
||||
Let `bls_aggregate_pubkeys(pubkeys: List[Bytes48]) -> Bytes48` return `pubkeys[0] + .... + pubkeys[len(pubkeys)-1]`, where `+` is the elliptic curve addition operation over the G1 curve. (When `len(pubkeys) == 0` the empty sum is the G1 point at infinity.)
|
||||
|
||||
### `bls_aggregate_signatures`
|
||||
|
||||
Let `bls_aggregate_signatures(signatures: List[Bytes96]) -> Bytes96` return `signatures[0] + .... + signatures[len(signatures)-1]`, where `+` is the elliptic curve addition operation over the G2 curve. (When `len(signatures) == 0` the empty sum is the G2 point at infinity.)
|
||||
|
||||
## Signature verification
|
||||
|
||||
In the following, `e` is the pairing function and `g` is the G1 generator with the following coordinates (see [here](https://github.com/zkcrypto/pairing/tree/master/src/bls12_381#g1)):
|
||||
|
||||
```python
|
||||
g_x = 3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507
|
||||
g_y = 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569
|
||||
g = Fq2([g_x, g_y])
|
||||
```
|
||||
|
||||
### `bls_verify`
|
||||
|
||||
Let `bls_verify(pubkey: Bytes48, message_hash: Bytes32, signature: Bytes96, domain: Bytes8) -> bool`:
|
||||
|
||||
* Verify that `pubkey` is a valid G1 point.
|
||||
* Verify that `signature` is a valid G2 point.
|
||||
* Verify that `e(pubkey, hash_to_G2(message_hash, domain)) == e(g, signature)`.
|
||||
|
||||
### `bls_verify_multiple`
|
||||
|
||||
Let `bls_verify_multiple(pubkeys: List[Bytes48], message_hashes: List[Bytes32], signature: Bytes96, domain: Bytes8) -> bool`:
|
||||
|
||||
* Verify that each `pubkey` in `pubkeys` is a valid G1 point.
|
||||
* Verify that `signature` is a valid G2 point.
|
||||
* Verify that `len(pubkeys)` equals `len(message_hashes)` and denote the length `L`.
|
||||
* Verify that `e(pubkeys[0], hash_to_G2(message_hashes[0], domain)) * ... * e(pubkeys[L-1], hash_to_G2(message_hashes[L-1], domain)) == e(g, signature)`.
|
|
@ -34,6 +34,7 @@
|
|||
- [`DepositMessage`](#depositmessage)
|
||||
- [`DepositData`](#depositdata)
|
||||
- [`BeaconBlockHeader`](#beaconblockheader)
|
||||
- [`SigningRoot`](#signingroot)
|
||||
- [Beacon operations](#beacon-operations)
|
||||
- [`ProposerSlashing`](#proposerslashing)
|
||||
- [`AttesterSlashing`](#attesterslashing)
|
||||
|
@ -58,8 +59,7 @@
|
|||
- [Crypto](#crypto)
|
||||
- [`hash`](#hash)
|
||||
- [`hash_tree_root`](#hash_tree_root)
|
||||
- [`bls_verify`](#bls_verify)
|
||||
- [`bls_aggregate_pubkeys`](#bls_aggregate_pubkeys)
|
||||
- [BLS Signatures](#bls-signatures)
|
||||
- [Predicates](#predicates)
|
||||
- [`is_active_validator`](#is_active_validator)
|
||||
- [`is_eligible_for_activation_queue`](#is_eligible_for_activation_queue)
|
||||
|
@ -76,6 +76,7 @@
|
|||
- [`compute_start_slot_at_epoch`](#compute_start_slot_at_epoch)
|
||||
- [`compute_activation_exit_epoch`](#compute_activation_exit_epoch)
|
||||
- [`compute_domain`](#compute_domain)
|
||||
- [`compute_signing_root`](#compute_signing_root)
|
||||
- [Beacon state accessors](#beacon-state-accessors)
|
||||
- [`get_current_epoch`](#get_current_epoch)
|
||||
- [`get_previous_epoch`](#get_previous_epoch)
|
||||
|
@ -378,6 +379,14 @@ class BeaconBlockHeader(Container):
|
|||
body_root: Root
|
||||
```
|
||||
|
||||
#### `SigningRoot`
|
||||
|
||||
```python
|
||||
class SigningRoot(Container):
|
||||
object_root: Root
|
||||
domain: Domain
|
||||
```
|
||||
|
||||
### Beacon operations
|
||||
|
||||
#### `ProposerSlashing`
|
||||
|
@ -574,13 +583,17 @@ def bytes_to_int(data: bytes) -> uint64:
|
|||
|
||||
`def hash_tree_root(object: SSZSerializable) -> Root` is a function for hashing objects into a single root by utilizing a hash tree structure, as defined in the [SSZ spec](../simple-serialize.md#merkleization).
|
||||
|
||||
#### `bls_verify`
|
||||
#### BLS Signatures
|
||||
|
||||
`bls_verify` is a function for verifying a BLS signature, as defined in the [BLS Signature spec](../bls_signature.md#bls_verify).
|
||||
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:
|
||||
|
||||
#### `bls_aggregate_pubkeys`
|
||||
- `def Sign(SK: int, message: Bytes) -> BLSSignature`
|
||||
- `def Verify(PK: BLSPubkey, message: Bytes, signature: BLSSignature) -> bool`
|
||||
- `def Aggregate(signatures: Sequence[BLSSignature]) -> BLSSignature`
|
||||
- `def FastAggregateVerify(PKs: Sequence[BLSSignature], message: Bytes, signature: BLSSignature) -> bool`
|
||||
- `def AggregateVerify(pairs: Sequence[PK: BLSSignature, message: Bytes], signature: BLSSignature) -> bool`
|
||||
|
||||
`bls_aggregate_pubkeys` is a function for aggregating multiple BLS public keys into a single aggregate key, as defined in the [BLS Signature spec](../bls_signature.md#bls_aggregate_pubkeys).
|
||||
Within these specifications, BLS signatures are treated as a module for notational clarity, thus to verify a signature `bls.Verify(...)` is used.
|
||||
|
||||
### Predicates
|
||||
|
||||
|
@ -663,14 +676,10 @@ def is_valid_indexed_attestation(state: BeaconState, indexed_attestation: Indexe
|
|||
if not indices == sorted(set(indices)):
|
||||
return False
|
||||
# Verify aggregate signature
|
||||
if not bls_verify(
|
||||
pubkey=bls_aggregate_pubkeys([state.validators[i].pubkey for i in indices]),
|
||||
message_hash=hash_tree_root(indexed_attestation.data),
|
||||
signature=indexed_attestation.signature,
|
||||
domain=get_domain(state, DOMAIN_BEACON_ATTESTER, indexed_attestation.data.target.epoch),
|
||||
):
|
||||
return False
|
||||
return True
|
||||
pubkeys = [state.validators[i].pubkey for i in indices]
|
||||
domain = get_domain(state, DOMAIN_BEACON_ATTESTER, indexed_attestation.data.target.epoch)
|
||||
signing_root = compute_signing_root(indexed_attestation.data, domain)
|
||||
return bls.FastAggregateVerify(pubkeys, signing_root, indexed_attestation.signature)
|
||||
```
|
||||
|
||||
#### `is_valid_merkle_branch`
|
||||
|
@ -788,6 +797,20 @@ def compute_domain(domain_type: DomainType, fork_version: Version=GENESIS_FORK_V
|
|||
return Domain(domain_type + fork_version)
|
||||
```
|
||||
|
||||
### `compute_signing_root`
|
||||
|
||||
```python
|
||||
def compute_signing_root(ssz_object: SSZObject, domain: Domain) -> Root:
|
||||
"""
|
||||
Return the signing root of an object by calculating the root of the object-domain tree.
|
||||
"""
|
||||
domain_wrapped_object = SigningRoot(
|
||||
object_root=hash_tree_root(ssz_object),
|
||||
domain=domain,
|
||||
)
|
||||
return hash_tree_root(domain_wrapped_object)
|
||||
```
|
||||
|
||||
### Beacon state accessors
|
||||
|
||||
#### `get_current_epoch`
|
||||
|
@ -941,11 +964,11 @@ def get_total_active_balance(state: BeaconState) -> Gwei:
|
|||
#### `get_domain`
|
||||
|
||||
```python
|
||||
def get_domain(state: BeaconState, domain_type: DomainType, message_epoch: Epoch=None) -> Domain:
|
||||
def get_domain(state: BeaconState, domain_type: DomainType, epoch: Epoch=None) -> Domain:
|
||||
"""
|
||||
Return the signature domain (fork version concatenated with domain type) of a message.
|
||||
"""
|
||||
epoch = get_current_epoch(state) if message_epoch is None else message_epoch
|
||||
epoch = get_current_epoch(state) if epoch is None else epoch
|
||||
fork_version = state.fork.previous_version if epoch < state.fork.epoch else state.fork.current_version
|
||||
return compute_domain(domain_type, fork_version)
|
||||
```
|
||||
|
@ -1136,8 +1159,8 @@ def state_transition(state: BeaconState, signed_block: SignedBeaconBlock, valida
|
|||
```python
|
||||
def verify_block_signature(state: BeaconState, signed_block: SignedBeaconBlock) -> bool:
|
||||
proposer = state.validators[get_beacon_proposer_index(state)]
|
||||
domain = get_domain(state, DOMAIN_BEACON_PROPOSER)
|
||||
return bls_verify(proposer.pubkey, hash_tree_root(signed_block.message), signed_block.signature, domain)
|
||||
signing_root = compute_signing_root(signed_block.message, get_domain(state, DOMAIN_BEACON_PROPOSER))
|
||||
return bls.Verify(proposer.pubkey, signing_root, signed_block.signature)
|
||||
```
|
||||
|
||||
```python
|
||||
|
@ -1436,7 +1459,8 @@ def process_randao(state: BeaconState, body: BeaconBlockBody) -> None:
|
|||
epoch = get_current_epoch(state)
|
||||
# Verify RANDAO reveal
|
||||
proposer = state.validators[get_beacon_proposer_index(state)]
|
||||
assert bls_verify(proposer.pubkey, hash_tree_root(epoch), body.randao_reveal, get_domain(state, DOMAIN_RANDAO))
|
||||
signing_root = compute_signing_root(epoch, get_domain(state, DOMAIN_RANDAO))
|
||||
assert bls.Verify(proposer.pubkey, signing_root, body.randao_reveal)
|
||||
# Mix in RANDAO reveal
|
||||
mix = xor(get_randao_mix(state, epoch), hash(body.randao_reveal))
|
||||
state.randao_mixes[epoch % EPOCHS_PER_HISTORICAL_VECTOR] = mix
|
||||
|
@ -1484,7 +1508,8 @@ def process_proposer_slashing(state: BeaconState, proposer_slashing: ProposerSla
|
|||
# Signatures are valid
|
||||
for signed_header in (proposer_slashing.signed_header_1, proposer_slashing.signed_header_2):
|
||||
domain = get_domain(state, DOMAIN_BEACON_PROPOSER, compute_epoch_at_slot(signed_header.message.slot))
|
||||
assert bls_verify(proposer.pubkey, hash_tree_root(signed_header.message), signed_header.signature, domain)
|
||||
signing_root = compute_signing_root(signed_header.message, domain)
|
||||
assert bls.Verify(proposer.pubkey, signing_root, signed_header.signature)
|
||||
|
||||
slash_validator(state, proposer_slashing.proposer_index)
|
||||
```
|
||||
|
@ -1562,12 +1587,12 @@ def process_deposit(state: BeaconState, deposit: Deposit) -> None:
|
|||
# Verify the deposit signature (proof of possession) for new validators.
|
||||
# Note: The deposit contract does not check signatures.
|
||||
# Note: Deposits are valid across forks, thus the deposit domain is retrieved directly from `compute_domain`.
|
||||
domain = compute_domain(DOMAIN_DEPOSIT)
|
||||
deposit_message = DepositMessage(
|
||||
pubkey=deposit.data.pubkey,
|
||||
withdrawal_credentials=deposit.data.withdrawal_credentials,
|
||||
amount=deposit.data.amount)
|
||||
if not bls_verify(pubkey, hash_tree_root(deposit_message), deposit.data.signature, domain):
|
||||
signing_root = compute_signing_root(deposit_message, compute_domain(DOMAIN_DEPOSIT))
|
||||
if not bls.Verify(pubkey, signing_root, deposit.data.signature):
|
||||
return
|
||||
|
||||
# Add validator and balance entries
|
||||
|
@ -1603,7 +1628,8 @@ def process_voluntary_exit(state: BeaconState, signed_voluntary_exit: SignedVolu
|
|||
assert get_current_epoch(state) >= validator.activation_epoch + PERSISTENT_COMMITTEE_PERIOD
|
||||
# Verify signature
|
||||
domain = get_domain(state, DOMAIN_VOLUNTARY_EXIT, voluntary_exit.epoch)
|
||||
assert bls_verify(validator.pubkey, hash_tree_root(voluntary_exit), signed_voluntary_exit.signature, domain)
|
||||
signing_root = compute_signing_root(voluntary_exit, domain)
|
||||
assert bls.Verify(validator.pubkey, signing_root, signed_voluntary_exit.signature)
|
||||
# Initiate exit
|
||||
initiate_validator_exit(state, voluntary_exit.validator_index)
|
||||
```
|
||||
|
|
|
@ -353,7 +353,7 @@ def custody_subchunkify(bytez: bytes) -> Sequence[bytes]:
|
|||
|
||||
```python
|
||||
def get_custody_chunk_bit(key: BLSSignature, chunk: bytes) -> bool:
|
||||
full_G2_element = bls_signature_to_G2(key)
|
||||
full_G2_element = bls.signature_to_G2(key)
|
||||
s = full_G2_element[0].coeffs
|
||||
bits = [legendre_bit((i + 1) * s[i % 2] + int.from_bytes(subchunk, "little"), BLS12_381_Q)
|
||||
for i, subchunk in enumerate(custody_subchunkify(chunk))]
|
||||
|
@ -429,16 +429,9 @@ def process_custody_key_reveal(state: BeaconState, reveal: CustodyKeyReveal) ->
|
|||
assert is_slashable_validator(revealer, get_current_epoch(state))
|
||||
|
||||
# Verify signature
|
||||
assert bls_verify(
|
||||
pubkey=revealer.pubkey,
|
||||
message_hash=hash_tree_root(epoch_to_sign),
|
||||
signature=reveal.reveal,
|
||||
domain=get_domain(
|
||||
state=state,
|
||||
domain_type=DOMAIN_RANDAO,
|
||||
message_epoch=epoch_to_sign,
|
||||
),
|
||||
)
|
||||
domain = get_domain(state, DOMAIN_RANDAO, epoch_to_sign)
|
||||
signing_root = compute_signing_root(epoch_to_sign, domain)
|
||||
assert bls.Verify(revealer.pubkey, signing_root, reveal.reveal)
|
||||
|
||||
# Decrement max reveal lateness if response is timely
|
||||
if epoch_to_sign + EPOCHS_PER_CUSTODY_PERIOD >= get_current_epoch(state):
|
||||
|
@ -487,21 +480,10 @@ def process_early_derived_secret_reveal(state: BeaconState, reveal: EarlyDerived
|
|||
# Verify signature correctness
|
||||
masker = state.validators[reveal.masker_index]
|
||||
pubkeys = [revealed_validator.pubkey, masker.pubkey]
|
||||
message_hashes = [
|
||||
hash_tree_root(reveal.epoch),
|
||||
reveal.mask,
|
||||
]
|
||||
|
||||
assert bls_verify_multiple(
|
||||
pubkeys=pubkeys,
|
||||
message_hashes=message_hashes,
|
||||
signature=reveal.reveal,
|
||||
domain=get_domain(
|
||||
state=state,
|
||||
domain_type=DOMAIN_RANDAO,
|
||||
message_epoch=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]]
|
||||
assert bls.AggregateVerify(zip(pubkeys, signing_roots), reveal.reveal)
|
||||
|
||||
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
|
||||
|
@ -598,7 +580,7 @@ def process_bit_challenge(state: BeaconState, challenge: CustodyBitChallenge) ->
|
|||
challenger = state.validators[challenge.challenger_index]
|
||||
domain = get_domain(state, DOMAIN_CUSTODY_BIT_CHALLENGE, get_current_epoch(state))
|
||||
# TODO incorrect hash-tree-root, but this changes with phase 1 PR #1483
|
||||
assert bls_verify(challenger.pubkey, hash_tree_root(challenge), challenge.signature, domain)
|
||||
assert bls.Verify(challenger.pubkey, compute_signing_root(challenge, domain), challenge.signature)
|
||||
# Verify challenger is slashable
|
||||
assert is_slashable_validator(challenger, get_current_epoch(state))
|
||||
# Verify attestation
|
||||
|
@ -622,7 +604,7 @@ def process_bit_challenge(state: BeaconState, challenge: CustodyBitChallenge) ->
|
|||
challenge.responder_index,
|
||||
)
|
||||
domain = get_domain(state, DOMAIN_RANDAO, epoch_to_sign)
|
||||
assert bls_verify(responder.pubkey, hash_tree_root(epoch_to_sign), challenge.responder_key, domain)
|
||||
assert bls.Verify(responder.pubkey, compute_signing_root(epoch_to_sign, domain), challenge.responder_key)
|
||||
# Verify the chunk count
|
||||
chunk_count = get_custody_chunk_count(attestation.data.crosslink)
|
||||
assert chunk_count == len(challenge.chunk_bits)
|
||||
|
|
|
@ -386,7 +386,7 @@ def process_shard_block_header(beacon_state: BeaconState, shard_state: ShardStat
|
|||
assert not proposer.slashed
|
||||
# Verify proposer signature
|
||||
domain = get_domain(beacon_state, DOMAIN_SHARD_PROPOSER, compute_epoch_of_shard_slot(block.slot))
|
||||
assert bls_verify(proposer.pubkey, hash_tree_root(block), block.signature, domain)
|
||||
assert bls.Verify(proposer.pubkey, compute_signing_root(block, domain), block.signature)
|
||||
```
|
||||
|
||||
#### Attestations
|
||||
|
@ -406,8 +406,9 @@ def process_shard_attestations(beacon_state: BeaconState, shard_state: ShardStat
|
|||
assert block.aggregation_bits[i] == 0b0
|
||||
# Verify attester aggregate signature
|
||||
domain = get_domain(beacon_state, DOMAIN_SHARD_ATTESTER, compute_epoch_of_shard_slot(block.slot))
|
||||
message = hash_tree_root(ShardAttestationData(slot=shard_state.slot, parent_root=block.parent_root))
|
||||
assert bls_verify(bls_aggregate_pubkeys(pubkeys), message, block.attestations, domain)
|
||||
shard_attestation_data = ShardAttestationData(slot=shard_state.slot, parent_root=block.parent_root)
|
||||
signing_root = compute_signing_root(shard_attestation_data, domain)
|
||||
assert bls.FastAggregateVerify(pubkeys, signing_root, block.attestations)
|
||||
# Proposer micro-reward
|
||||
proposer_index = get_shard_proposer_index(beacon_state, shard_state.shard, block.slot)
|
||||
reward = attestation_count * get_base_reward(beacon_state, proposer_index) // PROPOSER_REWARD_QUOTIENT
|
||||
|
|
|
@ -135,9 +135,10 @@ def update_memory(memory: LightClientMemory, update: LightClientUpdate) -> None:
|
|||
assert 3 * sum(filter(lambda i: update.aggregation_bits[i], balances)) > 2 * sum(balances)
|
||||
|
||||
# Verify shard attestations
|
||||
pubkey = bls_aggregate_pubkeys(filter(lambda i: update.aggregation_bits[i], pubkeys))
|
||||
pubkeys = filter(lambda i: update.aggregation_bits[i], pubkeys)
|
||||
domain = compute_domain(DOMAIN_SHARD_ATTESTER, update.fork_version)
|
||||
assert bls_verify(pubkey, update.shard_block_root, update.signature, domain)
|
||||
signing_root = compute_signing_root(update.shard_block_root, domain)
|
||||
assert bls.FastAggregateVerify(pubkeys, signing_root, update.signature)
|
||||
|
||||
# Update period committees if entering a new period
|
||||
if next_period == current_period + 1:
|
||||
|
|
|
@ -120,7 +120,7 @@ To submit a deposit:
|
|||
- Set `deposit_data.withdrawal_credentials` to `withdrawal_credentials`.
|
||||
- Set `deposit_data.amount` to `amount`.
|
||||
- Let `deposit_message` be a `DepositMessage` with all the `DepositData` contents except the `signature`.
|
||||
- Let `signature` be the result of `bls_sign` of the `hash_tree_root(deposit_message)` with `domain=compute_domain(DOMAIN_DEPOSIT)`. (_Warning_: Deposits _must_ be signed with `GENESIS_FORK_VERSION`, calling `compute_domain` without a second argument defaults to the correct version).
|
||||
- Let `signature` be the result of `bls.Sign` of the `compute_signing_root(deposit_message, domain)` with `domain=compute_domain(DOMAIN_DEPOSIT)`. (_Warning_: Deposits _must_ be signed with `GENESIS_FORK_VERSION`, calling `compute_domain` without a second argument defaults to the correct version).
|
||||
- Let `deposit_data_root` be `hash_tree_root(deposit_data)`.
|
||||
- Send a transaction on the Ethereum 1.0 chain to `DEPOSIT_CONTRACT_ADDRESS` executing `def deposit(pubkey: bytes[48], withdrawal_credentials: bytes[32], signature: bytes[96], deposit_data_root: bytes32)` along with a deposit of `amount` Gwei.
|
||||
|
||||
|
@ -237,7 +237,8 @@ Set `block.body.randao_reveal = epoch_signature` where `epoch_signature` is obta
|
|||
```python
|
||||
def get_epoch_signature(state: BeaconState, block: BeaconBlock, privkey: int) -> BLSSignature:
|
||||
domain = get_domain(state, DOMAIN_RANDAO, compute_epoch_at_slot(block.slot))
|
||||
return bls_sign(privkey, hash_tree_root(compute_epoch_at_slot(block.slot)), domain)
|
||||
signing_root = compute_signing_root(compute_epoch_at_slot(block.slot), domain)
|
||||
return bls.Sign(privkey, signing_root)
|
||||
```
|
||||
|
||||
##### Eth1 Data
|
||||
|
@ -341,7 +342,8 @@ def compute_new_state_root(state: BeaconState, block: BeaconBlock) -> Root:
|
|||
```python
|
||||
def get_block_signature(state: BeaconState, header: BeaconBlockHeader, privkey: int) -> BLSSignature:
|
||||
domain = get_domain(state, DOMAIN_BEACON_PROPOSER, compute_epoch_at_slot(header.slot))
|
||||
return bls_sign(privkey, hash_tree_root(header), domain)
|
||||
signing_root = compute_signing_root(header, domain)
|
||||
return bls.Sign(privkey, signing_root)
|
||||
```
|
||||
|
||||
### Attesting
|
||||
|
@ -399,7 +401,8 @@ Set `attestation.signature = signed_attestation_data` where `signed_attestation_
|
|||
```python
|
||||
def get_signed_attestation_data(state: BeaconState, attestation: IndexedAttestation, privkey: int) -> BLSSignature:
|
||||
domain = get_domain(state, DOMAIN_BEACON_ATTESTER, attestation.data.target.epoch)
|
||||
return bls_sign(privkey, hash_tree_root(attestation.data), domain)
|
||||
signing_root = compute_signing_root(attestation.data, domain)
|
||||
return bls.Sign(privkey, signing_root)
|
||||
```
|
||||
|
||||
#### Broadcast attestation
|
||||
|
@ -417,7 +420,8 @@ A validator is selected to aggregate based upon the return value of `is_aggregat
|
|||
```python
|
||||
def get_slot_signature(state: BeaconState, slot: Slot, privkey: int) -> BLSSignature:
|
||||
domain = get_domain(state, DOMAIN_BEACON_ATTESTER, compute_epoch_at_slot(slot))
|
||||
return bls_sign(privkey, hash_tree_root(slot), domain)
|
||||
signing_root = compute_signing_root(slot, domain)
|
||||
return bls.Sign(privkey, signing_root)
|
||||
```
|
||||
|
||||
```python
|
||||
|
@ -448,7 +452,7 @@ Set `aggregate_attestation.signature = aggregate_signature` where `aggregate_sig
|
|||
```python
|
||||
def get_aggregate_signature(attestations: Sequence[Attestation]) -> BLSSignature:
|
||||
signatures = [attestation.signature for attestation in attestations]
|
||||
return bls_aggregate_signatures(signatures)
|
||||
return bls.Aggregate(signatures)
|
||||
```
|
||||
|
||||
#### Broadcast aggregate
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
py_ecc==1.7.1
|
||||
py_ecc==2.0.0
|
||||
eth-utils==1.6.0
|
||||
../../test_libs/gen_helpers
|
||||
|
|
|
@ -3,7 +3,7 @@ from typing import List
|
|||
from eth2spec.test.helpers.block import build_empty_block_for_next_slot, transition_unsigned_block, \
|
||||
build_empty_block
|
||||
from eth2spec.test.helpers.keys import privkeys
|
||||
from eth2spec.utils.bls import bls_sign, bls_aggregate_signatures
|
||||
from eth2spec.utils import bls
|
||||
from eth2spec.utils.ssz.ssz_typing import Bitlist
|
||||
|
||||
|
||||
|
@ -77,8 +77,7 @@ def sign_aggregate_attestation(spec, state, attestation_data, participants: List
|
|||
privkey
|
||||
)
|
||||
)
|
||||
|
||||
return bls_aggregate_signatures(signatures)
|
||||
return bls.Aggregate(signatures)
|
||||
|
||||
|
||||
def sign_indexed_attestation(spec, state, indexed_attestation):
|
||||
|
@ -97,15 +96,9 @@ def sign_attestation(spec, state, attestation):
|
|||
|
||||
|
||||
def get_attestation_signature(spec, state, attestation_data, privkey):
|
||||
return bls_sign(
|
||||
message_hash=attestation_data.hash_tree_root(),
|
||||
privkey=privkey,
|
||||
domain=spec.get_domain(
|
||||
state=state,
|
||||
domain_type=spec.DOMAIN_BEACON_ATTESTER,
|
||||
message_epoch=attestation_data.target.epoch,
|
||||
)
|
||||
)
|
||||
domain = spec.get_domain(state, spec.DOMAIN_BEACON_ATTESTER, attestation_data.target.epoch)
|
||||
signing_root = spec.compute_signing_root(attestation_data, domain)
|
||||
return bls.Sign(privkey, signing_root)
|
||||
|
||||
|
||||
def fill_aggregate_attestation(spec, state, attestation, signed=False):
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
from copy import deepcopy
|
||||
|
||||
from eth2spec.test.helpers.keys import privkeys
|
||||
from eth2spec.utils.bls import bls_sign, only_with_bls
|
||||
from eth2spec.utils import bls
|
||||
from eth2spec.utils.bls import only_with_bls
|
||||
from eth2spec.utils.ssz.ssz_impl import hash_tree_root
|
||||
|
||||
|
||||
|
@ -28,15 +29,9 @@ def apply_randao_reveal(spec, state, block, proposer_index=None):
|
|||
proposer_index = get_proposer_index_maybe(spec, state, block.slot, proposer_index)
|
||||
privkey = privkeys[proposer_index]
|
||||
|
||||
block.body.randao_reveal = bls_sign(
|
||||
privkey=privkey,
|
||||
message_hash=hash_tree_root(spec.compute_epoch_at_slot(block.slot)),
|
||||
domain=spec.get_domain(
|
||||
state,
|
||||
message_epoch=spec.compute_epoch_at_slot(block.slot),
|
||||
domain_type=spec.DOMAIN_RANDAO,
|
||||
)
|
||||
)
|
||||
domain = spec.get_domain(state, spec.DOMAIN_RANDAO, spec.compute_epoch_at_slot(block.slot))
|
||||
signing_root = spec.compute_signing_root(spec.compute_epoch_at_slot(block.slot), domain)
|
||||
block.body.randao_reveal = bls.Sign(privkey, signing_root)
|
||||
|
||||
|
||||
# Fully ignore the function if BLS is off, beacon-proposer index calculation is slow.
|
||||
|
@ -46,14 +41,10 @@ def apply_sig(spec, state, signed_block, proposer_index=None):
|
|||
|
||||
proposer_index = get_proposer_index_maybe(spec, state, block.slot, proposer_index)
|
||||
privkey = privkeys[proposer_index]
|
||||
domain = spec.get_domain(state, spec.DOMAIN_BEACON_PROPOSER, spec.compute_epoch_at_slot(block.slot))
|
||||
signing_root = spec.compute_signing_root(block, domain)
|
||||
|
||||
signed_block.signature = bls_sign(
|
||||
message_hash=hash_tree_root(block),
|
||||
privkey=privkey,
|
||||
domain=spec.get_domain(
|
||||
state,
|
||||
spec.DOMAIN_BEACON_PROPOSER,
|
||||
spec.compute_epoch_at_slot(block.slot)))
|
||||
signed_block.signature = bls.Sign(privkey, signing_root)
|
||||
|
||||
|
||||
def sign_block(spec, state, block, proposer_index=None):
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
from eth2spec.utils.bls import bls_sign
|
||||
from eth2spec.utils.ssz.ssz_impl import hash_tree_root
|
||||
from eth2spec.utils import bls
|
||||
|
||||
|
||||
def sign_block_header(spec, state, header, privkey):
|
||||
|
@ -7,8 +6,6 @@ def sign_block_header(spec, state, header, privkey):
|
|||
state=state,
|
||||
domain_type=spec.DOMAIN_BEACON_PROPOSER,
|
||||
)
|
||||
return spec.SignedBeaconBlockHeader(message=header, signature=bls_sign(
|
||||
message_hash=hash_tree_root(header),
|
||||
privkey=privkey,
|
||||
domain=domain,
|
||||
))
|
||||
signing_root = spec.compute_signing_root(header, domain)
|
||||
signature = bls.Sign(privkey, signing_root)
|
||||
return spec.SignedBeaconBlockHeader(message=header, signature=signature)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from eth2spec.test.helpers.keys import privkeys
|
||||
from eth2spec.utils.bls import bls_sign, bls_aggregate_signatures
|
||||
from eth2spec.utils import bls
|
||||
from eth2spec.utils.hash_function import hash
|
||||
from eth2spec.utils.ssz.ssz_typing import Bitlist, ByteVector, Bitvector
|
||||
from eth2spec.utils.ssz.ssz_impl import chunkify, pack, hash_tree_root
|
||||
|
@ -17,28 +17,15 @@ def get_valid_early_derived_secret_reveal(spec, state, epoch=None):
|
|||
epoch = current_epoch + spec.CUSTODY_PERIOD_TO_RANDAO_PADDING
|
||||
|
||||
# Generate the secret that is being revealed
|
||||
reveal = bls_sign(
|
||||
message_hash=hash_tree_root(spec.Epoch(epoch)),
|
||||
privkey=privkeys[revealed_index],
|
||||
domain=spec.get_domain(
|
||||
state=state,
|
||||
domain_type=spec.DOMAIN_RANDAO,
|
||||
message_epoch=epoch,
|
||||
),
|
||||
)
|
||||
domain = spec.get_domain(state, spec.DOMAIN_RANDAO, epoch)
|
||||
signing_root = spec.compute_signing_root(spec.Epoch(epoch), domain)
|
||||
reveal = bls.Sign(privkeys[revealed_index], signing_root)
|
||||
# Generate the mask (any random 32 bytes that don't reveal the masker's secret will do)
|
||||
mask = hash(reveal)
|
||||
# Generate masker's signature on the mask
|
||||
masker_signature = bls_sign(
|
||||
message_hash=mask,
|
||||
privkey=privkeys[masker_index],
|
||||
domain=spec.get_domain(
|
||||
state=state,
|
||||
domain_type=spec.DOMAIN_RANDAO,
|
||||
message_epoch=epoch,
|
||||
),
|
||||
)
|
||||
masked_reveal = bls_aggregate_signatures([reveal, masker_signature])
|
||||
signing_root = spec.compute_signing_root(mask, domain)
|
||||
masker_signature = bls.Sign(privkeys[masker_index], signing_root)
|
||||
masked_reveal = bls.Aggregate([reveal, masker_signature])
|
||||
|
||||
return spec.EarlyDerivedSecretReveal(
|
||||
revealed_index=revealed_index,
|
||||
|
@ -60,15 +47,9 @@ def get_valid_custody_key_reveal(spec, state, period=None):
|
|||
epoch_to_sign = spec.get_randao_epoch_for_custody_period(period, revealer_index)
|
||||
|
||||
# Generate the secret that is being revealed
|
||||
reveal = bls_sign(
|
||||
message_hash=hash_tree_root(spec.Epoch(epoch_to_sign)),
|
||||
privkey=privkeys[revealer_index],
|
||||
domain=spec.get_domain(
|
||||
state=state,
|
||||
domain_type=spec.DOMAIN_RANDAO,
|
||||
message_epoch=epoch_to_sign,
|
||||
),
|
||||
)
|
||||
domain = spec.get_domain(state, spec.DOMAIN_RANDAO, epoch_to_sign)
|
||||
signing_root = spec.compute_signing_root(spec.Epoch(epoch_to_sign), domain)
|
||||
reveal = bls.Sign(privkeys[revealer_index], signing_root)
|
||||
return spec.CustodyKeyReveal(
|
||||
revealer_index=revealer_index,
|
||||
reveal=reveal,
|
||||
|
@ -92,15 +73,9 @@ def get_valid_bit_challenge(spec, state, attestation, invalid_custody_bit=False)
|
|||
responder_index)
|
||||
|
||||
# Generate the responder key
|
||||
responder_key = bls_sign(
|
||||
message_hash=hash_tree_root(spec.Epoch(epoch)),
|
||||
privkey=privkeys[responder_index],
|
||||
domain=spec.get_domain(
|
||||
state=state,
|
||||
domain_type=spec.DOMAIN_RANDAO,
|
||||
message_epoch=epoch,
|
||||
),
|
||||
)
|
||||
domain = spec.get_domain(state, spec.DOMAIN_RANDAO, epoch)
|
||||
signing_root = spec.compute_signing_root(spec.Epoch(epoch), domain)
|
||||
responder_key = bls.Sign(privkeys[responder_index], signing_root)
|
||||
|
||||
chunk_count = spec.get_custody_chunk_count(attestation.data.crosslink)
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
from eth2spec.test.helpers.keys import pubkeys, privkeys
|
||||
from eth2spec.utils.bls import bls_sign
|
||||
from eth2spec.utils import bls
|
||||
from eth2spec.utils.merkle_minimal import calc_merkle_tree_from_leaves, get_merkle_proof
|
||||
from eth2spec.utils.ssz.ssz_impl import hash_tree_root
|
||||
from eth2spec.utils.ssz.ssz_typing import List
|
||||
|
@ -21,12 +21,9 @@ def sign_deposit_data(spec, deposit_data, privkey):
|
|||
pubkey=deposit_data.pubkey,
|
||||
withdrawal_credentials=deposit_data.withdrawal_credentials,
|
||||
amount=deposit_data.amount)
|
||||
signature = bls_sign(
|
||||
message_hash=hash_tree_root(deposit_message),
|
||||
privkey=privkey,
|
||||
domain=spec.compute_domain(spec.DOMAIN_DEPOSIT),
|
||||
)
|
||||
deposit_data.signature = signature
|
||||
domain = spec.compute_domain(spec.DOMAIN_DEPOSIT)
|
||||
signing_root = spec.compute_signing_root(deposit_message, domain)
|
||||
deposit_data.signature = bls.Sign(privkey, signing_root)
|
||||
|
||||
|
||||
def build_deposit(spec,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from py_ecc import bls
|
||||
from py_ecc.bls import G2ProofOfPossession as bls
|
||||
from eth2spec.phase0 import spec
|
||||
|
||||
privkeys = [i + 1 for i in range(spec.SLOTS_PER_EPOCH * 16)]
|
||||
pubkeys = [bls.privtopub(privkey) for privkey in privkeys]
|
||||
pubkeys = [bls.PrivToPub(privkey) for privkey in privkeys]
|
||||
pubkey_to_privkey = {pubkey: privkey for privkey, pubkey in zip(privkeys, pubkeys)}
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
from eth2spec.test.helpers.keys import privkeys
|
||||
from eth2spec.utils.bls import (
|
||||
bls_aggregate_signatures,
|
||||
bls_sign,
|
||||
)
|
||||
from eth2spec.utils import bls
|
||||
|
||||
|
||||
def sign_shard_attestation(spec, beacon_state, shard_state, block, participants):
|
||||
|
@ -24,17 +21,10 @@ def sign_shard_attestation(spec, beacon_state, shard_state, block, participants)
|
|||
privkey,
|
||||
)
|
||||
)
|
||||
|
||||
return bls_aggregate_signatures(signatures)
|
||||
return bls.Aggregate(signatures)
|
||||
|
||||
|
||||
def get_attestation_signature(spec, beacon_state, shard_state, message_hash, block_epoch, privkey):
|
||||
return bls_sign(
|
||||
message_hash=message_hash,
|
||||
privkey=privkey,
|
||||
domain=spec.get_domain(
|
||||
state=beacon_state,
|
||||
domain_type=spec.DOMAIN_SHARD_ATTESTER,
|
||||
message_epoch=block_epoch,
|
||||
)
|
||||
)
|
||||
domain = spec.get_domain(beacon_state, spec.DOMAIN_SHARD_ATTESTER, block_epoch)
|
||||
signing_root = spec.compute_signing_root(message_hash, domain)
|
||||
return bls.Sign(privkey, signing_root)
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
from copy import deepcopy
|
||||
|
||||
from eth2spec.test.helpers.keys import privkeys
|
||||
from eth2spec.utils.bls import (
|
||||
bls_sign,
|
||||
only_with_bls,
|
||||
)
|
||||
from eth2spec.utils import bls
|
||||
from eth2spec.utils.bls import only_with_bls
|
||||
from eth2spec.utils.ssz.ssz_impl import (
|
||||
hash_tree_root,
|
||||
)
|
||||
|
@ -20,16 +18,9 @@ def sign_shard_block(spec, beacon_state, shard_state, block, proposer_index=None
|
|||
proposer_index = spec.get_shard_proposer_index(beacon_state, shard_state.shard, block.slot)
|
||||
|
||||
privkey = privkeys[proposer_index]
|
||||
|
||||
block.signature = bls_sign(
|
||||
message_hash=hash_tree_root(block),
|
||||
privkey=privkey,
|
||||
domain=spec.get_domain(
|
||||
beacon_state,
|
||||
spec.DOMAIN_SHARD_PROPOSER,
|
||||
spec.compute_epoch_of_shard_slot(block.slot),
|
||||
)
|
||||
)
|
||||
domain = spec.get_domain(beacon_state, spec.DOMAIN_SHARD_PROPOSER, spec.compute_epoch_of_shard_slot(block.slot))
|
||||
signing_root = spec.compute_signing_root(block, domain)
|
||||
block.signature = bls.Sign(privkey, signing_root)
|
||||
|
||||
|
||||
def build_empty_shard_block(spec,
|
||||
|
|
|
@ -1,17 +1,10 @@
|
|||
from eth2spec.utils.bls import bls_sign
|
||||
from eth2spec.utils.ssz.ssz_impl import hash_tree_root
|
||||
from eth2spec.utils import bls
|
||||
|
||||
|
||||
def sign_voluntary_exit(spec, state, voluntary_exit, privkey):
|
||||
domain = spec.get_domain(state, spec.DOMAIN_VOLUNTARY_EXIT, voluntary_exit.epoch)
|
||||
signing_root = spec.compute_signing_root(voluntary_exit, domain)
|
||||
return spec.SignedVoluntaryExit(
|
||||
message=voluntary_exit,
|
||||
signature=bls_sign(
|
||||
message_hash=hash_tree_root(voluntary_exit),
|
||||
privkey=privkey,
|
||||
domain=spec.get_domain(
|
||||
state=state,
|
||||
domain_type=spec.DOMAIN_VOLUNTARY_EXIT,
|
||||
message_epoch=voluntary_exit.epoch,
|
||||
)
|
||||
)
|
||||
signature=bls.Sign(privkey, signing_root)
|
||||
)
|
||||
|
|
|
@ -6,7 +6,7 @@ from eth2spec.test.helpers.deposits import (
|
|||
deposit_from_context)
|
||||
from eth2spec.test.helpers.state import get_balance
|
||||
from eth2spec.test.helpers.keys import privkeys, pubkeys
|
||||
from eth2spec.utils.bls import bls_sign
|
||||
from eth2spec.utils import bls
|
||||
|
||||
|
||||
def run_deposit_processing(spec, state, deposit, validator_index, valid=True, effective=True):
|
||||
|
@ -106,14 +106,11 @@ def test_invalid_sig_other_version(spec, state):
|
|||
withdrawal_credentials = spec.BLS_WITHDRAWAL_PREFIX + spec.hash(pubkey)[1:]
|
||||
|
||||
# Go through the effort of manually signing, not something normally done. This sig domain will be invalid.
|
||||
deposit_message = spec.DepositMessage(pubkey=pubkey, withdrawal_credentials=withdrawal_credentials, amount=amount)
|
||||
domain = spec.compute_domain(domain_type=spec.DOMAIN_DEPOSIT, fork_version=spec.Version('0xaabbccdd'))
|
||||
deposit_data = spec.DepositData(
|
||||
pubkey=pubkey, withdrawal_credentials=withdrawal_credentials, amount=amount,
|
||||
signature=bls_sign(
|
||||
message_hash=spec.hash_tree_root(
|
||||
spec.DepositMessage(pubkey=pubkey, withdrawal_credentials=withdrawal_credentials, amount=amount)),
|
||||
privkey=privkey,
|
||||
domain=spec.compute_domain(domain_type=spec.DOMAIN_DEPOSIT, fork_version=spec.Version('0xaabbccdd')),
|
||||
)
|
||||
signature=bls.Sign(privkey, spec.compute_signing_root(deposit_message, domain))
|
||||
)
|
||||
deposit, root, _ = deposit_from_context(spec, [deposit_data], 0)
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
from copy import deepcopy
|
||||
|
||||
from eth2spec.utils.ssz.ssz_impl import hash_tree_root
|
||||
from eth2spec.utils.bls import bls_sign
|
||||
from eth2spec.utils import bls
|
||||
|
||||
from eth2spec.test.helpers.state import get_balance, state_transition_and_sign_block, next_slot
|
||||
from eth2spec.test.helpers.block import build_empty_block_for_next_slot, build_empty_block, sign_block, \
|
||||
|
@ -108,15 +107,11 @@ def test_invalid_block_sig(spec, state):
|
|||
yield 'pre', state
|
||||
|
||||
block = build_empty_block_for_next_slot(spec, state)
|
||||
domain = spec.get_domain(state, spec.DOMAIN_BEACON_PROPOSER, spec.compute_epoch_at_slot(block.slot))
|
||||
signing_root = spec.compute_signing_root(block, domain)
|
||||
invalid_signed_block = spec.SignedBeaconBlock(
|
||||
message=block,
|
||||
signature=bls_sign(
|
||||
message_hash=hash_tree_root(block),
|
||||
privkey=123456,
|
||||
domain=spec.get_domain(
|
||||
state,
|
||||
spec.DOMAIN_BEACON_PROPOSER,
|
||||
spec.compute_epoch_at_slot(block.slot)))
|
||||
signature=bls.Sign(123456, signing_root)
|
||||
)
|
||||
expect_assertion_error(lambda: spec.state_transition(state, invalid_signed_block))
|
||||
|
||||
|
@ -421,16 +416,11 @@ def test_voluntary_exit(spec, state):
|
|||
epoch=spec.get_current_epoch(state),
|
||||
validator_index=validator_index,
|
||||
)
|
||||
domain = spec.get_domain(state, spec.DOMAIN_VOLUNTARY_EXIT)
|
||||
signing_root = spec.compute_signing_root(voluntary_exit, domain)
|
||||
signed_voluntary_exit = spec.SignedVoluntaryExit(
|
||||
message=voluntary_exit,
|
||||
signature=bls_sign(
|
||||
message_hash=hash_tree_root(voluntary_exit),
|
||||
privkey=privkeys[validator_index],
|
||||
domain=spec.get_domain(
|
||||
state=state,
|
||||
domain_type=spec.DOMAIN_VOLUNTARY_EXIT,
|
||||
)
|
||||
)
|
||||
signature=bls.Sign(privkeys[validator_index], signing_root)
|
||||
)
|
||||
|
||||
# Add to state via block transition
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
from py_ecc import bls
|
||||
from py_ecc.bls import G2ProofOfPossession as bls
|
||||
from py_ecc.bls.g2_primatives import signature_to_G2 as _signature_to_G2
|
||||
|
||||
# Flag to make BLS active or not. Used for testing, do not ignore BLS in production unless you know what you are doing.
|
||||
bls_active = True
|
||||
|
||||
STUB_SIGNATURE = b'\x11' * 96
|
||||
STUB_PUBKEY = b'\x22' * 48
|
||||
STUB_COORDINATES = bls.api.signature_to_G2(bls.sign(b"", 0, b"\0" * 8))
|
||||
STUB_COORDINATES = _signature_to_G2(bls.Sign(0, b""))
|
||||
|
||||
|
||||
def only_with_bls(alt_return=None):
|
||||
|
@ -23,33 +24,30 @@ def only_with_bls(alt_return=None):
|
|||
|
||||
|
||||
@only_with_bls(alt_return=True)
|
||||
def bls_verify(pubkey, message_hash, signature, domain):
|
||||
return bls.verify(message_hash=message_hash, pubkey=pubkey,
|
||||
signature=signature, domain=domain)
|
||||
def Verify(PK, message, signature):
|
||||
return bls.Verify(PK, message, signature)
|
||||
|
||||
|
||||
@only_with_bls(alt_return=True)
|
||||
def bls_verify_multiple(pubkeys, message_hashes, signature, domain):
|
||||
return bls.verify_multiple(pubkeys=pubkeys, message_hashes=message_hashes,
|
||||
signature=signature, domain=domain)
|
||||
def AggregateVerify(pairs, signature):
|
||||
return bls.AggregateVerify(pairs, signature)
|
||||
|
||||
|
||||
@only_with_bls(alt_return=STUB_PUBKEY)
|
||||
def bls_aggregate_pubkeys(pubkeys):
|
||||
return bls.aggregate_pubkeys(pubkeys)
|
||||
@only_with_bls(alt_return=True)
|
||||
def FastAggregateVerify(PKs, message, signature):
|
||||
return bls.FastAggregateVerify(PKs, message, signature)
|
||||
|
||||
|
||||
@only_with_bls(alt_return=STUB_SIGNATURE)
|
||||
def bls_aggregate_signatures(signatures):
|
||||
return bls.aggregate_signatures(signatures)
|
||||
def Aggregate(signatures):
|
||||
return bls.Aggregate(signatures)
|
||||
|
||||
|
||||
@only_with_bls(alt_return=STUB_SIGNATURE)
|
||||
def bls_sign(message_hash, privkey, domain):
|
||||
return bls.sign(message_hash=message_hash, privkey=privkey,
|
||||
domain=domain)
|
||||
def Sign(SK, message):
|
||||
return bls.Sign(SK, message)
|
||||
|
||||
|
||||
@only_with_bls(alt_return=STUB_COORDINATES)
|
||||
def bls_signature_to_G2(signature):
|
||||
return bls.api.signature_to_G2(signature)
|
||||
def signature_to_G2(signature):
|
||||
return _signature_to_G2(signature)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
eth-utils>=1.3.0,<2
|
||||
eth-typing>=2.1.0,<3.0.0
|
||||
pycryptodome==3.9.4
|
||||
py_ecc==1.7.1
|
||||
py_ecc==2.0.0
|
||||
dataclasses==0.6
|
||||
ssz==0.1.3
|
||||
|
|
|
@ -8,7 +8,7 @@ setup(
|
|||
"eth-utils>=1.3.0,<2",
|
||||
"eth-typing>=2.1.0,<3.0.0",
|
||||
"pycryptodome==3.9.4",
|
||||
"py_ecc==1.7.1",
|
||||
"py_ecc==2.0.0",
|
||||
"ssz==0.1.3",
|
||||
"dataclasses==0.6",
|
||||
]
|
||||
|
|
Loading…
Reference in New Issue