-
Notifications
You must be signed in to change notification settings - Fork 0
feat(test-specs): add container definitions for ssz-engine api #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: ssz/master
Are you sure you want to change the base?
Changes from all commits
2a1bc92
351d603
3bbb42a
d51e841
b81a658
3c76516
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,311 @@ | ||
| """ | ||
| SSZ container types and helpers for the REST+SSZ Engine API. | ||
| """ | ||
|
|
||
| from typing import Any, Dict, Mapping, Sequence, Type, TypeVar | ||
|
|
||
| from remerkleable.complex import Container | ||
| from remerkleable.core import View | ||
|
|
||
| from .constants import ( | ||
| MAX_BYTES_PER_EXECUTION_REQUEST, | ||
| MAX_BYTES_PER_TX, | ||
| MAX_EXECUTION_REQUESTS_PER_PAYLOAD, | ||
| MAX_EXTRA_DATA_BYTES, | ||
| MAX_TXS_PER_PAYLOAD, | ||
| MAX_WITHDRAWALS_PER_PAYLOAD, | ||
| ) | ||
| from .containers import ( | ||
| BlobAndProofV1, | ||
| BlobAndProofV2, | ||
| BlobCellsAndProofs, | ||
| BlobsBundleV1, | ||
| BlobsBundleV2, | ||
| BlobsV1Request, | ||
| BlobsV1Response, | ||
| BlobsV2Request, | ||
| BlobsV2Response, | ||
| BlobsV3Response, | ||
| BlobsV4Request, | ||
| BlobsV4Response, | ||
| BlobV1Entry, | ||
| BlobV2Entry, | ||
| BlobV4Entry, | ||
| BodiesByHashRequest, | ||
| BodiesResponse, | ||
| BodyEntry, | ||
| BuiltPayloadAmsterdam, | ||
| BuiltPayloadCancun, | ||
| BuiltPayloadOsaka, | ||
| BuiltPayloadParis, | ||
| BuiltPayloadPrague, | ||
| BuiltPayloadShanghai, | ||
| CapabilitiesResponse, | ||
| ClientVersion, | ||
| ExecutionPayloadAmsterdam, | ||
| ExecutionPayloadBodyAmsterdam, | ||
| ExecutionPayloadBodyCancun, | ||
| ExecutionPayloadBodyOsaka, | ||
| ExecutionPayloadBodyParis, | ||
| ExecutionPayloadBodyPrague, | ||
| ExecutionPayloadBodyShanghai, | ||
| ExecutionPayloadCancun, | ||
| ExecutionPayloadEnvelopeAmsterdam, | ||
| ExecutionPayloadEnvelopeCancun, | ||
| ExecutionPayloadEnvelopeOsaka, | ||
| ExecutionPayloadEnvelopeParis, | ||
| ExecutionPayloadEnvelopePrague, | ||
| ExecutionPayloadEnvelopeShanghai, | ||
| ExecutionPayloadOsaka, | ||
| ExecutionPayloadParis, | ||
| ExecutionPayloadPrague, | ||
| ExecutionPayloadShanghai, | ||
| ForkchoiceState, | ||
| ForkchoiceUpdateAmsterdam, | ||
| ForkchoiceUpdateCancun, | ||
| ForkchoiceUpdateOsaka, | ||
| ForkchoiceUpdateParis, | ||
| ForkchoiceUpdatePrague, | ||
| ForkchoiceUpdateResponse, | ||
| ForkchoiceUpdateShanghai, | ||
| IdentityResponse, | ||
| PayloadAttributesAmsterdam, | ||
| PayloadAttributesCancun, | ||
| PayloadAttributesOsaka, | ||
| PayloadAttributesParis, | ||
| PayloadAttributesPrague, | ||
| PayloadAttributesShanghai, | ||
| PayloadStatus, | ||
| Withdrawal, | ||
| ) | ||
| from .random_value import ( | ||
| RandomizationMode, | ||
| deterministic_seed, | ||
| get_random_ssz_object, | ||
| ) | ||
| from .ssz_types import ( | ||
| Address, | ||
| Bloom, | ||
| Bytes4, | ||
| Bytes8, | ||
| Bytes32, | ||
| Bytes48, | ||
| Hash32, | ||
| Root, | ||
| VersionedHash, | ||
| ) | ||
|
|
||
| ViewT = TypeVar("ViewT", bound=View) | ||
|
|
||
|
|
||
| def encode_bytes(value: View) -> bytes: | ||
| """Serialize an SSZ value to its canonical byte encoding.""" | ||
| return value.encode_bytes() | ||
|
|
||
|
|
||
| def decode_bytes(ssz_type: Type[ViewT], data: bytes) -> ViewT: | ||
| """Deserialize ``data`` into an SSZ value of ``ssz_type``.""" | ||
| return ssz_type.decode_bytes(data) | ||
|
|
||
|
|
||
| def hash_tree_root(value: View) -> bytes: | ||
| """Return the 32-byte SSZ `hash_tree_root` of an SSZ value.""" | ||
| return bytes(value.hash_tree_root()) | ||
|
|
||
|
|
||
| EXECUTION_PAYLOAD_BY_FORK: Dict[str, Type[Container]] = { | ||
| "Paris": ExecutionPayloadParis, | ||
| "Shanghai": ExecutionPayloadShanghai, | ||
| "Cancun": ExecutionPayloadCancun, | ||
| "Prague": ExecutionPayloadPrague, | ||
| "Osaka": ExecutionPayloadOsaka, | ||
| "Amsterdam": ExecutionPayloadAmsterdam, | ||
| } | ||
|
|
||
|
|
||
| EXECUTION_PAYLOAD_ENVELOPE_BY_FORK: Dict[str, Type[Container]] = { | ||
| "Paris": ExecutionPayloadEnvelopeParis, | ||
| "Shanghai": ExecutionPayloadEnvelopeShanghai, | ||
| "Cancun": ExecutionPayloadEnvelopeCancun, | ||
| "Prague": ExecutionPayloadEnvelopePrague, | ||
| "Osaka": ExecutionPayloadEnvelopeOsaka, | ||
| "Amsterdam": ExecutionPayloadEnvelopeAmsterdam, | ||
| } | ||
|
|
||
|
|
||
| def _build(cls: Any, fork: str, candidates: Mapping[str, Any]) -> View: | ||
| kwargs = {} | ||
| for name in cls.fields(): | ||
| value = candidates.get(name) | ||
| if value is None: | ||
| raise ValueError( | ||
| f"{cls.__name__} ({fork}) requires field {name!r}" | ||
| ) | ||
| kwargs[name] = value | ||
| return cls(**kwargs) | ||
|
|
||
|
|
||
| def envelope_bytes( | ||
| fork: str, | ||
| *, | ||
| parent_hash: bytes, | ||
| fee_recipient: bytes, | ||
| state_root: bytes, | ||
| receipts_root: bytes, | ||
| logs_bloom: bytes, | ||
|
Comment on lines
+148
to
+155
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't these be SSZ types?
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. envelope_bytes is intentionally a plain-values builder: callers pass ordinary bytes/int, and it wraps them into the SSZ containers internally, so plain parameter types are the arguments |
||
| prev_randao: bytes, | ||
| block_number: int, | ||
| gas_limit: int, | ||
| gas_used: int, | ||
| timestamp: int, | ||
| extra_data: bytes, | ||
| base_fee_per_gas: int, | ||
| block_hash: bytes, | ||
| transactions: Sequence[bytes], | ||
| withdrawals: Sequence[Mapping[str, Any]] | None = None, | ||
| blob_gas_used: int | None = None, | ||
| excess_blob_gas: int | None = None, | ||
| block_access_list: bytes | None = None, | ||
| slot_number: int | None = None, | ||
| parent_beacon_block_root: bytes | None = None, | ||
| execution_requests: Sequence[bytes] | None = None, | ||
| ) -> bytes: | ||
| """ | ||
| Build a fork's `newPayload` envelope from plain values and return its | ||
| canonical SSZ byte encoding. | ||
| """ | ||
| if fork not in EXECUTION_PAYLOAD_ENVELOPE_BY_FORK: | ||
| raise ValueError(f"unknown fork: {fork!r}") | ||
|
|
||
| def _opt_bytes(value: bytes | None) -> bytes | None: | ||
| return None if value is None else bytes(value) | ||
|
|
||
| payload_values: Mapping[str, Any] = { | ||
| "parent_hash": bytes(parent_hash), | ||
| "fee_recipient": bytes(fee_recipient), | ||
| "state_root": bytes(state_root), | ||
| "receipts_root": bytes(receipts_root), | ||
| "logs_bloom": bytes(logs_bloom), | ||
| "prev_randao": bytes(prev_randao), | ||
| "block_number": block_number, | ||
| "gas_limit": gas_limit, | ||
| "gas_used": gas_used, | ||
| "timestamp": timestamp, | ||
| "extra_data": bytes(extra_data), | ||
| "base_fee_per_gas": base_fee_per_gas, | ||
| "block_hash": bytes(block_hash), | ||
| "transactions": [bytes(tx) for tx in transactions], | ||
| "withdrawals": ( | ||
| None | ||
| if withdrawals is None | ||
| else [Withdrawal(**w) for w in withdrawals] | ||
| ), | ||
| "blob_gas_used": blob_gas_used, | ||
| "excess_blob_gas": excess_blob_gas, | ||
| "block_access_list": _opt_bytes(block_access_list), | ||
| "slot_number": slot_number, | ||
| } | ||
| payload = _build(EXECUTION_PAYLOAD_BY_FORK[fork], fork, payload_values) | ||
|
|
||
| envelope_values: Mapping[str, Any] = { | ||
| "payload": payload, | ||
| "parent_beacon_block_root": _opt_bytes(parent_beacon_block_root), | ||
| "execution_requests": ( | ||
| None | ||
| if execution_requests is None | ||
| else [bytes(r) for r in execution_requests] | ||
| ), | ||
| } | ||
| envelope = _build( | ||
| EXECUTION_PAYLOAD_ENVELOPE_BY_FORK[fork], fork, envelope_values | ||
| ) | ||
| return encode_bytes(envelope) | ||
|
|
||
|
|
||
| __all__ = ( | ||
| "EXECUTION_PAYLOAD_BY_FORK", | ||
| "EXECUTION_PAYLOAD_ENVELOPE_BY_FORK", | ||
| "Address", | ||
| "BlobAndProofV1", | ||
| "BlobAndProofV2", | ||
| "BlobCellsAndProofs", | ||
| "BlobsBundleV1", | ||
| "BlobsBundleV2", | ||
| "BlobsV1Request", | ||
| "BlobsV1Response", | ||
| "BlobsV2Request", | ||
| "BlobsV2Response", | ||
| "BlobsV3Response", | ||
| "BlobsV4Request", | ||
| "BlobsV4Response", | ||
| "BlobV1Entry", | ||
| "BlobV2Entry", | ||
| "BlobV4Entry", | ||
| "Bloom", | ||
| "BodiesByHashRequest", | ||
| "BodiesResponse", | ||
| "BodyEntry", | ||
| "BuiltPayloadAmsterdam", | ||
| "BuiltPayloadCancun", | ||
| "BuiltPayloadOsaka", | ||
| "BuiltPayloadParis", | ||
| "BuiltPayloadPrague", | ||
| "BuiltPayloadShanghai", | ||
| "Bytes32", | ||
| "Bytes4", | ||
| "Bytes48", | ||
| "Bytes8", | ||
| "CapabilitiesResponse", | ||
| "ClientVersion", | ||
| "ExecutionPayloadAmsterdam", | ||
| "ExecutionPayloadBodyAmsterdam", | ||
| "ExecutionPayloadBodyCancun", | ||
| "ExecutionPayloadBodyOsaka", | ||
| "ExecutionPayloadBodyParis", | ||
| "ExecutionPayloadBodyPrague", | ||
| "ExecutionPayloadBodyShanghai", | ||
| "ExecutionPayloadCancun", | ||
| "ExecutionPayloadEnvelopeAmsterdam", | ||
| "ExecutionPayloadEnvelopeCancun", | ||
| "ExecutionPayloadEnvelopeOsaka", | ||
| "ExecutionPayloadEnvelopeParis", | ||
| "ExecutionPayloadEnvelopePrague", | ||
| "ExecutionPayloadEnvelopeShanghai", | ||
| "ExecutionPayloadOsaka", | ||
| "ExecutionPayloadParis", | ||
| "ExecutionPayloadPrague", | ||
| "ExecutionPayloadShanghai", | ||
| "ForkchoiceState", | ||
| "ForkchoiceUpdateAmsterdam", | ||
| "ForkchoiceUpdateCancun", | ||
| "ForkchoiceUpdateOsaka", | ||
| "ForkchoiceUpdateParis", | ||
| "ForkchoiceUpdatePrague", | ||
| "ForkchoiceUpdateResponse", | ||
| "ForkchoiceUpdateShanghai", | ||
| "Hash32", | ||
| "IdentityResponse", | ||
| "MAX_BYTES_PER_EXECUTION_REQUEST", | ||
| "MAX_BYTES_PER_TX", | ||
| "MAX_EXECUTION_REQUESTS_PER_PAYLOAD", | ||
| "MAX_EXTRA_DATA_BYTES", | ||
| "MAX_TXS_PER_PAYLOAD", | ||
| "MAX_WITHDRAWALS_PER_PAYLOAD", | ||
| "PayloadAttributesAmsterdam", | ||
| "PayloadAttributesCancun", | ||
| "PayloadAttributesOsaka", | ||
| "PayloadAttributesParis", | ||
| "PayloadAttributesPrague", | ||
| "PayloadAttributesShanghai", | ||
| "PayloadStatus", | ||
| "RandomizationMode", | ||
| "Root", | ||
| "VersionedHash", | ||
| "Withdrawal", | ||
| "decode_bytes", | ||
| "deterministic_seed", | ||
| "encode_bytes", | ||
| "envelope_bytes", | ||
| "get_random_ssz_object", | ||
| "hash_tree_root", | ||
| ) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| """SSZ size limits for the REST+SSZ Engine API.""" | ||
|
|
||
| # Payload / envelope limits. | ||
| MAX_BYTES_PER_TX = 2**30 | ||
| MAX_TXS_PER_PAYLOAD = 2**20 | ||
| MAX_WITHDRAWALS_PER_PAYLOAD = 2**4 | ||
| BYTES_PER_LOGS_BLOOM = 256 | ||
| MAX_EXTRA_DATA_BYTES = 2**5 | ||
| MAX_BAL_BYTES = MAX_BYTES_PER_TX | ||
| MAX_EXECUTION_REQUESTS_PER_PAYLOAD = 2**8 | ||
| MAX_BYTES_PER_EXECUTION_REQUEST = MAX_BYTES_PER_TX | ||
|
|
||
| # Blob / cell limits | ||
| MAX_BLOB_COMMITMENTS_PER_BLOCK = 2**12 | ||
| FIELD_ELEMENTS_PER_BLOB = 4096 | ||
| BYTES_PER_FIELD_ELEMENT = 32 | ||
| BYTES_PER_BLOB = FIELD_ELEMENTS_PER_BLOB * BYTES_PER_FIELD_ELEMENT | ||
| CELLS_PER_EXT_BLOB = 128 | ||
| FIELD_ELEMENTS_PER_CELL = 64 | ||
| BYTES_PER_CELL = FIELD_ELEMENTS_PER_CELL * BYTES_PER_FIELD_ELEMENT | ||
|
|
||
| # Blob-pool / bodies. | ||
| MAX_VERSIONED_HASHES_PER_REQUEST = 128 | ||
| MAX_BLOBS_REQUEST = MAX_VERSIONED_HASHES_PER_REQUEST | ||
| MAX_BODIES_REQUEST = 2**5 | ||
|
|
||
| # Status / error limits. | ||
| MAX_ERROR_BYTES = 1024 | ||
|
|
||
| # Identity / capabilities limits. | ||
| MAX_CLIENT_CODE_LENGTH = 2 | ||
| MAX_CLIENT_NAME_LENGTH = 64 | ||
| MAX_CLIENT_VERSION_LENGTH = 64 | ||
| MAX_CLIENT_VERSIONS = 4 | ||
| MAX_CAPABILITY_NAME_LENGTH = 64 | ||
| MAX_CAPABILITIES = 64 |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should the
BuiltPayloadcontainers really exist? Will clients have this?