mirror of
https://github.com/status-im/eth2.0-specs.git
synced 2025-02-02 13:53:27 +00:00
EIP-4844: Make the spec executable
- Implement all the required glue code to make things executable - Implement a dummy KZG trusted setup Co-authored-by: Hsiao-Wei Wang <hsiaowei.eth@gmail.com>
This commit is contained in:
parent
5b9bf41de6
commit
567a25f883
@ -142,7 +142,19 @@ jobs:
|
||||
command: make citest fork=capella
|
||||
- store_test_results:
|
||||
path: tests/core/pyspec/test-reports
|
||||
|
||||
test-eip4844:
|
||||
docker:
|
||||
- image: circleci/python:3.8
|
||||
working_directory: ~/specs-repo
|
||||
steps:
|
||||
- restore_cache:
|
||||
key: v3-specs-repo-{{ .Branch }}-{{ .Revision }}
|
||||
- restore_pyspec_cached_venv
|
||||
- run:
|
||||
name: Run py-tests
|
||||
command: make citest fork=eip4844
|
||||
- store_test_results:
|
||||
path: tests/core/pyspec/test-reports
|
||||
table_of_contents:
|
||||
docker:
|
||||
- image: circleci/node:10.16.3
|
||||
@ -260,6 +272,9 @@ workflows:
|
||||
- test-capella:
|
||||
requires:
|
||||
- install_pyspec_test
|
||||
- test-eip4844:
|
||||
requires:
|
||||
- install_pyspec_test
|
||||
- table_of_contents
|
||||
- codespell
|
||||
- lint:
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -19,6 +19,7 @@ tests/core/pyspec/eth2spec/phase0/
|
||||
tests/core/pyspec/eth2spec/altair/
|
||||
tests/core/pyspec/eth2spec/bellatrix/
|
||||
tests/core/pyspec/eth2spec/capella/
|
||||
tests/core/pyspec/eth2spec/eip4844/
|
||||
|
||||
# coverage reports
|
||||
.htmlcov
|
||||
|
2
Makefile
2
Makefile
@ -136,7 +136,7 @@ codespell:
|
||||
lint: pyspec
|
||||
. venv/bin/activate; cd $(PY_SPEC_DIR); \
|
||||
flake8 --config $(LINTER_CONFIG_FILE) ./eth2spec \
|
||||
&& pylint --disable=all --enable unused-argument ./eth2spec/phase0 ./eth2spec/altair ./eth2spec/bellatrix \
|
||||
&& pylint --disable=all --enable unused-argument ./eth2spec/phase0 ./eth2spec/altair ./eth2spec/bellatrix ./eth2spec/capella \
|
||||
&& mypy --config-file $(LINTER_CONFIG_FILE) -p eth2spec.phase0 -p eth2spec.altair -p eth2spec.bellatrix -p eth2spec.capella
|
||||
|
||||
lint_generators: pyspec
|
||||
|
@ -47,9 +47,9 @@ BELLATRIX_FORK_EPOCH: 18446744073709551615
|
||||
# Capella
|
||||
CAPELLA_FORK_VERSION: 0x03000000
|
||||
CAPELLA_FORK_EPOCH: 18446744073709551615
|
||||
# Sharding
|
||||
SHARDING_FORK_VERSION: 0x04000000
|
||||
SHARDING_FORK_EPOCH: 18446744073709551615
|
||||
# EIP4844
|
||||
EIP4844_FORK_VERSION: 0x04000000
|
||||
EIP4844_FORK_EPOCH: 18446744073709551615
|
||||
|
||||
|
||||
|
||||
|
@ -46,9 +46,9 @@ BELLATRIX_FORK_EPOCH: 18446744073709551615
|
||||
# Capella
|
||||
CAPELLA_FORK_VERSION: 0x03000001
|
||||
CAPELLA_FORK_EPOCH: 18446744073709551615
|
||||
# Sharding
|
||||
SHARDING_FORK_VERSION: 0x04000001
|
||||
SHARDING_FORK_EPOCH: 18446744073709551615
|
||||
# EIP4844
|
||||
EIP4844_FORK_VERSION: 0x04000001
|
||||
EIP4844_FORK_EPOCH: 18446744073709551615
|
||||
|
||||
|
||||
# Time parameters
|
||||
|
8
presets/mainnet/eip4844.yaml
Normal file
8
presets/mainnet/eip4844.yaml
Normal file
@ -0,0 +1,8 @@
|
||||
# Mainnet preset - Phase0
|
||||
|
||||
# Misc
|
||||
# ---------------------------------------------------------------
|
||||
# `uint64(4096)`
|
||||
FIELD_ELEMENTS_PER_BLOB: 4096
|
||||
# `uint64(2**4)` (= 16)
|
||||
MAX_BLOBS_PER_BLOCK: 16
|
8
presets/minimal/eip4844.yaml
Normal file
8
presets/minimal/eip4844.yaml
Normal file
@ -0,0 +1,8 @@
|
||||
# Minimal preset - Phase0
|
||||
|
||||
# Misc
|
||||
# ---------------------------------------------------------------
|
||||
# [customized]
|
||||
FIELD_ELEMENTS_PER_BLOB: 4
|
||||
# `uint64(2**4)` (= 16)
|
||||
MAX_BLOBS_PER_BLOCK: 16
|
79
setup.py
79
setup.py
@ -45,6 +45,7 @@ PHASE0 = 'phase0'
|
||||
ALTAIR = 'altair'
|
||||
BELLATRIX = 'bellatrix'
|
||||
CAPELLA = 'capella'
|
||||
EIP4844 = 'eip4844'
|
||||
|
||||
|
||||
# The helper functions that are used when defining constants
|
||||
@ -208,6 +209,9 @@ def get_spec(file_name: Path, preset: Dict[str, str], config: Dict[str, str]) ->
|
||||
elif source.startswith("class"):
|
||||
class_name, parent_class = _get_class_info_from_source(source)
|
||||
# check consistency with spec
|
||||
if class_name != current_name:
|
||||
print('class_name', class_name, 'current_name', current_name)
|
||||
|
||||
assert class_name == current_name
|
||||
if parent_class:
|
||||
assert parent_class == "Container"
|
||||
@ -230,7 +234,7 @@ def get_spec(file_name: Path, preset: Dict[str, str], config: Dict[str, str]) ->
|
||||
|
||||
if not _is_constant_id(name):
|
||||
# Check for short type declarations
|
||||
if value.startswith(("uint", "Bytes", "ByteList", "Union")):
|
||||
if value.startswith(("uint", "Bytes", "ByteList", "Union", "Vector", "List")):
|
||||
custom_types[name] = value
|
||||
continue
|
||||
|
||||
@ -304,7 +308,7 @@ class SpecBuilder(ABC):
|
||||
|
||||
@classmethod
|
||||
@abstractmethod
|
||||
def hardcoded_custom_type_dep_constants(cls) -> Dict[str, str]: # TODO
|
||||
def hardcoded_custom_type_dep_constants(cls, spec_object) -> Dict[str, str]: # TODO
|
||||
"""
|
||||
The constants that are required for custom types.
|
||||
"""
|
||||
@ -432,7 +436,7 @@ get_attesting_indices = cache_this(
|
||||
return {}
|
||||
|
||||
@classmethod
|
||||
def hardcoded_custom_type_dep_constants(cls) -> Dict[str, str]:
|
||||
def hardcoded_custom_type_dep_constants(cls, spec_object) -> Dict[str, str]:
|
||||
return {}
|
||||
|
||||
@classmethod
|
||||
@ -547,11 +551,11 @@ EXECUTION_ENGINE = NoopExecutionEngine()"""
|
||||
|
||||
|
||||
@classmethod
|
||||
def hardcoded_custom_type_dep_constants(cls) -> str:
|
||||
def hardcoded_custom_type_dep_constants(cls, spec_object) -> str:
|
||||
constants = {
|
||||
'MAX_BYTES_PER_TRANSACTION': 'uint64(2**30)',
|
||||
'MAX_BYTES_PER_TRANSACTION': spec_object.preset_vars['MAX_BYTES_PER_TRANSACTION'].value,
|
||||
}
|
||||
return {**super().hardcoded_custom_type_dep_constants(), **constants}
|
||||
return {**super().hardcoded_custom_type_dep_constants(spec_object), **constants}
|
||||
|
||||
|
||||
#
|
||||
@ -567,14 +571,57 @@ from eth2spec.bellatrix import {preset_name} as bellatrix
|
||||
'''
|
||||
|
||||
|
||||
#
|
||||
# EIP4844SpecBuilder
|
||||
#
|
||||
class EIP4844SpecBuilder(BellatrixSpecBuilder):
|
||||
fork: str = EIP4844
|
||||
|
||||
@classmethod
|
||||
def imports(cls, preset_name: str):
|
||||
return super().imports(preset_name) + f'''
|
||||
from eth2spec.utils import kzg
|
||||
from eth2spec.bellatrix import {preset_name} as bellatrix
|
||||
'''
|
||||
|
||||
@classmethod
|
||||
def sundry_functions(cls) -> str:
|
||||
return super().sundry_functions() + '''
|
||||
# TODO: for mainnet, load pre-generated trusted setup file to reduce building time.
|
||||
# TESTING_FIELD_ELEMENTS_PER_BLOB is hardcoded copy from minimal presets
|
||||
TESTING_FIELD_ELEMENTS_PER_BLOB = 4
|
||||
TESTING_SECRET = 1337
|
||||
TESTING_KZG_SETUP_G1 = kzg.generate_setup(bls.G1, TESTING_SECRET, TESTING_FIELD_ELEMENTS_PER_BLOB)
|
||||
TESTING_KZG_SETUP_G2 = kzg.generate_setup(bls.G2, TESTING_SECRET, TESTING_FIELD_ELEMENTS_PER_BLOB)
|
||||
TESTING_KZG_SETUP_LAGRANGE = kzg.get_lagrange(TESTING_KZG_SETUP_G1)
|
||||
|
||||
KZG_SETUP_G1 = [bls.G1_to_bytes48(p) for p in TESTING_KZG_SETUP_G1]
|
||||
KZG_SETUP_G2 = [bls.G2_to_bytes96(p) for p in TESTING_KZG_SETUP_G2]
|
||||
KZG_SETUP_LAGRANGE = TESTING_KZG_SETUP_LAGRANGE
|
||||
ROOTS_OF_UNITY = kzg.compute_roots_of_unity(TESTING_FIELD_ELEMENTS_PER_BLOB)
|
||||
|
||||
|
||||
def retrieve_blobs_sidecar(slot: Slot, beacon_block_root: Root) -> BlobsSidecar:
|
||||
pass'''
|
||||
|
||||
@classmethod
|
||||
def hardcoded_custom_type_dep_constants(cls, spec_object) -> str:
|
||||
constants = {
|
||||
'FIELD_ELEMENTS_PER_BLOB': spec_object.preset_vars['FIELD_ELEMENTS_PER_BLOB'].value,
|
||||
'MAX_BLOBS_PER_BLOCK': spec_object.preset_vars['MAX_BLOBS_PER_BLOCK'].value,
|
||||
}
|
||||
return {**super().hardcoded_custom_type_dep_constants(spec_object), **constants}
|
||||
|
||||
|
||||
|
||||
spec_builders = {
|
||||
builder.fork: builder
|
||||
for builder in (Phase0SpecBuilder, AltairSpecBuilder, BellatrixSpecBuilder, CapellaSpecBuilder)
|
||||
for builder in (Phase0SpecBuilder, AltairSpecBuilder, BellatrixSpecBuilder, CapellaSpecBuilder, EIP4844SpecBuilder)
|
||||
}
|
||||
|
||||
|
||||
def is_spec_defined_type(value: str) -> bool:
|
||||
return value.startswith('ByteList') or value.startswith('Union')
|
||||
return value.startswith(('ByteList', 'Union', 'Vector', 'List'))
|
||||
|
||||
|
||||
def objects_to_spec(preset_name: str,
|
||||
@ -652,7 +699,7 @@ def objects_to_spec(preset_name: str,
|
||||
ordered_class_objects_spec = '\n\n\n'.join(ordered_class_objects.values())
|
||||
ssz_dep_constants = '\n'.join(map(lambda x: '%s = %s' % (x, builder.hardcoded_ssz_dep_constants()[x]), builder.hardcoded_ssz_dep_constants()))
|
||||
ssz_dep_constants_verification = '\n'.join(map(lambda x: 'assert %s == %s' % (x, spec_object.ssz_dep_constants[x]), builder.hardcoded_ssz_dep_constants()))
|
||||
custom_type_dep_constants = '\n'.join(map(lambda x: '%s = %s' % (x, builder.hardcoded_custom_type_dep_constants()[x]), builder.hardcoded_custom_type_dep_constants()))
|
||||
custom_type_dep_constants = '\n'.join(map(lambda x: '%s = %s' % (x, builder.hardcoded_custom_type_dep_constants(spec_object)[x]), builder.hardcoded_custom_type_dep_constants(spec_object)))
|
||||
spec = (
|
||||
builder.imports(preset_name)
|
||||
+ builder.preparations()
|
||||
@ -869,14 +916,14 @@ class PySpecCommand(Command):
|
||||
if len(self.md_doc_paths) == 0:
|
||||
print("no paths were specified, using default markdown file paths for pyspec"
|
||||
" build (spec fork: %s)" % self.spec_fork)
|
||||
if self.spec_fork in (PHASE0, ALTAIR, BELLATRIX, CAPELLA):
|
||||
if self.spec_fork in (PHASE0, ALTAIR, BELLATRIX, CAPELLA, EIP4844):
|
||||
self.md_doc_paths = """
|
||||
specs/phase0/beacon-chain.md
|
||||
specs/phase0/fork-choice.md
|
||||
specs/phase0/validator.md
|
||||
specs/phase0/weak-subjectivity.md
|
||||
"""
|
||||
if self.spec_fork in (ALTAIR, BELLATRIX, CAPELLA):
|
||||
if self.spec_fork in (ALTAIR, BELLATRIX, CAPELLA, EIP4844):
|
||||
self.md_doc_paths += """
|
||||
specs/altair/beacon-chain.md
|
||||
specs/altair/bls.md
|
||||
@ -885,7 +932,7 @@ class PySpecCommand(Command):
|
||||
specs/altair/p2p-interface.md
|
||||
specs/altair/sync-protocol.md
|
||||
"""
|
||||
if self.spec_fork in (BELLATRIX, CAPELLA):
|
||||
if self.spec_fork in (BELLATRIX, CAPELLA, EIP4844):
|
||||
self.md_doc_paths += """
|
||||
specs/bellatrix/beacon-chain.md
|
||||
specs/bellatrix/fork.md
|
||||
@ -902,6 +949,14 @@ class PySpecCommand(Command):
|
||||
specs/capella/validator.md
|
||||
specs/capella/p2p-interface.md
|
||||
"""
|
||||
if self.spec_fork == EIP4844:
|
||||
self.md_doc_paths += """
|
||||
specs/eip4844/beacon-chain.md
|
||||
specs/eip4844/fork.md
|
||||
specs/eip4844/polynomial-commitments.md
|
||||
specs/eip4844/p2p-interface.md
|
||||
specs/eip4844/validator.md
|
||||
"""
|
||||
if len(self.md_doc_paths) == 0:
|
||||
raise Exception('no markdown files specified, and spec fork "%s" is unknown', self.spec_fork)
|
||||
|
||||
|
@ -51,7 +51,7 @@ def pytest_addoption(parser):
|
||||
|
||||
def _validate_fork_name(forks):
|
||||
for fork in forks:
|
||||
if fork not in ALL_PHASES:
|
||||
if fork not in set(ALL_PHASES):
|
||||
raise ValueError(
|
||||
f'The given --fork argument "{fork}" is not an available fork.'
|
||||
f' The available forks: {ALL_PHASES}'
|
||||
|
@ -7,13 +7,14 @@ from eth2spec.phase0 import mainnet as spec_phase0_mainnet, minimal as spec_phas
|
||||
from eth2spec.altair import mainnet as spec_altair_mainnet, minimal as spec_altair_minimal
|
||||
from eth2spec.bellatrix import mainnet as spec_bellatrix_mainnet, minimal as spec_bellatrix_minimal
|
||||
from eth2spec.capella import mainnet as spec_capella_mainnet, minimal as spec_capella_minimal
|
||||
from eth2spec.eip4844 import mainnet as spec_eip4844_mainnet, minimal as spec_eip4844_minimal
|
||||
from eth2spec.utils import bls
|
||||
|
||||
from .exceptions import SkippedTest
|
||||
from .helpers.constants import (
|
||||
PHASE0, ALTAIR, BELLATRIX, CAPELLA,
|
||||
PHASE0, ALTAIR, BELLATRIX, CAPELLA, EIP4844,
|
||||
MINIMAL, MAINNET,
|
||||
ALL_PHASES, FORKS_BEFORE_ALTAIR, FORKS_BEFORE_BELLATRIX, FORKS_BEFORE_CAPELLA,
|
||||
ALL_PHASES, FORKS_BEFORE_ALTAIR, FORKS_BEFORE_BELLATRIX,
|
||||
ALL_FORK_UPGRADES,
|
||||
)
|
||||
from .helpers.typing import SpecForkName, PresetBaseName
|
||||
@ -76,12 +77,14 @@ spec_targets: Dict[PresetBaseName, Dict[SpecForkName, Spec]] = {
|
||||
ALTAIR: spec_altair_minimal,
|
||||
BELLATRIX: spec_bellatrix_minimal,
|
||||
CAPELLA: spec_capella_minimal,
|
||||
EIP4844: spec_eip4844_minimal,
|
||||
},
|
||||
MAINNET: {
|
||||
PHASE0: spec_phase0_mainnet,
|
||||
ALTAIR: spec_altair_mainnet,
|
||||
BELLATRIX: spec_bellatrix_mainnet,
|
||||
CAPELLA: spec_capella_mainnet,
|
||||
EIP4844: spec_eip4844_mainnet
|
||||
},
|
||||
}
|
||||
|
||||
@ -576,12 +579,13 @@ def is_post_bellatrix(spec):
|
||||
|
||||
|
||||
def is_post_capella(spec):
|
||||
return spec.fork not in FORKS_BEFORE_CAPELLA
|
||||
return spec.fork == CAPELLA
|
||||
|
||||
|
||||
with_altair_and_later = with_all_phases_except([PHASE0])
|
||||
with_bellatrix_and_later = with_all_phases_except([PHASE0, ALTAIR])
|
||||
with_capella_and_later = with_all_phases_except([PHASE0, ALTAIR, BELLATRIX])
|
||||
with_capella_and_later = with_all_phases_except([PHASE0, ALTAIR, BELLATRIX, EIP4844])
|
||||
with_eip4844_and_later = with_all_phases_except([PHASE0, ALTAIR, BELLATRIX, CAPELLA])
|
||||
|
||||
|
||||
def only_generator(reason):
|
||||
|
@ -14,9 +14,15 @@ CAPELLA = SpecForkName('capella')
|
||||
SHARDING = SpecForkName('sharding')
|
||||
CUSTODY_GAME = SpecForkName('custody_game')
|
||||
DAS = SpecForkName('das')
|
||||
EIP4844 = SpecForkName('eip4844')
|
||||
|
||||
# The forks that pytest runs with.
|
||||
ALL_PHASES = (PHASE0, ALTAIR, BELLATRIX, CAPELLA)
|
||||
# The forks that pytest can run with.
|
||||
ALL_PHASES = (
|
||||
# Formal forks
|
||||
PHASE0, ALTAIR, BELLATRIX, CAPELLA,
|
||||
# Experimental patches
|
||||
EIP4844,
|
||||
)
|
||||
# The forks that output to the test vectors.
|
||||
TESTGEN_FORKS = (PHASE0, ALTAIR, BELLATRIX)
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
from eth2spec.test.helpers.constants import FORKS_BEFORE_CAPELLA
|
||||
from eth2spec.test.context import is_post_capella
|
||||
|
||||
|
||||
def build_empty_execution_payload(spec, state, randao_mix=None):
|
||||
@ -28,7 +28,7 @@ def build_empty_execution_payload(spec, state, randao_mix=None):
|
||||
block_hash=spec.Hash32(),
|
||||
transactions=empty_txs,
|
||||
)
|
||||
if spec.fork not in FORKS_BEFORE_CAPELLA:
|
||||
if is_post_capella(spec):
|
||||
num_withdrawals = min(spec.MAX_WITHDRAWALS_PER_PAYLOAD, len(state.withdrawal_queue))
|
||||
payload.withdrawals = state.withdrawal_queue[:num_withdrawals]
|
||||
|
||||
@ -55,7 +55,7 @@ def get_execution_payload_header(spec, execution_payload):
|
||||
block_hash=execution_payload.block_hash,
|
||||
transactions_root=spec.hash_tree_root(execution_payload.transactions)
|
||||
)
|
||||
if spec.fork not in FORKS_BEFORE_CAPELLA:
|
||||
if is_post_capella(spec):
|
||||
payload_header.withdrawals_root = spec.hash_tree_root(execution_payload.withdrawals)
|
||||
return payload_header
|
||||
|
||||
|
@ -13,6 +13,7 @@ from eth2spec.test.helpers.constants import (
|
||||
ALTAIR,
|
||||
BELLATRIX,
|
||||
CAPELLA,
|
||||
EIP4844,
|
||||
)
|
||||
from eth2spec.test.helpers.deposits import (
|
||||
prepare_state_and_deposit,
|
||||
@ -150,6 +151,8 @@ def do_fork(state, spec, post_spec, fork_epoch, with_block=True, operation_dict=
|
||||
state = post_spec.upgrade_to_bellatrix(state)
|
||||
elif post_spec.fork == CAPELLA:
|
||||
state = post_spec.upgrade_to_capella(state)
|
||||
elif post_spec.fork == EIP4844:
|
||||
state = post_spec.upgrade_to_eip4844(state)
|
||||
|
||||
assert state.fork.epoch == fork_epoch
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
from eth2spec.test.helpers.constants import (
|
||||
ALTAIR, BELLATRIX,
|
||||
FORKS_BEFORE_ALTAIR, FORKS_BEFORE_BELLATRIX, FORKS_BEFORE_CAPELLA,
|
||||
ALTAIR, BELLATRIX, CAPELLA,
|
||||
FORKS_BEFORE_ALTAIR, FORKS_BEFORE_BELLATRIX,
|
||||
)
|
||||
from eth2spec.test.helpers.keys import pubkeys
|
||||
|
||||
@ -20,7 +20,7 @@ def build_mock_validator(spec, i: int, balance: int):
|
||||
effective_balance=min(balance - balance % spec.EFFECTIVE_BALANCE_INCREMENT, spec.MAX_EFFECTIVE_BALANCE)
|
||||
)
|
||||
|
||||
if spec.fork not in FORKS_BEFORE_CAPELLA:
|
||||
if spec.fork in (CAPELLA):
|
||||
validator.fully_withdrawn_epoch = spec.FAR_FUTURE_EPOCH
|
||||
|
||||
return validator
|
||||
|
81
tests/core/pyspec/eth2spec/test/helpers/sharding.py
Normal file
81
tests/core/pyspec/eth2spec/test/helpers/sharding.py
Normal file
@ -0,0 +1,81 @@
|
||||
import random
|
||||
from eth2spec.utils.ssz.ssz_typing import (
|
||||
Container,
|
||||
Bytes20, Bytes32,
|
||||
ByteList,
|
||||
List,
|
||||
Union,
|
||||
boolean,
|
||||
uint256, uint64,
|
||||
)
|
||||
from eth2spec.utils.ssz.ssz_impl import serialize
|
||||
|
||||
|
||||
#
|
||||
# Containers from EIP-4844
|
||||
#
|
||||
MAX_CALLDATA_SIZE = 2**24
|
||||
MAX_VERSIONED_HASHES_LIST_SIZE = 2**24
|
||||
MAX_ACCESS_LIST_STORAGE_KEYS = 2**24
|
||||
MAX_ACCESS_LIST_SIZE = 2**24
|
||||
|
||||
|
||||
class AccessTuple(Container):
|
||||
address: Bytes20 # Address = Bytes20
|
||||
storage_keys: List[Bytes32, MAX_ACCESS_LIST_STORAGE_KEYS]
|
||||
|
||||
|
||||
class ECDSASignature(Container):
|
||||
y_parity: boolean
|
||||
r: uint256
|
||||
s: uint256
|
||||
|
||||
|
||||
class BlobTransaction(Container):
|
||||
chain_id: uint256
|
||||
nonce: uint64
|
||||
priority_fee_per_gas: uint256
|
||||
max_basefee_per_gas: uint256
|
||||
gas: uint64
|
||||
to: Union[None, Bytes20] # Address = Bytes20
|
||||
value: uint256
|
||||
data: ByteList[MAX_CALLDATA_SIZE]
|
||||
access_list: List[AccessTuple, MAX_ACCESS_LIST_SIZE]
|
||||
blob_versioned_hashes: List[Bytes32, MAX_VERSIONED_HASHES_LIST_SIZE]
|
||||
|
||||
|
||||
class SignedBlobTransaction(Container):
|
||||
message: BlobTransaction
|
||||
signature: ECDSASignature
|
||||
|
||||
|
||||
def get_sample_blob(spec, rng=None):
|
||||
if rng is None:
|
||||
rng = random.Random(5566)
|
||||
|
||||
return spec.Blob([
|
||||
rng.randint(0, spec.BLS_MODULUS - 1)
|
||||
for _ in range(spec.FIELD_ELEMENTS_PER_BLOB)
|
||||
])
|
||||
|
||||
|
||||
def get_sample_opaque_tx(spec, blob_count=1, rng=None):
|
||||
blobs = []
|
||||
blob_kzg_commitments = []
|
||||
blob_versioned_hashes = []
|
||||
for _ in range(blob_count):
|
||||
blob = get_sample_blob(spec, rng)
|
||||
blob_commitment = spec.KZGCommitment(spec.blob_to_kzg_commitment(blob))
|
||||
blob_versioned_hash = spec.kzg_commitment_to_versioned_hash(blob_commitment)
|
||||
blobs.append(blob)
|
||||
blob_kzg_commitments.append(blob_commitment)
|
||||
blob_versioned_hashes.append(blob_versioned_hash)
|
||||
|
||||
signed_blob_tx = SignedBlobTransaction(
|
||||
message=BlobTransaction(
|
||||
blob_versioned_hashes=blob_versioned_hashes,
|
||||
)
|
||||
)
|
||||
serialized_tx = serialize(signed_blob_tx)
|
||||
opaque_tx = spec.uint_to_bytes(spec.BLOB_TX_TYPE) + serialized_tx
|
||||
return opaque_tx, blobs, blob_kzg_commitments
|
@ -45,6 +45,7 @@ from eth2spec.test.context import (
|
||||
@with_all_phases
|
||||
@spec_state_test
|
||||
def test_prev_slot_block_transition(spec, state):
|
||||
print('spec.fork', spec.fork)
|
||||
# Go to clean slot
|
||||
spec.process_slots(state, state.slot + 1)
|
||||
# Make a block for it
|
||||
|
@ -1,7 +1,7 @@
|
||||
from eth2spec.test.context import with_all_phases, spec_state_test
|
||||
from eth2spec.test.helpers.block import build_empty_block_for_next_slot
|
||||
from eth2spec.test.helpers.attestations import get_valid_attestation, sign_attestation
|
||||
from eth2spec.test.helpers.constants import PHASE0, ALTAIR, BELLATRIX, CAPELLA
|
||||
from eth2spec.test.helpers.constants import ALL_PHASES
|
||||
from eth2spec.test.helpers.state import transition_to, state_transition_and_sign_block, next_epoch, next_slot
|
||||
from eth2spec.test.helpers.fork_choice import get_genesis_forkchoice_store
|
||||
|
||||
@ -19,7 +19,7 @@ def run_on_attestation(spec, state, store, attestation, valid=True):
|
||||
spec.on_attestation(store, attestation)
|
||||
|
||||
sample_index = indexed_attestation.attesting_indices[0]
|
||||
if spec.fork in (PHASE0, ALTAIR, BELLATRIX, CAPELLA):
|
||||
if spec.fork in ALL_PHASES:
|
||||
latest_message = spec.LatestMessage(
|
||||
epoch=attestation.data.target.epoch,
|
||||
root=attestation.data.beacon_block_root,
|
||||
|
@ -1,5 +1,25 @@
|
||||
from py_ecc.bls import G2ProofOfPossession as py_ecc_bls
|
||||
from py_ecc.bls.g2_primatives import signature_to_G2 as _signature_to_G2
|
||||
from py_ecc.optimized_bls12_381 import ( # noqa: F401
|
||||
G1,
|
||||
G2,
|
||||
Z1,
|
||||
Z2,
|
||||
add,
|
||||
multiply,
|
||||
neg,
|
||||
pairing,
|
||||
final_exponentiate,
|
||||
FQ12
|
||||
)
|
||||
from py_ecc.bls.g2_primitives import ( # noqa: F401
|
||||
G1_to_pubkey as G1_to_bytes48,
|
||||
pubkey_to_G1 as bytes48_to_G1,
|
||||
G2_to_signature as G2_to_bytes96,
|
||||
signature_to_G2 as bytes96_to_G2,
|
||||
)
|
||||
|
||||
|
||||
import milagro_bls_binding as milagro_bls # noqa: F401 for BLS switching option
|
||||
|
||||
# Flag to make BLS active or not. Used for testing, do not ignore BLS in production unless you know what you are doing.
|
||||
@ -109,3 +129,12 @@ def SkToPk(SK):
|
||||
return bls.SkToPk(SK)
|
||||
else:
|
||||
return bls.SkToPk(SK.to_bytes(32, 'big'))
|
||||
|
||||
|
||||
def pairing_check(values):
|
||||
p_q_1, p_q_2 = values
|
||||
final_exponentiation = final_exponentiate(
|
||||
pairing(p_q_1[1], p_q_1[0], final_exponentiate=False)
|
||||
* pairing(p_q_2[1], p_q_2[0], final_exponentiate=False)
|
||||
)
|
||||
return final_exponentiation == FQ12.one()
|
||||
|
80
tests/core/pyspec/eth2spec/utils/kzg.py
Normal file
80
tests/core/pyspec/eth2spec/utils/kzg.py
Normal file
@ -0,0 +1,80 @@
|
||||
# Ref:
|
||||
# - https://github.com/ethereum/research/blob/8f084630528ba33d92b2bc05edf5338dd193c6f1/trusted_setup/trusted_setup.py
|
||||
# - https://github.com/asn-d6/kzgverify
|
||||
from py_ecc.optimized_bls12_381 import ( # noqa: F401
|
||||
G1,
|
||||
G2,
|
||||
Z1,
|
||||
Z2,
|
||||
curve_order as BLS_MODULUS,
|
||||
add,
|
||||
multiply,
|
||||
neg,
|
||||
)
|
||||
from eth2spec.utils import bls
|
||||
|
||||
|
||||
PRIMITIVE_ROOT_OF_UNITY = 7
|
||||
|
||||
|
||||
def generate_setup(generator, secret, length):
|
||||
"""
|
||||
Generate trusted setup of ``generator`` in ``length``.
|
||||
"""
|
||||
result = [generator]
|
||||
for _ in range(1, length):
|
||||
result.append(multiply(result[-1], secret))
|
||||
return tuple(result)
|
||||
|
||||
|
||||
def fft(vals, modulus, domain):
|
||||
"""
|
||||
FFT for group elements
|
||||
"""
|
||||
if len(vals) == 1:
|
||||
return vals
|
||||
L = fft(vals[::2], modulus, domain[::2])
|
||||
R = fft(vals[1::2], modulus, domain[::2])
|
||||
o = [0] * len(vals)
|
||||
for i, (x, y) in enumerate(zip(L, R)):
|
||||
y_times_root = multiply(y, domain[i])
|
||||
o[i] = add(x, y_times_root)
|
||||
o[i + len(L)] = add(x, neg(y_times_root))
|
||||
return o
|
||||
|
||||
|
||||
def compute_root_of_unity(length) -> int:
|
||||
"""
|
||||
Generate a w such that ``w**length = 1``.
|
||||
"""
|
||||
assert (BLS_MODULUS - 1) % length == 0
|
||||
return pow(PRIMITIVE_ROOT_OF_UNITY, (BLS_MODULUS - 1) // length, BLS_MODULUS)
|
||||
|
||||
|
||||
def compute_roots_of_unity(field_elements_per_blob):
|
||||
"""
|
||||
Compute a list of roots of unity for a given order.
|
||||
The order must divide the BLS multiplicative group order, i.e. BLS_MODULUS - 1
|
||||
"""
|
||||
assert (BLS_MODULUS - 1) % field_elements_per_blob == 0
|
||||
root_of_unity = compute_root_of_unity(length=field_elements_per_blob)
|
||||
|
||||
roots = []
|
||||
current_root_of_unity = 1
|
||||
for _ in range(field_elements_per_blob):
|
||||
roots.append(current_root_of_unity)
|
||||
current_root_of_unity = current_root_of_unity * root_of_unity % BLS_MODULUS
|
||||
return roots
|
||||
|
||||
|
||||
def get_lagrange(setup):
|
||||
"""
|
||||
Convert a G1 or G2 portion of a setup into the Lagrange basis.
|
||||
"""
|
||||
root_of_unity = compute_root_of_unity(len(setup))
|
||||
assert pow(root_of_unity, len(setup), BLS_MODULUS) == 1
|
||||
domain = [pow(root_of_unity, i, BLS_MODULUS) for i in range(len(setup))]
|
||||
# TODO: introduce an IFFT function for simplicity
|
||||
fft_output = fft(setup, BLS_MODULUS, domain)
|
||||
inv_length = pow(len(setup), BLS_MODULUS - 2, BLS_MODULUS)
|
||||
return [bls.G1_to_bytes48(multiply(fft_output[-i], inv_length)) for i in range(len(fft_output))]
|
Loading…
x
Reference in New Issue
Block a user