We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Use custom types for container definitions
This is the "successor" to #695 which was recently closed for staleness. I'm intending to address this alongside a rewrite of #917.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `scripts/build_spec.py`
Content:
```
1 import re
2 from function_puller import (
3     get_spec,
4     SpecObject,
5 )
6 from argparse import ArgumentParser
7 from typing import (
8     Dict,
9     List,
10     Optional,
11 )
12 
13 
14 PHASE0_IMPORTS = '''from typing import (
15     Any,
16     Dict,
17     List,
18     NewType,
19     Tuple,
20 )
21 
22 from eth2spec.utils.ssz.ssz_impl import (
23     hash_tree_root,
24     signing_root,
25 )
26 from eth2spec.utils.ssz.ssz_typing import (
27     # unused: uint8, uint16, uint32, uint128, uint256,
28     uint64, Container, Vector, BytesN
29 )
30 from eth2spec.utils.bls import (
31     bls_aggregate_pubkeys,
32     bls_verify,
33     bls_verify_multiple,
34 )
35 # Note: 'int' type defaults to being interpreted as a uint64 by SSZ implementation.
36 
37 from eth2spec.utils.hash_function import hash
38 '''
39 PHASE1_IMPORTS = '''from typing import (
40     Any,
41     Dict,
42     List,
43     NewType,
44     Tuple,
45 )
46 
47 from eth2spec.utils.ssz.ssz_impl import (
48     hash_tree_root,
49     signing_root,
50     serialize,
51     is_empty,
52 )
53 from eth2spec.utils.ssz.ssz_typing import (
54     # unused: uint8, uint16, uint32, uint128, uint256,
55     uint64, Container, Vector, BytesN
56 )
57 from eth2spec.utils.bls import (
58     bls_aggregate_pubkeys,
59     bls_verify,
60     bls_verify_multiple,
61 )
62 
63 from eth2spec.utils.hash_function import hash
64 '''
65 NEW_TYPES = {
66     'Slot': 'int',
67     'Epoch': 'int',
68     'Shard': 'int',
69     'ValidatorIndex': 'int',
70     'Gwei': 'int',
71 }
72 BYTE_TYPES = [4, 32, 48, 96]
73 SUNDRY_FUNCTIONS = '''
74 def get_ssz_type_by_name(name: str) -> Container:
75     return globals()[name]
76 
77 
78 # Monkey patch validator compute committee code
79 _compute_committee = compute_committee
80 committee_cache = {}
81 
82 
83 def compute_committee(indices: List[ValidatorIndex], seed: Bytes32, index: int, count: int) -> List[ValidatorIndex]:
84     param_hash = (hash_tree_root(indices), seed, index, count)
85 
86     if param_hash in committee_cache:
87         return committee_cache[param_hash]
88     else:
89         ret = _compute_committee(indices, seed, index, count)
90         committee_cache[param_hash] = ret
91         return ret
92 
93 
94 # Monkey patch hash cache
95 _hash = hash
96 hash_cache = {}
97 
98 
99 def hash(x):
100     if x in hash_cache:
101         return hash_cache[x]
102     else:
103         ret = _hash(x)
104         hash_cache[x] = ret
105         return ret
106 
107 
108 # Access to overwrite spec constants based on configuration
109 def apply_constants_preset(preset: Dict[str, Any]):
110     global_vars = globals()
111     for k, v in preset.items():
112         global_vars[k] = v
113 
114     # Deal with derived constants
115     global_vars['GENESIS_EPOCH'] = slot_to_epoch(GENESIS_SLOT)
116 
117     # Initialize SSZ types again, to account for changed lengths
118     init_SSZ_types()
119 '''
120 
121 
122 def objects_to_spec(functions: Dict[str, str],
123                     constants: Dict[str, str],
124                     ssz_objects: Dict[str, str],
125                     inserts: Dict[str, str],
126                     imports: Dict[str, str],
127                     new_types: Dict[str, str],
128                     byte_types: List[int],
129                     ) -> str:
130     """
131     Given all the objects that constitute a spec, combine them into a single pyfile.
132     """
133     new_type_definitions = \
134         '\n'.join(['''%s = NewType('%s', %s)''' % (key, key, value) for key, value in new_types.items()])
135     new_type_definitions += '\n' + '\n'.join(['Bytes%s = BytesN[%s]' % (n, n) for n in byte_types])
136     functions_spec = '\n\n'.join(functions.values())
137     constants_spec = '\n'.join(map(lambda x: '%s = %s' % (x, constants[x]), constants))
138     ssz_objects_instantiation_spec = '\n\n'.join(ssz_objects.values())
139     ssz_objects_reinitialization_spec = (
140         'def init_SSZ_types():\n    global_vars = globals()\n\n    '
141         + '\n\n    '.join([re.sub(r'(?!\n\n)\n', r'\n    ', value[:-1]) for value in ssz_objects.values()])
142         + '\n\n'
143         + '\n'.join(map(lambda x: '    global_vars[\'%s\'] = %s' % (x, x), ssz_objects.keys()))
144     )
145     spec = (
146         imports
147         + '\n' + new_type_definitions
148         + '\n\n' + constants_spec
149         + '\n\n\n' + ssz_objects_instantiation_spec
150         + '\n\n' + functions_spec
151         + '\n' + SUNDRY_FUNCTIONS
152         + '\n\n' + ssz_objects_reinitialization_spec
153         + '\n'
154     )
155     # Handle @inserts
156     for key, value in inserts.items():
157         spec = re.sub('[ ]*# %s\\n' % key, value, spec)
158     return spec
159 
160 
161 def combine_functions(old_functions: Dict[str, str], new_functions: Dict[str, str]) -> Dict[str, str]:
162     for key, value in new_functions.items():
163         old_functions[key] = value
164     return old_functions
165 
166 
167 def combine_constants(old_constants: Dict[str, str], new_constants: Dict[str, str]) -> Dict[str, str]:
168     for key, value in new_constants.items():
169         old_constants[key] = value
170     return old_constants
171 
172 
173 def dependency_order_ssz_objects(objects: Dict[str, str]) -> None:
174     """
175     Determines which SSZ Object is depenedent on which other and orders them appropriately
176     """
177     items = list(objects.items())
178     for key, value in items:
179         dependencies = re.findall(r'(: [A-Z][\w[]*)', value)
180         dependencies = map(lambda x: re.sub(r'\W|Vector|List|Container|uint\d+|Bytes\d+|bytes', '', x), dependencies)
181         for dep in dependencies:
182             if dep in NEW_TYPES or len(dep) == 0:
183                 continue
184             key_list = list(objects.keys())
185             for item in [dep, key] + key_list[key_list.index(dep)+1:]:
186                 objects[item] = objects.pop(item)
187 
188 
189 def combine_ssz_objects(old_objects: Dict[str, str], new_objects: Dict[str, str]) -> Dict[str, str]:
190     """
191     Takes in old spec and new spec ssz objects, combines them,
192     and returns the newer versions of the objects in dependency order.
193     """
194     for key, value in new_objects.items():
195         if key in old_objects:
196             # remove trailing newline
197             old_objects[key] = old_objects[key]
198             # remove leading variable name
199             value = re.sub(r'^class [\w]*\(Container\):\n', '', value)
200         old_objects[key] = old_objects.get(key, '') + value
201     dependency_order_ssz_objects(old_objects)
202     return old_objects
203 
204 
205 # inserts are handeled the same way as functions
206 combine_inserts = combine_functions
207 
208 
209 def combine_spec_objects(spec0: SpecObject, spec1: SpecObject) -> SpecObject:
210     """
211     Takes in two spec variants (as tuples of their objects) and combines them using the appropriate combiner function.
212     """
213     functions0, constants0, ssz_objects0, inserts0 = spec0
214     functions1, constants1, ssz_objects1, inserts1 = spec1
215     functions = combine_functions(functions0, functions1)
216     constants = combine_constants(constants0, constants1)
217     ssz_objects = combine_ssz_objects(ssz_objects0, ssz_objects1)
218     inserts = combine_inserts(inserts0, inserts1)
219     return functions, constants, ssz_objects, inserts
220 
221 
222 def build_phase0_spec(sourcefile: str, outfile: str=None) -> Optional[str]:
223     functions, constants, ssz_objects, inserts = get_spec(sourcefile)
224     spec = objects_to_spec(functions, constants, ssz_objects, inserts, PHASE0_IMPORTS, NEW_TYPES, BYTE_TYPES)
225     if outfile is not None:
226         with open(outfile, 'w') as out:
227             out.write(spec)
228     return spec
229 
230 
231 def build_phase1_spec(phase0_sourcefile: str,
232                       phase1_custody_sourcefile: str,
233                       phase1_shard_sourcefile: str,
234                       outfile: str=None) -> Optional[str]:
235     phase0_spec = get_spec(phase0_sourcefile)
236     phase1_custody = get_spec(phase1_custody_sourcefile)
237     phase1_shard_data = get_spec(phase1_shard_sourcefile)
238     spec_objects = phase0_spec
239     for value in [phase1_custody, phase1_shard_data]:
240         spec_objects = combine_spec_objects(spec_objects, value)
241     spec = objects_to_spec(*spec_objects, PHASE1_IMPORTS, NEW_TYPES, BYTE_TYPES)
242     if outfile is not None:
243         with open(outfile, 'w') as out:
244             out.write(spec)
245     return spec
246 
247 
248 if __name__ == '__main__':
249     description = '''
250 Build the specs from the md docs.
251 If building phase 0:
252     1st argument is input spec.md
253     2nd argument is output spec.py
254 
255 If building phase 1:
256     1st argument is input spec_phase0.md
257     2nd argument is input spec_phase1_custody.md
258     3rd argument is input spec_phase1_shard_data.md
259     4th argument is output spec.py
260 '''
261     parser = ArgumentParser(description=description)
262     parser.add_argument("-p", "--phase", dest="phase", type=int, default=0, help="Build for phase #")
263     parser.add_argument(dest="files", help="Input and output files", nargs="+")
264 
265     args = parser.parse_args()
266     if args.phase == 0:
267         if len(args.files) == 2:
268             build_phase0_spec(*args.files)
269         else:
270             print(" Phase 0 requires an output as well as an input file.")
271     elif args.phase == 1:
272         if len(args.files) == 4:
273             build_phase1_spec(*args.files)
274         else:
275             print(" Phase 1 requires an output as well as 3 input files (phase0.md and phase1.md, phase1.md)")
276     else:
277         print("Invalid phase: {0}".format(args.phase))
278
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/scripts/build_spec.py b/scripts/build_spec.py
--- a/scripts/build_spec.py
+++ b/scripts/build_spec.py
@@ -130,9 +130,10 @@
     """
     Given all the objects that constitute a spec, combine them into a single pyfile.
     """
-    new_type_definitions = \
-        '\n'.join(['''%s = NewType('%s', %s)''' % (key, key, value) for key, value in new_types.items()])
-    new_type_definitions += '\n' + '\n'.join(['Bytes%s = BytesN[%s]' % (n, n) for n in byte_types])
+    new_type_definitions = '\n'.join(['Bytes%s = BytesN[%s]' % (n, n) for n in byte_types])
+    new_type_definitions += '\n' + '\n'.join(['Hash = Bytes32', 'BLSPubkey = Bytes48', 'BLSSignature = Bytes96'])
+    new_type_definitions += \
+        '\n' + '\n'.join(['''%s = NewType('%s', %s)''' % (key, key, value) for key, value in new_types.items()])
     functions_spec = '\n\n'.join(functions.values())
     constants_spec = '\n'.join(map(lambda x: '%s = %s' % (x, constants[x]), constants))
     ssz_objects_instantiation_spec = '\n\n'.join(ssz_objects.values())
@@ -177,7 +178,7 @@
     items = list(objects.items())
     for key, value in items:
         dependencies = re.findall(r'(: [A-Z][\w[]*)', value)
-        dependencies = map(lambda x: re.sub(r'\W|Vector|List|Container|uint\d+|Bytes\d+|bytes', '', x), dependencies)
+        dependencies = map(lambda x: re.sub(r'\W|Vector|List|Container|Hash|BLSPubkey|BLSSignature|uint\d+|Bytes\d+|bytes', '', x), dependencies)
         for dep in dependencies:
             if dep in NEW_TYPES or len(dep) == 0:
                 continue

{"golden_diff": "diff --git a/scripts/build_spec.py b/scripts/build_spec.py\n--- a/scripts/build_spec.py\n+++ b/scripts/build_spec.py\n@@ -130,9 +130,10 @@\n     \"\"\"\n     Given all the objects that constitute a spec, combine them into a single pyfile.\n     \"\"\"\n-    new_type_definitions = \\\n-        '\\n'.join(['''%s = NewType('%s', %s)''' % (key, key, value) for key, value in new_types.items()])\n-    new_type_definitions += '\\n' + '\\n'.join(['Bytes%s = BytesN[%s]' % (n, n) for n in byte_types])\n+    new_type_definitions = '\\n'.join(['Bytes%s = BytesN[%s]' % (n, n) for n in byte_types])\n+    new_type_definitions += '\\n' + '\\n'.join(['Hash = Bytes32', 'BLSPubkey = Bytes48', 'BLSSignature = Bytes96'])\n+    new_type_definitions += \\\n+        '\\n' + '\\n'.join(['''%s = NewType('%s', %s)''' % (key, key, value) for key, value in new_types.items()])\n     functions_spec = '\\n\\n'.join(functions.values())\n     constants_spec = '\\n'.join(map(lambda x: '%s = %s' % (x, constants[x]), constants))\n     ssz_objects_instantiation_spec = '\\n\\n'.join(ssz_objects.values())\n@@ -177,7 +178,7 @@\n     items = list(objects.items())\n     for key, value in items:\n         dependencies = re.findall(r'(: [A-Z][\\w[]*)', value)\n-        dependencies = map(lambda x: re.sub(r'\\W|Vector|List|Container|uint\\d+|Bytes\\d+|bytes', '', x), dependencies)\n+        dependencies = map(lambda x: re.sub(r'\\W|Vector|List|Container|Hash|BLSPubkey|BLSSignature|uint\\d+|Bytes\\d+|bytes', '', x), dependencies)\n         for dep in dependencies:\n             if dep in NEW_TYPES or len(dep) == 0:\n                 continue\n", "issue": "Use custom types for container definitions\nThis is the \"successor\" to #695 which was recently closed for staleness. I'm intending to address this alongside a rewrite of #917.\n", "before_files": [{"content": "import re\nfrom function_puller import (\n    get_spec,\n    SpecObject,\n)\nfrom argparse import ArgumentParser\nfrom typing import (\n    Dict,\n    List,\n    Optional,\n)\n\n\nPHASE0_IMPORTS = '''from typing import (\n    Any,\n    Dict,\n    List,\n    NewType,\n    Tuple,\n)\n\nfrom eth2spec.utils.ssz.ssz_impl import (\n    hash_tree_root,\n    signing_root,\n)\nfrom eth2spec.utils.ssz.ssz_typing import (\n    # unused: uint8, uint16, uint32, uint128, uint256,\n    uint64, Container, Vector, BytesN\n)\nfrom eth2spec.utils.bls import (\n    bls_aggregate_pubkeys,\n    bls_verify,\n    bls_verify_multiple,\n)\n# Note: 'int' type defaults to being interpreted as a uint64 by SSZ implementation.\n\nfrom eth2spec.utils.hash_function import hash\n'''\nPHASE1_IMPORTS = '''from typing import (\n    Any,\n    Dict,\n    List,\n    NewType,\n    Tuple,\n)\n\nfrom eth2spec.utils.ssz.ssz_impl import (\n    hash_tree_root,\n    signing_root,\n    serialize,\n    is_empty,\n)\nfrom eth2spec.utils.ssz.ssz_typing import (\n    # unused: uint8, uint16, uint32, uint128, uint256,\n    uint64, Container, Vector, BytesN\n)\nfrom eth2spec.utils.bls import (\n    bls_aggregate_pubkeys,\n    bls_verify,\n    bls_verify_multiple,\n)\n\nfrom eth2spec.utils.hash_function import hash\n'''\nNEW_TYPES = {\n    'Slot': 'int',\n    'Epoch': 'int',\n    'Shard': 'int',\n    'ValidatorIndex': 'int',\n    'Gwei': 'int',\n}\nBYTE_TYPES = [4, 32, 48, 96]\nSUNDRY_FUNCTIONS = '''\ndef get_ssz_type_by_name(name: str) -> Container:\n    return globals()[name]\n\n\n# Monkey patch validator compute committee code\n_compute_committee = compute_committee\ncommittee_cache = {}\n\n\ndef compute_committee(indices: List[ValidatorIndex], seed: Bytes32, index: int, count: int) -> List[ValidatorIndex]:\n    param_hash = (hash_tree_root(indices), seed, index, count)\n\n    if param_hash in committee_cache:\n        return committee_cache[param_hash]\n    else:\n        ret = _compute_committee(indices, seed, index, count)\n        committee_cache[param_hash] = ret\n        return ret\n\n\n# Monkey patch hash cache\n_hash = hash\nhash_cache = {}\n\n\ndef hash(x):\n    if x in hash_cache:\n        return hash_cache[x]\n    else:\n        ret = _hash(x)\n        hash_cache[x] = ret\n        return ret\n\n\n# Access to overwrite spec constants based on configuration\ndef apply_constants_preset(preset: Dict[str, Any]):\n    global_vars = globals()\n    for k, v in preset.items():\n        global_vars[k] = v\n\n    # Deal with derived constants\n    global_vars['GENESIS_EPOCH'] = slot_to_epoch(GENESIS_SLOT)\n\n    # Initialize SSZ types again, to account for changed lengths\n    init_SSZ_types()\n'''\n\n\ndef objects_to_spec(functions: Dict[str, str],\n                    constants: Dict[str, str],\n                    ssz_objects: Dict[str, str],\n                    inserts: Dict[str, str],\n                    imports: Dict[str, str],\n                    new_types: Dict[str, str],\n                    byte_types: List[int],\n                    ) -> str:\n    \"\"\"\n    Given all the objects that constitute a spec, combine them into a single pyfile.\n    \"\"\"\n    new_type_definitions = \\\n        '\\n'.join(['''%s = NewType('%s', %s)''' % (key, key, value) for key, value in new_types.items()])\n    new_type_definitions += '\\n' + '\\n'.join(['Bytes%s = BytesN[%s]' % (n, n) for n in byte_types])\n    functions_spec = '\\n\\n'.join(functions.values())\n    constants_spec = '\\n'.join(map(lambda x: '%s = %s' % (x, constants[x]), constants))\n    ssz_objects_instantiation_spec = '\\n\\n'.join(ssz_objects.values())\n    ssz_objects_reinitialization_spec = (\n        'def init_SSZ_types():\\n    global_vars = globals()\\n\\n    '\n        + '\\n\\n    '.join([re.sub(r'(?!\\n\\n)\\n', r'\\n    ', value[:-1]) for value in ssz_objects.values()])\n        + '\\n\\n'\n        + '\\n'.join(map(lambda x: '    global_vars[\\'%s\\'] = %s' % (x, x), ssz_objects.keys()))\n    )\n    spec = (\n        imports\n        + '\\n' + new_type_definitions\n        + '\\n\\n' + constants_spec\n        + '\\n\\n\\n' + ssz_objects_instantiation_spec\n        + '\\n\\n' + functions_spec\n        + '\\n' + SUNDRY_FUNCTIONS\n        + '\\n\\n' + ssz_objects_reinitialization_spec\n        + '\\n'\n    )\n    # Handle @inserts\n    for key, value in inserts.items():\n        spec = re.sub('[ ]*# %s\\\\n' % key, value, spec)\n    return spec\n\n\ndef combine_functions(old_functions: Dict[str, str], new_functions: Dict[str, str]) -> Dict[str, str]:\n    for key, value in new_functions.items():\n        old_functions[key] = value\n    return old_functions\n\n\ndef combine_constants(old_constants: Dict[str, str], new_constants: Dict[str, str]) -> Dict[str, str]:\n    for key, value in new_constants.items():\n        old_constants[key] = value\n    return old_constants\n\n\ndef dependency_order_ssz_objects(objects: Dict[str, str]) -> None:\n    \"\"\"\n    Determines which SSZ Object is depenedent on which other and orders them appropriately\n    \"\"\"\n    items = list(objects.items())\n    for key, value in items:\n        dependencies = re.findall(r'(: [A-Z][\\w[]*)', value)\n        dependencies = map(lambda x: re.sub(r'\\W|Vector|List|Container|uint\\d+|Bytes\\d+|bytes', '', x), dependencies)\n        for dep in dependencies:\n            if dep in NEW_TYPES or len(dep) == 0:\n                continue\n            key_list = list(objects.keys())\n            for item in [dep, key] + key_list[key_list.index(dep)+1:]:\n                objects[item] = objects.pop(item)\n\n\ndef combine_ssz_objects(old_objects: Dict[str, str], new_objects: Dict[str, str]) -> Dict[str, str]:\n    \"\"\"\n    Takes in old spec and new spec ssz objects, combines them,\n    and returns the newer versions of the objects in dependency order.\n    \"\"\"\n    for key, value in new_objects.items():\n        if key in old_objects:\n            # remove trailing newline\n            old_objects[key] = old_objects[key]\n            # remove leading variable name\n            value = re.sub(r'^class [\\w]*\\(Container\\):\\n', '', value)\n        old_objects[key] = old_objects.get(key, '') + value\n    dependency_order_ssz_objects(old_objects)\n    return old_objects\n\n\n# inserts are handeled the same way as functions\ncombine_inserts = combine_functions\n\n\ndef combine_spec_objects(spec0: SpecObject, spec1: SpecObject) -> SpecObject:\n    \"\"\"\n    Takes in two spec variants (as tuples of their objects) and combines them using the appropriate combiner function.\n    \"\"\"\n    functions0, constants0, ssz_objects0, inserts0 = spec0\n    functions1, constants1, ssz_objects1, inserts1 = spec1\n    functions = combine_functions(functions0, functions1)\n    constants = combine_constants(constants0, constants1)\n    ssz_objects = combine_ssz_objects(ssz_objects0, ssz_objects1)\n    inserts = combine_inserts(inserts0, inserts1)\n    return functions, constants, ssz_objects, inserts\n\n\ndef build_phase0_spec(sourcefile: str, outfile: str=None) -> Optional[str]:\n    functions, constants, ssz_objects, inserts = get_spec(sourcefile)\n    spec = objects_to_spec(functions, constants, ssz_objects, inserts, PHASE0_IMPORTS, NEW_TYPES, BYTE_TYPES)\n    if outfile is not None:\n        with open(outfile, 'w') as out:\n            out.write(spec)\n    return spec\n\n\ndef build_phase1_spec(phase0_sourcefile: str,\n                      phase1_custody_sourcefile: str,\n                      phase1_shard_sourcefile: str,\n                      outfile: str=None) -> Optional[str]:\n    phase0_spec = get_spec(phase0_sourcefile)\n    phase1_custody = get_spec(phase1_custody_sourcefile)\n    phase1_shard_data = get_spec(phase1_shard_sourcefile)\n    spec_objects = phase0_spec\n    for value in [phase1_custody, phase1_shard_data]:\n        spec_objects = combine_spec_objects(spec_objects, value)\n    spec = objects_to_spec(*spec_objects, PHASE1_IMPORTS, NEW_TYPES, BYTE_TYPES)\n    if outfile is not None:\n        with open(outfile, 'w') as out:\n            out.write(spec)\n    return spec\n\n\nif __name__ == '__main__':\n    description = '''\nBuild the specs from the md docs.\nIf building phase 0:\n    1st argument is input spec.md\n    2nd argument is output spec.py\n\nIf building phase 1:\n    1st argument is input spec_phase0.md\n    2nd argument is input spec_phase1_custody.md\n    3rd argument is input spec_phase1_shard_data.md\n    4th argument is output spec.py\n'''\n    parser = ArgumentParser(description=description)\n    parser.add_argument(\"-p\", \"--phase\", dest=\"phase\", type=int, default=0, help=\"Build for phase #\")\n    parser.add_argument(dest=\"files\", help=\"Input and output files\", nargs=\"+\")\n\n    args = parser.parse_args()\n    if args.phase == 0:\n        if len(args.files) == 2:\n            build_phase0_spec(*args.files)\n        else:\n            print(\" Phase 0 requires an output as well as an input file.\")\n    elif args.phase == 1:\n        if len(args.files) == 4:\n            build_phase1_spec(*args.files)\n        else:\n            print(\" Phase 1 requires an output as well as 3 input files (phase0.md and phase1.md, phase1.md)\")\n    else:\n        print(\"Invalid phase: {0}\".format(args.phase))\n", "path": "scripts/build_spec.py"}], "after_files": [{"content": "import re\nfrom function_puller import (\n    get_spec,\n    SpecObject,\n)\nfrom argparse import ArgumentParser\nfrom typing import (\n    Dict,\n    List,\n    Optional,\n)\n\n\nPHASE0_IMPORTS = '''from typing import (\n    Any,\n    Dict,\n    List,\n    NewType,\n    Tuple,\n)\n\nfrom eth2spec.utils.ssz.ssz_impl import (\n    hash_tree_root,\n    signing_root,\n)\nfrom eth2spec.utils.ssz.ssz_typing import (\n    # unused: uint8, uint16, uint32, uint128, uint256,\n    uint64, Container, Vector, BytesN\n)\nfrom eth2spec.utils.bls import (\n    bls_aggregate_pubkeys,\n    bls_verify,\n    bls_verify_multiple,\n)\n# Note: 'int' type defaults to being interpreted as a uint64 by SSZ implementation.\n\nfrom eth2spec.utils.hash_function import hash\n'''\nPHASE1_IMPORTS = '''from typing import (\n    Any,\n    Dict,\n    List,\n    NewType,\n    Tuple,\n)\n\nfrom eth2spec.utils.ssz.ssz_impl import (\n    hash_tree_root,\n    signing_root,\n    serialize,\n    is_empty,\n)\nfrom eth2spec.utils.ssz.ssz_typing import (\n    # unused: uint8, uint16, uint32, uint128, uint256,\n    uint64, Container, Vector, BytesN\n)\nfrom eth2spec.utils.bls import (\n    bls_aggregate_pubkeys,\n    bls_verify,\n    bls_verify_multiple,\n)\n\nfrom eth2spec.utils.hash_function import hash\n'''\nNEW_TYPES = {\n    'Slot': 'int',\n    'Epoch': 'int',\n    'Shard': 'int',\n    'ValidatorIndex': 'int',\n    'Gwei': 'int',\n}\nBYTE_TYPES = [4, 32, 48, 96]\nSUNDRY_FUNCTIONS = '''\ndef get_ssz_type_by_name(name: str) -> Container:\n    return globals()[name]\n\n\n# Monkey patch validator compute committee code\n_compute_committee = compute_committee\ncommittee_cache = {}\n\n\ndef compute_committee(indices: List[ValidatorIndex], seed: Bytes32, index: int, count: int) -> List[ValidatorIndex]:\n    param_hash = (hash_tree_root(indices), seed, index, count)\n\n    if param_hash in committee_cache:\n        return committee_cache[param_hash]\n    else:\n        ret = _compute_committee(indices, seed, index, count)\n        committee_cache[param_hash] = ret\n        return ret\n\n\n# Monkey patch hash cache\n_hash = hash\nhash_cache = {}\n\n\ndef hash(x):\n    if x in hash_cache:\n        return hash_cache[x]\n    else:\n        ret = _hash(x)\n        hash_cache[x] = ret\n        return ret\n\n\n# Access to overwrite spec constants based on configuration\ndef apply_constants_preset(preset: Dict[str, Any]):\n    global_vars = globals()\n    for k, v in preset.items():\n        global_vars[k] = v\n\n    # Deal with derived constants\n    global_vars['GENESIS_EPOCH'] = slot_to_epoch(GENESIS_SLOT)\n\n    # Initialize SSZ types again, to account for changed lengths\n    init_SSZ_types()\n'''\n\n\ndef objects_to_spec(functions: Dict[str, str],\n                    constants: Dict[str, str],\n                    ssz_objects: Dict[str, str],\n                    inserts: Dict[str, str],\n                    imports: Dict[str, str],\n                    new_types: Dict[str, str],\n                    byte_types: List[int],\n                    ) -> str:\n    \"\"\"\n    Given all the objects that constitute a spec, combine them into a single pyfile.\n    \"\"\"\n    new_type_definitions = '\\n'.join(['Bytes%s = BytesN[%s]' % (n, n) for n in byte_types])\n    new_type_definitions += '\\n' + '\\n'.join(['Hash = Bytes32', 'BLSPubkey = Bytes48', 'BLSSignature = Bytes96'])\n    new_type_definitions += \\\n        '\\n' + '\\n'.join(['''%s = NewType('%s', %s)''' % (key, key, value) for key, value in new_types.items()])\n    functions_spec = '\\n\\n'.join(functions.values())\n    constants_spec = '\\n'.join(map(lambda x: '%s = %s' % (x, constants[x]), constants))\n    ssz_objects_instantiation_spec = '\\n\\n'.join(ssz_objects.values())\n    ssz_objects_reinitialization_spec = (\n        'def init_SSZ_types():\\n    global_vars = globals()\\n\\n    '\n        + '\\n\\n    '.join([re.sub(r'(?!\\n\\n)\\n', r'\\n    ', value[:-1]) for value in ssz_objects.values()])\n        + '\\n\\n'\n        + '\\n'.join(map(lambda x: '    global_vars[\\'%s\\'] = %s' % (x, x), ssz_objects.keys()))\n    )\n    spec = (\n        imports\n        + '\\n' + new_type_definitions\n        + '\\n\\n' + constants_spec\n        + '\\n\\n\\n' + ssz_objects_instantiation_spec\n        + '\\n\\n' + functions_spec\n        + '\\n' + SUNDRY_FUNCTIONS\n        + '\\n\\n' + ssz_objects_reinitialization_spec\n        + '\\n'\n    )\n    # Handle @inserts\n    for key, value in inserts.items():\n        spec = re.sub('[ ]*# %s\\\\n' % key, value, spec)\n    return spec\n\n\ndef combine_functions(old_functions: Dict[str, str], new_functions: Dict[str, str]) -> Dict[str, str]:\n    for key, value in new_functions.items():\n        old_functions[key] = value\n    return old_functions\n\n\ndef combine_constants(old_constants: Dict[str, str], new_constants: Dict[str, str]) -> Dict[str, str]:\n    for key, value in new_constants.items():\n        old_constants[key] = value\n    return old_constants\n\n\ndef dependency_order_ssz_objects(objects: Dict[str, str]) -> None:\n    \"\"\"\n    Determines which SSZ Object is depenedent on which other and orders them appropriately\n    \"\"\"\n    items = list(objects.items())\n    for key, value in items:\n        dependencies = re.findall(r'(: [A-Z][\\w[]*)', value)\n        dependencies = map(lambda x: re.sub(r'\\W|Vector|List|Container|Hash|BLSPubkey|BLSSignature|uint\\d+|Bytes\\d+|bytes', '', x), dependencies)\n        for dep in dependencies:\n            if dep in NEW_TYPES or len(dep) == 0:\n                continue\n            key_list = list(objects.keys())\n            for item in [dep, key] + key_list[key_list.index(dep)+1:]:\n                objects[item] = objects.pop(item)\n\n\ndef combine_ssz_objects(old_objects: Dict[str, str], new_objects: Dict[str, str]) -> Dict[str, str]:\n    \"\"\"\n    Takes in old spec and new spec ssz objects, combines them,\n    and returns the newer versions of the objects in dependency order.\n    \"\"\"\n    for key, value in new_objects.items():\n        if key in old_objects:\n            # remove trailing newline\n            old_objects[key] = old_objects[key]\n            # remove leading variable name\n            value = re.sub(r'^class [\\w]*\\(Container\\):\\n', '', value)\n        old_objects[key] = old_objects.get(key, '') + value\n    dependency_order_ssz_objects(old_objects)\n    return old_objects\n\n\n# inserts are handeled the same way as functions\ncombine_inserts = combine_functions\n\n\ndef combine_spec_objects(spec0: SpecObject, spec1: SpecObject) -> SpecObject:\n    \"\"\"\n    Takes in two spec variants (as tuples of their objects) and combines them using the appropriate combiner function.\n    \"\"\"\n    functions0, constants0, ssz_objects0, inserts0 = spec0\n    functions1, constants1, ssz_objects1, inserts1 = spec1\n    functions = combine_functions(functions0, functions1)\n    constants = combine_constants(constants0, constants1)\n    ssz_objects = combine_ssz_objects(ssz_objects0, ssz_objects1)\n    inserts = combine_inserts(inserts0, inserts1)\n    return functions, constants, ssz_objects, inserts\n\n\ndef build_phase0_spec(sourcefile: str, outfile: str=None) -> Optional[str]:\n    functions, constants, ssz_objects, inserts = get_spec(sourcefile)\n    spec = objects_to_spec(functions, constants, ssz_objects, inserts, PHASE0_IMPORTS, NEW_TYPES, BYTE_TYPES)\n    if outfile is not None:\n        with open(outfile, 'w') as out:\n            out.write(spec)\n    return spec\n\n\ndef build_phase1_spec(phase0_sourcefile: str,\n                      phase1_custody_sourcefile: str,\n                      phase1_shard_sourcefile: str,\n                      outfile: str=None) -> Optional[str]:\n    phase0_spec = get_spec(phase0_sourcefile)\n    phase1_custody = get_spec(phase1_custody_sourcefile)\n    phase1_shard_data = get_spec(phase1_shard_sourcefile)\n    spec_objects = phase0_spec\n    for value in [phase1_custody, phase1_shard_data]:\n        spec_objects = combine_spec_objects(spec_objects, value)\n    spec = objects_to_spec(*spec_objects, PHASE1_IMPORTS, NEW_TYPES, BYTE_TYPES)\n    if outfile is not None:\n        with open(outfile, 'w') as out:\n            out.write(spec)\n    return spec\n\n\nif __name__ == '__main__':\n    description = '''\nBuild the specs from the md docs.\nIf building phase 0:\n    1st argument is input spec.md\n    2nd argument is output spec.py\n\nIf building phase 1:\n    1st argument is input spec_phase0.md\n    2nd argument is input spec_phase1_custody.md\n    3rd argument is input spec_phase1_shard_data.md\n    4th argument is output spec.py\n'''\n    parser = ArgumentParser(description=description)\n    parser.add_argument(\"-p\", \"--phase\", dest=\"phase\", type=int, default=0, help=\"Build for phase #\")\n    parser.add_argument(dest=\"files\", help=\"Input and output files\", nargs=\"+\")\n\n    args = parser.parse_args()\n    if args.phase == 0:\n        if len(args.files) == 2:\n            build_phase0_spec(*args.files)\n        else:\n            print(\" Phase 0 requires an output as well as an input file.\")\n    elif args.phase == 1:\n        if len(args.files) == 4:\n            build_phase1_spec(*args.files)\n        else:\n            print(\" Phase 1 requires an output as well as 3 input files (phase0.md and phase1.md, phase1.md)\")\n    else:\n        print(\"Invalid phase: {0}\".format(args.phase))\n", "path": "scripts/build_spec.py"}]}