Merge branch 'dev' into last-minute-cleanups-2

This commit is contained in:
Hsiao-Wei Wang 2019-07-01 09:36:13 +08:00
commit 83a68feac6
No known key found for this signature in database
GPG Key ID: 95B070122902DEA4
14 changed files with 73 additions and 44 deletions

View File

@ -117,9 +117,9 @@ MAX_TRANSFERS: 0
# Signature domains # Signature domains
# --------------------------------------------------------------- # ---------------------------------------------------------------
DOMAIN_BEACON_PROPOSER: 0 DOMAIN_BEACON_PROPOSER: 0x00000000
DOMAIN_RANDAO: 1 DOMAIN_RANDAO: 0x01000000
DOMAIN_ATTESTATION: 2 DOMAIN_ATTESTATION: 0x02000000
DOMAIN_DEPOSIT: 3 DOMAIN_DEPOSIT: 0x03000000
DOMAIN_VOLUNTARY_EXIT: 4 DOMAIN_VOLUNTARY_EXIT: 0x04000000
DOMAIN_TRANSFER: 5 DOMAIN_TRANSFER: 0x05000000

View File

@ -118,9 +118,9 @@ MAX_TRANSFERS: 0
# Signature domains # Signature domains
# --------------------------------------------------------------- # ---------------------------------------------------------------
DOMAIN_BEACON_PROPOSER: 0 DOMAIN_BEACON_PROPOSER: 0x00000000
DOMAIN_RANDAO: 1 DOMAIN_RANDAO: 0x01000000
DOMAIN_ATTESTATION: 2 DOMAIN_ATTESTATION: 0x02000000
DOMAIN_DEPOSIT: 3 DOMAIN_DEPOSIT: 0x03000000
DOMAIN_VOLUNTARY_EXIT: 4 DOMAIN_VOLUNTARY_EXIT: 0x04000000
DOMAIN_TRANSFER: 5 DOMAIN_TRANSFER: 0x05000000

View File

@ -25,7 +25,7 @@ from eth2spec.utils.ssz.ssz_impl import (
) )
from eth2spec.utils.ssz.ssz_typing import ( from eth2spec.utils.ssz.ssz_typing import (
bit, boolean, Container, List, Vector, uint64, bit, boolean, Container, List, Vector, uint64,
Bytes1, Bytes4, Bytes32, Bytes48, Bytes96, Bitlist, Bitvector, Bytes1, Bytes4, Bytes8, Bytes32, Bytes48, Bytes96, Bitlist, Bitvector,
) )
from eth2spec.utils.bls import ( from eth2spec.utils.bls import (
bls_aggregate_pubkeys, bls_aggregate_pubkeys,
@ -52,7 +52,7 @@ from eth2spec.utils.ssz.ssz_impl import (
) )
from eth2spec.utils.ssz.ssz_typing import ( from eth2spec.utils.ssz.ssz_typing import (
bit, boolean, Container, List, Vector, Bytes, uint64, bit, boolean, Container, List, Vector, Bytes, uint64,
Bytes1, Bytes4, Bytes32, Bytes48, Bytes96, Bitlist, Bitvector, Bytes1, Bytes4, Bytes8, Bytes32, Bytes48, Bytes96, Bitlist, Bitvector,
) )
from eth2spec.utils.bls import ( from eth2spec.utils.bls import (
bls_aggregate_pubkeys, bls_aggregate_pubkeys,
@ -94,7 +94,10 @@ def compute_committee(indices: Sequence[ValidatorIndex], # type: ignore
def apply_constants_preset(preset: Dict[str, Any]) -> None: def apply_constants_preset(preset: Dict[str, Any]) -> None:
global_vars = globals() global_vars = globals()
for k, v in preset.items(): for k, v in preset.items():
global_vars[k] = v if k.startswith('DOMAIN_'):
global_vars[k] = DomainType(v) # domain types are defined as bytes in the configs
else:
global_vars[k] = v
# Deal with derived constants # Deal with derived constants
global_vars['GENESIS_EPOCH'] = compute_epoch_of_slot(GENESIS_SLOT) global_vars['GENESIS_EPOCH'] = compute_epoch_of_slot(GENESIS_SLOT)
@ -135,6 +138,9 @@ def objects_to_spec(functions: Dict[str, str],
) )
) )
functions_spec = '\n\n'.join(functions.values()) functions_spec = '\n\n'.join(functions.values())
for k in list(constants.keys()):
if k.startswith('DOMAIN_'):
constants[k] = f"DomainType(({constants[k]}).to_bytes(length=4, byteorder='little'))"
constants_spec = '\n'.join(map(lambda x: '%s = %s' % (x, constants[x]), constants)) constants_spec = '\n'.join(map(lambda x: '%s = %s' % (x, constants[x]), constants))
ssz_objects_instantiation_spec = '\n\n'.join(ssz_objects.values()) ssz_objects_instantiation_spec = '\n\n'.join(ssz_objects.values())
ssz_objects_reinitialization_spec = ( ssz_objects_reinitialization_spec = (

View File

@ -71,10 +71,10 @@ We require:
G2_cofactor = 305502333931268344200999753193121504214466019254188142667664032982267604182971884026507427359259977847832272839041616661285803823378372096355777062779109 G2_cofactor = 305502333931268344200999753193121504214466019254188142667664032982267604182971884026507427359259977847832272839041616661285803823378372096355777062779109
q = 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787 q = 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787
def hash_to_G2(message_hash: Bytes32, domain: uint64) -> Tuple[uint384, uint384]: def hash_to_G2(message_hash: Bytes32, domain: Bytes8) -> Tuple[uint384, uint384]:
# Initial candidate x coordinate # Initial candidate x coordinate
x_re = int.from_bytes(hash(message_hash + bytes8(domain) + b'\x01'), 'big') x_re = int.from_bytes(hash(message_hash + domain + b'\x01'), 'big')
x_im = int.from_bytes(hash(message_hash + bytes8(domain) + b'\x02'), '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 x_coordinate = Fq2([x_re, x_im]) # x = x_re + i * x_im
# Test candidate y coordinates until a one is found # Test candidate y coordinates until a one is found
@ -130,7 +130,7 @@ g = Fq2([g_x, g_y])
### `bls_verify` ### `bls_verify`
Let `bls_verify(pubkey: Bytes48, message_hash: Bytes32, signature: Bytes96, domain: uint64) -> bool`: Let `bls_verify(pubkey: Bytes48, message_hash: Bytes32, signature: Bytes96, domain: Bytes8) -> bool`:
* Verify that `pubkey` is a valid G1 point. * Verify that `pubkey` is a valid G1 point.
* Verify that `signature` is a valid G2 point. * Verify that `signature` is a valid G2 point.
@ -138,7 +138,7 @@ Let `bls_verify(pubkey: Bytes48, message_hash: Bytes32, signature: Bytes96, doma
### `bls_verify_multiple` ### `bls_verify_multiple`
Let `bls_verify_multiple(pubkeys: List[Bytes48], message_hashes: List[Bytes32], signature: Bytes96, domain: uint64) -> bool`: 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 each `pubkey` in `pubkeys` is a valid G1 point.
* Verify that `signature` is a valid G2 point. * Verify that `signature` is a valid G2 point.

View File

@ -19,7 +19,7 @@
- [State list lengths](#state-list-lengths) - [State list lengths](#state-list-lengths)
- [Rewards and penalties](#rewards-and-penalties) - [Rewards and penalties](#rewards-and-penalties)
- [Max operations per block](#max-operations-per-block) - [Max operations per block](#max-operations-per-block)
- [Signature domains](#signature-domains) - [Signature domain types](#signature-domain-types)
- [Containers](#containers) - [Containers](#containers)
- [Misc dependencies](#misc-dependencies) - [Misc dependencies](#misc-dependencies)
- [`Fork`](#fork) - [`Fork`](#fork)
@ -147,8 +147,10 @@ We define the following Python custom types for type hinting and readability:
| `Shard` | `uint64` | a shard number | | `Shard` | `uint64` | a shard number |
| `ValidatorIndex` | `uint64` | a validator registry index | | `ValidatorIndex` | `uint64` | a validator registry index |
| `Gwei` | `uint64` | an amount in Gwei | | `Gwei` | `uint64` | an amount in Gwei |
| `Version` | `Bytes4` | a fork version number |
| `Hash` | `Bytes32` | a hash | | `Hash` | `Bytes32` | a hash |
| `Version` | `Bytes4` | a fork version number |
| `DomainType` | `Bytes4` | a signature domain type |
| `Domain` | `Bytes8` | a signature domain |
| `BLSPubkey` | `Bytes48` | a BLS12-381 public key | | `BLSPubkey` | `Bytes48` | a BLS12-381 public key |
| `BLSSignature` | `Bytes96` | a BLS12-381 signature | | `BLSSignature` | `Bytes96` | a BLS12-381 signature |
@ -248,7 +250,9 @@ The following values are (non-configurable) constants used throughout the specif
| `MAX_VOLUNTARY_EXITS` | `2**4` (= 16) | | `MAX_VOLUNTARY_EXITS` | `2**4` (= 16) |
| `MAX_TRANSFERS` | `0` | | `MAX_TRANSFERS` | `0` |
### Signature domains ### Signature domain types
The following types are defined, mapping into `DomainType` (little endian):
| Name | Value | | Name | Value |
| - | - | | - | - |
@ -513,6 +517,7 @@ class BeaconState(Container):
# Shuffling # Shuffling
start_shard: Shard start_shard: Shard
randao_mixes: Vector[Hash, EPOCHS_PER_HISTORICAL_VECTOR] randao_mixes: Vector[Hash, EPOCHS_PER_HISTORICAL_VECTOR]
active_index_roots: Vector[Hash, EPOCHS_PER_HISTORICAL_VECTOR] # Active index digests for light clients
compact_committees_roots: Vector[Hash, EPOCHS_PER_HISTORICAL_VECTOR] # Committee digests for light clients compact_committees_roots: Vector[Hash, EPOCHS_PER_HISTORICAL_VECTOR] # Committee digests for light clients
# Slashings # Slashings
slashings: Vector[Gwei, EPOCHS_PER_SLASHINGS_VECTOR] # Per-epoch sums of slashed effective balances slashings: Vector[Gwei, EPOCHS_PER_SLASHINGS_VECTOR] # Per-epoch sums of slashed effective balances
@ -771,11 +776,11 @@ def compute_activation_exit_epoch(epoch: Epoch) -> Epoch:
#### `compute_domain` #### `compute_domain`
```python ```python
def compute_domain(domain_type: uint64, fork_version: Version=Version()) -> int: def compute_domain(domain_type: DomainType, fork_version: Version=Version()) -> Domain:
""" """
Return the domain for the ``domain_type`` and ``fork_version``. Return the domain for the ``domain_type`` and ``fork_version``.
""" """
return bytes_to_int(int_to_bytes(domain_type, length=4) + fork_version) return Domain(domain_type + fork_version)
``` ```
### Beacon state accessors ### Beacon state accessors
@ -861,9 +866,8 @@ def get_seed(state: BeaconState, epoch: Epoch) -> Hash:
Return the seed at ``epoch``. Return the seed at ``epoch``.
""" """
mix = get_randao_mix(state, Epoch(epoch + EPOCHS_PER_HISTORICAL_VECTOR - MIN_SEED_LOOKAHEAD)) # Avoid underflow mix = get_randao_mix(state, Epoch(epoch + EPOCHS_PER_HISTORICAL_VECTOR - MIN_SEED_LOOKAHEAD)) # Avoid underflow
active_indices = get_active_validator_indices(state, epoch) active_index_root = state.active_index_roots[epoch % EPOCHS_PER_HISTORICAL_VECTOR]
active_indices_root = hash_tree_root(List[ValidatorIndex, VALIDATOR_REGISTRY_LIMIT](active_indices)) return hash(mix + active_index_root + int_to_bytes(epoch, length=32))
return hash(mix + active_indices_root + int_to_bytes(epoch, length=32))
``` ```
#### `get_committee_count` #### `get_committee_count`
@ -1001,7 +1005,7 @@ def get_total_active_balance(state: BeaconState) -> Gwei:
#### `get_domain` #### `get_domain`
```python ```python
def get_domain(state: BeaconState, domain_type: uint64, message_epoch: Epoch=None) -> int: def get_domain(state: BeaconState, domain_type: DomainType, message_epoch: Epoch=None) -> Domain:
""" """
Return the signature domain (fork version concatenated with domain type) of a message. Return the signature domain (fork version concatenated with domain type) of a message.
""" """
@ -1149,9 +1153,12 @@ def initialize_beacon_state_from_eth1(eth1_block_hash: Hash,
validator.activation_eligibility_epoch = GENESIS_EPOCH validator.activation_eligibility_epoch = GENESIS_EPOCH
validator.activation_epoch = GENESIS_EPOCH validator.activation_epoch = GENESIS_EPOCH
# Populate compact_committees_roots # Populate active_index_roots and compact_committees_roots
indices_list = List[ValidatorIndex, VALIDATOR_REGISTRY_LIMIT](get_active_validator_indices(state, GENESIS_EPOCH))
active_index_root = hash_tree_root(indices_list)
committee_root = get_compact_committees_root(state, GENESIS_EPOCH) committee_root = get_compact_committees_root(state, GENESIS_EPOCH)
for index in range(EPOCHS_PER_HISTORICAL_VECTOR): for index in range(EPOCHS_PER_HISTORICAL_VECTOR):
state.active_index_roots[index] = active_index_root
state.compact_committees_roots[index] = committee_root state.compact_committees_roots[index] = committee_root
return state return state
``` ```
@ -1495,7 +1502,12 @@ def process_final_updates(state: BeaconState) -> None:
# Update start shard # Update start shard
state.start_shard = Shard((state.start_shard + get_shard_delta(state, current_epoch)) % SHARD_COUNT) state.start_shard = Shard((state.start_shard + get_shard_delta(state, current_epoch)) % SHARD_COUNT)
# Set active index root # Set active index root
committee_root_position = (next_epoch + ACTIVATION_EXIT_DELAY) % EPOCHS_PER_HISTORICAL_VECTOR index_epoch = Epoch(next_epoch + ACTIVATION_EXIT_DELAY)
index_root_position = index_epoch % EPOCHS_PER_HISTORICAL_VECTOR
indices_list = List[ValidatorIndex, VALIDATOR_REGISTRY_LIMIT](get_active_validator_indices(state, index_epoch))
state.active_index_roots[index_root_position] = hash_tree_root(indices_list)
# Set committees root
committee_root_position = next_epoch % EPOCHS_PER_HISTORICAL_VECTOR
state.compact_committees_roots[committee_root_position] = get_compact_committees_root(state, next_epoch) state.compact_committees_roots[committee_root_position] = get_compact_committees_root(state, next_epoch)
# Reset slashings # Reset slashings
state.slashings[next_epoch % EPOCHS_PER_SLASHINGS_VECTOR] = Gwei(0) state.slashings[next_epoch % EPOCHS_PER_SLASHINGS_VECTOR] = Gwei(0)

View File

@ -109,7 +109,9 @@ This document details the beacon chain additions and changes in Phase 1 of Ether
| - | - | | - | - |
| `EARLY_DERIVED_SECRET_REVEAL_SLOT_REWARD_MULTIPLE` | `2**1` (= 2) | | `EARLY_DERIVED_SECRET_REVEAL_SLOT_REWARD_MULTIPLE` | `2**1` (= 2) |
### Signature domains ### Signature domain types
The following types are defined, mapping into `DomainType` (little endian):
| Name | Value | | Name | Value |
| - | - | | - | - |

View File

@ -63,7 +63,9 @@ This document describes the shard data layer and the shard fork choice rule in P
| `CROSSLINK_LOOKBACK` | `2**0` (= 1) | epochs | 6.2 minutes | | `CROSSLINK_LOOKBACK` | `2**0` (= 1) | epochs | 6.2 minutes |
| `PERSISTENT_COMMITTEE_PERIOD` | `2**11` (= 2,048) | epochs | ~9 days | | `PERSISTENT_COMMITTEE_PERIOD` | `2**11` (= 2,048) | epochs | ~9 days |
### Signature domains ### Signature domain types
The following types are defined, mapping into `DomainType` (little endian):
| Name | Value | | Name | Value |
| - | - | | - | - |

View File

@ -5,9 +5,9 @@ A BLS compressed-hash to G2.
## Test case format ## Test case format
```yaml ```yaml
input: input:
message: bytes32, message: bytes32
domain: uint64 -- the domain domain: bytes8 -- the BLS domain
output: List[bytes48] -- length of two output: List[bytes48] -- length of two
``` ```

View File

@ -7,7 +7,7 @@ A BLS uncompressed-hash to G2.
```yaml ```yaml
input: input:
message: bytes32 message: bytes32
domain: uint64 -- the domain domain: bytes8 -- the BLS domain
output: List[List[bytes48]] -- 3 lists, each a length of two output: List[List[bytes48]] -- 3 lists, each a length of two
``` ```

View File

@ -8,7 +8,7 @@ Message signing with BLS should produce a signature.
input: input:
privkey: bytes32 -- the private key used for signing privkey: bytes32 -- the private key used for signing
message: bytes32 -- input message to sign (a hash) message: bytes32 -- input message to sign (a hash)
domain: uint64 -- the domain domain: bytes8 -- the BLS domain
output: bytes96 -- expected signature output: bytes96 -- expected signature
``` ```

View File

@ -89,7 +89,7 @@ def case01_message_hash_G2_uncompressed():
yield { yield {
'input': { 'input': {
'message': '0x' + msg.hex(), 'message': '0x' + msg.hex(),
'domain': domain 'domain': int_to_hex(domain, byte_length=8)
}, },
'output': hash_message(msg, domain) 'output': hash_message(msg, domain)
} }
@ -101,7 +101,7 @@ def case02_message_hash_G2_compressed():
yield { yield {
'input': { 'input': {
'message': '0x' + msg.hex(), 'message': '0x' + msg.hex(),
'domain': domain 'domain': int_to_hex(domain, byte_length=8)
}, },
'output': hash_message_compressed(msg, domain) 'output': hash_message_compressed(msg, domain)
} }
@ -126,7 +126,7 @@ def case04_sign_messages():
'input': { 'input': {
'privkey': int_to_hex(privkey), 'privkey': int_to_hex(privkey),
'message': '0x' + message.hex(), 'message': '0x' + message.hex(),
'domain': domain 'domain': int_to_hex(domain, byte_length=8)
}, },
'output': '0x' + sig.hex() 'output': '0x' + sig.hex()
} }

View File

@ -43,9 +43,12 @@ def create_genesis_state(spec, num_validators):
validator.activation_eligibility_epoch = spec.GENESIS_EPOCH validator.activation_eligibility_epoch = spec.GENESIS_EPOCH
validator.activation_epoch = spec.GENESIS_EPOCH validator.activation_epoch = spec.GENESIS_EPOCH
genesis_active_index_root = hash_tree_root(List[spec.ValidatorIndex, spec.VALIDATOR_REGISTRY_LIMIT](
spec.get_active_validator_indices(state, spec.GENESIS_EPOCH)))
genesis_compact_committees_root = hash_tree_root(List[spec.ValidatorIndex, spec.VALIDATOR_REGISTRY_LIMIT]( genesis_compact_committees_root = hash_tree_root(List[spec.ValidatorIndex, spec.VALIDATOR_REGISTRY_LIMIT](
spec.get_active_validator_indices(state, spec.GENESIS_EPOCH))) spec.get_active_validator_indices(state, spec.GENESIS_EPOCH)))
for index in range(spec.EPOCHS_PER_HISTORICAL_VECTOR): for index in range(spec.EPOCHS_PER_HISTORICAL_VECTOR):
state.active_index_roots[index] = genesis_active_index_root
state.compact_committees_roots[index] = genesis_compact_committees_root state.compact_committees_roots[index] = genesis_compact_committees_root
return state return state

View File

@ -23,12 +23,14 @@ def only_with_bls(alt_return=None):
@only_with_bls(alt_return=True) @only_with_bls(alt_return=True)
def bls_verify(pubkey, message_hash, signature, domain): def bls_verify(pubkey, message_hash, signature, domain):
return bls.verify(message_hash=message_hash, pubkey=pubkey, signature=signature, domain=domain) return bls.verify(message_hash=message_hash, pubkey=pubkey,
signature=signature, domain=int.from_bytes(domain, byteorder='little'))
@only_with_bls(alt_return=True) @only_with_bls(alt_return=True)
def bls_verify_multiple(pubkeys, message_hashes, signature, domain): def bls_verify_multiple(pubkeys, message_hashes, signature, domain):
return bls.verify_multiple(pubkeys, message_hashes, signature, domain) return bls.verify_multiple(pubkeys=pubkeys, message_hashes=message_hashes,
signature=signature, domain=int.from_bytes(domain, byteorder='little'))
@only_with_bls(alt_return=STUB_PUBKEY) @only_with_bls(alt_return=STUB_PUBKEY)
@ -43,4 +45,5 @@ def bls_aggregate_signatures(signatures):
@only_with_bls(alt_return=STUB_SIGNATURE) @only_with_bls(alt_return=STUB_SIGNATURE)
def bls_sign(message_hash, privkey, domain): def bls_sign(message_hash, privkey, domain):
return bls.sign(message_hash=message_hash, privkey=privkey, domain=domain) return bls.sign(message_hash=message_hash, privkey=privkey,
domain=int.from_bytes(domain, byteorder='little'))

View File

@ -498,6 +498,7 @@ class BytesN(BaseBytes):
# Helpers for common BytesN types # Helpers for common BytesN types
Bytes1: BytesType = BytesN[1] Bytes1: BytesType = BytesN[1]
Bytes4: BytesType = BytesN[4] Bytes4: BytesType = BytesN[4]
Bytes8: BytesType = BytesN[8]
Bytes32: BytesType = BytesN[32] Bytes32: BytesType = BytesN[32]
Bytes48: BytesType = BytesN[48] Bytes48: BytesType = BytesN[48]
Bytes96: BytesType = BytesN[96] Bytes96: BytesType = BytesN[96]