Phase 0 new BLS

This commit is contained in:
Carl Beekhuizen 2019-12-17 12:04:56 +02:00
parent 88e954a9c7
commit 502ee29537
No known key found for this signature in database
GPG Key ID: 8F29E54F49E7AAB5
14 changed files with 136 additions and 322 deletions

View File

@ -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,23 @@ 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,
Verify,
Sign,
Aggregate,
FastAggregateVerify,
bls_aggregate_pubkeys,
bls_verify,
bls_sign,
)
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,
@ -56,10 +59,11 @@ from eth2spec.utils.ssz.ssz_typing import (
uint64, bit, boolean, byte,
)
from eth2spec.utils.bls import (
Verify,
Sign,
Aggregate,
FastAggregateVerify,
bls_aggregate_pubkeys,
bls_verify,
bls_verify_multiple,
bls_signature_to_G2,
)
from eth2spec.utils.hash_function import hash
@ -67,6 +71,7 @@ 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:

View File

@ -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)`.

View File

@ -379,6 +379,14 @@ class BeaconBlockHeader(Container):
body_root: Root
```
#### `DomainWrapper`
```python
class DomainWrapper(Container):
root: Root
domain: Domain
```
### Beacon operations
#### `ProposerSlashing`
@ -575,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).
#### `bls_aggregate_pubkeys`
Specifically, eth2 uses the `BLS_SIG_BLS12381G2-SHA256-SSWU-RO-_POP_` ciphersuite where it makes use of the following functions:
`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).
* `def Sign(SK: int, message: Bytes) -> BLSSignature`
* `def Verify(PK: BLSPubkey, message: Bytes, signature: BLSSignature) -> bool`
* `def Aggregate(signatures: Sequence[BLSSignature]) -> BLSSignature`
* `def bls_aggregate_pubkeys(PKs: Sequence[BLSPubkey]) -> BLSPubkey`
* `def FastAggregateVerify(PKs: Sequence[BLSSignature], message: Bytes, signature: BLSSignature) -> bool`
### Predicates
@ -664,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)
message = compute_domain_wrapper_root(indexed_attestation.data, domain)
return FastAggregateVerify(pubkeys, message, indexed_attestation.signature)
```
#### `is_valid_merkle_branch`
@ -789,6 +797,17 @@ def compute_domain(domain_type: DomainType, fork_version: Version=Version()) ->
return Domain(domain_type + fork_version)
```
### `compute_domain_wrapper_root`
```python
def compute_domain_wrapper_root(object: SSZObject, domain: Domain) -> Root:
domain_wrapped_object = DomainWrapper(
root=hash_tree_root(object),
domain=domain,
)
return hash_tree_root(domain_wrapped_object)
```
### Beacon state accessors
#### `get_current_epoch`
@ -1131,8 +1150,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)
message = compute_domain_wrapper_root(signed_block.message, get_domain(state, DOMAIN_BEACON_PROPOSER))
return Verify(proposer.pubkey, message, signed_block.signature)
```
```python
@ -1431,7 +1450,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))
message = compute_domain_wrapper_root(epoch, get_domain(state, DOMAIN_RANDAO))
assert Verify(proposer.pubkey, message, 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
@ -1478,8 +1498,11 @@ def process_proposer_slashing(state: BeaconState, proposer_slashing: ProposerSla
assert is_slashable_validator(proposer, get_current_epoch(state))
# 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)
message = compute_domain_wrapper_root(
object=signed_header.message,
domain=get_domain(state, DOMAIN_BEACON_PROPOSER, compute_epoch_at_slot(signed_header.message.slot)),
)
assert Verify(proposer.pubkey, message, signed_header.signature)
slash_validator(state, proposer_slashing.proposer_index)
```
@ -1557,12 +1580,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):
message = compute_domain_wrapper_root(deposit_message, compute_domain(DOMAIN_DEPOSIT))
if not Verify(pubkey, message, deposit.data.signature):
return
# Add validator and balance entries
@ -1598,7 +1621,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)
message = compute_domain_wrapper_root(voluntary_exit, domain)
assert Verify(validator.pubkey, message, signed_voluntary_exit.signature)
# Initiate exit
initiate_validator_exit(state, voluntary_exit.validator_index)
```

View File

@ -117,7 +117,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)`. (Deposits are valid regardless of fork version, `compute_domain` will default to zeroes there).
- Let `signature` be the result of `Sign` of the `compute_domain_wrapper_root(deposit_message, domain)` with `domain=compute_domain(DOMAIN_DEPOSIT)`. (Deposits are valid regardless of fork version, `compute_domain` will default to zeroes there).
- 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.
@ -234,7 +234,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)
message = compute_domain_wrapper_root(compute_epoch_at_slot(block.slot), domain)
return Sign(privkey, message)
```
##### Eth1 Data
@ -311,7 +312,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)
message = compute_domain_wrapper_root(compute_epoch_at_slot(header), domain)
return Sign(privkey, message)
```
### Attesting
@ -369,7 +371,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)
message = compute_domain_wrapper_root(attestation.data, domain)
return Sign(privkey, message)
```
#### Broadcast attestation
@ -387,7 +390,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)
message = compute_domain_wrapper_root(slot, domain)
return Sign(privkey, message)
```
```python
@ -418,7 +422,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 Aggregate(signatures)
```
#### Broadcast aggregate

View File

@ -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.bls import Sign, Aggregate
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 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)
message = spec.compute_domain_wrapper_root(attestation_data, domain)
return Sign(privkey, message)
def fill_aggregate_attestation(spec, state, attestation, signed=False):

View File

@ -1,7 +1,7 @@
from copy import deepcopy
from eth2spec.test.helpers.keys import privkeys
from eth2spec.utils.bls import bls_sign, only_with_bls
from eth2spec.utils.bls import Sign, only_with_bls
from eth2spec.utils.ssz.ssz_impl import hash_tree_root
@ -28,15 +28,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))
message = spec.compute_domain_wrapper_root(spec.compute_epoch_at_slot(block.slot), domain)
block.body.randao_reveal = Sign(privkey, message)
# Fully ignore the function if BLS is off, beacon-proposer index calculation is slow.
@ -46,14 +40,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))
message = compute_domain_wrapper_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 = Sign(privkey, message)
def sign_block(spec, state, block, proposer_index=None):

View File

@ -1,4 +1,4 @@
from eth2spec.utils.bls import bls_sign
from eth2spec.utils.bls import Sign
from eth2spec.utils.ssz.ssz_impl import hash_tree_root
@ -7,8 +7,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,
))
message = spec.compute_domain_wrapper_root(header, domain)
signature = Sign(privkey, message)
return spec.SignedBeaconBlockHeader(message=header, signature=signature)

View File

@ -1,5 +1,5 @@
from eth2spec.test.helpers.keys import privkeys
from eth2spec.utils.bls import bls_sign, bls_aggregate_signatures
from eth2spec.utils.bls import Sign, Aggregate
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)
message = spec.compute_domain_wrapper_root(spec.Epoch(epoch), domain)
reveal = Sign(privkeys[revealed_index], message)
# 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])
message = spec.compute_domain_wrapper_root(mask, domain)
masker_signature = Sign(privkeys[masker_index], message)
masked_reveal = 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)
message = spec.compute_domain_wrapper_root(spec.Epoch(epoch_to_sign), domain)
reveal = Sign(privkeys[revealer_index], message)
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)
message = spec.compute_domain_wrapper_root(spec.compute_domain_wrapper_root, domain)
responder_key = Sign(privkeys[responder_index], message)
chunk_count = spec.get_custody_chunk_count(attestation.data.crosslink)

View File

@ -1,5 +1,5 @@
from eth2spec.test.helpers.keys import pubkeys, privkeys
from eth2spec.utils.bls import bls_sign
from eth2spec.utils.bls import Sign
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
@ -30,12 +30,8 @@ def sign_deposit_data(spec, deposit_data, privkey, state=None):
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=domain,
)
deposit_data.signature = signature
message = spec.compute_domain_wrapper_root(deposit_message, domain)
deposit_data.signature = Sign(privkey, message)
def build_deposit(spec,

View File

@ -1,7 +1,7 @@
from eth2spec.test.helpers.keys import privkeys
from eth2spec.utils.bls import (
bls_aggregate_signatures,
bls_sign,
Aggregate,
Sign,
)
@ -25,16 +25,10 @@ def sign_shard_attestation(spec, beacon_state, shard_state, block, participants)
)
)
return bls_aggregate_signatures(signatures)
return 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)
message = spec.compute_domain_wrapper(message_hash, domain)
return Sign(privkey, message)

View File

@ -2,7 +2,7 @@ from copy import deepcopy
from eth2spec.test.helpers.keys import privkeys
from eth2spec.utils.bls import (
bls_sign,
Sign,
only_with_bls,
)
from eth2spec.utils.ssz.ssz_impl import (
@ -21,15 +21,9 @@ def sign_shard_block(spec, beacon_state, shard_state, block, proposer_index=None
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, compute_epoch_of_shard_slot(block.slot))
message = spec.compute_domain_wrapper(block, domain)
block.signature = Sign(privkey, message)
def build_empty_shard_block(spec,

View File

@ -1,17 +1,11 @@
from eth2spec.utils.bls import bls_sign
from eth2spec.utils.bls import Sign
from eth2spec.utils.ssz.ssz_impl import hash_tree_root
def sign_voluntary_exit(spec, state, voluntary_exit, privkey):
domain = spec.get_domain(state, spec.DOMAIN_VOLUNTARY_EXIT, voluntary_exit.epoch)
message = spec.compute_domain_wrapper_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=Sign(privkey, message)
)

View File

@ -1,7 +1,7 @@
from copy import deepcopy
from eth2spec.utils.ssz.ssz_impl import hash_tree_root
from eth2spec.utils.bls import bls_sign
from eth2spec.utils.bls import Sign
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, \
@ -104,15 +104,11 @@ def test_zero_block_sig(spec, state):
@always_bls
def test_invalid_block_sig(spec, 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))
message = spec.compute_domain_wrapper_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=Sign(123456, message)
)
expect_assertion_error(lambda: spec.state_transition(state, invalid_signed_block))
@ -417,16 +413,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)
message = spec.compute_domain_wrapper_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=Sign(privkeys[validator_index], message)
)
# Add to state via block transition

View File

@ -23,31 +23,35 @@ 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(message_hash=message, pubkey=PK, signature=signature, domain=b'')
# @only_with_bls(alt_return=True)
# def AggregateVerify(PKs, messages, signature):
# return bls.verify_multiple(pubkeys=pubkeys, message_hashes=messages, signature=signature, domain=b'')
@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 FastAggregateVerify(PKs, message, signature):
aggregate_pubkey = bls.aggregate_pubkeys(PKs)
return bls.verify(pubkey=aggregate_pubkey, message_hash=message, signature=signature, domain=b'')
@only_with_bls(alt_return=STUB_PUBKEY)
def bls_aggregate_pubkeys(pubkeys):
def bls_aggregate_pubkeys(PKs):
return bls.aggregate_pubkeys(pubkeys)
@only_with_bls(alt_return=STUB_SIGNATURE)
def bls_aggregate_signatures(signatures):
def Aggregate(signatures):
return bls.aggregate_signatures(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(message_hash=message, privkey=SK,
domain=b'')
@only_with_bls(alt_return=STUB_COORDINATES)