Skip to content

Commit

Permalink
Merge pull request #1246 from ethereum/fix-bls-domain-type
Browse files Browse the repository at this point in the history
Fix bls domain type
  • Loading branch information
djrtwo authored Jul 1, 2019
2 parents 2ab55bf + af57190 commit e5ced03
Show file tree
Hide file tree
Showing 13 changed files with 56 additions and 38 deletions.
12 changes: 6 additions & 6 deletions configs/constant_presets/mainnet.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,9 @@ MAX_TRANSFERS: 0

# Signature domains
# ---------------------------------------------------------------
DOMAIN_BEACON_PROPOSER: 0
DOMAIN_RANDAO: 1
DOMAIN_ATTESTATION: 2
DOMAIN_DEPOSIT: 3
DOMAIN_VOLUNTARY_EXIT: 4
DOMAIN_TRANSFER: 5
DOMAIN_BEACON_PROPOSER: 0x00000000
DOMAIN_RANDAO: 0x01000000
DOMAIN_ATTESTATION: 0x02000000
DOMAIN_DEPOSIT: 0x03000000
DOMAIN_VOLUNTARY_EXIT: 0x04000000
DOMAIN_TRANSFER: 0x05000000
12 changes: 6 additions & 6 deletions configs/constant_presets/minimal.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,9 @@ MAX_TRANSFERS: 0

# Signature domains
# ---------------------------------------------------------------
DOMAIN_BEACON_PROPOSER: 0
DOMAIN_RANDAO: 1
DOMAIN_ATTESTATION: 2
DOMAIN_DEPOSIT: 3
DOMAIN_VOLUNTARY_EXIT: 4
DOMAIN_TRANSFER: 5
DOMAIN_BEACON_PROPOSER: 0x00000000
DOMAIN_RANDAO: 0x01000000
DOMAIN_ATTESTATION: 0x02000000
DOMAIN_DEPOSIT: 0x03000000
DOMAIN_VOLUNTARY_EXIT: 0x04000000
DOMAIN_TRANSFER: 0x05000000
12 changes: 9 additions & 3 deletions scripts/build_spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
)
from eth2spec.utils.ssz.ssz_typing import (
bit, boolean, Container, List, Vector, uint64,
Bytes4, Bytes32, Bytes48, Bytes96, Bitlist, Bitvector,
Bytes4, Bytes8, Bytes32, Bytes48, Bytes96, Bitlist, Bitvector,
)
from eth2spec.utils.bls import (
bls_aggregate_pubkeys,
Expand All @@ -52,7 +52,7 @@
)
from eth2spec.utils.ssz.ssz_typing import (
bit, boolean, Container, List, Vector, Bytes, uint64,
Bytes4, Bytes32, Bytes48, Bytes96, Bitlist, Bitvector,
Bytes4, Bytes8, Bytes32, Bytes48, Bytes96, Bitlist, Bitvector,
)
from eth2spec.utils.bls import (
bls_aggregate_pubkeys,
Expand Down Expand Up @@ -94,7 +94,10 @@ def compute_committee(indices: Sequence[ValidatorIndex], # type: ignore
def apply_constants_preset(preset: Dict[str, Any]) -> None:
global_vars = globals()
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
global_vars['GENESIS_EPOCH'] = compute_epoch_of_slot(GENESIS_SLOT)
Expand Down Expand Up @@ -135,6 +138,9 @@ def objects_to_spec(functions: Dict[str, str],
)
)
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))
ssz_objects_instantiation_spec = '\n\n'.join(ssz_objects.values())
ssz_objects_reinitialization_spec = (
Expand Down
10 changes: 5 additions & 5 deletions specs/bls_signature.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,10 @@ We require:
G2_cofactor = 305502333931268344200999753193121504214466019254188142667664032982267604182971884026507427359259977847832272839041616661285803823378372096355777062779109
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
x_re = int.from_bytes(hash(message_hash + bytes8(domain) + b'\x01'), 'big')
x_im = int.from_bytes(hash(message_hash + bytes8(domain) + b'\x02'), 'big')
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
Expand Down Expand Up @@ -130,15 +130,15 @@ g = Fq2([g_x, g_y])

### `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 `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: 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 `signature` is a valid G2 point.
Expand Down
14 changes: 9 additions & 5 deletions specs/core/0_beacon-chain.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,10 @@ We define the following Python custom types for type hinting and readability:
| `Shard` | `uint64` | a shard number |
| `ValidatorIndex` | `uint64` | a validator registry index |
| `Gwei` | `uint64` | an amount in Gwei |
| `Version` | `Bytes4` | a fork version number |
| `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 |
| `BLSSignature` | `Bytes96` | a BLS12-381 signature |

Expand Down Expand Up @@ -250,7 +252,9 @@ The following values are (non-configurable) constants used throughout the specif
| `MAX_VOLUNTARY_EXITS` | `2**4` (= 16) |
| `MAX_TRANSFERS` | `0` |

### Signature domains
### Signature domain types

The following types are defined, mapping into `DomainType` (little endian):

| Name | Value |
| - | - |
Expand Down Expand Up @@ -775,11 +779,11 @@ def compute_activation_exit_epoch(epoch: Epoch) -> Epoch:
#### `compute_domain`

```python
def compute_domain(domain_type: uint64, fork_version: bytes=b'\x00' * 4) -> int:
def compute_domain(domain_type: DomainType, fork_version: Version=Version()) -> Domain:
"""
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
Expand Down Expand Up @@ -1004,7 +1008,7 @@ def get_total_active_balance(state: BeaconState) -> Gwei:
#### `get_domain`

```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.
"""
Expand Down
4 changes: 3 additions & 1 deletion specs/core/1_custody-game.md
Original file line number Diff line number Diff line change
Expand Up @@ -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) |

### Signature domains
### Signature domain types

The following types are defined, mapping into `DomainType` (little endian):

| Name | Value |
| - | - |
Expand Down
4 changes: 3 additions & 1 deletion specs/core/1_shard-data-chains.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
| `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 |
| - | - |
Expand Down
6 changes: 3 additions & 3 deletions specs/test_formats/bls/msg_hash_g2_compressed.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ A BLS compressed-hash to G2.
## Test case format

```yaml
input:
message: bytes32,
domain: uint64 -- the domain
input:
message: bytes32
domain: bytes8 -- the BLS domain
output: List[bytes48] -- length of two
```
Expand Down
2 changes: 1 addition & 1 deletion specs/test_formats/bls/msg_hash_g2_uncompressed.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ A BLS uncompressed-hash to G2.
```yaml
input:
message: bytes32
domain: uint64 -- the domain
domain: bytes8 -- the BLS domain
output: List[List[bytes48]] -- 3 lists, each a length of two
```
Expand Down
2 changes: 1 addition & 1 deletion specs/test_formats/bls/sign_msg.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Message signing with BLS should produce a signature.
input:
privkey: bytes32 -- the private key used for signing
message: bytes32 -- input message to sign (a hash)
domain: uint64 -- the domain
domain: bytes8 -- the BLS domain
output: bytes96 -- expected signature
```
Expand Down
6 changes: 3 additions & 3 deletions test_generators/bls/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ def case01_message_hash_G2_uncompressed():
yield {
'input': {
'message': '0x' + msg.hex(),
'domain': domain
'domain': int_to_hex(domain, byte_length=8)
},
'output': hash_message(msg, domain)
}
Expand All @@ -101,7 +101,7 @@ def case02_message_hash_G2_compressed():
yield {
'input': {
'message': '0x' + msg.hex(),
'domain': domain
'domain': int_to_hex(domain, byte_length=8)
},
'output': hash_message_compressed(msg, domain)
}
Expand All @@ -126,7 +126,7 @@ def case04_sign_messages():
'input': {
'privkey': int_to_hex(privkey),
'message': '0x' + message.hex(),
'domain': domain
'domain': int_to_hex(domain, byte_length=8)
},
'output': '0x' + sig.hex()
}
Expand Down
9 changes: 6 additions & 3 deletions test_libs/pyspec/eth2spec/utils/bls.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,14 @@ def entry(*args, **kw):

@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)
return bls.verify(message_hash=message_hash, pubkey=pubkey,
signature=signature, domain=int.from_bytes(domain, byteorder='little'))


@only_with_bls(alt_return=True)
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)
Expand All @@ -43,4 +45,5 @@ def 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)
return bls.sign(message_hash=message_hash, privkey=privkey,
domain=int.from_bytes(domain, byteorder='little'))
1 change: 1 addition & 0 deletions test_libs/pyspec/eth2spec/utils/ssz/ssz_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,7 @@ def is_fixed_size(cls):

# Helpers for common BytesN types.
Bytes4: BytesType = BytesN[4]
Bytes8: BytesType = BytesN[8]
Bytes32: BytesType = BytesN[32]
Bytes48: BytesType = BytesN[48]
Bytes96: BytesType = BytesN[96]

0 comments on commit e5ced03

Please sign in to comment.