mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-02-01 08:35:24 -05:00
Compare commits
3 Commits
simplify-p
...
develop
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
571c6f39aa | ||
|
|
55fe85c887 | ||
|
|
31f77567dd |
3
changelog/jtraglia-add-specrefs-readme.md
Normal file
3
changelog/jtraglia-add-specrefs-readme.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
### Added
|
||||||
|
|
||||||
|
- Added README for maintaining specrefs.
|
||||||
3
changelog/jtraglia-nightly-reftests-with-run-id.md
Normal file
3
changelog/jtraglia-nightly-reftests-with-run-id.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
### Added
|
||||||
|
|
||||||
|
- The ability to download the nightly reference tests from a specific day.
|
||||||
3
changelog/syjn99_docs-ssz-ql.md
Normal file
3
changelog/syjn99_docs-ssz-ql.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
### Ignored
|
||||||
|
|
||||||
|
- Add handy documentation for SSZ Query package (`encoding/ssz/query`).
|
||||||
190
encoding/ssz/query/doc.md
Normal file
190
encoding/ssz/query/doc.md
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
# SSZ Query Package
|
||||||
|
|
||||||
|
The `encoding/ssz/query` package provides a system for analyzing and querying SSZ ([Simple Serialize](https://github.com/ethereum/consensus-specs/blob/master/ssz/simple-serialize.md)) data structures, as well as generating Merkle proofs from them. It enables runtime analysis of SSZ-serialized Go objects with reflection, path-based queries through nested structures, generalized index calculation, and Merkle proof generation.
|
||||||
|
|
||||||
|
This package is designed to be generic. It operates on arbitrary SSZ-serialized Go values at runtime, so the same query/proof machinery applies equally to any SSZ type, including the BeaconState/BeaconBlock.
|
||||||
|
|
||||||
|
## Usage Example
|
||||||
|
|
||||||
|
```go
|
||||||
|
// 1. Analyze an SSZ object
|
||||||
|
block := ðpb.BeaconBlock{...}
|
||||||
|
info, err := query.AnalyzeObject(block)
|
||||||
|
|
||||||
|
// 2. Parse a path
|
||||||
|
path, err := query.ParsePath(".body.attestations[0].data.slot")
|
||||||
|
|
||||||
|
// 3. Get the generalized index
|
||||||
|
gindex, err := query.GetGeneralizedIndexFromPath(info, path)
|
||||||
|
|
||||||
|
// 4. Generate a Merkle proof
|
||||||
|
proof, err := info.Prove(gindex)
|
||||||
|
|
||||||
|
// 5. Get offset and length to slice the SSZ-encoded bytes
|
||||||
|
sszBytes, _ := block.MarshalSSZ()
|
||||||
|
_, offset, length, err := query.CalculateOffsetAndLength(info, path)
|
||||||
|
// slotBytes contains the SSZ-encoded value at the queried path
|
||||||
|
slotBytes := sszBytes[offset : offset+length]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Exported API
|
||||||
|
|
||||||
|
The main exported API consists of:
|
||||||
|
|
||||||
|
```go
|
||||||
|
// AnalyzeObject analyzes an SSZ object and returns its structural information
|
||||||
|
func AnalyzeObject(obj SSZObject) (*SszInfo, error)
|
||||||
|
|
||||||
|
// ParsePath parses a path string like ".field1.field2[0].field3"
|
||||||
|
func ParsePath(rawPath string) (Path, error)
|
||||||
|
|
||||||
|
// CalculateOffsetAndLength computes byte offset and length for a path within an SSZ object
|
||||||
|
func CalculateOffsetAndLength(sszInfo *SszInfo, path Path) (*SszInfo, uint64, uint64, error)
|
||||||
|
|
||||||
|
// GetGeneralizedIndexFromPath calculates the generalized index for a given path
|
||||||
|
func GetGeneralizedIndexFromPath(info *SszInfo, path Path) (uint64, error)
|
||||||
|
|
||||||
|
// Prove generates a Merkle proof for a target generalized index
|
||||||
|
func (s *SszInfo) Prove(gindex uint64) (*fastssz.Proof, error)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Type System
|
||||||
|
|
||||||
|
### SSZ Types
|
||||||
|
|
||||||
|
The package now supports [all standard SSZ types](https://github.com/ethereum/consensus-specs/blob/master/ssz/simple-serialize.md#typing) except `ProgressiveList`, `ProgressiveContainer`, `ProgressiveBitlist`, `Union`, and `CompatibleUnion`.
|
||||||
|
|
||||||
|
### Core Data Structures
|
||||||
|
|
||||||
|
#### `SszInfo`
|
||||||
|
|
||||||
|
The `SszInfo` structure contains complete structural metadata for an SSZ type:
|
||||||
|
|
||||||
|
```go
|
||||||
|
type SszInfo struct {
|
||||||
|
sszType SszType // SSZ Type classification
|
||||||
|
typ reflect.Type // Go reflect.Type
|
||||||
|
source SSZObject // Original SSZObject reference. Mostly used for reusing SSZ methods like `HashTreeRoot`.
|
||||||
|
isVariable bool // True if contains variable-size fields
|
||||||
|
|
||||||
|
// Composite types have corresponding metadata. Other fields would be nil except for the current type.
|
||||||
|
containerInfo *containerInfo
|
||||||
|
listInfo *listInfo
|
||||||
|
vectorInfo *vectorInfo
|
||||||
|
bitlistInfo *bitlistInfo
|
||||||
|
bitvectorInfo *bitvectorInfo
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `Path`
|
||||||
|
|
||||||
|
The `Path` structure represents navigation paths through SSZ structures. It supports accessing a field by field name, accessing an element by index (list/vector type), and finding the length of homogenous collection types. The `ParsePath` function parses a raw string into a `Path` instance, which is commonly used in other APIs like `CalculateOffsetAndLength` and `GetGeneralizedIndexFromPath`.
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Path struct {
|
||||||
|
Length bool // Flag for length queries (e.g., len(.field))
|
||||||
|
Elements []PathElement // Sequence of field accesses and indices
|
||||||
|
}
|
||||||
|
|
||||||
|
type PathElement struct {
|
||||||
|
Name string // Field name
|
||||||
|
Index *uint64 // list/vector index (nil if not an index access)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Implementation Details
|
||||||
|
|
||||||
|
### Type Analysis (`analyzer.go`)
|
||||||
|
|
||||||
|
The `AnalyzeObject` function performs recursive type introspection using Go reflection:
|
||||||
|
|
||||||
|
1. **Type Inspection** - Examines Go `reflect.Value` to determine SSZ type
|
||||||
|
- Basic types (`uint8`, `uint16`, `uint32`, `uint64`, `bool`): `SSZType` constants
|
||||||
|
- Slices: Determined from struct tags (`ssz-size` for vectors, `ssz-max` for lists). There is a related [write-up](https://hackmd.io/@junsong/H101DKnwxl) regarding struct tags.
|
||||||
|
- Structs: Analyzed as Containers with field ordering from JSON tags
|
||||||
|
- Pointers: Dereferenced automatically
|
||||||
|
|
||||||
|
2. **Variable-Length Population** - Determines actual sizes at runtime
|
||||||
|
- For lists: Iterates elements, caches sizes for variable-element lists
|
||||||
|
- For containers: Recursively populates variable fields, adjusts offsets
|
||||||
|
- For bitlists: Decodes bit length from bitvector
|
||||||
|
|
||||||
|
3. **Offset Calculation** - Computes byte positions within serialized data
|
||||||
|
- Fixed-size fields: Offset = sum of preceding field sizes
|
||||||
|
- Variable-size fields: Offset stored as 4-byte pointer entries
|
||||||
|
|
||||||
|
### Path Parsing (`path.go`)
|
||||||
|
|
||||||
|
The `ParsePath` function parses path strings with the following rules:
|
||||||
|
|
||||||
|
- **Dot notation**: `.field1.field2` for field access
|
||||||
|
- **Array indexing**: `[0]`, `[42]` for element access
|
||||||
|
- **Length queries**: `len(.field)` for list/vector lengths
|
||||||
|
- **Character set**: Only `[A-Za-z0-9._\[\]\(\)]` allowed
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```go
|
||||||
|
path, _ := ParsePath(".nested.array_field[5].inner_field")
|
||||||
|
// Returns: Path{
|
||||||
|
// Elements: [
|
||||||
|
// PathElement{Name: "nested"},
|
||||||
|
// PathElement{Name: "array_field", Index: <Pointer to uint64(5)>},
|
||||||
|
// PathElement{Name: "inner_field"}
|
||||||
|
// ]
|
||||||
|
// }
|
||||||
|
```
|
||||||
|
|
||||||
|
### Generalized Index Calculation (`generalized_index.go`)
|
||||||
|
|
||||||
|
The generalized index is a tree position identifier. This package follows the [Ethereum consensus-specs](https://github.com/ethereum/consensus-specs/blob/master/ssz/merkle-proofs.md#generalized-merkle-tree-index) to calculate the generalized index.
|
||||||
|
|
||||||
|
### Merkle Proof Generation (`merkle_proof.go`, `proof_collector.go`)
|
||||||
|
|
||||||
|
The `Prove` method generates Merkle proofs using a single-sweep merkleization algorithm:
|
||||||
|
|
||||||
|
#### Algorithm Overview
|
||||||
|
|
||||||
|
**Key Terms:**
|
||||||
|
|
||||||
|
- **Target gindex** (generalized index): The position of the SSZ element you want to prove, expressed as a generalized Merkle tree index. Stored in `Proof.Index`.
|
||||||
|
- Note: The generalized index for root is 1.
|
||||||
|
- **Registered gindices**: The set of tree positions whose node hashes must be captured during merkleization in order to later assemble the proof.
|
||||||
|
- **Sibling node**: The node that shares the same parent as another node.
|
||||||
|
- **Leaf value**: The 32-byte hash of the target node (the node being proven). Stored in `Proof.Leaf`.
|
||||||
|
|
||||||
|
**Phases:**
|
||||||
|
|
||||||
|
1. **Registration Phase** (`addTarget`)
|
||||||
|
> Goal: determine exactly which sibling hashes are needed for the proof.
|
||||||
|
|
||||||
|
- Record the target gindex as the proof target.
|
||||||
|
- Starting from the target node, walk the Merkle tree from the leaf (target gindex) to the root (gindex = 1).
|
||||||
|
- At each step:
|
||||||
|
- Compute and register the sibling gindex (`i XOR 1`) as “must collect”.
|
||||||
|
- Move to the parent (`i = i/2`).
|
||||||
|
- This produces the full set of registered gindices (the sibling nodes on the target-to-root path).
|
||||||
|
|
||||||
|
2. **Merkleization Phase** (`merkleize`)
|
||||||
|
> Goal: recursively merkleize the tree and capture the needed hashes.
|
||||||
|
|
||||||
|
- Recursively traverse the SSZ structure and compute Merkle tree node hashes from leaves to root.
|
||||||
|
- Whenever the traversal computes a node whose gindex is in registered gindices, store that node’s hash for later proof construction.
|
||||||
|
|
||||||
|
3. **Proof Assembly Phase** (`toProof`)
|
||||||
|
> Goal: create the final `fastssz.Proof` object in the correct format and order.
|
||||||
|
|
||||||
|
```go
|
||||||
|
// Proof represents a merkle proof against a general index.
|
||||||
|
type Proof struct {
|
||||||
|
Index int
|
||||||
|
Leaf []byte
|
||||||
|
Hashes [][]byte
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- Set `Proof.Index` to the target gindex.
|
||||||
|
- Set `Proof.Leaf` to the 32-byte hash of the target node.
|
||||||
|
- Build `Proof.Hashes` by walking from the target node up to (but not including) the root:
|
||||||
|
- At node `i`, append the stored hash for the sibling (`i XOR 1`).
|
||||||
|
- Move to the parent (`i = i/2`).
|
||||||
|
- The resulting `Proof.Hashes` is ordered from the target level upward, containing one sibling hash per tree level on the path to the root.
|
||||||
35
specrefs/README.md
Normal file
35
specrefs/README.md
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# Specification References
|
||||||
|
|
||||||
|
This directory contains specification reference tracking files managed by
|
||||||
|
[ethspecify](https://github.com/jtraglia/ethspecify).
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Install `ethspecify` with the following command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pipx install ethspecify
|
||||||
|
```
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> You can run `ethspecify <cmd>` in the `specrefs` directory or
|
||||||
|
> `ethspecify <cmd> --path=specrefs` from the project's root directory.
|
||||||
|
|
||||||
|
## Maintenance
|
||||||
|
|
||||||
|
When adding support for a new specification version, follow these steps:
|
||||||
|
|
||||||
|
0. Change directory into the `specrefs` directory.
|
||||||
|
1. Update the version in `.ethspecify.yml` configuration.
|
||||||
|
2. Run `ethspecify process` to update/populate specrefs.
|
||||||
|
3. Run `ethspecify check` to check specrefs.
|
||||||
|
4. If there are errors, use the error message as a guide to fix the issue. If
|
||||||
|
there are new specrefs with empty sources, implement/locate each item and
|
||||||
|
update each specref source list. If you choose not to implement an item,
|
||||||
|
add an exception to the appropriate section the the `.ethspecify.yml`
|
||||||
|
configuration.
|
||||||
|
5. Repeat steps 3 and 4 until `ethspecify check` passes.
|
||||||
|
6. Run `git diff` to view updated specrefs. If an object/function/etc has
|
||||||
|
changed, make the necessary updates to the implementation.
|
||||||
|
7. Lastly, in the project's root directory, run `act -j check-specrefs` to
|
||||||
|
ensure everything is correct.
|
||||||
@@ -22,9 +22,13 @@ There are tests for mainnet and minimal config, so for each config we will add a
|
|||||||
## Running nightly spectests
|
## Running nightly spectests
|
||||||
|
|
||||||
Since [PR 15312](https://github.com/OffchainLabs/prysm/pull/15312), Prysm has support to download "nightly" spectests from github via a starlark rule configuration by environment variable.
|
Since [PR 15312](https://github.com/OffchainLabs/prysm/pull/15312), Prysm has support to download "nightly" spectests from github via a starlark rule configuration by environment variable.
|
||||||
Set `--repo_env=CONSENSUS_SPEC_TESTS_VERSION=nightly` when running spectest to download the "nightly" spectests.
|
Set `--repo_env=CONSENSUS_SPEC_TESTS_VERSION=nightly` or `--repo_env=CONSENSUS_SPEC_TESTS_VERSION=nightly-<run_id>` when running spectest to download the "nightly" spectests.
|
||||||
Note: A GITHUB_TOKEN environment variable is required to be set. The github token must be a [fine grained token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-fine-grained-personal-access-token).
|
Note: A GITHUB_TOKEN environment variable is required to be set. The github token does not need to be associated with your main account; it can be from a "burner account". And the token does not need to be a fine-grained token; it can be a classic token.
|
||||||
|
|
||||||
```
|
```
|
||||||
bazel test //... --test_tag_filters=spectest --repo_env=CONSENSUS_SPEC_TESTS_VERSION=nightly
|
bazel test //... --test_tag_filters=spectest --repo_env=CONSENSUS_SPEC_TESTS_VERSION=nightly
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
bazel test //... --test_tag_filters=spectest --repo_env=CONSENSUS_SPEC_TESTS_VERSION=nightly-21422848633
|
||||||
|
```
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
# bazel build @consensus_spec_tests//:test_data
|
# bazel build @consensus_spec_tests//:test_data
|
||||||
# bazel build @consensus_spec_tests//:test_data --repo_env=CONSENSUS_SPEC_TESTS_VERSION=nightly
|
# bazel build @consensus_spec_tests//:test_data --repo_env=CONSENSUS_SPEC_TESTS_VERSION=nightly
|
||||||
|
# bazel build @consensus_spec_tests//:test_data --repo_env=CONSENSUS_SPEC_TESTS_VERSION=nightly-<run_id>
|
||||||
|
|
||||||
def _get_redirected_url(repository_ctx, url, headers):
|
def _get_redirected_url(repository_ctx, url, headers):
|
||||||
if not repository_ctx.which("curl"):
|
if not repository_ctx.which("curl"):
|
||||||
@@ -24,7 +25,7 @@ def _impl(repository_ctx):
|
|||||||
version = repository_ctx.getenv("CONSENSUS_SPEC_TESTS_VERSION") or repository_ctx.attr.version
|
version = repository_ctx.getenv("CONSENSUS_SPEC_TESTS_VERSION") or repository_ctx.attr.version
|
||||||
token = repository_ctx.getenv("GITHUB_TOKEN") or ""
|
token = repository_ctx.getenv("GITHUB_TOKEN") or ""
|
||||||
|
|
||||||
if version == "nightly":
|
if version == "nightly" or version.startswith("nightly-"):
|
||||||
print("Downloading nightly tests")
|
print("Downloading nightly tests")
|
||||||
if not token:
|
if not token:
|
||||||
fail("Error GITHUB_TOKEN is not set")
|
fail("Error GITHUB_TOKEN is not set")
|
||||||
@@ -34,16 +35,22 @@ def _impl(repository_ctx):
|
|||||||
"Accept": "application/vnd.github+json",
|
"Accept": "application/vnd.github+json",
|
||||||
}
|
}
|
||||||
|
|
||||||
repository_ctx.download(
|
if version.startswith("nightly-"):
|
||||||
"https://api.github.com/repos/%s/actions/workflows/%s/runs?branch=%s&status=success&per_page=1"
|
run_id = version.split("nightly-", 1)[1]
|
||||||
% (repository_ctx.attr.repo, repository_ctx.attr.workflow, repository_ctx.attr.branch),
|
if not run_id:
|
||||||
headers = headers,
|
fail("Error invalid run id")
|
||||||
output = "runs.json"
|
else:
|
||||||
)
|
repository_ctx.download(
|
||||||
|
"https://api.github.com/repos/%s/actions/workflows/%s/runs?branch=%s&status=success&per_page=1"
|
||||||
|
% (repository_ctx.attr.repo, repository_ctx.attr.workflow, repository_ctx.attr.branch),
|
||||||
|
headers = headers,
|
||||||
|
output = "runs.json"
|
||||||
|
)
|
||||||
|
|
||||||
run_id = json.decode(repository_ctx.read("runs.json"))["workflow_runs"][0]["id"]
|
run_id = json.decode(repository_ctx.read("runs.json"))["workflow_runs"][0]["id"]
|
||||||
repository_ctx.delete("runs.json")
|
repository_ctx.delete("runs.json")
|
||||||
|
|
||||||
|
print("Run id:", run_id)
|
||||||
repository_ctx.download(
|
repository_ctx.download(
|
||||||
"https://api.github.com/repos/%s/actions/runs/%s/artifacts"
|
"https://api.github.com/repos/%s/actions/runs/%s/artifacts"
|
||||||
% (repository_ctx.attr.repo, run_id),
|
% (repository_ctx.attr.repo, run_id),
|
||||||
@@ -108,8 +115,8 @@ consensus_spec_tests = repository_rule(
|
|||||||
"version": attr.string(mandatory = True),
|
"version": attr.string(mandatory = True),
|
||||||
"flavors": attr.string_dict(mandatory = True),
|
"flavors": attr.string_dict(mandatory = True),
|
||||||
"repo": attr.string(default = "ethereum/consensus-specs"),
|
"repo": attr.string(default = "ethereum/consensus-specs"),
|
||||||
"workflow": attr.string(default = "generate_vectors.yml"),
|
"workflow": attr.string(default = "nightly-reftests.yml"),
|
||||||
"branch": attr.string(default = "dev"),
|
"branch": attr.string(default = "master"),
|
||||||
"release_url_template": attr.string(default = "https://github.com/ethereum/consensus-specs/releases/download/%s"),
|
"release_url_template": attr.string(default = "https://github.com/ethereum/consensus-specs/releases/download/%s"),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -51,7 +51,6 @@ go_library(
|
|||||||
"//consensus-types/primitives:go_default_library",
|
"//consensus-types/primitives:go_default_library",
|
||||||
"//consensus-types/validator:go_default_library",
|
"//consensus-types/validator:go_default_library",
|
||||||
"//encoding/bytesutil:go_default_library",
|
"//encoding/bytesutil:go_default_library",
|
||||||
"//encoding/ssz:go_default_library",
|
|
||||||
"//monitoring/tracing/trace:go_default_library",
|
"//monitoring/tracing/trace:go_default_library",
|
||||||
"//network/httputil:go_default_library",
|
"//network/httputil:go_default_library",
|
||||||
"//proto/engine/v1:go_default_library",
|
"//proto/engine/v1:go_default_library",
|
||||||
|
|||||||
@@ -55,153 +55,114 @@ func (c *beaconApiValidatorClient) beaconBlock(ctx context.Context, slot primiti
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// sszBlockCodec defines SSZ unmarshalers for a fork's block and blinded block types.
|
|
||||||
type sszBlockCodec struct {
|
|
||||||
unmarshalBlock func([]byte) (*ethpb.GenericBeaconBlock, error)
|
|
||||||
unmarshalBlinded func([]byte) (*ethpb.GenericBeaconBlock, error) // nil for Phase0/Altair
|
|
||||||
}
|
|
||||||
|
|
||||||
type sszCodecEntry struct {
|
|
||||||
minVersion int
|
|
||||||
codec sszBlockCodec
|
|
||||||
}
|
|
||||||
|
|
||||||
// sszCodecs is ordered descending by version so that unknown future versions
|
|
||||||
// fall through to the latest known fork (matching the original if-cascade).
|
|
||||||
var sszCodecs = []sszCodecEntry{
|
|
||||||
{
|
|
||||||
minVersion: version.Fulu,
|
|
||||||
codec: sszBlockCodec{
|
|
||||||
unmarshalBlock: func(data []byte) (*ethpb.GenericBeaconBlock, error) {
|
|
||||||
block := ðpb.BeaconBlockContentsFulu{}
|
|
||||||
if err := block.UnmarshalSSZ(data); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Fulu{Fulu: block}}, nil
|
|
||||||
},
|
|
||||||
unmarshalBlinded: func(data []byte) (*ethpb.GenericBeaconBlock, error) {
|
|
||||||
blindedBlock := ðpb.BlindedBeaconBlockFulu{}
|
|
||||||
if err := blindedBlock.UnmarshalSSZ(data); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_BlindedFulu{BlindedFulu: blindedBlock}, IsBlinded: true}, nil
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
minVersion: version.Electra,
|
|
||||||
codec: sszBlockCodec{
|
|
||||||
unmarshalBlock: func(data []byte) (*ethpb.GenericBeaconBlock, error) {
|
|
||||||
block := ðpb.BeaconBlockContentsElectra{}
|
|
||||||
if err := block.UnmarshalSSZ(data); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Electra{Electra: block}}, nil
|
|
||||||
},
|
|
||||||
unmarshalBlinded: func(data []byte) (*ethpb.GenericBeaconBlock, error) {
|
|
||||||
blindedBlock := ðpb.BlindedBeaconBlockElectra{}
|
|
||||||
if err := blindedBlock.UnmarshalSSZ(data); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_BlindedElectra{BlindedElectra: blindedBlock}, IsBlinded: true}, nil
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
minVersion: version.Deneb,
|
|
||||||
codec: sszBlockCodec{
|
|
||||||
unmarshalBlock: func(data []byte) (*ethpb.GenericBeaconBlock, error) {
|
|
||||||
block := ðpb.BeaconBlockContentsDeneb{}
|
|
||||||
if err := block.UnmarshalSSZ(data); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Deneb{Deneb: block}}, nil
|
|
||||||
},
|
|
||||||
unmarshalBlinded: func(data []byte) (*ethpb.GenericBeaconBlock, error) {
|
|
||||||
blindedBlock := ðpb.BlindedBeaconBlockDeneb{}
|
|
||||||
if err := blindedBlock.UnmarshalSSZ(data); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_BlindedDeneb{BlindedDeneb: blindedBlock}, IsBlinded: true}, nil
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
minVersion: version.Capella,
|
|
||||||
codec: sszBlockCodec{
|
|
||||||
unmarshalBlock: func(data []byte) (*ethpb.GenericBeaconBlock, error) {
|
|
||||||
block := ðpb.BeaconBlockCapella{}
|
|
||||||
if err := block.UnmarshalSSZ(data); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Capella{Capella: block}}, nil
|
|
||||||
},
|
|
||||||
unmarshalBlinded: func(data []byte) (*ethpb.GenericBeaconBlock, error) {
|
|
||||||
blindedBlock := ðpb.BlindedBeaconBlockCapella{}
|
|
||||||
if err := blindedBlock.UnmarshalSSZ(data); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_BlindedCapella{BlindedCapella: blindedBlock}, IsBlinded: true}, nil
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
minVersion: version.Bellatrix,
|
|
||||||
codec: sszBlockCodec{
|
|
||||||
unmarshalBlock: func(data []byte) (*ethpb.GenericBeaconBlock, error) {
|
|
||||||
block := ðpb.BeaconBlockBellatrix{}
|
|
||||||
if err := block.UnmarshalSSZ(data); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Bellatrix{Bellatrix: block}}, nil
|
|
||||||
},
|
|
||||||
unmarshalBlinded: func(data []byte) (*ethpb.GenericBeaconBlock, error) {
|
|
||||||
blindedBlock := ðpb.BlindedBeaconBlockBellatrix{}
|
|
||||||
if err := blindedBlock.UnmarshalSSZ(data); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_BlindedBellatrix{BlindedBellatrix: blindedBlock}, IsBlinded: true}, nil
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
minVersion: version.Altair,
|
|
||||||
codec: sszBlockCodec{
|
|
||||||
unmarshalBlock: func(data []byte) (*ethpb.GenericBeaconBlock, error) {
|
|
||||||
block := ðpb.BeaconBlockAltair{}
|
|
||||||
if err := block.UnmarshalSSZ(data); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Altair{Altair: block}}, nil
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
minVersion: version.Phase0,
|
|
||||||
codec: sszBlockCodec{
|
|
||||||
unmarshalBlock: func(data []byte) (*ethpb.GenericBeaconBlock, error) {
|
|
||||||
block := ðpb.BeaconBlock{}
|
|
||||||
if err := block.UnmarshalSSZ(data); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Phase0{Phase0: block}}, nil
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func processBlockSSZResponse(ver int, data []byte, isBlinded bool) (*ethpb.GenericBeaconBlock, error) {
|
func processBlockSSZResponse(ver int, data []byte, isBlinded bool) (*ethpb.GenericBeaconBlock, error) {
|
||||||
for _, entry := range sszCodecs {
|
if ver >= version.Fulu {
|
||||||
if ver >= entry.minVersion {
|
return processBlockSSZResponseFulu(data, isBlinded)
|
||||||
if isBlinded && entry.codec.unmarshalBlinded != nil {
|
}
|
||||||
return entry.codec.unmarshalBlinded(data)
|
if ver >= version.Electra {
|
||||||
}
|
return processBlockSSZResponseElectra(data, isBlinded)
|
||||||
return entry.codec.unmarshalBlock(data)
|
}
|
||||||
|
if ver >= version.Deneb {
|
||||||
|
return processBlockSSZResponseDeneb(data, isBlinded)
|
||||||
|
}
|
||||||
|
if ver >= version.Capella {
|
||||||
|
return processBlockSSZResponseCapella(data, isBlinded)
|
||||||
|
}
|
||||||
|
if ver >= version.Bellatrix {
|
||||||
|
return processBlockSSZResponseBellatrix(data, isBlinded)
|
||||||
|
}
|
||||||
|
if ver >= version.Altair {
|
||||||
|
block := ðpb.BeaconBlockAltair{}
|
||||||
|
if err := block.UnmarshalSSZ(data); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Altair{Altair: block}}, nil
|
||||||
|
}
|
||||||
|
if ver >= version.Phase0 {
|
||||||
|
block := ðpb.BeaconBlock{}
|
||||||
|
if err := block.UnmarshalSSZ(data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Phase0{Phase0: block}}, nil
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("unsupported block version %s", version.String(ver))
|
return nil, fmt.Errorf("unsupported block version %s", version.String(ver))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func processBlockSSZResponseFulu(data []byte, isBlinded bool) (*ethpb.GenericBeaconBlock, error) {
|
||||||
|
if isBlinded {
|
||||||
|
blindedBlock := ðpb.BlindedBeaconBlockFulu{}
|
||||||
|
if err := blindedBlock.UnmarshalSSZ(data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_BlindedFulu{BlindedFulu: blindedBlock}, IsBlinded: true}, nil
|
||||||
|
}
|
||||||
|
block := ðpb.BeaconBlockContentsFulu{}
|
||||||
|
if err := block.UnmarshalSSZ(data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Fulu{Fulu: block}}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func processBlockSSZResponseElectra(data []byte, isBlinded bool) (*ethpb.GenericBeaconBlock, error) {
|
||||||
|
if isBlinded {
|
||||||
|
blindedBlock := ðpb.BlindedBeaconBlockElectra{}
|
||||||
|
if err := blindedBlock.UnmarshalSSZ(data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_BlindedElectra{BlindedElectra: blindedBlock}, IsBlinded: true}, nil
|
||||||
|
}
|
||||||
|
block := ðpb.BeaconBlockContentsElectra{}
|
||||||
|
if err := block.UnmarshalSSZ(data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Electra{Electra: block}}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func processBlockSSZResponseDeneb(data []byte, isBlinded bool) (*ethpb.GenericBeaconBlock, error) {
|
||||||
|
if isBlinded {
|
||||||
|
blindedBlock := ðpb.BlindedBeaconBlockDeneb{}
|
||||||
|
if err := blindedBlock.UnmarshalSSZ(data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_BlindedDeneb{BlindedDeneb: blindedBlock}, IsBlinded: true}, nil
|
||||||
|
}
|
||||||
|
block := ðpb.BeaconBlockContentsDeneb{}
|
||||||
|
if err := block.UnmarshalSSZ(data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Deneb{Deneb: block}}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func processBlockSSZResponseCapella(data []byte, isBlinded bool) (*ethpb.GenericBeaconBlock, error) {
|
||||||
|
if isBlinded {
|
||||||
|
blindedBlock := ðpb.BlindedBeaconBlockCapella{}
|
||||||
|
if err := blindedBlock.UnmarshalSSZ(data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_BlindedCapella{BlindedCapella: blindedBlock}, IsBlinded: true}, nil
|
||||||
|
}
|
||||||
|
block := ðpb.BeaconBlockCapella{}
|
||||||
|
if err := block.UnmarshalSSZ(data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Capella{Capella: block}}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func processBlockSSZResponseBellatrix(data []byte, isBlinded bool) (*ethpb.GenericBeaconBlock, error) {
|
||||||
|
if isBlinded {
|
||||||
|
blindedBlock := ðpb.BlindedBeaconBlockBellatrix{}
|
||||||
|
if err := blindedBlock.UnmarshalSSZ(data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_BlindedBellatrix{BlindedBellatrix: blindedBlock}, IsBlinded: true}, nil
|
||||||
|
}
|
||||||
|
block := ðpb.BeaconBlockBellatrix{}
|
||||||
|
if err := block.UnmarshalSSZ(data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ðpb.GenericBeaconBlock{Block: ðpb.GenericBeaconBlock_Bellatrix{Bellatrix: block}}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func convertBlockToGeneric(decoder *json.Decoder, dest ethpb.GenericConverter, version string, isBlinded bool) (*ethpb.GenericBeaconBlock, error) {
|
func convertBlockToGeneric(decoder *json.Decoder, dest ethpb.GenericConverter, version string, isBlinded bool) (*ethpb.GenericBeaconBlock, error) {
|
||||||
typeName := version
|
typeName := version
|
||||||
if isBlinded {
|
if isBlinded {
|
||||||
@@ -219,52 +180,69 @@ func convertBlockToGeneric(decoder *json.Decoder, dest ethpb.GenericConverter, v
|
|||||||
return genericBlock, nil
|
return genericBlock, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// jsonBlockTypes defines factory functions for creating block and blinded block structs for JSON decoding.
|
|
||||||
type jsonBlockTypes struct {
|
|
||||||
newBlock func() ethpb.GenericConverter
|
|
||||||
newBlinded func() ethpb.GenericConverter // nil for Phase0/Altair
|
|
||||||
}
|
|
||||||
|
|
||||||
var jsonBlockFactories = map[string]jsonBlockTypes{
|
|
||||||
version.String(version.Phase0): {
|
|
||||||
newBlock: func() ethpb.GenericConverter { return &structs.BeaconBlock{} },
|
|
||||||
},
|
|
||||||
version.String(version.Altair): {
|
|
||||||
newBlock: func() ethpb.GenericConverter { return &structs.BeaconBlockAltair{} },
|
|
||||||
},
|
|
||||||
version.String(version.Bellatrix): {
|
|
||||||
newBlock: func() ethpb.GenericConverter { return &structs.BeaconBlockBellatrix{} },
|
|
||||||
newBlinded: func() ethpb.GenericConverter { return &structs.BlindedBeaconBlockBellatrix{} },
|
|
||||||
},
|
|
||||||
version.String(version.Capella): {
|
|
||||||
newBlock: func() ethpb.GenericConverter { return &structs.BeaconBlockCapella{} },
|
|
||||||
newBlinded: func() ethpb.GenericConverter { return &structs.BlindedBeaconBlockCapella{} },
|
|
||||||
},
|
|
||||||
version.String(version.Deneb): {
|
|
||||||
newBlock: func() ethpb.GenericConverter { return &structs.BeaconBlockContentsDeneb{} },
|
|
||||||
newBlinded: func() ethpb.GenericConverter { return &structs.BlindedBeaconBlockDeneb{} },
|
|
||||||
},
|
|
||||||
version.String(version.Electra): {
|
|
||||||
newBlock: func() ethpb.GenericConverter { return &structs.BeaconBlockContentsElectra{} },
|
|
||||||
newBlinded: func() ethpb.GenericConverter { return &structs.BlindedBeaconBlockElectra{} },
|
|
||||||
},
|
|
||||||
version.String(version.Fulu): {
|
|
||||||
newBlock: func() ethpb.GenericConverter { return &structs.BeaconBlockContentsFulu{} },
|
|
||||||
newBlinded: func() ethpb.GenericConverter { return &structs.BlindedBeaconBlockFulu{} },
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func processBlockJSONResponse(ver string, isBlinded bool, decoder *json.Decoder) (*ethpb.GenericBeaconBlock, error) {
|
func processBlockJSONResponse(ver string, isBlinded bool, decoder *json.Decoder) (*ethpb.GenericBeaconBlock, error) {
|
||||||
if decoder == nil {
|
if decoder == nil {
|
||||||
return nil, errors.New("no produce block json decoder found")
|
return nil, errors.New("no produce block json decoder found")
|
||||||
}
|
}
|
||||||
|
|
||||||
factory, ok := jsonBlockFactories[ver]
|
switch ver {
|
||||||
if !ok {
|
case version.String(version.Phase0):
|
||||||
|
return convertBlockToGeneric(decoder, &structs.BeaconBlock{}, version.String(version.Phase0), false)
|
||||||
|
|
||||||
|
case version.String(version.Altair):
|
||||||
|
return convertBlockToGeneric(decoder, &structs.BeaconBlockAltair{}, "altair", false)
|
||||||
|
|
||||||
|
case version.String(version.Bellatrix):
|
||||||
|
return processBellatrixBlock(decoder, isBlinded)
|
||||||
|
|
||||||
|
case version.String(version.Capella):
|
||||||
|
return processCapellaBlock(decoder, isBlinded)
|
||||||
|
|
||||||
|
case version.String(version.Deneb):
|
||||||
|
return processDenebBlock(decoder, isBlinded)
|
||||||
|
|
||||||
|
case version.String(version.Electra):
|
||||||
|
return processElectraBlock(decoder, isBlinded)
|
||||||
|
|
||||||
|
case version.String(version.Fulu):
|
||||||
|
return processFuluBlock(decoder, isBlinded)
|
||||||
|
|
||||||
|
default:
|
||||||
return nil, errors.Errorf("unsupported consensus version `%s`", ver)
|
return nil, errors.Errorf("unsupported consensus version `%s`", ver)
|
||||||
}
|
}
|
||||||
if isBlinded && factory.newBlinded != nil {
|
}
|
||||||
return convertBlockToGeneric(decoder, factory.newBlinded(), ver, true)
|
|
||||||
}
|
func processBellatrixBlock(decoder *json.Decoder, isBlinded bool) (*ethpb.GenericBeaconBlock, error) {
|
||||||
return convertBlockToGeneric(decoder, factory.newBlock(), ver, false)
|
if isBlinded {
|
||||||
|
return convertBlockToGeneric(decoder, &structs.BlindedBeaconBlockBellatrix{}, "bellatrix", true)
|
||||||
|
}
|
||||||
|
return convertBlockToGeneric(decoder, &structs.BeaconBlockBellatrix{}, "bellatrix", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func processCapellaBlock(decoder *json.Decoder, isBlinded bool) (*ethpb.GenericBeaconBlock, error) {
|
||||||
|
if isBlinded {
|
||||||
|
return convertBlockToGeneric(decoder, &structs.BlindedBeaconBlockCapella{}, "capella", true)
|
||||||
|
}
|
||||||
|
return convertBlockToGeneric(decoder, &structs.BeaconBlockCapella{}, "capella", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func processDenebBlock(decoder *json.Decoder, isBlinded bool) (*ethpb.GenericBeaconBlock, error) {
|
||||||
|
if isBlinded {
|
||||||
|
return convertBlockToGeneric(decoder, &structs.BlindedBeaconBlockDeneb{}, "deneb", true)
|
||||||
|
}
|
||||||
|
return convertBlockToGeneric(decoder, &structs.BeaconBlockContentsDeneb{}, "deneb", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func processElectraBlock(decoder *json.Decoder, isBlinded bool) (*ethpb.GenericBeaconBlock, error) {
|
||||||
|
if isBlinded {
|
||||||
|
return convertBlockToGeneric(decoder, &structs.BlindedBeaconBlockElectra{}, "electra", true)
|
||||||
|
}
|
||||||
|
return convertBlockToGeneric(decoder, &structs.BeaconBlockContentsElectra{}, "electra", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func processFuluBlock(decoder *json.Decoder, isBlinded bool) (*ethpb.GenericBeaconBlock, error) {
|
||||||
|
if isBlinded {
|
||||||
|
return convertBlockToGeneric(decoder, &structs.BlindedBeaconBlockFulu{}, "fulu", true)
|
||||||
|
}
|
||||||
|
return convertBlockToGeneric(decoder, &structs.BeaconBlockContentsFulu{}, "fulu", false)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/OffchainLabs/prysm/v7/api/server/structs"
|
"github.com/OffchainLabs/prysm/v7/api/server/structs"
|
||||||
"github.com/OffchainLabs/prysm/v7/encoding/ssz"
|
|
||||||
"github.com/OffchainLabs/prysm/v7/network/httputil"
|
"github.com/OffchainLabs/prysm/v7/network/httputil"
|
||||||
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
|
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@@ -22,128 +21,34 @@ type blockProcessingResult struct {
|
|||||||
marshalJSON func() ([]byte, error)
|
marshalJSON func() ([]byte, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type sszMarshaler interface {
|
|
||||||
MarshalSSZ() ([]byte, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
func buildBlockResult(
|
|
||||||
versionName string,
|
|
||||||
blinded bool,
|
|
||||||
sszObj sszMarshaler,
|
|
||||||
rootObj ssz.Hashable,
|
|
||||||
jsonFn func() ([]byte, error),
|
|
||||||
) (*blockProcessingResult, error) {
|
|
||||||
beaconBlockRoot, err := rootObj.HashTreeRoot()
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrapf(err, "failed to compute block root for %s beacon block", versionName)
|
|
||||||
}
|
|
||||||
|
|
||||||
ssz, err := sszObj.MarshalSSZ()
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrapf(err, "failed to serialize %s beacon block", versionName)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &blockProcessingResult{
|
|
||||||
consensusVersion: versionName,
|
|
||||||
blinded: blinded,
|
|
||||||
beaconBlockRoot: beaconBlockRoot,
|
|
||||||
marshalledSSZ: ssz,
|
|
||||||
marshalJSON: jsonFn,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *beaconApiValidatorClient) proposeBeaconBlock(ctx context.Context, in *ethpb.GenericSignedBeaconBlock) (*ethpb.ProposeResponse, error) {
|
func (c *beaconApiValidatorClient) proposeBeaconBlock(ctx context.Context, in *ethpb.GenericSignedBeaconBlock) (*ethpb.ProposeResponse, error) {
|
||||||
var res *blockProcessingResult
|
var res *blockProcessingResult
|
||||||
var err error
|
var err error
|
||||||
switch blockType := in.Block.(type) {
|
switch blockType := in.Block.(type) {
|
||||||
case *ethpb.GenericSignedBeaconBlock_Phase0:
|
case *ethpb.GenericSignedBeaconBlock_Phase0:
|
||||||
res, err = buildBlockResult("phase0", false, blockType.Phase0, blockType.Phase0.Block, func() ([]byte, error) {
|
res, err = handlePhase0Block(blockType)
|
||||||
return json.Marshal(structs.SignedBeaconBlockPhase0FromConsensus(blockType.Phase0))
|
|
||||||
})
|
|
||||||
case *ethpb.GenericSignedBeaconBlock_Altair:
|
case *ethpb.GenericSignedBeaconBlock_Altair:
|
||||||
res, err = buildBlockResult("altair", false, blockType.Altair, blockType.Altair.Block, func() ([]byte, error) {
|
res, err = handleAltairBlock(blockType)
|
||||||
return json.Marshal(structs.SignedBeaconBlockAltairFromConsensus(blockType.Altair))
|
|
||||||
})
|
|
||||||
case *ethpb.GenericSignedBeaconBlock_Bellatrix:
|
case *ethpb.GenericSignedBeaconBlock_Bellatrix:
|
||||||
res, err = buildBlockResult("bellatrix", false, blockType.Bellatrix, blockType.Bellatrix.Block, func() ([]byte, error) {
|
res, err = handleBellatrixBlock(blockType)
|
||||||
signedBlock, err := structs.SignedBeaconBlockBellatrixFromConsensus(blockType.Bellatrix)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "failed to convert bellatrix beacon block")
|
|
||||||
}
|
|
||||||
return json.Marshal(signedBlock)
|
|
||||||
})
|
|
||||||
case *ethpb.GenericSignedBeaconBlock_BlindedBellatrix:
|
case *ethpb.GenericSignedBeaconBlock_BlindedBellatrix:
|
||||||
res, err = buildBlockResult("bellatrix", true, blockType.BlindedBellatrix, blockType.BlindedBellatrix.Block, func() ([]byte, error) {
|
res, err = handleBlindedBellatrixBlock(blockType)
|
||||||
signedBlock, err := structs.SignedBlindedBeaconBlockBellatrixFromConsensus(blockType.BlindedBellatrix)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "failed to convert blinded bellatrix beacon block")
|
|
||||||
}
|
|
||||||
return json.Marshal(signedBlock)
|
|
||||||
})
|
|
||||||
case *ethpb.GenericSignedBeaconBlock_Capella:
|
case *ethpb.GenericSignedBeaconBlock_Capella:
|
||||||
res, err = buildBlockResult("capella", false, blockType.Capella, blockType.Capella.Block, func() ([]byte, error) {
|
res, err = handleCapellaBlock(blockType)
|
||||||
signedBlock, err := structs.SignedBeaconBlockCapellaFromConsensus(blockType.Capella)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "failed to convert capella beacon block")
|
|
||||||
}
|
|
||||||
return json.Marshal(signedBlock)
|
|
||||||
})
|
|
||||||
case *ethpb.GenericSignedBeaconBlock_BlindedCapella:
|
case *ethpb.GenericSignedBeaconBlock_BlindedCapella:
|
||||||
res, err = buildBlockResult("capella", true, blockType.BlindedCapella, blockType.BlindedCapella.Block, func() ([]byte, error) {
|
res, err = handleBlindedCapellaBlock(blockType)
|
||||||
signedBlock, err := structs.SignedBlindedBeaconBlockCapellaFromConsensus(blockType.BlindedCapella)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "failed to convert blinded capella beacon block")
|
|
||||||
}
|
|
||||||
return json.Marshal(signedBlock)
|
|
||||||
})
|
|
||||||
case *ethpb.GenericSignedBeaconBlock_Deneb:
|
case *ethpb.GenericSignedBeaconBlock_Deneb:
|
||||||
res, err = buildBlockResult("deneb", false, blockType.Deneb, blockType.Deneb.Block, func() ([]byte, error) {
|
res, err = handleDenebBlockContents(blockType)
|
||||||
signedBlock, err := structs.SignedBeaconBlockContentsDenebFromConsensus(blockType.Deneb)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "failed to convert deneb beacon block contents")
|
|
||||||
}
|
|
||||||
return json.Marshal(signedBlock)
|
|
||||||
})
|
|
||||||
case *ethpb.GenericSignedBeaconBlock_BlindedDeneb:
|
case *ethpb.GenericSignedBeaconBlock_BlindedDeneb:
|
||||||
res, err = buildBlockResult("deneb", true, blockType.BlindedDeneb, blockType.BlindedDeneb, func() ([]byte, error) {
|
res, err = handleBlindedDenebBlock(blockType)
|
||||||
signedBlock, err := structs.SignedBlindedBeaconBlockDenebFromConsensus(blockType.BlindedDeneb)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "failed to convert deneb blinded beacon block")
|
|
||||||
}
|
|
||||||
return json.Marshal(signedBlock)
|
|
||||||
})
|
|
||||||
case *ethpb.GenericSignedBeaconBlock_Electra:
|
case *ethpb.GenericSignedBeaconBlock_Electra:
|
||||||
res, err = buildBlockResult("electra", false, blockType.Electra, blockType.Electra.Block, func() ([]byte, error) {
|
res, err = handleElectraBlockContents(blockType)
|
||||||
signedBlock, err := structs.SignedBeaconBlockContentsElectraFromConsensus(blockType.Electra)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "failed to convert electra beacon block contents")
|
|
||||||
}
|
|
||||||
return json.Marshal(signedBlock)
|
|
||||||
})
|
|
||||||
case *ethpb.GenericSignedBeaconBlock_BlindedElectra:
|
case *ethpb.GenericSignedBeaconBlock_BlindedElectra:
|
||||||
res, err = buildBlockResult("electra", true, blockType.BlindedElectra, blockType.BlindedElectra, func() ([]byte, error) {
|
res, err = handleBlindedElectraBlock(blockType)
|
||||||
signedBlock, err := structs.SignedBlindedBeaconBlockElectraFromConsensus(blockType.BlindedElectra)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "failed to convert electra blinded beacon block")
|
|
||||||
}
|
|
||||||
return json.Marshal(signedBlock)
|
|
||||||
})
|
|
||||||
case *ethpb.GenericSignedBeaconBlock_Fulu:
|
case *ethpb.GenericSignedBeaconBlock_Fulu:
|
||||||
res, err = buildBlockResult("fulu", false, blockType.Fulu, blockType.Fulu.Block, func() ([]byte, error) {
|
res, err = handleFuluBlockContents(blockType)
|
||||||
signedBlock, err := structs.SignedBeaconBlockContentsFuluFromConsensus(blockType.Fulu)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "failed to convert fulu beacon block contents")
|
|
||||||
}
|
|
||||||
return json.Marshal(signedBlock)
|
|
||||||
})
|
|
||||||
case *ethpb.GenericSignedBeaconBlock_BlindedFulu:
|
case *ethpb.GenericSignedBeaconBlock_BlindedFulu:
|
||||||
res, err = buildBlockResult("fulu", true, blockType.BlindedFulu, blockType.BlindedFulu, func() ([]byte, error) {
|
res, err = handleBlindedFuluBlock(blockType)
|
||||||
signedBlock, err := structs.SignedBlindedBeaconBlockFuluFromConsensus(blockType.BlindedFulu)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "failed to convert fulu blinded beacon block")
|
|
||||||
}
|
|
||||||
return json.Marshal(signedBlock)
|
|
||||||
})
|
|
||||||
default:
|
default:
|
||||||
return nil, errors.Errorf("unsupported block type %T", in.Block)
|
return nil, errors.Errorf("unsupported block type %T", in.Block)
|
||||||
}
|
}
|
||||||
@@ -211,3 +116,357 @@ func (c *beaconApiValidatorClient) proposeBeaconBlock(ctx context.Context, in *e
|
|||||||
|
|
||||||
return ðpb.ProposeResponse{BlockRoot: res.beaconBlockRoot[:]}, nil
|
return ðpb.ProposeResponse{BlockRoot: res.beaconBlockRoot[:]}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func handlePhase0Block(block *ethpb.GenericSignedBeaconBlock_Phase0) (*blockProcessingResult, error) {
|
||||||
|
var res blockProcessingResult
|
||||||
|
res.consensusVersion = "phase0"
|
||||||
|
res.blinded = false
|
||||||
|
|
||||||
|
beaconBlockRoot, err := block.Phase0.Block.HashTreeRoot()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to compute block root for phase0 beacon block")
|
||||||
|
}
|
||||||
|
res.beaconBlockRoot = beaconBlockRoot
|
||||||
|
|
||||||
|
// Marshal SSZ
|
||||||
|
ssz, err := block.Phase0.MarshalSSZ()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to serialize block for phase0 beacon block")
|
||||||
|
}
|
||||||
|
res.marshalledSSZ = ssz
|
||||||
|
|
||||||
|
// Set up JSON marshalling function for fallback
|
||||||
|
res.marshalJSON = func() ([]byte, error) {
|
||||||
|
signedBlock := structs.SignedBeaconBlockPhase0FromConsensus(block.Phase0)
|
||||||
|
return json.Marshal(signedBlock)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleAltairBlock(block *ethpb.GenericSignedBeaconBlock_Altair) (*blockProcessingResult, error) {
|
||||||
|
var res blockProcessingResult
|
||||||
|
res.consensusVersion = "altair"
|
||||||
|
res.blinded = false
|
||||||
|
|
||||||
|
beaconBlockRoot, err := block.Altair.Block.HashTreeRoot()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to compute block root for altair beacon block")
|
||||||
|
}
|
||||||
|
res.beaconBlockRoot = beaconBlockRoot
|
||||||
|
|
||||||
|
// Marshal SSZ
|
||||||
|
ssz, err := block.Altair.MarshalSSZ()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to serialize block for altair beacon block")
|
||||||
|
}
|
||||||
|
res.marshalledSSZ = ssz
|
||||||
|
|
||||||
|
// Set up JSON marshalling function for fallback
|
||||||
|
res.marshalJSON = func() ([]byte, error) {
|
||||||
|
signedBlock := structs.SignedBeaconBlockAltairFromConsensus(block.Altair)
|
||||||
|
return json.Marshal(signedBlock)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleBellatrixBlock(block *ethpb.GenericSignedBeaconBlock_Bellatrix) (*blockProcessingResult, error) {
|
||||||
|
var res blockProcessingResult
|
||||||
|
res.consensusVersion = "bellatrix"
|
||||||
|
res.blinded = false
|
||||||
|
|
||||||
|
beaconBlockRoot, err := block.Bellatrix.Block.HashTreeRoot()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to compute block root for bellatrix beacon block")
|
||||||
|
}
|
||||||
|
res.beaconBlockRoot = beaconBlockRoot
|
||||||
|
|
||||||
|
// Marshal SSZ
|
||||||
|
ssz, err := block.Bellatrix.MarshalSSZ()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to serialize block for bellatrix beacon block")
|
||||||
|
}
|
||||||
|
res.marshalledSSZ = ssz
|
||||||
|
|
||||||
|
// Set up JSON marshalling function for fallback
|
||||||
|
res.marshalJSON = func() ([]byte, error) {
|
||||||
|
signedBlock, err := structs.SignedBeaconBlockBellatrixFromConsensus(block.Bellatrix)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to convert bellatrix beacon block")
|
||||||
|
}
|
||||||
|
return json.Marshal(signedBlock)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleBlindedBellatrixBlock(block *ethpb.GenericSignedBeaconBlock_BlindedBellatrix) (*blockProcessingResult, error) {
|
||||||
|
var res blockProcessingResult
|
||||||
|
res.consensusVersion = "bellatrix"
|
||||||
|
res.blinded = true
|
||||||
|
|
||||||
|
beaconBlockRoot, err := block.BlindedBellatrix.Block.HashTreeRoot()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to compute block root for bellatrix beacon block")
|
||||||
|
}
|
||||||
|
res.beaconBlockRoot = beaconBlockRoot
|
||||||
|
|
||||||
|
// Marshal SSZ
|
||||||
|
ssz, err := block.BlindedBellatrix.MarshalSSZ()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to serialize block for bellatrix beacon block")
|
||||||
|
}
|
||||||
|
res.marshalledSSZ = ssz
|
||||||
|
|
||||||
|
// Set up JSON marshalling function for fallback
|
||||||
|
res.marshalJSON = func() ([]byte, error) {
|
||||||
|
signedBlock, err := structs.SignedBlindedBeaconBlockBellatrixFromConsensus(block.BlindedBellatrix)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to convert blinded bellatrix beacon block")
|
||||||
|
}
|
||||||
|
return json.Marshal(signedBlock)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleCapellaBlock(block *ethpb.GenericSignedBeaconBlock_Capella) (*blockProcessingResult, error) {
|
||||||
|
var res blockProcessingResult
|
||||||
|
res.consensusVersion = "capella"
|
||||||
|
res.blinded = false
|
||||||
|
|
||||||
|
beaconBlockRoot, err := block.Capella.Block.HashTreeRoot()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to compute block root for capella beacon block")
|
||||||
|
}
|
||||||
|
res.beaconBlockRoot = beaconBlockRoot
|
||||||
|
|
||||||
|
// Marshal SSZ
|
||||||
|
ssz, err := block.Capella.MarshalSSZ()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to serialize capella beacon block")
|
||||||
|
}
|
||||||
|
res.marshalledSSZ = ssz
|
||||||
|
|
||||||
|
// Set up JSON marshalling function for fallback
|
||||||
|
res.marshalJSON = func() ([]byte, error) {
|
||||||
|
signedBlock, err := structs.SignedBeaconBlockCapellaFromConsensus(block.Capella)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to convert capella beacon block")
|
||||||
|
}
|
||||||
|
return json.Marshal(signedBlock)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleBlindedCapellaBlock(block *ethpb.GenericSignedBeaconBlock_BlindedCapella) (*blockProcessingResult, error) {
|
||||||
|
var res blockProcessingResult
|
||||||
|
res.consensusVersion = "capella"
|
||||||
|
res.blinded = true
|
||||||
|
|
||||||
|
beaconBlockRoot, err := block.BlindedCapella.Block.HashTreeRoot()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to compute block root for blinded capella beacon block")
|
||||||
|
}
|
||||||
|
res.beaconBlockRoot = beaconBlockRoot
|
||||||
|
|
||||||
|
// Marshal SSZ
|
||||||
|
ssz, err := block.BlindedCapella.MarshalSSZ()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to serialize blinded capella beacon block")
|
||||||
|
}
|
||||||
|
res.marshalledSSZ = ssz
|
||||||
|
|
||||||
|
// Set up JSON marshalling function for fallback
|
||||||
|
res.marshalJSON = func() ([]byte, error) {
|
||||||
|
signedBlock, err := structs.SignedBlindedBeaconBlockCapellaFromConsensus(block.BlindedCapella)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to convert blinded capella beacon block")
|
||||||
|
}
|
||||||
|
return json.Marshal(signedBlock)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleDenebBlockContents(block *ethpb.GenericSignedBeaconBlock_Deneb) (*blockProcessingResult, error) {
|
||||||
|
var res blockProcessingResult
|
||||||
|
res.consensusVersion = "deneb"
|
||||||
|
res.blinded = false
|
||||||
|
|
||||||
|
beaconBlockRoot, err := block.Deneb.Block.HashTreeRoot()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to compute block root for deneb beacon block")
|
||||||
|
}
|
||||||
|
res.beaconBlockRoot = beaconBlockRoot
|
||||||
|
|
||||||
|
// Marshal SSZ
|
||||||
|
ssz, err := block.Deneb.MarshalSSZ()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to serialize deneb beacon block")
|
||||||
|
}
|
||||||
|
res.marshalledSSZ = ssz
|
||||||
|
|
||||||
|
// Set up JSON marshalling function for fallback
|
||||||
|
res.marshalJSON = func() ([]byte, error) {
|
||||||
|
signedBlock, err := structs.SignedBeaconBlockContentsDenebFromConsensus(block.Deneb)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to convert deneb beacon block contents")
|
||||||
|
}
|
||||||
|
return json.Marshal(signedBlock)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleBlindedDenebBlock(block *ethpb.GenericSignedBeaconBlock_BlindedDeneb) (*blockProcessingResult, error) {
|
||||||
|
var res blockProcessingResult
|
||||||
|
res.consensusVersion = "deneb"
|
||||||
|
res.blinded = true
|
||||||
|
|
||||||
|
beaconBlockRoot, err := block.BlindedDeneb.HashTreeRoot()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to compute block root for deneb blinded beacon block")
|
||||||
|
}
|
||||||
|
res.beaconBlockRoot = beaconBlockRoot
|
||||||
|
|
||||||
|
// Marshal SSZ
|
||||||
|
ssz, err := block.BlindedDeneb.MarshalSSZ()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to serialize blinded deneb beacon block")
|
||||||
|
}
|
||||||
|
res.marshalledSSZ = ssz
|
||||||
|
|
||||||
|
// Set up JSON marshalling function for fallback
|
||||||
|
res.marshalJSON = func() ([]byte, error) {
|
||||||
|
signedBlock, err := structs.SignedBlindedBeaconBlockDenebFromConsensus(block.BlindedDeneb)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to convert deneb blinded beacon block")
|
||||||
|
}
|
||||||
|
return json.Marshal(signedBlock)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleElectraBlockContents(block *ethpb.GenericSignedBeaconBlock_Electra) (*blockProcessingResult, error) {
|
||||||
|
var res blockProcessingResult
|
||||||
|
res.consensusVersion = "electra"
|
||||||
|
res.blinded = false
|
||||||
|
|
||||||
|
beaconBlockRoot, err := block.Electra.Block.HashTreeRoot()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to compute block root for electra beacon block")
|
||||||
|
}
|
||||||
|
res.beaconBlockRoot = beaconBlockRoot
|
||||||
|
|
||||||
|
// Marshal SSZ
|
||||||
|
ssz, err := block.Electra.MarshalSSZ()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to serialize electra beacon block")
|
||||||
|
}
|
||||||
|
res.marshalledSSZ = ssz
|
||||||
|
|
||||||
|
// Set up JSON marshalling function for fallback
|
||||||
|
res.marshalJSON = func() ([]byte, error) {
|
||||||
|
signedBlock, err := structs.SignedBeaconBlockContentsElectraFromConsensus(block.Electra)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to convert electra beacon block contents")
|
||||||
|
}
|
||||||
|
return json.Marshal(signedBlock)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleBlindedElectraBlock(block *ethpb.GenericSignedBeaconBlock_BlindedElectra) (*blockProcessingResult, error) {
|
||||||
|
var res blockProcessingResult
|
||||||
|
res.consensusVersion = "electra"
|
||||||
|
res.blinded = true
|
||||||
|
|
||||||
|
beaconBlockRoot, err := block.BlindedElectra.HashTreeRoot()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to compute block root for electra blinded beacon block")
|
||||||
|
}
|
||||||
|
res.beaconBlockRoot = beaconBlockRoot
|
||||||
|
|
||||||
|
// Marshal SSZ
|
||||||
|
ssz, err := block.BlindedElectra.MarshalSSZ()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to serialize blinded electra beacon block")
|
||||||
|
}
|
||||||
|
res.marshalledSSZ = ssz
|
||||||
|
|
||||||
|
// Set up JSON marshalling function for fallback
|
||||||
|
res.marshalJSON = func() ([]byte, error) {
|
||||||
|
signedBlock, err := structs.SignedBlindedBeaconBlockElectraFromConsensus(block.BlindedElectra)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to convert electra blinded beacon block")
|
||||||
|
}
|
||||||
|
return json.Marshal(signedBlock)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleFuluBlockContents(block *ethpb.GenericSignedBeaconBlock_Fulu) (*blockProcessingResult, error) {
|
||||||
|
var res blockProcessingResult
|
||||||
|
res.consensusVersion = "fulu"
|
||||||
|
res.blinded = false
|
||||||
|
|
||||||
|
beaconBlockRoot, err := block.Fulu.Block.HashTreeRoot()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to compute block root for fulu beacon block")
|
||||||
|
}
|
||||||
|
res.beaconBlockRoot = beaconBlockRoot
|
||||||
|
|
||||||
|
// Marshal SSZ
|
||||||
|
ssz, err := block.Fulu.MarshalSSZ()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to serialize fulu beacon block")
|
||||||
|
}
|
||||||
|
res.marshalledSSZ = ssz
|
||||||
|
|
||||||
|
// Set up JSON marshalling function for fallback
|
||||||
|
res.marshalJSON = func() ([]byte, error) {
|
||||||
|
signedBlock, err := structs.SignedBeaconBlockContentsFuluFromConsensus(block.Fulu)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to convert fulu beacon block contents")
|
||||||
|
}
|
||||||
|
return json.Marshal(signedBlock)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleBlindedFuluBlock(block *ethpb.GenericSignedBeaconBlock_BlindedFulu) (*blockProcessingResult, error) {
|
||||||
|
var res blockProcessingResult
|
||||||
|
res.consensusVersion = "fulu"
|
||||||
|
res.blinded = true
|
||||||
|
|
||||||
|
beaconBlockRoot, err := block.BlindedFulu.HashTreeRoot()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to compute block root for fulu blinded beacon block")
|
||||||
|
}
|
||||||
|
res.beaconBlockRoot = beaconBlockRoot
|
||||||
|
|
||||||
|
// Marshal SSZ
|
||||||
|
ssz, err := block.BlindedFulu.MarshalSSZ()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to serialize blinded fulu beacon block")
|
||||||
|
}
|
||||||
|
res.marshalledSSZ = ssz
|
||||||
|
|
||||||
|
// Set up JSON marshalling function for fallback
|
||||||
|
res.marshalJSON = func() ([]byte, error) {
|
||||||
|
signedBlock, err := structs.SignedBlindedBeaconBlockFuluFromConsensus(block.BlindedFulu)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to convert fulu blinded beacon block")
|
||||||
|
}
|
||||||
|
return json.Marshal(signedBlock)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &res, nil
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user