Skip to content

Commit

Permalink
get the proofs SPEC dependent
Browse files Browse the repository at this point in the history
  • Loading branch information
MaxMustermann2 committed Nov 14, 2024
1 parent 01d74b9 commit 85e38c9
Show file tree
Hide file tree
Showing 23 changed files with 1,212 additions and 357 deletions.
247 changes: 183 additions & 64 deletions beacon/capella.go

Large diffs are not rendered by default.

409 changes: 206 additions & 203 deletions beacon/deneb.go

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions beacon/shared.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
func ComputeValidatorTreeLeaves(validators []*phase0.Validator) ([]phase0.Root, error) {
validatorNodeList := make([]phase0.Root, len(validators))
for i := 0; i < len(validators); i++ {
// the validator structure does not change across any versions, so we can use fastssz
validatorRoot, err := validators[i].HashTreeRoot()
if err != nil {
return nil, err
Expand Down Expand Up @@ -112,6 +113,7 @@ func ProveBlockRootAgainstBeaconStateViaHistoricalSummaries(beaconStateTopLevelR
func ProveHistoricalSummaryAgainstHistoricalSummariesList(historicalSummaries []*capella.HistoricalSummary, historicalSummaryIndex uint64) (common.Proof, error) {
historicalSummaryNodeList := make([]phase0.Root, len(historicalSummaries))
for i := 0; i < len(historicalSummaries); i++ {
// historical summaries structure is not expected to change across versions, so we can use fastssz
historicalSummaryRoot, err := historicalSummaries[i].HashTreeRoot()
if err != nil {
return nil, err
Expand Down Expand Up @@ -178,6 +180,7 @@ func ProveWithdrawalListAgainstExecutionPayload(executionPayloadFieldRoots []pha
func ProveWithdrawalAgainstWithdrawalList(withdrawals []*capella.Withdrawal, withdrawalIndex uint8) (common.Proof, error) {
withdrawalNodeList := make([]phase0.Root, len(withdrawals))
for i := 0; i < len(withdrawals); i++ {
// not a dynamic structure, so we can use fastssz
withdrawalRoot, err := withdrawals[i].HashTreeRoot()
if err != nil {
return nil, err
Expand Down
140 changes: 140 additions & 0 deletions beacon/spec.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
package beacon

import (
"errors"
"fmt"
)

// GetValueFromKey returns the value of a key from a spec map, as the specified type T.
// If T is `int`, value is validated to be non-negative.
func GetValueFromKey[T int | uint64](spec map[string]any, key string) (T, error) {
if val, ok := spec[key]; ok {
// Use a type switch to handle int and uint64 cases
switch v := val.(type) {
case int:
if v < 0 && isType[T, int]() {
return T(0), errors.New("value for key " + key + " is negative, expected non-negative")
}
return T(v), nil
case uint64:
return T(v), nil
default:
return T(0), errors.New("type mismatch or unsupported type")
}
} else {
return T(0), errors.New(key + " not found in spec")
}
}

// Helper function to check the type
func isType[T, V any]() bool {
var t T
var v V
return fmt.Sprintf("%T", t) == fmt.Sprintf("%T", v)
}

// GetEth1DataVotesLength returns the number of eth1 data votes in a voting period.
func GetEth1DataVotesLength(spec map[string]any) (uint64, error) {
slotsPerEpoch, err := GetValueFromKey[uint64](spec, "SLOTS_PER_EPOCH")
if err != nil {
return 0, err
}
epochsPerEth1VotingPeriod, err := GetValueFromKey[uint64](spec, "EPOCHS_PER_ETH1_VOTING_PERIOD")
if err != nil {
return 0, err
}
return slotsPerEpoch * epochsPerEth1VotingPeriod, nil
}

// GetSlotsPerHistoricalRoot returns the number of slots per historical root.
func GetSlotsPerHistoricalRoot(spec map[string]any) (int, error) {
return GetValueFromKey[int](spec, "SLOTS_PER_HISTORICAL_ROOT")
}

// GetHistoricalRootsLimit returns the maximum number of historical roots that are stored.
func GetHistoricalRootsLimit(spec map[string]any) (int, error) {
return GetValueFromKey[int](spec, "HISTORICAL_ROOTS_LIMIT")
}

// GetValidatorRegistryLimit returns the maximum number of validators that can be registered.
func GetValidatorRegistryLimit(spec map[string]any) (uint64, error) {
return GetValueFromKey[uint64](spec, "VALIDATOR_REGISTRY_LIMIT")
}

// GetEpochsPerHistoricalVector returns the number of epochs per historical vector.
// It is used as the number of RANDAO Mixes.
func GetEpochsPerHistoricalVector(spec map[string]any) (int, error) {
return GetValueFromKey[int](spec, "EPOCHS_PER_HISTORICAL_VECTOR")
}

// GetEpochsPerSlashingsVector returns the number of epochs per slashings vector.
// It is used as the number of slashings stored in a beacon state.
func GetEpochsPerSlashingsVector(spec map[string]any) (int, error) {
return GetValueFromKey[int](spec, "EPOCHS_PER_SLASHINGS_VECTOR")
}

// GetMaxProposerSlashings returns the maximum number of proposer slashings that can be stored
// in a beacon state.
func GetMaxProposerSlashings(spec map[string]any) (uint64, error) {
return GetValueFromKey[uint64](spec, "MAX_PROPOSER_SLASHINGS")
}

// GetMaxAttesterSlashings returns the maximum number of attester slashings that can be stored
// in a beacon body.
func GetMaxAttesterSlashings(spec map[string]any) (uint64, error) {
return GetValueFromKey[uint64](spec, "MAX_ATTESTER_SLASHINGS")
}

// GetMaxAttestations returns the maximum number of attestations that can be stored
// in a beacon block body.
func GetMaxAttestations(spec map[string]any) (uint64, error) {
return GetValueFromKey[uint64](spec, "MAX_ATTESTATIONS")
}

// GetMaxDeposits returns the maximum number of deposits that can be stored
// in a beacon block body.
func GetMaxDeposits(spec map[string]any) (uint64, error) {
return GetValueFromKey[uint64](spec, "MAX_DEPOSITS")
}

// GetMaxVoluntaryExits returns the maximum number of voluntary exits that can
// be stored in a beacon block body.
func GetMaxVoluntaryExits(spec map[string]any) (uint64, error) {
return GetValueFromKey[uint64](spec, "MAX_VOLUNTARY_EXITS")
}

// GetMaxBLSToExecutionChanges returns the maximum number of BLS to execution changes that can
// be stored in a beacon block body.
func GetMaxBLSToExecutionChanges(spec map[string]any) (uint64, error) {
return GetValueFromKey[uint64](spec, "MAX_BLS_TO_EXECUTION_CHANGES")
}

// GetMaxBlobCommitments returns the maximum number of blob commitments that can be stored in
// a beacon block body.
func GetMaxBlobCommitments(spec map[string]any) (int, error) {
return GetValueFromKey[int](spec, "MAX_BLOB_COMMITMENTS_PER_BLOCK")
}

// GetMaxExtraDataBytes returns the maximum number of extra data bytes that can be stored in
// an execution payload.
func GetMaxExtraDataBytes(spec map[string]any) (uint64, error) {
return GetValueFromKey[uint64](spec, "MAX_EXTRA_DATA_BYTES")
}

// GetMaxTransactions returns the maximum number of transactions that can be stored
// in an execution payload.
func GetMaxTransactions(spec map[string]any) (uint64, error) {
return GetValueFromKey[uint64](spec, "MAX_TRANSACTIONS_PER_PAYLOAD")
}

// GetMaxBytesPerTransaction returns the maximum size of a transaction included in the
// execution payload.
func GetMaxBytesPerTransaction(spec map[string]any) (uint64, error) {
return GetValueFromKey[uint64](spec, "MAX_BYTES_PER_TRANSACTION")
}

// GetMaxWithdrawals returns the maximum number of withdrawals that can be stored in
// an execution payload.
func GetMaxWithdrawals(spec map[string]any) (uint64, error) {
return GetValueFromKey[uint64](spec, "MAX_WITHDRAWALS_PER_PAYLOAD")
}
8 changes: 7 additions & 1 deletion common/merkle_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,5 +189,11 @@ func ValidateProof(root phase0.Root, proof [][32]byte, element phase0.Root, inde
layer_index = layer_index / 2
}

return target_hash == root
res := target_hash == root

// fmt.Printf(
// "Validated proof root: %#x, leaf: %#x, index: %d, result: %t\n",
// root, element, index, res,
// )
return res
}
99 changes: 99 additions & 0 deletions common_utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"os"
"strconv"
"strings"
"time"

beacon "github.com/Layr-Labs/eigenpod-proofs-generation/beacon"
"github.com/Layr-Labs/eigenpod-proofs-generation/common"
Expand Down Expand Up @@ -312,6 +313,104 @@ func ParseDenebStateJSONFile(filePath string) (*beaconStateJSONDeneb, error) {
return &actualData, nil
}

// ParseSpecFile reads a spec.json and parses it. Since there is no spec type yet defined, it
// does some manual processing. The spec must be downloaded as follow:
// curl -s $BEACON_API_URL/eth/v1/config/spec | jq .data > spec.json
func ParseSpecJSONFile(filePath string) (map[string]any, error) {
data, err := ioutil.ReadFile(filePath)
if err != nil {
log.Debug().Str("file", filePath).Msgf("error with reading file: %v", err)
return nil, err
}
var unmarshalAsString map[string]string
if err := json.Unmarshal(data, &unmarshalAsString); err != nil {
log.Debug().Msgf("error with JSON unmarshalling: %v", err)
return nil, err
}
res := make(map[string]any, len(unmarshalAsString))
// copied from spec.go in go-eth2-client/http
for k, v := range unmarshalAsString {
// Handle domains.
if strings.HasPrefix(k, "DOMAIN_") {
byteVal, err := hex.DecodeString(strings.TrimPrefix(v, "0x"))
if err == nil {
var domainType phase0.DomainType
copy(domainType[:], byteVal)
res[k] = domainType
continue
}
}
// Handle fork versions.
if strings.HasSuffix(k, "_FORK_VERSION") {
byteVal, err := hex.DecodeString(strings.TrimPrefix(v, "0x"))
if err == nil {
var version phase0.Version
copy(version[:], byteVal)
res[k] = version
continue
}
}
// Handle hex strings.
if strings.HasPrefix(v, "0x") {
byteVal, err := hex.DecodeString(strings.TrimPrefix(v, "0x"))
if err == nil {
res[k] = byteVal
continue
}
}
// Handle times.
if strings.HasSuffix(k, "_TIME") {
intVal, err := strconv.ParseInt(v, 10, 64)
if err == nil && intVal != 0 {
res[k] = time.Unix(intVal, 0)
continue
}
}
// Handle durations.
if strings.HasPrefix(k, "SECONDS_PER_") || k == "GENESIS_DELAY" {
intVal, err := strconv.ParseUint(v, 10, 64)
if err == nil && intVal != 0 {
res[k] = time.Duration(intVal) * time.Second
continue
}
}
// Handle integers.
if v == "0" {
res[k] = uint64(0)
continue
}
intVal, err := strconv.ParseUint(v, 10, 64)
if err == nil && intVal != 0 {
res[k] = intVal
continue
}
// assume it is a string
res[k] = v
}
// The application mask domain type is not provided by all nodes, so add it here if not present.
if _, exists := res["DOMAIN_APPLICATION_MASK"]; !exists {
res["DOMAIN_APPLICATION_MASK"] = phase0.DomainType{0x00, 0x00, 0x00, 0x01}
}
// The BLS to execution change domain type is not provided by all nodes, so add it here if not present.
if _, exists := res["DOMAIN_BLS_TO_EXECUTION_CHANGE"]; !exists {
res["DOMAIN_BLS_TO_EXECUTION_CHANGE"] = phase0.DomainType{0x0a, 0x00, 0x00, 0x00}
}
// The builder application domain type is not officially part of the spec, so add it here if not present.
if _, exists := res["DOMAIN_APPLICATION_BUILDER"]; !exists {
res["DOMAIN_APPLICATION_BUILDER"] = phase0.DomainType{0x00, 0x00, 0x00, 0x01}
}
if _, exists := res["MAX_TRANSACTIONS_PER_PAYLOAD"]; !exists {
res["MAX_TRANSACTIONS_PER_PAYLOAD"] = 1048576
}
if _, exists := res["MAX_BYTES_PER_TRANSACTION"]; !exists {
res["MAX_BYTES_PER_TRANSACTION"] = 1073741824
}
if _, exists := res["MAX_BLOB_COMMITMENTS_PER_BLOCK"]; !exists {
res["MAX_BLOB_COMMITMENTS_PER_BLOCK"] = 4096
}
return res, nil
}

func ParseCapellaStateJSONFile(filePath string) (*beaconStateJSONCapella, error) {
data, err := ioutil.ReadFile(filePath)

Expand Down
Loading

0 comments on commit 85e38c9

Please sign in to comment.