Define Custom Types via function_puller

This commit is contained in:
Hsiao-Wei Wang 2019-06-15 16:57:50 -04:00
parent 8577cff72e
commit 00a68e28b5
No known key found for this signature in database
GPG Key ID: 95B070122902DEA4
4 changed files with 43 additions and 38 deletions

View File

@ -128,11 +128,11 @@ def apply_constants_preset(preset: Dict[str, Any]) -> None:
def objects_to_spec(functions: Dict[str, str], def objects_to_spec(functions: Dict[str, str],
custom_types: Dict[str, str],
constants: Dict[str, str], constants: Dict[str, str],
ssz_objects: Dict[str, str], ssz_objects: Dict[str, str],
inserts: Dict[str, str], inserts: Dict[str, str],
imports: Dict[str, str], imports: Dict[str, str],
new_types: Dict[str, str],
byte_types: List[int], byte_types: List[int],
) -> str: ) -> str:
""" """
@ -144,7 +144,7 @@ def objects_to_spec(functions: Dict[str, str],
f"class {key}({value}):\n" f"class {key}({value}):\n"
f" def __init__(self, _x: uint64) -> None:\n" f" def __init__(self, _x: uint64) -> None:\n"
f" ...\n" f" ...\n"
for key, value in new_types.items() for key, value in custom_types.items()
] ]
) )
) )
@ -225,18 +225,19 @@ def combine_spec_objects(spec0: SpecObject, spec1: SpecObject) -> SpecObject:
""" """
Takes in two spec variants (as tuples of their objects) and combines them using the appropriate combiner function. Takes in two spec variants (as tuples of their objects) and combines them using the appropriate combiner function.
""" """
functions0, constants0, ssz_objects0, inserts0 = spec0 functions0, custom_types0, constants0, ssz_objects0, inserts0 = spec0
functions1, constants1, ssz_objects1, inserts1 = spec1 functions1, custom_types1, constants1, ssz_objects1, inserts1 = spec1
functions = combine_functions(functions0, functions1) functions = combine_functions(functions0, functions1)
custom_types = combine_constants(custom_types0, custom_types1)
constants = combine_constants(constants0, constants1) constants = combine_constants(constants0, constants1)
ssz_objects = combine_ssz_objects(ssz_objects0, ssz_objects1) ssz_objects = combine_ssz_objects(ssz_objects0, ssz_objects1)
inserts = combine_inserts(inserts0, inserts1) inserts = combine_inserts(inserts0, inserts1)
return functions, constants, ssz_objects, inserts return functions, custom_types, constants, ssz_objects, inserts
def build_phase0_spec(sourcefile: str, outfile: str=None) -> Optional[str]: def build_phase0_spec(sourcefile: str, outfile: str=None) -> Optional[str]:
functions, constants, ssz_objects, inserts = get_spec(sourcefile) functions, custom_types, constants, ssz_objects, inserts = get_spec(sourcefile)
spec = objects_to_spec(functions, constants, ssz_objects, inserts, PHASE0_IMPORTS, NEW_TYPES, BYTE_TYPES) spec = objects_to_spec(functions, custom_types, constants, ssz_objects, inserts, PHASE0_IMPORTS, BYTE_TYPES)
if outfile is not None: if outfile is not None:
with open(outfile, 'w') as out: with open(outfile, 'w') as out:
out.write(spec) out.write(spec)
@ -253,7 +254,7 @@ def build_phase1_spec(phase0_sourcefile: str,
spec_objects = phase0_spec spec_objects = phase0_spec
for value in [phase1_custody, phase1_shard_data]: for value in [phase1_custody, phase1_shard_data]:
spec_objects = combine_spec_objects(spec_objects, value) spec_objects = combine_spec_objects(spec_objects, value)
spec = objects_to_spec(*spec_objects, PHASE1_IMPORTS, NEW_TYPES, BYTE_TYPES) spec = objects_to_spec(*spec_objects, PHASE1_IMPORTS, BYTE_TYPES)
if outfile is not None: if outfile is not None:
with open(outfile, 'w') as out: with open(outfile, 'w') as out:
out.write(spec) out.write(spec)

View File

@ -29,6 +29,7 @@ def get_spec(file_name: str) -> SpecObject:
inserts = {} inserts = {}
function_matcher = re.compile(FUNCTION_REGEX) function_matcher = re.compile(FUNCTION_REGEX)
inserts_matcher = re.compile(BEGIN_INSERT_REGEX) inserts_matcher = re.compile(BEGIN_INSERT_REGEX)
custom_types = {}
for linenum, line in enumerate(open(file_name).readlines()): for linenum, line in enumerate(open(file_name).readlines()):
line = line.rstrip() line = line.rstrip()
if pulling_from is None and len(line) > 0 and line[0] == '#' and line[-1] == '`': if pulling_from is None and len(line) > 0 and line[0] == '#' and line[-1] == '`':
@ -64,7 +65,7 @@ def get_spec(file_name: str) -> SpecObject:
ssz_objects[current_name] = ssz_objects.get(current_name, '') + line + '\n' ssz_objects[current_name] = ssz_objects.get(current_name, '') + line + '\n'
else: else:
functions[current_name] = functions.get(current_name, '') + line + '\n' functions[current_name] = functions.get(current_name, '') + line + '\n'
# Handle constant table entries # Handle constant and custom types table entries
elif pulling_from is None and len(line) > 0 and line[0] == '|': elif pulling_from is None and len(line) > 0 and line[0] == '|':
row = line[1:].split('|') row = line[1:].split('|')
if len(row) >= 2: if len(row) >= 2:
@ -72,6 +73,9 @@ def get_spec(file_name: str) -> SpecObject:
row[i] = row[i].strip().strip('`') row[i] = row[i].strip().strip('`')
if '`' in row[i]: if '`' in row[i]:
row[i] = row[i][:row[i].find('`')] row[i] = row[i][:row[i].find('`')]
if row[1].startswith('uint') or row[1].startswith('bytes'):
custom_types[row[0]] = row[1]
else:
eligible = True eligible = True
if row[0][0] not in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ_': if row[0][0] not in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ_':
eligible = False eligible = False
@ -80,4 +84,4 @@ def get_spec(file_name: str) -> SpecObject:
eligible = False eligible = False
if eligible: if eligible:
constants[row[0]] = row[1].replace('**TBD**', '0x1234567890123456789012345678901234567890') constants[row[0]] = row[1].replace('**TBD**', '0x1234567890123456789012345678901234567890')
return functions, constants, ssz_objects, inserts return functions, custom_types, constants, ssz_objects, inserts

View File

@ -10,6 +10,7 @@
- [Introduction](#introduction) - [Introduction](#introduction)
- [Notation](#notation) - [Notation](#notation)
- [Terminology](#terminology) - [Terminology](#terminology)
- [Custom types](#custom-types)
- [Constants](#constants) - [Constants](#constants)
- [Misc](#misc) - [Misc](#misc)
- [Deposit contract](#deposit-contract) - [Deposit contract](#deposit-contract)
@ -45,7 +46,6 @@
- [`BeaconBlock`](#beaconblock) - [`BeaconBlock`](#beaconblock)
- [Beacon state](#beacon-state) - [Beacon state](#beacon-state)
- [`BeaconState`](#beaconstate) - [`BeaconState`](#beaconstate)
- [Custom types](#custom-types)
- [Helper functions](#helper-functions) - [Helper functions](#helper-functions)
- [`xor`](#xor) - [`xor`](#xor)
- [`hash`](#hash) - [`hash`](#hash)
@ -150,6 +150,20 @@ Code snippets appearing in `this style` are to be interpreted as Python code.
* **Withdrawal period**—the number of slots between a [validator](#dfn-validator) exit and the [validator](#dfn-validator) balance being withdrawable. * **Withdrawal period**—the number of slots between a [validator](#dfn-validator) exit and the [validator](#dfn-validator) balance being withdrawable.
* **Genesis time**—the Unix time of the genesis beacon chain block at slot 0. * **Genesis time**—the Unix time of the genesis beacon chain block at slot 0.
## Custom types
We define the following Python custom types for type hinting and readability:
| Name | SSZ equivalent | Description |
| - | - | - |
| `Slot` | `uint64` | a slot number |
| `Epoch` | `uint64` | an epoch number |
| `Shard` | `uint64` | a shard number |
| `ValidatorIndex` | `uint64` | a validator registry index |
| `Gwei` | `uint64` | an amount in Gwei |
| `BLSPubkey` | `Bytes48` | a BLS12-381 public key |
| `BLSSignature` | `Bytes96` | a BLS12-381 signature |
## Constants ## Constants
*Note*: The default mainnet values for the constants are included here for spec-design purposes. *Note*: The default mainnet values for the constants are included here for spec-design purposes.
@ -178,12 +192,12 @@ These configurations are updated for releases, but may be out of sync during `de
### Gwei values ### Gwei values
| Name | Value | Unit | | Name | Value |
| - | - | :-: | | - | - | :-: |
| `MIN_DEPOSIT_AMOUNT` | `Gwei(2**0 * 10**9)` (= 1,000,000,000) | Gwei | | `MIN_DEPOSIT_AMOUNT` | `Gwei(2**0 * 10**9)` (= 1,000,000,000) |
| `MAX_EFFECTIVE_BALANCE` | `Gwei(2**5 * 10**9)` (= 32,000,000,000) | Gwei | | `MAX_EFFECTIVE_BALANCE` | `Gwei(2**5 * 10**9)` (= 32,000,000,000) |
| `EJECTION_BALANCE` | `Gwei(2**4 * 10**9)` (= 16,000,000,000) | Gwei | | `EJECTION_BALANCE` | `Gwei(2**4 * 10**9)` (= 16,000,000,000) |
| `EFFECTIVE_BALANCE_INCREMENT` | `Gwei(2**0 * 10**9)` (= 1,000,000,000) | Gwei | | `EFFECTIVE_BALANCE_INCREMENT` | `Gwei(2**0 * 10**9)` (= 1,000,000,000) |
### Initial values ### Initial values
@ -563,20 +577,6 @@ class BeaconState(Container):
deposit_index: uint64 deposit_index: uint64
``` ```
## Custom types
We define the following Python custom types for type hinting and readability:
| Name | SSZ equivalent | Description |
| - | - | - |
| `Slot` | `uint64` | a slot number |
| `Epoch` | `uint64` | an epoch number |
| `Shard` | `uint64` | a shard number |
| `ValidatorIndex` | `uint64` | a validator registry index |
| `Gwei` | `uint64` | an amount in Gwei |
| `BLSPubkey` | `Bytes48` | a BLS12-381 public key |
| `BLSSignature` | `Bytes96` | a BLS12-381 signature |
## Helper functions ## Helper functions
*Note*: The definitions below are for specification purposes and are not necessarily optimal implementations. *Note*: The definitions below are for specification purposes and are not necessarily optimal implementations.

View File

@ -51,7 +51,7 @@ class uint64(uint):
def __new__(cls, value, *args, **kwargs): def __new__(cls, value, *args, **kwargs):
if value.bit_length() > 64: if value.bit_length() > 64:
raise ValueError("value out of bounds for uint128") raise ValueError("value out of bounds for uint64")
return super().__new__(cls, value) return super().__new__(cls, value)