Compare commits

...

6 Commits

Author SHA1 Message Date
terence tsao
926f2ade15 James's feedback 2026-01-10 04:31:12 +08:00
terence tsao
3343ce768d Add gloas payload header processing
Add Gloas execution payload header processing and state integration

Implement Gloas fork support in consensus-types/blocks

Add Gloas state fields to beacon state implementation
2026-01-08 23:09:51 -08:00
Potuz
158c09ca8c Add --low-valcount-sweep feature flag for withdrawal sweep bound (#16231)
Gate the withdrawal sweep optimization (using min of validator count and
MaxValidatorsPerWithdrawalsSweep) behind a hidden feature flag that
defaults to false. Enable the flag for spectests to match consensus
spec.

The backported changes were from
[4788](https://github.com/ethereum/consensus-specs/pull/4788)

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 16:14:03 +00:00
Bastin
17245f4fac Ephemeral debug logfile (#16108)
**What type of PR is this?**
Feature

**What does this PR do? Why is it needed?**
This PR introduces an ephemeral log file that captures debug logs for 24
hours.

- it captures debug logs regardless of the user provided (or
non-provided) `--verbosity` flag.
- it allows a maximum of 250MB for each log file. 
- it keeps 1 backup logfile in case of size-based rotations. (as opposed
to time-based)
- this is enabled by default for beacon and validator nodes.
- the log files live in `datadir/logs/` directory under the names of
`beacon-chain.log` and `validator.log`. backups have a timestamp in
their name as well.
- the feature can be disabled using the `--disable-ephemeral-log-file`
flag.
2026-01-08 14:16:22 +00:00
Bastin
53b0a574ab Set logging verbosity per writer hook instead of globally (#16106)
**What type of PR is this?**
Feature

**What does this PR do? Why is it needed?**
This PR sets the logging verbosity level per writer hook (per output:
terminal, log file, etc) rather than setting a global logrus level which
limits customizing each output.

it set the terminal and log file output to be the same as the user
provided `--verbosity` flag. so nothing changes in reality.

it also introduces a `SetLoggingLevel()` to be used instead of
`logrus.SetLeveL()` in order for us to be able to set a different
baseline level later on if needed. (my next PR will use this).

I'm only making this change in the `beacon-chain` and `validator` apps,
skipping tools like `bootnode` and `client-stats`.
2026-01-08 12:19:16 +00:00
terence
c96d188468 gloas: add builders registry and update state fields (#16164)
This pr implements the Gloas builder registry and related beacon state
fields per the spec, including proto/SSZ updates and state-native wiring
for builders, payload availability, pending payments/withdrawals, and
expected withdrawals. This aligns BeaconState with the Gloas container
changes and adds supporting hashing/copy helpers.

Spec ref:
https://github.com/ethereum/consensus-specs/blob/master/specs/gloas/beacon-chain.md
2026-01-07 21:51:56 +00:00
76 changed files with 3590 additions and 823 deletions

View File

@@ -26,6 +26,7 @@ go_library(
"//beacon-chain/core/time:go_default_library", "//beacon-chain/core/time:go_default_library",
"//beacon-chain/core/validators:go_default_library", "//beacon-chain/core/validators:go_default_library",
"//beacon-chain/state:go_default_library", "//beacon-chain/state:go_default_library",
"//config/features:go_default_library",
"//config/fieldparams:go_default_library", "//config/fieldparams:go_default_library",
"//config/params:go_default_library", "//config/params:go_default_library",
"//consensus-types:go_default_library", "//consensus-types:go_default_library",

View File

@@ -7,6 +7,7 @@ import (
"github.com/OffchainLabs/prysm/v7/beacon-chain/core/helpers" "github.com/OffchainLabs/prysm/v7/beacon-chain/core/helpers"
"github.com/OffchainLabs/prysm/v7/beacon-chain/core/signing" "github.com/OffchainLabs/prysm/v7/beacon-chain/core/signing"
"github.com/OffchainLabs/prysm/v7/beacon-chain/state" "github.com/OffchainLabs/prysm/v7/beacon-chain/state"
"github.com/OffchainLabs/prysm/v7/config/features"
fieldparams "github.com/OffchainLabs/prysm/v7/config/fieldparams" fieldparams "github.com/OffchainLabs/prysm/v7/config/fieldparams"
"github.com/OffchainLabs/prysm/v7/config/params" "github.com/OffchainLabs/prysm/v7/config/params"
"github.com/OffchainLabs/prysm/v7/consensus-types/interfaces" "github.com/OffchainLabs/prysm/v7/consensus-types/interfaces"
@@ -212,8 +213,12 @@ func ProcessWithdrawals(st state.BeaconState, executionData interfaces.Execution
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not get next withdrawal validator index") return nil, errors.Wrap(err, "could not get next withdrawal validator index")
} }
bound := min(uint64(st.NumValidators()), params.BeaconConfig().MaxValidatorsPerWithdrawalsSweep) if features.Get().LowValcountSweep {
nextValidatorIndex += primitives.ValidatorIndex(bound) bound := min(uint64(st.NumValidators()), params.BeaconConfig().MaxValidatorsPerWithdrawalsSweep)
nextValidatorIndex += primitives.ValidatorIndex(bound)
} else {
nextValidatorIndex += primitives.ValidatorIndex(params.BeaconConfig().MaxValidatorsPerWithdrawalsSweep)
}
nextValidatorIndex = nextValidatorIndex % primitives.ValidatorIndex(st.NumValidators()) nextValidatorIndex = nextValidatorIndex % primitives.ValidatorIndex(st.NumValidators())
} else { } else {
nextValidatorIndex = expectedWithdrawals[len(expectedWithdrawals)-1].ValidatorIndex + 1 nextValidatorIndex = expectedWithdrawals[len(expectedWithdrawals)-1].ValidatorIndex + 1

View File

@@ -0,0 +1,45 @@
load("@prysm//tools/go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = ["bid.go"],
importpath = "github.com/OffchainLabs/prysm/v7/beacon-chain/core/gloas",
visibility = ["//visibility:public"],
deps = [
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/core/signing:go_default_library",
"//beacon-chain/state:go_default_library",
"//config/fieldparams:go_default_library",
"//config/params:go_default_library",
"//consensus-types/blocks:go_default_library",
"//consensus-types/interfaces:go_default_library",
"//crypto/bls:go_default_library",
"//crypto/bls/common:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//time/slots:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = ["bid_test.go"],
embed = [":go_default_library"],
deps = [
"//beacon-chain/core/signing:go_default_library",
"//beacon-chain/state/state-native:go_default_library",
"//config/params:go_default_library",
"//consensus-types/interfaces:go_default_library",
"//consensus-types/primitives:go_default_library",
"//crypto/bls:go_default_library",
"//crypto/bls/common:go_default_library",
"//encoding/bytesutil:go_default_library",
"//proto/engine/v1:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//proto/prysm/v1alpha1/validator-client:go_default_library",
"//runtime/version:go_default_library",
"//testing/require:go_default_library",
"//time/slots:go_default_library",
"@com_github_prysmaticlabs_fastssz//:go_default_library",
"@org_golang_google_protobuf//proto:go_default_library",
],
)

View File

@@ -0,0 +1,197 @@
package gloas
import (
"errors"
"fmt"
"github.com/OffchainLabs/prysm/v7/beacon-chain/core/helpers"
"github.com/OffchainLabs/prysm/v7/beacon-chain/core/signing"
"github.com/OffchainLabs/prysm/v7/beacon-chain/state"
fieldparams "github.com/OffchainLabs/prysm/v7/config/fieldparams"
"github.com/OffchainLabs/prysm/v7/config/params"
"github.com/OffchainLabs/prysm/v7/consensus-types/blocks"
"github.com/OffchainLabs/prysm/v7/consensus-types/interfaces"
"github.com/OffchainLabs/prysm/v7/crypto/bls"
"github.com/OffchainLabs/prysm/v7/crypto/bls/common"
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v7/time/slots"
)
// ProcessExecutionPayloadBid processes a signed execution payload bid in the Gloas fork.
// Spec v1.7.0-alpha.0 (pseudocode):
// process_execution_payload_bid(state: BeaconState, block: BeaconBlock):
//
// signed_bid = block.body.signed_execution_payload_bid
// bid = signed_bid.message
// builder_index = bid.builder_index
// amount = bid.value
// if builder_index == BUILDER_INDEX_SELF_BUILD:
// assert amount == 0
// assert signed_bid.signature == G2_POINT_AT_INFINITY
// else:
// assert is_active_builder(state, builder_index)
// assert can_builder_cover_bid(state, builder_index, amount)
// assert verify_execution_payload_bid_signature(state, signed_bid)
// assert bid.slot == block.slot
// assert bid.parent_block_hash == state.latest_block_hash
// assert bid.parent_block_root == block.parent_root
// assert bid.prev_randao == get_randao_mix(state, get_current_epoch(state))
// if amount > 0:
// state.builder_pending_payments[...] = BuilderPendingPayment(weight=0, withdrawal=BuilderPendingWithdrawal(fee_recipient=bid.fee_recipient, amount=amount, builder_index=builder_index))
// state.latest_execution_payload_bid = bid
func ProcessExecutionPayloadBid(st state.BeaconState, block interfaces.ReadOnlyBeaconBlock) error {
signedBid, err := block.Body().SignedExecutionPayloadBid()
if err != nil {
return fmt.Errorf("failed to get signed execution payload bid: %w", err)
}
wrappedBid, err := blocks.WrappedROSignedExecutionPayloadBid(signedBid)
if err != nil {
return fmt.Errorf("failed to wrap signed bid: %w", err)
}
bid, err := wrappedBid.Bid()
if err != nil {
return fmt.Errorf("failed to get bid from wrapped bid: %w", err)
}
builderIndex := bid.BuilderIndex()
amount := bid.Value()
if builderIndex == params.BeaconConfig().BuilderIndexSelfBuild {
if amount != 0 {
return fmt.Errorf("self-build amount must be zero, got %d", amount)
}
if wrappedBid.Signature() != common.InfiniteSignature {
return errors.New("self-build signature must be point at infinity")
}
} else {
ok, err := st.IsActiveBuilder(builderIndex)
if err != nil {
return fmt.Errorf("builder active check failed: %w", err)
}
if !ok {
return fmt.Errorf("builder %d is not active", builderIndex)
}
ok, err = st.CanBuilderCoverBid(builderIndex, amount)
if err != nil {
return fmt.Errorf("builder balance check failed: %w", err)
}
if !ok {
return fmt.Errorf("builder %d cannot cover bid amount %d", builderIndex, amount)
}
if err := validatePayloadBidSignature(st, wrappedBid); err != nil {
return fmt.Errorf("bid signature validation failed: %w", err)
}
}
if err := validateBidConsistency(st, bid, block); err != nil {
return fmt.Errorf("bid consistency validation failed: %w", err)
}
if amount > 0 {
feeRecipient := bid.FeeRecipient()
pendingPayment := &ethpb.BuilderPendingPayment{
Weight: 0,
Withdrawal: &ethpb.BuilderPendingWithdrawal{
FeeRecipient: feeRecipient[:],
Amount: amount,
BuilderIndex: builderIndex,
},
}
slotIndex := params.BeaconConfig().SlotsPerEpoch + (bid.Slot() % params.BeaconConfig().SlotsPerEpoch)
if err := st.SetBuilderPendingPayment(slotIndex, pendingPayment); err != nil {
return fmt.Errorf("failed to set pending payment: %w", err)
}
}
if err := st.SetExecutionPayloadBid(bid); err != nil {
return fmt.Errorf("failed to cache execution payload bid: %w", err)
}
return nil
}
// validateBidConsistency checks that the bid is consistent with the current beacon state.
func validateBidConsistency(st state.BeaconState, bid interfaces.ROExecutionPayloadBid, block interfaces.ReadOnlyBeaconBlock) error {
if bid.Slot() != block.Slot() {
return fmt.Errorf("bid slot %d does not match block slot %d", bid.Slot(), block.Slot())
}
latestBlockHash, err := st.LatestBlockHash()
if err != nil {
return fmt.Errorf("failed to get latest block hash: %w", err)
}
if bid.ParentBlockHash() != latestBlockHash {
return fmt.Errorf("bid parent block hash mismatch: got %x, expected %x",
bid.ParentBlockHash(), latestBlockHash)
}
if bid.ParentBlockRoot() != block.ParentRoot() {
return fmt.Errorf("bid parent block root mismatch: got %x, expected %x",
bid.ParentBlockRoot(), block.ParentRoot())
}
randaoMix, err := helpers.RandaoMix(st, slots.ToEpoch(st.Slot()))
if err != nil {
return fmt.Errorf("failed to get randao mix: %w", err)
}
if bid.PrevRandao() != [32]byte(randaoMix) {
return fmt.Errorf("bid prev randao mismatch: got %x, expected %x", bid.PrevRandao(), randaoMix)
}
return nil
}
// validatePayloadBidSignature verifies the BLS signature on a signed execution payload bid.
// It validates that the signature was created by the builder specified in the bid
// using the appropriate domain for the beacon builder.
func validatePayloadBidSignature(st state.ReadOnlyBeaconState, signedBid interfaces.ROSignedExecutionPayloadBid) error {
bid, err := signedBid.Bid()
if err != nil {
return fmt.Errorf("failed to get bid: %w", err)
}
builder, err := st.BuilderAtIndex(bid.BuilderIndex())
if err != nil {
return fmt.Errorf("failed to get builder: %w", err)
}
if len(builder.Pubkey) != fieldparams.BLSPubkeyLength {
return fmt.Errorf("invalid builder public key length: %d", len(builder.Pubkey))
}
publicKey, err := bls.PublicKeyFromBytes(builder.Pubkey)
if err != nil {
return fmt.Errorf("invalid builder public key: %w", err)
}
signatureBytes := signedBid.Signature()
signature, err := bls.SignatureFromBytes(signatureBytes[:])
if err != nil {
return fmt.Errorf("invalid signature format: %w", err)
}
currentEpoch := slots.ToEpoch(bid.Slot())
domain, err := signing.Domain(
st.Fork(),
currentEpoch,
params.BeaconConfig().DomainBeaconBuilder,
st.GenesisValidatorsRoot(),
)
if err != nil {
return fmt.Errorf("failed to compute signing domain: %w", err)
}
signingRoot, err := signedBid.SigningRoot(domain)
if err != nil {
return fmt.Errorf("failed to compute signing root: %w", err)
}
if !signature.Verify(publicKey, signingRoot[:]) {
return fmt.Errorf("signature verification failed: %w", signing.ErrSigFailedToVerify)
}
return nil
}

View File

@@ -0,0 +1,628 @@
package gloas
import (
"bytes"
"testing"
"github.com/OffchainLabs/prysm/v7/beacon-chain/core/signing"
state_native "github.com/OffchainLabs/prysm/v7/beacon-chain/state/state-native"
"github.com/OffchainLabs/prysm/v7/config/params"
"github.com/OffchainLabs/prysm/v7/consensus-types/interfaces"
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
"github.com/OffchainLabs/prysm/v7/crypto/bls"
"github.com/OffchainLabs/prysm/v7/crypto/bls/common"
"github.com/OffchainLabs/prysm/v7/encoding/bytesutil"
enginev1 "github.com/OffchainLabs/prysm/v7/proto/engine/v1"
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
validatorpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1/validator-client"
"github.com/OffchainLabs/prysm/v7/runtime/version"
"github.com/OffchainLabs/prysm/v7/testing/require"
"github.com/OffchainLabs/prysm/v7/time/slots"
fastssz "github.com/prysmaticlabs/fastssz"
"google.golang.org/protobuf/proto"
)
type stubBlockBody struct {
signedBid *ethpb.SignedExecutionPayloadBid
}
func (s stubBlockBody) Version() int { return version.Gloas }
func (s stubBlockBody) RandaoReveal() [96]byte { return [96]byte{} }
func (s stubBlockBody) Eth1Data() *ethpb.Eth1Data { return nil }
func (s stubBlockBody) Graffiti() [32]byte { return [32]byte{} }
func (s stubBlockBody) ProposerSlashings() []*ethpb.ProposerSlashing { return nil }
func (s stubBlockBody) AttesterSlashings() []ethpb.AttSlashing { return nil }
func (s stubBlockBody) Attestations() []ethpb.Att { return nil }
func (s stubBlockBody) Deposits() []*ethpb.Deposit { return nil }
func (s stubBlockBody) VoluntaryExits() []*ethpb.SignedVoluntaryExit { return nil }
func (s stubBlockBody) SyncAggregate() (*ethpb.SyncAggregate, error) { return nil, nil }
func (s stubBlockBody) IsNil() bool { return s.signedBid == nil }
func (s stubBlockBody) HashTreeRoot() ([32]byte, error) { return [32]byte{}, nil }
func (s stubBlockBody) Proto() (proto.Message, error) { return nil, nil }
func (s stubBlockBody) Execution() (interfaces.ExecutionData, error) { return nil, nil }
func (s stubBlockBody) BLSToExecutionChanges() ([]*ethpb.SignedBLSToExecutionChange, error) {
return nil, nil
}
func (s stubBlockBody) BlobKzgCommitments() ([][]byte, error) { return nil, nil }
func (s stubBlockBody) ExecutionRequests() (*enginev1.ExecutionRequests, error) {
return nil, nil
}
func (s stubBlockBody) PayloadAttestations() ([]*ethpb.PayloadAttestation, error) {
return nil, nil
}
func (s stubBlockBody) SignedExecutionPayloadBid() (*ethpb.SignedExecutionPayloadBid, error) {
return s.signedBid, nil
}
func (s stubBlockBody) MarshalSSZ() ([]byte, error) { return nil, nil }
func (s stubBlockBody) MarshalSSZTo([]byte) ([]byte, error) { return nil, nil }
func (s stubBlockBody) UnmarshalSSZ([]byte) error { return nil }
func (s stubBlockBody) SizeSSZ() int { return 0 }
type stubBlock struct {
slot primitives.Slot
proposer primitives.ValidatorIndex
parentRoot [32]byte
body stubBlockBody
v int
}
func (s stubBlock) Slot() primitives.Slot { return s.slot }
func (s stubBlock) ProposerIndex() primitives.ValidatorIndex { return s.proposer }
func (s stubBlock) ParentRoot() [32]byte { return s.parentRoot }
func (s stubBlock) StateRoot() [32]byte { return [32]byte{} }
func (s stubBlock) Body() interfaces.ReadOnlyBeaconBlockBody { return s.body }
func (s stubBlock) IsNil() bool { return false }
func (s stubBlock) IsBlinded() bool { return false }
func (s stubBlock) HashTreeRoot() ([32]byte, error) { return [32]byte{}, nil }
func (s stubBlock) Proto() (proto.Message, error) { return nil, nil }
func (s stubBlock) MarshalSSZ() ([]byte, error) { return nil, nil }
func (s stubBlock) MarshalSSZTo([]byte) ([]byte, error) { return nil, nil }
func (s stubBlock) UnmarshalSSZ([]byte) error { return nil }
func (s stubBlock) SizeSSZ() int { return 0 }
func (s stubBlock) Version() int { return s.v }
func (s stubBlock) AsSignRequestObject() (validatorpb.SignRequestObject, error) {
return nil, nil
}
func (s stubBlock) HashTreeRootWith(*fastssz.Hasher) error { return nil }
func buildGloasState(t *testing.T, slot primitives.Slot, proposerIdx primitives.ValidatorIndex, builderIdx primitives.BuilderIndex, balance uint64, randao [32]byte, latestHash [32]byte, builderPubkey [48]byte) *state_native.BeaconState {
t.Helper()
cfg := params.BeaconConfig()
blockRoots := make([][]byte, cfg.SlotsPerHistoricalRoot)
stateRoots := make([][]byte, cfg.SlotsPerHistoricalRoot)
for i := range blockRoots {
blockRoots[i] = bytes.Repeat([]byte{0xAA}, 32)
stateRoots[i] = bytes.Repeat([]byte{0xBB}, 32)
}
randaoMixes := make([][]byte, cfg.EpochsPerHistoricalVector)
for i := range randaoMixes {
randaoMixes[i] = randao[:]
}
withdrawalCreds := make([]byte, 32)
withdrawalCreds[0] = cfg.BuilderWithdrawalPrefixByte
validatorCount := int(proposerIdx) + 1
validators := make([]*ethpb.Validator, validatorCount)
balances := make([]uint64, validatorCount)
for i := range validatorCount {
validators[i] = &ethpb.Validator{
PublicKey: builderPubkey[:],
WithdrawalCredentials: withdrawalCreds,
EffectiveBalance: balance,
Slashed: false,
ActivationEligibilityEpoch: 0,
ActivationEpoch: 0,
ExitEpoch: cfg.FarFutureEpoch,
WithdrawableEpoch: cfg.FarFutureEpoch,
}
balances[i] = balance
}
payments := make([]*ethpb.BuilderPendingPayment, cfg.SlotsPerEpoch*2)
for i := range payments {
payments[i] = &ethpb.BuilderPendingPayment{Withdrawal: &ethpb.BuilderPendingWithdrawal{}}
}
var builders []*ethpb.Builder
if builderIdx != params.BeaconConfig().BuilderIndexSelfBuild {
builderCount := int(builderIdx) + 1
builders = make([]*ethpb.Builder, builderCount)
builders[builderCount-1] = &ethpb.Builder{
Pubkey: builderPubkey[:],
Version: []byte{0},
ExecutionAddress: bytes.Repeat([]byte{0x01}, 20),
Balance: primitives.Gwei(balance),
DepositEpoch: 0,
WithdrawableEpoch: cfg.FarFutureEpoch,
}
}
stProto := &ethpb.BeaconStateGloas{
Slot: slot,
GenesisValidatorsRoot: bytes.Repeat([]byte{0x11}, 32),
Fork: &ethpb.Fork{
CurrentVersion: bytes.Repeat([]byte{0x22}, 4),
PreviousVersion: bytes.Repeat([]byte{0x22}, 4),
Epoch: 0,
},
BlockRoots: blockRoots,
StateRoots: stateRoots,
RandaoMixes: randaoMixes,
Validators: validators,
Balances: balances,
LatestBlockHash: latestHash[:],
BuilderPendingPayments: payments,
BuilderPendingWithdrawals: []*ethpb.BuilderPendingWithdrawal{},
Builders: builders,
FinalizedCheckpoint: &ethpb.Checkpoint{
Epoch: 1,
},
}
st, err := state_native.InitializeFromProtoGloas(stProto)
require.NoError(t, err)
return st.(*state_native.BeaconState)
}
func signBid(t *testing.T, sk common.SecretKey, bid *ethpb.ExecutionPayloadBid, fork *ethpb.Fork, genesisRoot [32]byte) [96]byte {
t.Helper()
epoch := slots.ToEpoch(primitives.Slot(bid.Slot))
domain, err := signing.Domain(fork, epoch, params.BeaconConfig().DomainBeaconBuilder, genesisRoot[:])
require.NoError(t, err)
root, err := signing.ComputeSigningRoot(bid, domain)
require.NoError(t, err)
sig := sk.Sign(root[:]).Marshal()
var out [96]byte
copy(out[:], sig)
return out
}
func TestProcessExecutionPayloadBid_SelfBuildSuccess(t *testing.T) {
slot := primitives.Slot(12)
proposerIdx := primitives.ValidatorIndex(0)
builderIdx := params.BeaconConfig().BuilderIndexSelfBuild
randao := [32]byte(bytes.Repeat([]byte{0xAA}, 32))
latestHash := [32]byte(bytes.Repeat([]byte{0xBB}, 32))
pubKey := [48]byte{}
state := buildGloasState(t, slot, proposerIdx, builderIdx, params.BeaconConfig().MinActivationBalance+1000, randao, latestHash, pubKey)
bid := &ethpb.ExecutionPayloadBid{
ParentBlockHash: latestHash[:],
ParentBlockRoot: bytes.Repeat([]byte{0xCC}, 32),
BlockHash: bytes.Repeat([]byte{0xDD}, 32),
PrevRandao: randao[:],
GasLimit: 1,
BuilderIndex: builderIdx,
Slot: slot,
Value: 0,
ExecutionPayment: 0,
BlobKzgCommitmentsRoot: bytes.Repeat([]byte{0xEE}, 32),
FeeRecipient: bytes.Repeat([]byte{0xFF}, 20),
}
signed := &ethpb.SignedExecutionPayloadBid{
Message: bid,
Signature: common.InfiniteSignature[:],
}
block := stubBlock{
slot: slot,
proposer: proposerIdx,
parentRoot: bytesutil.ToBytes32(bid.ParentBlockRoot),
body: stubBlockBody{signedBid: signed},
v: version.Gloas,
}
require.NoError(t, ProcessExecutionPayloadBid(state, block))
stateProto, ok := state.ToProto().(*ethpb.BeaconStateGloas)
require.Equal(t, true, ok)
slotIndex := params.BeaconConfig().SlotsPerEpoch + (slot % params.BeaconConfig().SlotsPerEpoch)
require.Equal(t, primitives.Gwei(0), stateProto.BuilderPendingPayments[slotIndex].Withdrawal.Amount)
}
func TestProcessExecutionPayloadBid_SelfBuildNonZeroAmountFails(t *testing.T) {
slot := primitives.Slot(2)
proposerIdx := primitives.ValidatorIndex(0)
builderIdx := params.BeaconConfig().BuilderIndexSelfBuild
randao := [32]byte{}
latestHash := [32]byte{1}
state := buildGloasState(t, slot, proposerIdx, builderIdx, params.BeaconConfig().MinActivationBalance+1000, randao, latestHash, [48]byte{})
bid := &ethpb.ExecutionPayloadBid{
ParentBlockHash: latestHash[:],
ParentBlockRoot: bytes.Repeat([]byte{0xAA}, 32),
BlockHash: bytes.Repeat([]byte{0xBB}, 32),
PrevRandao: randao[:],
BuilderIndex: builderIdx,
Slot: slot,
Value: 10,
ExecutionPayment: 0,
BlobKzgCommitmentsRoot: bytes.Repeat([]byte{0xCC}, 32),
FeeRecipient: bytes.Repeat([]byte{0xDD}, 20),
}
signed := &ethpb.SignedExecutionPayloadBid{
Message: bid,
Signature: common.InfiniteSignature[:],
}
block := stubBlock{
slot: slot,
proposer: proposerIdx,
parentRoot: bytesutil.ToBytes32(bid.ParentBlockRoot),
body: stubBlockBody{signedBid: signed},
v: version.Gloas,
}
err := ProcessExecutionPayloadBid(state, block)
require.ErrorContains(t, "self-build amount must be zero", err)
}
func TestProcessExecutionPayloadBid_PendingPaymentAndCacheBid(t *testing.T) {
slot := primitives.Slot(8)
builderIdx := primitives.BuilderIndex(1)
proposerIdx := primitives.ValidatorIndex(2)
randao := [32]byte(bytes.Repeat([]byte{0xAA}, 32))
latestHash := [32]byte(bytes.Repeat([]byte{0xBB}, 32))
sk, err := bls.RandKey()
require.NoError(t, err)
pub := sk.PublicKey().Marshal()
var pubKey [48]byte
copy(pubKey[:], pub)
balance := params.BeaconConfig().MinActivationBalance + 1_000_000
state := buildGloasState(t, slot, proposerIdx, builderIdx, balance, randao, latestHash, pubKey)
bid := &ethpb.ExecutionPayloadBid{
ParentBlockHash: latestHash[:],
ParentBlockRoot: bytes.Repeat([]byte{0xCC}, 32),
BlockHash: bytes.Repeat([]byte{0xDD}, 32),
PrevRandao: randao[:],
GasLimit: 1,
BuilderIndex: builderIdx,
Slot: slot,
Value: 500_000,
ExecutionPayment: 1,
BlobKzgCommitmentsRoot: bytes.Repeat([]byte{0xEE}, 32),
FeeRecipient: bytes.Repeat([]byte{0xFF}, 20),
}
genesis := bytesutil.ToBytes32(state.GenesisValidatorsRoot())
sig := signBid(t, sk, bid, state.Fork(), genesis)
signed := &ethpb.SignedExecutionPayloadBid{
Message: bid,
Signature: sig[:],
}
block := stubBlock{
slot: slot,
proposer: proposerIdx, // not self-build
parentRoot: bytesutil.ToBytes32(bid.ParentBlockRoot),
body: stubBlockBody{signedBid: signed},
v: version.Gloas,
}
require.NoError(t, ProcessExecutionPayloadBid(state, block))
stateProto, ok := state.ToProto().(*ethpb.BeaconStateGloas)
require.Equal(t, true, ok)
slotIndex := params.BeaconConfig().SlotsPerEpoch + (slot % params.BeaconConfig().SlotsPerEpoch)
require.Equal(t, primitives.Gwei(500_000), stateProto.BuilderPendingPayments[slotIndex].Withdrawal.Amount)
require.NotNil(t, stateProto.LatestExecutionPayloadBid)
require.Equal(t, primitives.BuilderIndex(1), stateProto.LatestExecutionPayloadBid.BuilderIndex)
require.Equal(t, primitives.Gwei(500_000), stateProto.LatestExecutionPayloadBid.Value)
}
func TestProcessExecutionPayloadBid_BuilderNotActive(t *testing.T) {
slot := primitives.Slot(4)
builderIdx := primitives.BuilderIndex(1)
proposerIdx := primitives.ValidatorIndex(2)
randao := [32]byte(bytes.Repeat([]byte{0x01}, 32))
latestHash := [32]byte(bytes.Repeat([]byte{0x02}, 32))
sk, err := bls.RandKey()
require.NoError(t, err)
var pubKey [48]byte
copy(pubKey[:], sk.PublicKey().Marshal())
state := buildGloasState(t, slot, proposerIdx, builderIdx, params.BeaconConfig().MinDepositAmount+1000, randao, latestHash, pubKey)
// Make builder inactive by setting withdrawable_epoch.
stateProto := state.ToProto().(*ethpb.BeaconStateGloas)
stateProto.Builders[int(builderIdx)].WithdrawableEpoch = 0
stateIface, err := state_native.InitializeFromProtoGloas(stateProto)
require.NoError(t, err)
state = stateIface.(*state_native.BeaconState)
bid := &ethpb.ExecutionPayloadBid{
ParentBlockHash: latestHash[:],
ParentBlockRoot: bytes.Repeat([]byte{0x03}, 32),
BlockHash: bytes.Repeat([]byte{0x04}, 32),
PrevRandao: randao[:],
GasLimit: 1,
BuilderIndex: builderIdx,
Slot: slot,
Value: 10,
ExecutionPayment: 0,
BlobKzgCommitmentsRoot: bytes.Repeat([]byte{0x05}, 32),
FeeRecipient: bytes.Repeat([]byte{0x06}, 20),
}
genesis := bytesutil.ToBytes32(state.GenesisValidatorsRoot())
sig := signBid(t, sk, bid, state.Fork(), genesis)
signed := &ethpb.SignedExecutionPayloadBid{Message: bid, Signature: sig[:]}
block := stubBlock{
slot: slot,
proposer: proposerIdx,
parentRoot: bytesutil.ToBytes32(bid.ParentBlockRoot),
body: stubBlockBody{signedBid: signed},
v: version.Gloas,
}
err = ProcessExecutionPayloadBid(state, block)
require.ErrorContains(t, "is not active", err)
}
func TestProcessExecutionPayloadBid_CannotCoverBid(t *testing.T) {
slot := primitives.Slot(5)
builderIdx := primitives.BuilderIndex(1)
proposerIdx := primitives.ValidatorIndex(2)
randao := [32]byte(bytes.Repeat([]byte{0x0A}, 32))
latestHash := [32]byte(bytes.Repeat([]byte{0x0B}, 32))
sk, err := bls.RandKey()
require.NoError(t, err)
var pubKey [48]byte
copy(pubKey[:], sk.PublicKey().Marshal())
state := buildGloasState(t, slot, proposerIdx, builderIdx, params.BeaconConfig().MinDepositAmount+10, randao, latestHash, pubKey)
stateProto := state.ToProto().(*ethpb.BeaconStateGloas)
// Add pending balances to push below required balance.
stateProto.BuilderPendingWithdrawals = []*ethpb.BuilderPendingWithdrawal{
{Amount: 15, BuilderIndex: builderIdx},
}
stateProto.BuilderPendingPayments = []*ethpb.BuilderPendingPayment{
{Withdrawal: &ethpb.BuilderPendingWithdrawal{Amount: 20, BuilderIndex: builderIdx}},
}
stateIface, err := state_native.InitializeFromProtoGloas(stateProto)
require.NoError(t, err)
state = stateIface.(*state_native.BeaconState)
bid := &ethpb.ExecutionPayloadBid{
ParentBlockHash: latestHash[:],
ParentBlockRoot: bytes.Repeat([]byte{0xCC}, 32),
BlockHash: bytes.Repeat([]byte{0xDD}, 32),
PrevRandao: randao[:],
GasLimit: 1,
BuilderIndex: builderIdx,
Slot: slot,
Value: 25,
ExecutionPayment: 0,
BlobKzgCommitmentsRoot: bytes.Repeat([]byte{0xEE}, 32),
FeeRecipient: bytes.Repeat([]byte{0xFF}, 20),
}
genesis := bytesutil.ToBytes32(state.GenesisValidatorsRoot())
sig := signBid(t, sk, bid, state.Fork(), genesis)
signed := &ethpb.SignedExecutionPayloadBid{Message: bid, Signature: sig[:]}
block := stubBlock{
slot: slot,
proposer: proposerIdx,
parentRoot: bytesutil.ToBytes32(bid.ParentBlockRoot),
body: stubBlockBody{signedBid: signed},
v: version.Gloas,
}
err = ProcessExecutionPayloadBid(state, block)
require.ErrorContains(t, "cannot cover bid amount", err)
}
func TestProcessExecutionPayloadBid_InvalidSignature(t *testing.T) {
slot := primitives.Slot(6)
builderIdx := primitives.BuilderIndex(1)
proposerIdx := primitives.ValidatorIndex(2)
randao := [32]byte(bytes.Repeat([]byte{0xAA}, 32))
latestHash := [32]byte(bytes.Repeat([]byte{0xBB}, 32))
sk, err := bls.RandKey()
require.NoError(t, err)
var pubKey [48]byte
copy(pubKey[:], sk.PublicKey().Marshal())
state := buildGloasState(t, slot, proposerIdx, builderIdx, params.BeaconConfig().MinDepositAmount+1000, randao, latestHash, pubKey)
bid := &ethpb.ExecutionPayloadBid{
ParentBlockHash: latestHash[:],
ParentBlockRoot: bytes.Repeat([]byte{0xCC}, 32),
BlockHash: bytes.Repeat([]byte{0xDD}, 32),
PrevRandao: randao[:],
GasLimit: 1,
BuilderIndex: builderIdx,
Slot: slot,
Value: 10,
ExecutionPayment: 0,
BlobKzgCommitmentsRoot: bytes.Repeat([]byte{0xEE}, 32),
FeeRecipient: bytes.Repeat([]byte{0xFF}, 20),
}
// Use an invalid signature.
invalidSig := [96]byte{1}
signed := &ethpb.SignedExecutionPayloadBid{Message: bid, Signature: invalidSig[:]}
block := stubBlock{
slot: slot,
proposer: proposerIdx,
parentRoot: bytesutil.ToBytes32(bid.ParentBlockRoot),
body: stubBlockBody{signedBid: signed},
v: version.Gloas,
}
err = ProcessExecutionPayloadBid(state, block)
require.ErrorContains(t, "bid signature validation failed", err)
}
func TestProcessExecutionPayloadBid_SlotMismatch(t *testing.T) {
slot := primitives.Slot(10)
builderIdx := primitives.BuilderIndex(1)
proposerIdx := primitives.ValidatorIndex(2)
randao := [32]byte(bytes.Repeat([]byte{0xAA}, 32))
latestHash := [32]byte(bytes.Repeat([]byte{0xBB}, 32))
sk, err := bls.RandKey()
require.NoError(t, err)
var pubKey [48]byte
copy(pubKey[:], sk.PublicKey().Marshal())
state := buildGloasState(t, slot, proposerIdx, builderIdx, params.BeaconConfig().MinDepositAmount+1000, randao, latestHash, pubKey)
bid := &ethpb.ExecutionPayloadBid{
ParentBlockHash: latestHash[:],
ParentBlockRoot: bytes.Repeat([]byte{0xAA}, 32),
BlockHash: bytes.Repeat([]byte{0xBB}, 32),
PrevRandao: randao[:],
GasLimit: 1,
BuilderIndex: builderIdx,
Slot: slot + 1, // mismatch
Value: 1,
ExecutionPayment: 0,
BlobKzgCommitmentsRoot: bytes.Repeat([]byte{0xCC}, 32),
FeeRecipient: bytes.Repeat([]byte{0xDD}, 20),
}
genesis := bytesutil.ToBytes32(state.GenesisValidatorsRoot())
sig := signBid(t, sk, bid, state.Fork(), genesis)
signed := &ethpb.SignedExecutionPayloadBid{Message: bid, Signature: sig[:]}
block := stubBlock{
slot: slot,
proposer: proposerIdx,
parentRoot: bytesutil.ToBytes32(bid.ParentBlockRoot),
body: stubBlockBody{signedBid: signed},
v: version.Gloas,
}
err = ProcessExecutionPayloadBid(state, block)
require.ErrorContains(t, "bid slot", err)
}
func TestProcessExecutionPayloadBid_ParentHashMismatch(t *testing.T) {
slot := primitives.Slot(11)
builderIdx := primitives.BuilderIndex(1)
proposerIdx := primitives.ValidatorIndex(2)
randao := [32]byte(bytes.Repeat([]byte{0xAA}, 32))
latestHash := [32]byte(bytes.Repeat([]byte{0xBB}, 32))
sk, err := bls.RandKey()
require.NoError(t, err)
var pubKey [48]byte
copy(pubKey[:], sk.PublicKey().Marshal())
state := buildGloasState(t, slot, proposerIdx, builderIdx, params.BeaconConfig().MinDepositAmount+1000, randao, latestHash, pubKey)
bid := &ethpb.ExecutionPayloadBid{
ParentBlockHash: bytes.Repeat([]byte{0x11}, 32), // mismatch
ParentBlockRoot: bytes.Repeat([]byte{0x22}, 32),
BlockHash: bytes.Repeat([]byte{0x33}, 32),
PrevRandao: randao[:],
GasLimit: 1,
BuilderIndex: builderIdx,
Slot: slot,
Value: 1,
ExecutionPayment: 0,
BlobKzgCommitmentsRoot: bytes.Repeat([]byte{0x44}, 32),
FeeRecipient: bytes.Repeat([]byte{0x55}, 20),
}
genesis := bytesutil.ToBytes32(state.GenesisValidatorsRoot())
sig := signBid(t, sk, bid, state.Fork(), genesis)
signed := &ethpb.SignedExecutionPayloadBid{Message: bid, Signature: sig[:]}
block := stubBlock{
slot: slot,
proposer: proposerIdx,
parentRoot: bytesutil.ToBytes32(bid.ParentBlockRoot),
body: stubBlockBody{signedBid: signed},
v: version.Gloas,
}
err = ProcessExecutionPayloadBid(state, block)
require.ErrorContains(t, "parent block hash mismatch", err)
}
func TestProcessExecutionPayloadBid_ParentRootMismatch(t *testing.T) {
slot := primitives.Slot(12)
builderIdx := primitives.BuilderIndex(1)
proposerIdx := primitives.ValidatorIndex(2)
randao := [32]byte(bytes.Repeat([]byte{0xAA}, 32))
latestHash := [32]byte(bytes.Repeat([]byte{0xBB}, 32))
sk, err := bls.RandKey()
require.NoError(t, err)
var pubKey [48]byte
copy(pubKey[:], sk.PublicKey().Marshal())
state := buildGloasState(t, slot, proposerIdx, builderIdx, params.BeaconConfig().MinDepositAmount+1000, randao, latestHash, pubKey)
parentRoot := bytes.Repeat([]byte{0x22}, 32)
bid := &ethpb.ExecutionPayloadBid{
ParentBlockHash: latestHash[:],
ParentBlockRoot: parentRoot,
BlockHash: bytes.Repeat([]byte{0x33}, 32),
PrevRandao: randao[:],
GasLimit: 1,
BuilderIndex: builderIdx,
Slot: slot,
Value: 1,
ExecutionPayment: 0,
BlobKzgCommitmentsRoot: bytes.Repeat([]byte{0x44}, 32),
FeeRecipient: bytes.Repeat([]byte{0x55}, 20),
}
genesis := bytesutil.ToBytes32(state.GenesisValidatorsRoot())
sig := signBid(t, sk, bid, state.Fork(), genesis)
signed := &ethpb.SignedExecutionPayloadBid{Message: bid, Signature: sig[:]}
block := stubBlock{
slot: slot,
proposer: proposerIdx,
parentRoot: bytesutil.ToBytes32(bytes.Repeat([]byte{0x99}, 32)), // mismatch
body: stubBlockBody{signedBid: signed},
v: version.Gloas,
}
err = ProcessExecutionPayloadBid(state, block)
require.ErrorContains(t, "parent block root mismatch", err)
}
func TestProcessExecutionPayloadBid_PrevRandaoMismatch(t *testing.T) {
slot := primitives.Slot(13)
builderIdx := primitives.BuilderIndex(1)
proposerIdx := primitives.ValidatorIndex(2)
randao := [32]byte(bytes.Repeat([]byte{0xAA}, 32))
latestHash := [32]byte(bytes.Repeat([]byte{0xBB}, 32))
sk, err := bls.RandKey()
require.NoError(t, err)
var pubKey [48]byte
copy(pubKey[:], sk.PublicKey().Marshal())
state := buildGloasState(t, slot, proposerIdx, builderIdx, params.BeaconConfig().MinDepositAmount+1000, randao, latestHash, pubKey)
bid := &ethpb.ExecutionPayloadBid{
ParentBlockHash: latestHash[:],
ParentBlockRoot: bytes.Repeat([]byte{0x22}, 32),
BlockHash: bytes.Repeat([]byte{0x33}, 32),
PrevRandao: bytes.Repeat([]byte{0x01}, 32), // mismatch
GasLimit: 1,
BuilderIndex: builderIdx,
Slot: slot,
Value: 1,
ExecutionPayment: 0,
BlobKzgCommitmentsRoot: bytes.Repeat([]byte{0x44}, 32),
FeeRecipient: bytes.Repeat([]byte{0x55}, 20),
}
genesis := bytesutil.ToBytes32(state.GenesisValidatorsRoot())
sig := signBid(t, sk, bid, state.Fork(), genesis)
signed := &ethpb.SignedExecutionPayloadBid{Message: bid, Signature: sig[:]}
block := stubBlock{
slot: slot,
proposer: proposerIdx,
parentRoot: bytesutil.ToBytes32(bid.ParentBlockRoot),
body: stubBlockBody{signedBid: signed},
v: version.Gloas,
}
err = ProcessExecutionPayloadBid(state, block)
require.ErrorContains(t, "prev randao mismatch", err)
}

View File

@@ -168,6 +168,8 @@ func TestGetSpec(t *testing.T) {
config.BlobsidecarSubnetCount = 101 config.BlobsidecarSubnetCount = 101
config.BlobsidecarSubnetCountElectra = 102 config.BlobsidecarSubnetCountElectra = 102
config.SyncMessageDueBPS = 103 config.SyncMessageDueBPS = 103
config.BuilderWithdrawalPrefixByte = byte('b')
config.BuilderIndexSelfBuild = primitives.BuilderIndex(125)
var dbp [4]byte var dbp [4]byte
copy(dbp[:], []byte{'0', '0', '0', '1'}) copy(dbp[:], []byte{'0', '0', '0', '1'})
@@ -190,6 +192,9 @@ func TestGetSpec(t *testing.T) {
var daap [4]byte var daap [4]byte
copy(daap[:], []byte{'0', '0', '0', '7'}) copy(daap[:], []byte{'0', '0', '0', '7'})
config.DomainAggregateAndProof = daap config.DomainAggregateAndProof = daap
var dbb [4]byte
copy(dbb[:], []byte{'0', '0', '0', '8'})
config.DomainBeaconBuilder = dbb
var dam [4]byte var dam [4]byte
copy(dam[:], []byte{'1', '0', '0', '0'}) copy(dam[:], []byte{'1', '0', '0', '0'})
config.DomainApplicationMask = dam config.DomainApplicationMask = dam
@@ -205,7 +210,7 @@ func TestGetSpec(t *testing.T) {
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), &resp)) require.NoError(t, json.Unmarshal(writer.Body.Bytes(), &resp))
data, ok := resp.Data.(map[string]any) data, ok := resp.Data.(map[string]any)
require.Equal(t, true, ok) require.Equal(t, true, ok)
assert.Equal(t, 175, len(data)) assert.Equal(t, 178, len(data))
for k, v := range data { for k, v := range data {
t.Run(k, func(t *testing.T) { t.Run(k, func(t *testing.T) {
switch k { switch k {
@@ -419,8 +424,14 @@ func TestGetSpec(t *testing.T) {
assert.Equal(t, "0x0a000000", v) assert.Equal(t, "0x0a000000", v)
case "DOMAIN_APPLICATION_BUILDER": case "DOMAIN_APPLICATION_BUILDER":
assert.Equal(t, "0x00000001", v) assert.Equal(t, "0x00000001", v)
case "DOMAIN_BEACON_BUILDER":
assert.Equal(t, "0x30303038", v)
case "DOMAIN_BLOB_SIDECAR": case "DOMAIN_BLOB_SIDECAR":
assert.Equal(t, "0x00000000", v) assert.Equal(t, "0x00000000", v)
case "BUILDER_WITHDRAWAL_PREFIX":
assert.Equal(t, "0x62", v)
case "BUILDER_INDEX_SELF_BUILD":
assert.Equal(t, "125", v)
case "TRANSITION_TOTAL_DIFFICULTY": case "TRANSITION_TOTAL_DIFFICULTY":
assert.Equal(t, "0", v) assert.Equal(t, "0", v)
case "TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH": case "TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH":

View File

@@ -5,6 +5,7 @@ go_library(
srcs = [ srcs = [
"error.go", "error.go",
"interfaces.go", "interfaces.go",
"interfaces_gloas.go",
"prometheus.go", "prometheus.go",
], ],
importpath = "github.com/OffchainLabs/prysm/v7/beacon-chain/state", importpath = "github.com/OffchainLabs/prysm/v7/beacon-chain/state",

View File

@@ -63,6 +63,7 @@ type ReadOnlyBeaconState interface {
ReadOnlyDeposits ReadOnlyDeposits
ReadOnlyConsolidations ReadOnlyConsolidations
ReadOnlyProposerLookahead ReadOnlyProposerLookahead
readOnlyGloasFields
ToProtoUnsafe() any ToProtoUnsafe() any
ToProto() any ToProto() any
GenesisTime() time.Time GenesisTime() time.Time
@@ -98,6 +99,7 @@ type WriteOnlyBeaconState interface {
WriteOnlyWithdrawals WriteOnlyWithdrawals
WriteOnlyDeposits WriteOnlyDeposits
WriteOnlyProposerLookahead WriteOnlyProposerLookahead
writeOnlyGloasFields
SetGenesisTime(val time.Time) error SetGenesisTime(val time.Time) error
SetGenesisValidatorsRoot(val []byte) error SetGenesisValidatorsRoot(val []byte) error
SetSlot(val primitives.Slot) error SetSlot(val primitives.Slot) error

View File

@@ -0,0 +1,19 @@
package state
import (
"github.com/OffchainLabs/prysm/v7/consensus-types/interfaces"
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
)
type writeOnlyGloasFields interface {
SetExecutionPayloadBid(h interfaces.ROExecutionPayloadBid) error
SetBuilderPendingPayment(index primitives.Slot, payment *ethpb.BuilderPendingPayment) error
}
type readOnlyGloasFields interface {
BuilderAtIndex(primitives.BuilderIndex) (*ethpb.Builder, error)
IsActiveBuilder(primitives.BuilderIndex) (bool, error)
CanBuilderCoverBid(primitives.BuilderIndex, primitives.Gwei) (bool, error)
LatestBlockHash() ([32]byte, error)
}

View File

@@ -14,6 +14,7 @@ go_library(
"getters_deposits.go", "getters_deposits.go",
"getters_eth1.go", "getters_eth1.go",
"getters_exit.go", "getters_exit.go",
"getters_gloas.go",
"getters_misc.go", "getters_misc.go",
"getters_participation.go", "getters_participation.go",
"getters_payload_header.go", "getters_payload_header.go",
@@ -36,6 +37,7 @@ go_library(
"setters_deposit_requests.go", "setters_deposit_requests.go",
"setters_deposits.go", "setters_deposits.go",
"setters_eth1.go", "setters_eth1.go",
"setters_gloas.go",
"setters_misc.go", "setters_misc.go",
"setters_participation.go", "setters_participation.go",
"setters_payload_header.go", "setters_payload_header.go",
@@ -97,11 +99,13 @@ go_test(
"getters_deposit_requests_test.go", "getters_deposit_requests_test.go",
"getters_deposits_test.go", "getters_deposits_test.go",
"getters_exit_test.go", "getters_exit_test.go",
"getters_gloas_test.go",
"getters_participation_test.go", "getters_participation_test.go",
"getters_setters_lookahead_test.go", "getters_setters_lookahead_test.go",
"getters_test.go", "getters_test.go",
"getters_validator_test.go", "getters_validator_test.go",
"getters_withdrawal_test.go", "getters_withdrawal_test.go",
"gloas_test.go",
"hasher_test.go", "hasher_test.go",
"mvslice_fuzz_test.go", "mvslice_fuzz_test.go",
"proofs_test.go", "proofs_test.go",
@@ -113,6 +117,7 @@ go_test(
"setters_deposit_requests_test.go", "setters_deposit_requests_test.go",
"setters_deposits_test.go", "setters_deposits_test.go",
"setters_eth1_test.go", "setters_eth1_test.go",
"setters_gloas_test.go",
"setters_misc_test.go", "setters_misc_test.go",
"setters_participation_test.go", "setters_participation_test.go",
"setters_payload_header_test.go", "setters_payload_header_test.go",
@@ -156,6 +161,7 @@ go_test(
"@com_github_google_go_cmp//cmp:go_default_library", "@com_github_google_go_cmp//cmp:go_default_library",
"@com_github_prysmaticlabs_go_bitfield//:go_default_library", "@com_github_prysmaticlabs_go_bitfield//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library",
"@com_github_stretchr_testify//require:go_default_library",
"@org_golang_google_protobuf//proto:go_default_library", "@org_golang_google_protobuf//proto:go_default_library",
"@org_golang_google_protobuf//testing/protocmp:go_default_library", "@org_golang_google_protobuf//testing/protocmp:go_default_library",
], ],

View File

@@ -72,11 +72,13 @@ type BeaconState struct {
// Gloas fields // Gloas fields
latestExecutionPayloadBid *ethpb.ExecutionPayloadBid latestExecutionPayloadBid *ethpb.ExecutionPayloadBid
builders []*ethpb.Builder
nextWithdrawalBuilderIndex primitives.BuilderIndex
executionPayloadAvailability []byte executionPayloadAvailability []byte
builderPendingPayments []*ethpb.BuilderPendingPayment builderPendingPayments []*ethpb.BuilderPendingPayment
builderPendingWithdrawals []*ethpb.BuilderPendingWithdrawal builderPendingWithdrawals []*ethpb.BuilderPendingWithdrawal
latestBlockHash []byte latestBlockHash []byte
latestWithdrawalsRoot []byte payloadExpectedWithdrawals []*enginev1.Withdrawal
id uint64 id uint64
lock sync.RWMutex lock sync.RWMutex
@@ -134,11 +136,13 @@ type beaconStateMarshalable struct {
PendingConsolidations []*ethpb.PendingConsolidation `json:"pending_consolidations" yaml:"pending_consolidations"` PendingConsolidations []*ethpb.PendingConsolidation `json:"pending_consolidations" yaml:"pending_consolidations"`
ProposerLookahead []primitives.ValidatorIndex `json:"proposer_look_ahead" yaml:"proposer_look_ahead"` ProposerLookahead []primitives.ValidatorIndex `json:"proposer_look_ahead" yaml:"proposer_look_ahead"`
LatestExecutionPayloadBid *ethpb.ExecutionPayloadBid `json:"latest_execution_payload_bid" yaml:"latest_execution_payload_bid"` LatestExecutionPayloadBid *ethpb.ExecutionPayloadBid `json:"latest_execution_payload_bid" yaml:"latest_execution_payload_bid"`
Builders []*ethpb.Builder `json:"builders" yaml:"builders"`
NextWithdrawalBuilderIndex primitives.BuilderIndex `json:"next_withdrawal_builder_index" yaml:"next_withdrawal_builder_index"`
ExecutionPayloadAvailability []byte `json:"execution_payload_availability" yaml:"execution_payload_availability"` ExecutionPayloadAvailability []byte `json:"execution_payload_availability" yaml:"execution_payload_availability"`
BuilderPendingPayments []*ethpb.BuilderPendingPayment `json:"builder_pending_payments" yaml:"builder_pending_payments"` BuilderPendingPayments []*ethpb.BuilderPendingPayment `json:"builder_pending_payments" yaml:"builder_pending_payments"`
BuilderPendingWithdrawals []*ethpb.BuilderPendingWithdrawal `json:"builder_pending_withdrawals" yaml:"builder_pending_withdrawals"` BuilderPendingWithdrawals []*ethpb.BuilderPendingWithdrawal `json:"builder_pending_withdrawals" yaml:"builder_pending_withdrawals"`
LatestBlockHash []byte `json:"latest_block_hash" yaml:"latest_block_hash"` LatestBlockHash []byte `json:"latest_block_hash" yaml:"latest_block_hash"`
LatestWithdrawalsRoot []byte `json:"latest_withdrawals_root" yaml:"latest_withdrawals_root"` PayloadExpectedWithdrawals []*enginev1.Withdrawal `json:"payload_expected_withdrawals" yaml:"payload_expected_withdrawals"`
} }
func (b *BeaconState) MarshalJSON() ([]byte, error) { func (b *BeaconState) MarshalJSON() ([]byte, error) {
@@ -194,11 +198,13 @@ func (b *BeaconState) MarshalJSON() ([]byte, error) {
PendingConsolidations: b.pendingConsolidations, PendingConsolidations: b.pendingConsolidations,
ProposerLookahead: b.proposerLookahead, ProposerLookahead: b.proposerLookahead,
LatestExecutionPayloadBid: b.latestExecutionPayloadBid, LatestExecutionPayloadBid: b.latestExecutionPayloadBid,
Builders: b.builders,
NextWithdrawalBuilderIndex: b.nextWithdrawalBuilderIndex,
ExecutionPayloadAvailability: b.executionPayloadAvailability, ExecutionPayloadAvailability: b.executionPayloadAvailability,
BuilderPendingPayments: b.builderPendingPayments, BuilderPendingPayments: b.builderPendingPayments,
BuilderPendingWithdrawals: b.builderPendingWithdrawals, BuilderPendingWithdrawals: b.builderPendingWithdrawals,
LatestBlockHash: b.latestBlockHash, LatestBlockHash: b.latestBlockHash,
LatestWithdrawalsRoot: b.latestWithdrawalsRoot, PayloadExpectedWithdrawals: b.payloadExpectedWithdrawals,
} }
return json.Marshal(marshalable) return json.Marshal(marshalable)
} }

View File

@@ -0,0 +1,128 @@
package state_native
import (
"fmt"
"github.com/OffchainLabs/prysm/v7/config/params"
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v7/runtime/version"
)
// LatestBlockHash returns the hash of the latest execution block.
func (b *BeaconState) LatestBlockHash() ([32]byte, error) {
if b.version < version.Gloas {
return [32]byte{}, errNotSupported("LatestBlockHash", b.version)
}
b.lock.RLock()
defer b.lock.RUnlock()
if b.latestBlockHash == nil {
return [32]byte{}, nil
}
return [32]byte(b.latestBlockHash), nil
}
// BuilderAtIndex returns a copy of the builder at the provided index.
func (b *BeaconState) BuilderAtIndex(builderIndex primitives.BuilderIndex) (*ethpb.Builder, error) {
if b.version < version.Gloas {
return nil, errNotSupported("BuilderAtIndex", b.version)
}
b.lock.RLock()
defer b.lock.RUnlock()
return b.builderAtIndex(builderIndex)
}
// IsActiveBuilder returns true if the builder placement is finalized and it has not initiated exit.
// Spec v1.7.0-alpha.0 (pseudocode):
// def is_active_builder(state: BeaconState, builder_index: BuilderIndex) -> bool:
//
// builder = state.builders[builder_index]
// return (
// builder.deposit_epoch < state.finalized_checkpoint.epoch
// and builder.withdrawable_epoch == FAR_FUTURE_EPOCH
// )
func (b *BeaconState) IsActiveBuilder(builderIndex primitives.BuilderIndex) (bool, error) {
if b.version < version.Gloas {
return false, errNotSupported("IsActiveBuilder", b.version)
}
b.lock.RLock()
defer b.lock.RUnlock()
builder, err := b.builderAtIndex(builderIndex)
if err != nil {
return false, err
}
finalizedEpoch := b.finalizedCheckpoint.Epoch
return builder.DepositEpoch < finalizedEpoch && builder.WithdrawableEpoch == params.BeaconConfig().FarFutureEpoch, nil
}
// CanBuilderCoverBid returns true if the builder has enough balance to cover the given bid amount.
// Spec v1.7.0-alpha.0 (pseudocode):
// def can_builder_cover_bid(state: BeaconState, builder_index: BuilderIndex, bid_amount: Gwei) -> bool:
//
// builder_balance = state.builders[builder_index].balance
// pending_withdrawals_amount = get_pending_balance_to_withdraw_for_builder(state, builder_index)
// min_balance = MIN_DEPOSIT_AMOUNT + pending_withdrawals_amount
// if builder_balance < min_balance:
// return False
// return builder_balance - min_balance >= bid_amount
func (b *BeaconState) CanBuilderCoverBid(builderIndex primitives.BuilderIndex, bidAmount primitives.Gwei) (bool, error) {
if b.version < version.Gloas {
return false, errNotSupported("CanBuilderCoverBid", b.version)
}
b.lock.RLock()
defer b.lock.RUnlock()
builder, err := b.builderAtIndex(builderIndex)
if err != nil {
return false, err
}
pendingBalanceToWithdraw := b.builderPendingBalanceToWithdraw(builderIndex)
minBalance := params.BeaconConfig().MinDepositAmount + pendingBalanceToWithdraw
balance := uint64(builder.Balance)
if balance < minBalance {
return false, nil
}
return balance-minBalance >= uint64(bidAmount), nil
}
func (b *BeaconState) builderAtIndex(builderIndex primitives.BuilderIndex) (*ethpb.Builder, error) {
idx := uint64(builderIndex)
if idx >= uint64(len(b.builders)) {
return nil, fmt.Errorf("builder index %d out of range (len=%d)", builderIndex, len(b.builders))
}
builder := b.builders[idx]
if builder == nil {
return nil, fmt.Errorf("builder at index %d is nil", builderIndex)
}
return ethpb.CopyBuilder(builder), nil
}
// builderPendingBalanceToWithdraw mirrors get_pending_balance_to_withdraw_for_builder in the spec,
// summing both pending withdrawals and pending payments for a builder.
func (b *BeaconState) builderPendingBalanceToWithdraw(builderIndex primitives.BuilderIndex) uint64 {
var total uint64
for _, withdrawal := range b.builderPendingWithdrawals {
if withdrawal.BuilderIndex == builderIndex {
total += uint64(withdrawal.Amount)
}
}
for _, payment := range b.builderPendingPayments {
if payment.Withdrawal.BuilderIndex == builderIndex {
total += uint64(payment.Withdrawal.Amount)
}
}
return total
}

View File

@@ -0,0 +1,149 @@
package state_native_test
import (
"bytes"
"testing"
state_native "github.com/OffchainLabs/prysm/v7/beacon-chain/state/state-native"
"github.com/OffchainLabs/prysm/v7/config/params"
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v7/testing/require"
"github.com/OffchainLabs/prysm/v7/testing/util"
)
func TestLatestBlockHash(t *testing.T) {
t.Run("returns error before gloas", func(t *testing.T) {
st, _ := util.DeterministicGenesisState(t, 1)
_, err := st.LatestBlockHash()
require.ErrorContains(t, "is not supported", err)
})
t.Run("returns zero hash when unset", func(t *testing.T) {
st, err := state_native.InitializeFromProtoGloas(&ethpb.BeaconStateGloas{})
require.NoError(t, err)
got, err := st.LatestBlockHash()
require.NoError(t, err)
require.Equal(t, [32]byte{}, got)
})
t.Run("returns configured hash", func(t *testing.T) {
hashBytes := bytes.Repeat([]byte{0xAB}, 32)
var want [32]byte
copy(want[:], hashBytes)
st, err := state_native.InitializeFromProtoGloas(&ethpb.BeaconStateGloas{
LatestBlockHash: hashBytes,
})
require.NoError(t, err)
got, err := st.LatestBlockHash()
require.NoError(t, err)
require.Equal(t, want, got)
})
}
func TestBuilderAtIndex(t *testing.T) {
t.Run("returns error before gloas", func(t *testing.T) {
stIface, _ := util.DeterministicGenesisState(t, 1)
native, ok := stIface.(*state_native.BeaconState)
require.Equal(t, true, ok)
_, err := native.BuilderAtIndex(0)
require.ErrorContains(t, "is not supported", err)
})
t.Run("returns copy", func(t *testing.T) {
orig := &ethpb.Builder{Balance: 42}
stIface, err := state_native.InitializeFromProtoGloas(&ethpb.BeaconStateGloas{
Builders: []*ethpb.Builder{orig},
})
require.NoError(t, err)
st := stIface.(*state_native.BeaconState)
got, err := st.BuilderAtIndex(0)
require.NoError(t, err)
require.Equal(t, primitives.Gwei(42), got.Balance)
got.Balance = 99
require.Equal(t, primitives.Gwei(42), orig.Balance)
})
t.Run("out of range returns error", func(t *testing.T) {
stIface, err := state_native.InitializeFromProtoGloas(&ethpb.BeaconStateGloas{
Builders: []*ethpb.Builder{},
})
require.NoError(t, err)
st := stIface.(*state_native.BeaconState)
_, err = st.BuilderAtIndex(1)
require.ErrorContains(t, "out of range", err)
})
}
func TestBuilderHelpers(t *testing.T) {
t.Run("is active builder", func(t *testing.T) {
st, err := state_native.InitializeFromProtoGloas(&ethpb.BeaconStateGloas{
Builders: []*ethpb.Builder{
{
Balance: 10,
DepositEpoch: 0,
WithdrawableEpoch: params.BeaconConfig().FarFutureEpoch,
},
},
FinalizedCheckpoint: &ethpb.Checkpoint{Epoch: 1},
})
require.NoError(t, err)
active, err := st.IsActiveBuilder(0)
require.NoError(t, err)
require.Equal(t, true, active)
// Not active when withdrawable epoch is set.
stProto := &ethpb.BeaconStateGloas{
Builders: []*ethpb.Builder{
{
Balance: 10,
DepositEpoch: 0,
WithdrawableEpoch: 1,
},
},
FinalizedCheckpoint: &ethpb.Checkpoint{Epoch: 2},
}
stInactive, err := state_native.InitializeFromProtoGloas(stProto)
require.NoError(t, err)
active, err = stInactive.IsActiveBuilder(0)
require.NoError(t, err)
require.Equal(t, false, active)
})
t.Run("can builder cover bid", func(t *testing.T) {
stIface, err := state_native.InitializeFromProtoGloas(&ethpb.BeaconStateGloas{
Builders: []*ethpb.Builder{
{
Balance: primitives.Gwei(params.BeaconConfig().MinDepositAmount + 50),
DepositEpoch: 0,
WithdrawableEpoch: params.BeaconConfig().FarFutureEpoch,
},
},
BuilderPendingWithdrawals: []*ethpb.BuilderPendingWithdrawal{
{Amount: 10, BuilderIndex: 0},
},
BuilderPendingPayments: []*ethpb.BuilderPendingPayment{
{Withdrawal: &ethpb.BuilderPendingWithdrawal{Amount: 15, BuilderIndex: 0}},
},
FinalizedCheckpoint: &ethpb.Checkpoint{Epoch: 1},
})
require.NoError(t, err)
st := stIface.(*state_native.BeaconState)
ok, err := st.CanBuilderCoverBid(0, 20)
require.NoError(t, err)
require.Equal(t, true, ok)
ok, err = st.CanBuilderCoverBid(0, 30)
require.NoError(t, err)
require.Equal(t, false, ok)
})
}

View File

@@ -305,10 +305,12 @@ func (b *BeaconState) ToProtoUnsafe() any {
PendingConsolidations: b.pendingConsolidations, PendingConsolidations: b.pendingConsolidations,
ProposerLookahead: lookahead, ProposerLookahead: lookahead,
ExecutionPayloadAvailability: b.executionPayloadAvailability, ExecutionPayloadAvailability: b.executionPayloadAvailability,
Builders: b.builders,
NextWithdrawalBuilderIndex: b.nextWithdrawalBuilderIndex,
BuilderPendingPayments: b.builderPendingPayments, BuilderPendingPayments: b.builderPendingPayments,
BuilderPendingWithdrawals: b.builderPendingWithdrawals, BuilderPendingWithdrawals: b.builderPendingWithdrawals,
LatestBlockHash: b.latestBlockHash, LatestBlockHash: b.latestBlockHash,
LatestWithdrawalsRoot: b.latestWithdrawalsRoot, PayloadExpectedWithdrawals: b.payloadExpectedWithdrawals,
} }
default: default:
return nil return nil
@@ -607,10 +609,12 @@ func (b *BeaconState) ToProto() any {
PendingConsolidations: b.pendingConsolidationsVal(), PendingConsolidations: b.pendingConsolidationsVal(),
ProposerLookahead: lookahead, ProposerLookahead: lookahead,
ExecutionPayloadAvailability: b.executionPayloadAvailabilityVal(), ExecutionPayloadAvailability: b.executionPayloadAvailabilityVal(),
Builders: b.buildersVal(),
NextWithdrawalBuilderIndex: b.nextWithdrawalBuilderIndex,
BuilderPendingPayments: b.builderPendingPaymentsVal(), BuilderPendingPayments: b.builderPendingPaymentsVal(),
BuilderPendingWithdrawals: b.builderPendingWithdrawalsVal(), BuilderPendingWithdrawals: b.builderPendingWithdrawalsVal(),
LatestBlockHash: b.latestBlockHashVal(), LatestBlockHash: b.latestBlockHashVal(),
LatestWithdrawalsRoot: b.latestWithdrawalsRootVal(), PayloadExpectedWithdrawals: b.payloadExpectedWithdrawalsVal(),
} }
default: default:
return nil return nil

View File

@@ -1,6 +1,7 @@
package state_native package state_native
import ( import (
enginev1 "github.com/OffchainLabs/prysm/v7/proto/engine/v1"
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1" ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
) )
@@ -47,6 +48,22 @@ func (b *BeaconState) builderPendingWithdrawalsVal() []*ethpb.BuilderPendingWith
return withdrawals return withdrawals
} }
// buildersVal returns a copy of the builders registry.
// This assumes that a lock is already held on BeaconState.
func (b *BeaconState) buildersVal() []*ethpb.Builder {
if b.builders == nil {
return nil
}
builders := make([]*ethpb.Builder, len(b.builders))
for i := range builders {
builder := b.builders[i]
builders[i] = ethpb.CopyBuilder(builder)
}
return builders
}
// latestBlockHashVal returns a copy of the latest block hash. // latestBlockHashVal returns a copy of the latest block hash.
// This assumes that a lock is already held on BeaconState. // This assumes that a lock is already held on BeaconState.
func (b *BeaconState) latestBlockHashVal() []byte { func (b *BeaconState) latestBlockHashVal() []byte {
@@ -60,15 +77,17 @@ func (b *BeaconState) latestBlockHashVal() []byte {
return hash return hash
} }
// latestWithdrawalsRootVal returns a copy of the latest withdrawals root. // payloadExpectedWithdrawalsVal returns a copy of the payload expected withdrawals.
// This assumes that a lock is already held on BeaconState. // This assumes that a lock is already held on BeaconState.
func (b *BeaconState) latestWithdrawalsRootVal() []byte { func (b *BeaconState) payloadExpectedWithdrawalsVal() []*enginev1.Withdrawal {
if b.latestWithdrawalsRoot == nil { if b.payloadExpectedWithdrawals == nil {
return nil return nil
} }
root := make([]byte, len(b.latestWithdrawalsRoot)) withdrawals := make([]*enginev1.Withdrawal, len(b.payloadExpectedWithdrawals))
copy(root, b.latestWithdrawalsRoot) for i, withdrawal := range b.payloadExpectedWithdrawals {
withdrawals[i] = withdrawal.Copy()
}
return root return withdrawals
} }

View File

@@ -0,0 +1,43 @@
package state_native
import (
"testing"
enginev1 "github.com/OffchainLabs/prysm/v7/proto/engine/v1"
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
"github.com/stretchr/testify/require"
)
func TestBuildersVal(t *testing.T) {
st := &BeaconState{}
require.Nil(t, st.buildersVal())
st.builders = []*ethpb.Builder{
{Pubkey: []byte{0x01}, ExecutionAddress: []byte{0x02}, Balance: 3},
nil,
}
got := st.buildersVal()
require.Len(t, got, 2)
require.Nil(t, got[1])
require.Equal(t, st.builders[0], got[0])
require.NotSame(t, st.builders[0], got[0])
}
func TestPayloadExpectedWithdrawalsVal(t *testing.T) {
st := &BeaconState{}
require.Nil(t, st.payloadExpectedWithdrawalsVal())
st.payloadExpectedWithdrawals = []*enginev1.Withdrawal{
{Index: 1, ValidatorIndex: 2, Address: []byte{0x03}, Amount: 4},
nil,
}
got := st.payloadExpectedWithdrawalsVal()
require.Len(t, got, 2)
require.Nil(t, got[1])
require.Equal(t, st.payloadExpectedWithdrawals[0], got[0])
require.NotSame(t, st.payloadExpectedWithdrawals[0], got[0])
}

View File

@@ -342,6 +342,15 @@ func ComputeFieldRootsWithHasher(ctx context.Context, state *BeaconState) ([][]b
} }
if state.version >= version.Gloas { if state.version >= version.Gloas {
buildersRoot, err := stateutil.BuildersRoot(state.builders)
if err != nil {
return nil, errors.Wrap(err, "could not compute builders merkleization")
}
fieldRoots[types.Builders.RealPosition()] = buildersRoot[:]
nextWithdrawalBuilderIndexRoot := ssz.Uint64Root(uint64(state.nextWithdrawalBuilderIndex))
fieldRoots[types.NextWithdrawalBuilderIndex.RealPosition()] = nextWithdrawalBuilderIndexRoot[:]
epaRoot, err := stateutil.ExecutionPayloadAvailabilityRoot(state.executionPayloadAvailability) epaRoot, err := stateutil.ExecutionPayloadAvailabilityRoot(state.executionPayloadAvailability)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "could not compute execution payload availability merkleization") return nil, errors.Wrap(err, "could not compute execution payload availability merkleization")
@@ -366,8 +375,12 @@ func ComputeFieldRootsWithHasher(ctx context.Context, state *BeaconState) ([][]b
lbhRoot := bytesutil.ToBytes32(state.latestBlockHash) lbhRoot := bytesutil.ToBytes32(state.latestBlockHash)
fieldRoots[types.LatestBlockHash.RealPosition()] = lbhRoot[:] fieldRoots[types.LatestBlockHash.RealPosition()] = lbhRoot[:]
lwrRoot := bytesutil.ToBytes32(state.latestWithdrawalsRoot) expectedWithdrawalsRoot, err := ssz.WithdrawalSliceRoot(state.payloadExpectedWithdrawals, fieldparams.MaxWithdrawalsPerPayload)
fieldRoots[types.LatestWithdrawalsRoot.RealPosition()] = lwrRoot[:] if err != nil {
return nil, errors.Wrap(err, "could not compute payload expected withdrawals root")
}
fieldRoots[types.PayloadExpectedWithdrawals.RealPosition()] = expectedWithdrawalsRoot[:]
} }
return fieldRoots, nil return fieldRoots, nil
} }

View File

@@ -0,0 +1,63 @@
package state_native
import (
"fmt"
"github.com/OffchainLabs/prysm/v7/beacon-chain/state/state-native/types"
"github.com/OffchainLabs/prysm/v7/consensus-types/interfaces"
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v7/runtime/version"
)
// SetExecutionPayloadBid sets the latest execution payload bid in the state.
func (b *BeaconState) SetExecutionPayloadBid(h interfaces.ROExecutionPayloadBid) error {
if b.version < version.Gloas {
return errNotSupported("SetExecutionPayloadBid", b.version)
}
b.lock.Lock()
defer b.lock.Unlock()
parentBlockHash := h.ParentBlockHash()
parentBlockRoot := h.ParentBlockRoot()
blockHash := h.BlockHash()
randao := h.PrevRandao()
blobKzgCommitmentsRoot := h.BlobKzgCommitmentsRoot()
feeRecipient := h.FeeRecipient()
b.latestExecutionPayloadBid = &ethpb.ExecutionPayloadBid{
ParentBlockHash: parentBlockHash[:],
ParentBlockRoot: parentBlockRoot[:],
BlockHash: blockHash[:],
PrevRandao: randao[:],
GasLimit: h.GasLimit(),
BuilderIndex: h.BuilderIndex(),
Slot: h.Slot(),
Value: h.Value(),
ExecutionPayment: h.ExecutionPayment(),
BlobKzgCommitmentsRoot: blobKzgCommitmentsRoot[:],
FeeRecipient: feeRecipient[:],
}
b.markFieldAsDirty(types.LatestExecutionPayloadBid)
return nil
}
// SetBuilderPendingPayment sets a builder pending payment at the specified index.
func (b *BeaconState) SetBuilderPendingPayment(index primitives.Slot, payment *ethpb.BuilderPendingPayment) error {
if b.version < version.Gloas {
return errNotSupported("SetBuilderPendingPayment", b.version)
}
b.lock.Lock()
defer b.lock.Unlock()
if uint64(index) >= uint64(len(b.builderPendingPayments)) {
return fmt.Errorf("builder pending payments index %d out of range (len=%d)", index, len(b.builderPendingPayments))
}
b.builderPendingPayments[index] = ethpb.CopyBuilderPendingPayment(payment)
b.markFieldAsDirty(types.BuilderPendingPayments)
return nil
}

View File

@@ -0,0 +1,140 @@
package state_native
import (
"bytes"
"testing"
"github.com/OffchainLabs/prysm/v7/beacon-chain/state/state-native/types"
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v7/runtime/version"
"github.com/OffchainLabs/prysm/v7/testing/require"
)
type testExecutionPayloadBid struct {
parentBlockHash [32]byte
parentBlockRoot [32]byte
blockHash [32]byte
prevRandao [32]byte
blobKzgCommitmentsRoot [32]byte
feeRecipient [20]byte
gasLimit uint64
builderIndex primitives.BuilderIndex
slot primitives.Slot
value primitives.Gwei
executionPayment primitives.Gwei
}
func (t testExecutionPayloadBid) ParentBlockHash() [32]byte { return t.parentBlockHash }
func (t testExecutionPayloadBid) ParentBlockRoot() [32]byte { return t.parentBlockRoot }
func (t testExecutionPayloadBid) PrevRandao() [32]byte { return t.prevRandao }
func (t testExecutionPayloadBid) BlockHash() [32]byte { return t.blockHash }
func (t testExecutionPayloadBid) GasLimit() uint64 { return t.gasLimit }
func (t testExecutionPayloadBid) BuilderIndex() primitives.BuilderIndex {
return t.builderIndex
}
func (t testExecutionPayloadBid) Slot() primitives.Slot { return t.slot }
func (t testExecutionPayloadBid) Value() primitives.Gwei { return t.value }
func (t testExecutionPayloadBid) ExecutionPayment() primitives.Gwei {
return t.executionPayment
}
func (t testExecutionPayloadBid) BlobKzgCommitmentsRoot() [32]byte { return t.blobKzgCommitmentsRoot }
func (t testExecutionPayloadBid) FeeRecipient() [20]byte { return t.feeRecipient }
func (t testExecutionPayloadBid) IsNil() bool { return false }
func TestSetExecutionPayloadBid(t *testing.T) {
t.Run("previous fork returns expected error", func(t *testing.T) {
st := &BeaconState{version: version.Fulu}
err := st.SetExecutionPayloadBid(testExecutionPayloadBid{})
require.ErrorContains(t, "is not supported", err)
})
t.Run("sets bid and marks dirty", func(t *testing.T) {
var (
parentBlockHash = [32]byte(bytes.Repeat([]byte{0xAB}, 32))
parentBlockRoot = [32]byte(bytes.Repeat([]byte{0xCD}, 32))
blockHash = [32]byte(bytes.Repeat([]byte{0xEF}, 32))
prevRandao = [32]byte(bytes.Repeat([]byte{0x11}, 32))
blobRoot = [32]byte(bytes.Repeat([]byte{0x22}, 32))
feeRecipient [20]byte
)
copy(feeRecipient[:], bytes.Repeat([]byte{0x33}, len(feeRecipient)))
st := &BeaconState{
version: version.Gloas,
dirtyFields: make(map[types.FieldIndex]bool),
}
bid := testExecutionPayloadBid{
parentBlockHash: parentBlockHash,
parentBlockRoot: parentBlockRoot,
blockHash: blockHash,
prevRandao: prevRandao,
blobKzgCommitmentsRoot: blobRoot,
feeRecipient: feeRecipient,
gasLimit: 123,
builderIndex: 7,
slot: 9,
value: 11,
executionPayment: 22,
}
require.NoError(t, st.SetExecutionPayloadBid(bid))
require.NotNil(t, st.latestExecutionPayloadBid)
require.DeepEqual(t, parentBlockHash[:], st.latestExecutionPayloadBid.ParentBlockHash)
require.DeepEqual(t, parentBlockRoot[:], st.latestExecutionPayloadBid.ParentBlockRoot)
require.DeepEqual(t, blockHash[:], st.latestExecutionPayloadBid.BlockHash)
require.DeepEqual(t, prevRandao[:], st.latestExecutionPayloadBid.PrevRandao)
require.DeepEqual(t, blobRoot[:], st.latestExecutionPayloadBid.BlobKzgCommitmentsRoot)
require.DeepEqual(t, feeRecipient[:], st.latestExecutionPayloadBid.FeeRecipient)
require.Equal(t, uint64(123), st.latestExecutionPayloadBid.GasLimit)
require.Equal(t, primitives.BuilderIndex(7), st.latestExecutionPayloadBid.BuilderIndex)
require.Equal(t, primitives.Slot(9), st.latestExecutionPayloadBid.Slot)
require.Equal(t, primitives.Gwei(11), st.latestExecutionPayloadBid.Value)
require.Equal(t, primitives.Gwei(22), st.latestExecutionPayloadBid.ExecutionPayment)
require.Equal(t, true, st.dirtyFields[types.LatestExecutionPayloadBid])
})
}
func TestSetBuilderPendingPayment(t *testing.T) {
t.Run("previous fork returns expected error", func(t *testing.T) {
st := &BeaconState{version: version.Fulu}
err := st.SetBuilderPendingPayment(0, &ethpb.BuilderPendingPayment{})
require.ErrorContains(t, "is not supported", err)
})
t.Run("sets copy and marks dirty", func(t *testing.T) {
st := &BeaconState{
version: version.Gloas,
dirtyFields: make(map[types.FieldIndex]bool),
builderPendingPayments: make([]*ethpb.BuilderPendingPayment, 2),
}
payment := &ethpb.BuilderPendingPayment{
Weight: 2,
Withdrawal: &ethpb.BuilderPendingWithdrawal{
Amount: 99,
BuilderIndex: 1,
},
}
require.NoError(t, st.SetBuilderPendingPayment(1, payment))
require.DeepEqual(t, payment, st.builderPendingPayments[1])
require.Equal(t, true, st.dirtyFields[types.BuilderPendingPayments])
// Mutating the original should not affect the state copy.
payment.Withdrawal.Amount = 12345
require.Equal(t, primitives.Gwei(99), st.builderPendingPayments[1].Withdrawal.Amount)
})
t.Run("returns error on out of range index", func(t *testing.T) {
st := &BeaconState{
version: version.Gloas,
dirtyFields: make(map[types.FieldIndex]bool),
builderPendingPayments: make([]*ethpb.BuilderPendingPayment, 1),
}
err := st.SetBuilderPendingPayment(2, &ethpb.BuilderPendingPayment{})
require.ErrorContains(t, "out of range", err)
require.Equal(t, false, st.dirtyFields[types.BuilderPendingPayments])
})
}

View File

@@ -120,11 +120,13 @@ var (
) )
gloasAdditionalFields = []types.FieldIndex{ gloasAdditionalFields = []types.FieldIndex{
types.Builders,
types.NextWithdrawalBuilderIndex,
types.ExecutionPayloadAvailability, types.ExecutionPayloadAvailability,
types.BuilderPendingPayments, types.BuilderPendingPayments,
types.BuilderPendingWithdrawals, types.BuilderPendingWithdrawals,
types.LatestBlockHash, types.LatestBlockHash,
types.LatestWithdrawalsRoot, types.PayloadExpectedWithdrawals,
} }
gloasFields = slices.Concat( gloasFields = slices.Concat(
@@ -145,7 +147,7 @@ const (
denebSharedFieldRefCount = 7 denebSharedFieldRefCount = 7
electraSharedFieldRefCount = 10 electraSharedFieldRefCount = 10
fuluSharedFieldRefCount = 11 fuluSharedFieldRefCount = 11
gloasSharedFieldRefCount = 12 // Adds PendingBuilderWithdrawal to the shared-ref set and LatestExecutionPayloadHeader is removed gloasSharedFieldRefCount = 13 // Adds Builders + BuilderPendingWithdrawals to the shared-ref set and LatestExecutionPayloadHeader is removed
) )
// InitializeFromProtoPhase0 the beacon state from a protobuf representation. // InitializeFromProtoPhase0 the beacon state from a protobuf representation.
@@ -817,11 +819,13 @@ func InitializeFromProtoUnsafeGloas(st *ethpb.BeaconStateGloas) (state.BeaconSta
pendingConsolidations: st.PendingConsolidations, pendingConsolidations: st.PendingConsolidations,
proposerLookahead: proposerLookahead, proposerLookahead: proposerLookahead,
latestExecutionPayloadBid: st.LatestExecutionPayloadBid, latestExecutionPayloadBid: st.LatestExecutionPayloadBid,
builders: st.Builders,
nextWithdrawalBuilderIndex: st.NextWithdrawalBuilderIndex,
executionPayloadAvailability: st.ExecutionPayloadAvailability, executionPayloadAvailability: st.ExecutionPayloadAvailability,
builderPendingPayments: st.BuilderPendingPayments, builderPendingPayments: st.BuilderPendingPayments,
builderPendingWithdrawals: st.BuilderPendingWithdrawals, builderPendingWithdrawals: st.BuilderPendingWithdrawals,
latestBlockHash: st.LatestBlockHash, latestBlockHash: st.LatestBlockHash,
latestWithdrawalsRoot: st.LatestWithdrawalsRoot, payloadExpectedWithdrawals: st.PayloadExpectedWithdrawals,
dirtyFields: make(map[types.FieldIndex]bool, fieldCount), dirtyFields: make(map[types.FieldIndex]bool, fieldCount),
dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount), dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount),
stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount), stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount),
@@ -861,6 +865,7 @@ func InitializeFromProtoUnsafeGloas(st *ethpb.BeaconStateGloas) (state.BeaconSta
b.sharedFieldReferences[types.PendingPartialWithdrawals] = stateutil.NewRef(1) b.sharedFieldReferences[types.PendingPartialWithdrawals] = stateutil.NewRef(1)
b.sharedFieldReferences[types.PendingConsolidations] = stateutil.NewRef(1) b.sharedFieldReferences[types.PendingConsolidations] = stateutil.NewRef(1)
b.sharedFieldReferences[types.ProposerLookahead] = stateutil.NewRef(1) b.sharedFieldReferences[types.ProposerLookahead] = stateutil.NewRef(1)
b.sharedFieldReferences[types.Builders] = stateutil.NewRef(1) // New in Gloas.
b.sharedFieldReferences[types.BuilderPendingWithdrawals] = stateutil.NewRef(1) // New in Gloas. b.sharedFieldReferences[types.BuilderPendingWithdrawals] = stateutil.NewRef(1) // New in Gloas.
state.Count.Inc() state.Count.Inc()
@@ -932,6 +937,7 @@ func (b *BeaconState) Copy() state.BeaconState {
pendingDeposits: b.pendingDeposits, pendingDeposits: b.pendingDeposits,
pendingPartialWithdrawals: b.pendingPartialWithdrawals, pendingPartialWithdrawals: b.pendingPartialWithdrawals,
pendingConsolidations: b.pendingConsolidations, pendingConsolidations: b.pendingConsolidations,
builders: b.builders,
// Everything else, too small to be concerned about, constant size. // Everything else, too small to be concerned about, constant size.
genesisValidatorsRoot: b.genesisValidatorsRoot, genesisValidatorsRoot: b.genesisValidatorsRoot,
@@ -948,11 +954,12 @@ func (b *BeaconState) Copy() state.BeaconState {
latestExecutionPayloadHeaderCapella: b.latestExecutionPayloadHeaderCapella.Copy(), latestExecutionPayloadHeaderCapella: b.latestExecutionPayloadHeaderCapella.Copy(),
latestExecutionPayloadHeaderDeneb: b.latestExecutionPayloadHeaderDeneb.Copy(), latestExecutionPayloadHeaderDeneb: b.latestExecutionPayloadHeaderDeneb.Copy(),
latestExecutionPayloadBid: b.latestExecutionPayloadBid.Copy(), latestExecutionPayloadBid: b.latestExecutionPayloadBid.Copy(),
nextWithdrawalBuilderIndex: b.nextWithdrawalBuilderIndex,
executionPayloadAvailability: b.executionPayloadAvailabilityVal(), executionPayloadAvailability: b.executionPayloadAvailabilityVal(),
builderPendingPayments: b.builderPendingPaymentsVal(), builderPendingPayments: b.builderPendingPaymentsVal(),
builderPendingWithdrawals: b.builderPendingWithdrawalsVal(), builderPendingWithdrawals: b.builderPendingWithdrawalsVal(),
latestBlockHash: b.latestBlockHashVal(), latestBlockHash: b.latestBlockHashVal(),
latestWithdrawalsRoot: b.latestWithdrawalsRootVal(), payloadExpectedWithdrawals: b.payloadExpectedWithdrawalsVal(),
id: types.Enumerator.Inc(), id: types.Enumerator.Inc(),
@@ -1328,6 +1335,10 @@ func (b *BeaconState) rootSelector(ctx context.Context, field types.FieldIndex)
return stateutil.ProposerLookaheadRoot(b.proposerLookahead) return stateutil.ProposerLookaheadRoot(b.proposerLookahead)
case types.LatestExecutionPayloadBid: case types.LatestExecutionPayloadBid:
return b.latestExecutionPayloadBid.HashTreeRoot() return b.latestExecutionPayloadBid.HashTreeRoot()
case types.Builders:
return stateutil.BuildersRoot(b.builders)
case types.NextWithdrawalBuilderIndex:
return ssz.Uint64Root(uint64(b.nextWithdrawalBuilderIndex)), nil
case types.ExecutionPayloadAvailability: case types.ExecutionPayloadAvailability:
return stateutil.ExecutionPayloadAvailabilityRoot(b.executionPayloadAvailability) return stateutil.ExecutionPayloadAvailabilityRoot(b.executionPayloadAvailability)
@@ -1337,8 +1348,8 @@ func (b *BeaconState) rootSelector(ctx context.Context, field types.FieldIndex)
return stateutil.BuilderPendingWithdrawalsRoot(b.builderPendingWithdrawals) return stateutil.BuilderPendingWithdrawalsRoot(b.builderPendingWithdrawals)
case types.LatestBlockHash: case types.LatestBlockHash:
return bytesutil.ToBytes32(b.latestBlockHash), nil return bytesutil.ToBytes32(b.latestBlockHash), nil
case types.LatestWithdrawalsRoot: case types.PayloadExpectedWithdrawals:
return bytesutil.ToBytes32(b.latestWithdrawalsRoot), nil return ssz.WithdrawalSliceRoot(b.payloadExpectedWithdrawals, fieldparams.MaxWithdrawalsPerPayload)
} }
return [32]byte{}, errors.New("invalid field index provided") return [32]byte{}, errors.New("invalid field index provided")
} }

View File

@@ -116,6 +116,10 @@ func (f FieldIndex) String() string {
return "pendingConsolidations" return "pendingConsolidations"
case ProposerLookahead: case ProposerLookahead:
return "proposerLookahead" return "proposerLookahead"
case Builders:
return "builders"
case NextWithdrawalBuilderIndex:
return "nextWithdrawalBuilderIndex"
case ExecutionPayloadAvailability: case ExecutionPayloadAvailability:
return "executionPayloadAvailability" return "executionPayloadAvailability"
case BuilderPendingPayments: case BuilderPendingPayments:
@@ -124,8 +128,8 @@ func (f FieldIndex) String() string {
return "builderPendingWithdrawals" return "builderPendingWithdrawals"
case LatestBlockHash: case LatestBlockHash:
return "latestBlockHash" return "latestBlockHash"
case LatestWithdrawalsRoot: case PayloadExpectedWithdrawals:
return "latestWithdrawalsRoot" return "payloadExpectedWithdrawals"
default: default:
return fmt.Sprintf("unknown field index number: %d", f) return fmt.Sprintf("unknown field index number: %d", f)
} }
@@ -211,16 +215,20 @@ func (f FieldIndex) RealPosition() int {
return 36 return 36
case ProposerLookahead: case ProposerLookahead:
return 37 return 37
case ExecutionPayloadAvailability: case Builders:
return 38 return 38
case BuilderPendingPayments: case NextWithdrawalBuilderIndex:
return 39 return 39
case BuilderPendingWithdrawals: case ExecutionPayloadAvailability:
return 40 return 40
case LatestBlockHash: case BuilderPendingPayments:
return 41 return 41
case LatestWithdrawalsRoot: case BuilderPendingWithdrawals:
return 42 return 42
case LatestBlockHash:
return 43
case PayloadExpectedWithdrawals:
return 44
default: default:
return -1 return -1
} }
@@ -287,11 +295,13 @@ const (
PendingPartialWithdrawals // Electra: EIP-7251 PendingPartialWithdrawals // Electra: EIP-7251
PendingConsolidations // Electra: EIP-7251 PendingConsolidations // Electra: EIP-7251
ProposerLookahead // Fulu: EIP-7917 ProposerLookahead // Fulu: EIP-7917
Builders // Gloas: EIP-7732
NextWithdrawalBuilderIndex // Gloas: EIP-7732
ExecutionPayloadAvailability // Gloas: EIP-7732 ExecutionPayloadAvailability // Gloas: EIP-7732
BuilderPendingPayments // Gloas: EIP-7732 BuilderPendingPayments // Gloas: EIP-7732
BuilderPendingWithdrawals // Gloas: EIP-7732 BuilderPendingWithdrawals // Gloas: EIP-7732
LatestBlockHash // Gloas: EIP-7732 LatestBlockHash // Gloas: EIP-7732
LatestWithdrawalsRoot // Gloas: EIP-7732 PayloadExpectedWithdrawals // Gloas: EIP-7732
) )
// Enumerator keeps track of the number of states created since the node's start. // Enumerator keeps track of the number of states created since the node's start.

View File

@@ -6,6 +6,7 @@ go_library(
"block_header_root.go", "block_header_root.go",
"builder_pending_payments_root.go", "builder_pending_payments_root.go",
"builder_pending_withdrawals_root.go", "builder_pending_withdrawals_root.go",
"builders_root.go",
"eth1_root.go", "eth1_root.go",
"execution_payload_availability_root.go", "execution_payload_availability_root.go",
"field_root_attestation.go", "field_root_attestation.go",

View File

@@ -0,0 +1,12 @@
package stateutil
import (
fieldparams "github.com/OffchainLabs/prysm/v7/config/fieldparams"
"github.com/OffchainLabs/prysm/v7/encoding/ssz"
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
)
// BuildersRoot computes the SSZ root of a slice of Builder.
func BuildersRoot(slice []*ethpb.Builder) ([32]byte, error) {
return ssz.SliceRoot(slice, uint64(fieldparams.BuilderRegistryLimit))
}

View File

@@ -0,0 +1,5 @@
### Added
- Added an ephemeral debug logfile that for beacon and validator nodes that captures debug-level logs for 24 hours. It
also keeps 1 backup of in case of size-based rotation. The logfiles are stored in `datadir/logs/`. This feature is
enabled by default and can be disabled by setting the `--disable-ephemeral-log-file` flag.

View File

@@ -0,0 +1,4 @@
### Changed
- Moved verbosity settings to be configurable per hook, rather than just globally. This allows us to control the
verbosity of individual output independently.

View File

@@ -0,0 +1,2 @@
### Added
- Add a feature flag to pass spectests with low validator count.

View File

@@ -0,0 +1,3 @@
### Added
- Added basic Gloas builder support (`Builder` message and `BeaconStateGloas` `builders`/`next_withdrawal_builder_index` fields)

View File

@@ -0,0 +1,3 @@
### Added
- Add Gloas latest execution bid processing

View File

@@ -356,6 +356,12 @@ var (
Usage: "A comma-separated list of exponents (of 2) in decreasing order, defining the state diff hierarchy levels. The last exponent must be greater than or equal to 5.", Usage: "A comma-separated list of exponents (of 2) in decreasing order, defining the state diff hierarchy levels. The last exponent must be greater than or equal to 5.",
Value: cli.NewIntSlice(21, 18, 16, 13, 11, 9, 5), Value: cli.NewIntSlice(21, 18, 16, 13, 11, 9, 5),
} }
// DisableEphemeralLogFile disables the 24 hour debug log file.
DisableEphemeralLogFile = &cli.BoolFlag{
Name: "disable-ephemeral-log-file",
Usage: "Disables the creation of a debug log file that keeps 24 hours of logs.",
Value: false,
}
// DisableGetBlobsV2 disables the engine_getBlobsV2 usage. // DisableGetBlobsV2 disables the engine_getBlobsV2 usage.
DisableGetBlobsV2 = &cli.BoolFlag{ DisableGetBlobsV2 = &cli.BoolFlag{
Name: "disable-get-blobs-v2", Name: "disable-get-blobs-v2",

View File

@@ -158,6 +158,7 @@ var appFlags = []cli.Flag{
dasFlags.BackfillOldestSlot, dasFlags.BackfillOldestSlot,
dasFlags.BlobRetentionEpochFlag, dasFlags.BlobRetentionEpochFlag,
flags.BatchVerifierLimit, flags.BatchVerifierLimit,
flags.DisableEphemeralLogFile,
} }
func init() { func init() {
@@ -170,8 +171,15 @@ func before(ctx *cli.Context) error {
return errors.Wrap(err, "failed to load flags from config file") return errors.Wrap(err, "failed to load flags from config file")
} }
format := ctx.String(cmd.LogFormat.Name) // determine log verbosity
verbosity := ctx.String(cmd.VerbosityFlag.Name)
verbosityLevel, err := logrus.ParseLevel(verbosity)
if err != nil {
return errors.Wrap(err, "failed to parse log verbosity")
}
logs.SetLoggingLevel(verbosityLevel)
format := ctx.String(cmd.LogFormat.Name)
switch format { switch format {
case "text": case "text":
// disabling logrus default output so we can control it via different hooks // disabling logrus default output so we can control it via different hooks
@@ -185,8 +193,9 @@ func before(ctx *cli.Context) error {
formatter.ForceColors = true formatter.ForceColors = true
logrus.AddHook(&logs.WriterHook{ logrus.AddHook(&logs.WriterHook{
Formatter: formatter, Formatter: formatter,
Writer: os.Stderr, Writer: os.Stderr,
AllowedLevels: logrus.AllLevels[:verbosityLevel+1],
}) })
case "fluentd": case "fluentd":
f := joonix.NewFormatter() f := joonix.NewFormatter()
@@ -210,11 +219,17 @@ func before(ctx *cli.Context) error {
logFileName := ctx.String(cmd.LogFileName.Name) logFileName := ctx.String(cmd.LogFileName.Name)
if logFileName != "" { if logFileName != "" {
if err := logs.ConfigurePersistentLogging(logFileName, format); err != nil { if err := logs.ConfigurePersistentLogging(logFileName, format, verbosityLevel); err != nil {
log.WithError(err).Error("Failed to configuring logging to disk.") log.WithError(err).Error("Failed to configuring logging to disk.")
} }
} }
if !ctx.Bool(flags.DisableEphemeralLogFile.Name) {
if err := logs.ConfigureEphemeralLogFile(ctx.String(cmd.DataDirFlag.Name), ctx.App.Name); err != nil {
log.WithError(err).Error("Failed to configure debug log file")
}
}
if err := cmd.ExpandSingleEndpointIfFile(ctx, flags.ExecutionEngineEndpoint); err != nil { if err := cmd.ExpandSingleEndpointIfFile(ctx, flags.ExecutionEngineEndpoint); err != nil {
return errors.Wrap(err, "failed to expand single endpoint") return errors.Wrap(err, "failed to expand single endpoint")
} }
@@ -291,7 +306,7 @@ func startNode(ctx *cli.Context, cancel context.CancelFunc) error {
if err != nil { if err != nil {
return err return err
} }
logrus.SetLevel(level)
// Set libp2p logger to only panic logs for the info level. // Set libp2p logger to only panic logs for the info level.
golog.SetAllLoggers(golog.LevelPanic) golog.SetAllLoggers(golog.LevelPanic)

View File

@@ -200,6 +200,7 @@ var appHelpFlagGroups = []flagGroup{
cmd.LogFormat, cmd.LogFormat,
cmd.LogFileName, cmd.LogFileName,
cmd.VerbosityFlag, cmd.VerbosityFlag,
flags.DisableEphemeralLogFile,
}, },
}, },
{ // Feature flags. { // Feature flags.

View File

@@ -86,7 +86,7 @@ func main() {
logFileName := ctx.String(cmd.LogFileName.Name) logFileName := ctx.String(cmd.LogFileName.Name)
if logFileName != "" { if logFileName != "" {
if err := logs.ConfigurePersistentLogging(logFileName, format); err != nil { if err := logs.ConfigurePersistentLogging(logFileName, format, level); err != nil {
log.WithError(err).Error("Failed to configuring logging to disk.") log.WithError(err).Error("Failed to configuring logging to disk.")
} }
} }

View File

@@ -410,6 +410,12 @@ var (
Usage: "Maximum number of health checks to perform before exiting if not healthy. Set to 0 or a negative number for indefinite checks.", Usage: "Maximum number of health checks to perform before exiting if not healthy. Set to 0 or a negative number for indefinite checks.",
Value: DefaultMaxHealthChecks, Value: DefaultMaxHealthChecks,
} }
// DisableEphemeralLogFile disables the 24 hour debug log file.
DisableEphemeralLogFile = &cli.BoolFlag{
Name: "disable-ephemeral-log-file",
Usage: "Disables the creation of a debug log file that keeps 24 hours of logs.",
Value: false,
}
) )
// DefaultValidatorDir returns OS-specific default validator directory. // DefaultValidatorDir returns OS-specific default validator directory.

View File

@@ -115,6 +115,7 @@ var appFlags = []cli.Flag{
debug.BlockProfileRateFlag, debug.BlockProfileRateFlag,
debug.MutexProfileFractionFlag, debug.MutexProfileFractionFlag,
cmd.AcceptTosFlag, cmd.AcceptTosFlag,
flags.DisableEphemeralLogFile,
} }
func init() { func init() {
@@ -147,6 +148,14 @@ func main() {
return err return err
} }
// determine log verbosity
verbosity := ctx.String(cmd.VerbosityFlag.Name)
verbosityLevel, err := logrus.ParseLevel(verbosity)
if err != nil {
return errors.Wrap(err, "failed to parse log verbosity")
}
logs.SetLoggingLevel(verbosityLevel)
logFileName := ctx.String(cmd.LogFileName.Name) logFileName := ctx.String(cmd.LogFileName.Name)
format := ctx.String(cmd.LogFormat.Name) format := ctx.String(cmd.LogFormat.Name)
@@ -163,8 +172,9 @@ func main() {
formatter.ForceColors = true formatter.ForceColors = true
logrus.AddHook(&logs.WriterHook{ logrus.AddHook(&logs.WriterHook{
Formatter: formatter, Formatter: formatter,
Writer: os.Stderr, Writer: os.Stderr,
AllowedLevels: logrus.AllLevels[:verbosityLevel+1],
}) })
case "fluentd": case "fluentd":
f := joonix.NewFormatter() f := joonix.NewFormatter()
@@ -185,11 +195,17 @@ func main() {
} }
if logFileName != "" { if logFileName != "" {
if err := logs.ConfigurePersistentLogging(logFileName, format); err != nil { if err := logs.ConfigurePersistentLogging(logFileName, format, verbosityLevel); err != nil {
log.WithError(err).Error("Failed to configuring logging to disk.") log.WithError(err).Error("Failed to configuring logging to disk.")
} }
} }
if !ctx.Bool(flags.DisableEphemeralLogFile.Name) {
if err := logs.ConfigureEphemeralLogFile(ctx.String(cmd.DataDirFlag.Name), ctx.App.Name); err != nil {
log.WithError(err).Error("Failed to configure debug log file")
}
}
// Fix data dir for Windows users. // Fix data dir for Windows users.
outdatedDataDir := filepath.Join(file.HomeDir(), "AppData", "Roaming", "Eth2Validators") outdatedDataDir := filepath.Join(file.HomeDir(), "AppData", "Roaming", "Eth2Validators")
currentDataDir := flags.DefaultValidatorDir() currentDataDir := flags.DefaultValidatorDir()

View File

@@ -75,6 +75,7 @@ var appHelpFlagGroups = []flagGroup{
cmd.GrpcMaxCallRecvMsgSizeFlag, cmd.GrpcMaxCallRecvMsgSizeFlag,
cmd.AcceptTosFlag, cmd.AcceptTosFlag,
cmd.ApiTimeoutFlag, cmd.ApiTimeoutFlag,
flags.DisableEphemeralLogFile,
}, },
}, },
{ {

View File

@@ -80,6 +80,7 @@ type Flags struct {
SaveInvalidBlob bool // SaveInvalidBlob saves invalid blob to temp. SaveInvalidBlob bool // SaveInvalidBlob saves invalid blob to temp.
EnableDiscoveryReboot bool // EnableDiscoveryReboot allows the node to have its local listener to be rebooted in the event of discovery issues. EnableDiscoveryReboot bool // EnableDiscoveryReboot allows the node to have its local listener to be rebooted in the event of discovery issues.
LowValcountSweep bool // LowValcountSweep bounds withdrawal sweep by validator count.
// KeystoreImportDebounceInterval specifies the time duration the validator waits to reload new keys if they have // KeystoreImportDebounceInterval specifies the time duration the validator waits to reload new keys if they have
// changed on disk. This feature is for advanced use cases only. // changed on disk. This feature is for advanced use cases only.
@@ -284,6 +285,10 @@ func ConfigureBeaconChain(ctx *cli.Context) error {
logEnabled(ignoreUnviableAttestations) logEnabled(ignoreUnviableAttestations)
cfg.IgnoreUnviableAttestations = true cfg.IgnoreUnviableAttestations = true
} }
if ctx.Bool(lowValcountSweep.Name) {
logEnabled(lowValcountSweep)
cfg.LowValcountSweep = true
}
if ctx.IsSet(EnableStateDiff.Name) { if ctx.IsSet(EnableStateDiff.Name) {
logEnabled(EnableStateDiff) logEnabled(EnableStateDiff)

View File

@@ -211,6 +211,13 @@ var (
Name: "ignore-unviable-attestations", Name: "ignore-unviable-attestations",
Usage: "Ignores attestations whose target state is not viable with respect to the current head (avoid expensive state replay from lagging attesters).", Usage: "Ignores attestations whose target state is not viable with respect to the current head (avoid expensive state replay from lagging attesters).",
} }
// lowValcountSweep bounds withdrawal sweep by validator count.
lowValcountSweep = &cli.BoolFlag{
Name: "low-valcount-sweep",
Usage: "Uses validator count bound for withdrawal sweep when validator count is less than MaxValidatorsPerWithdrawalsSweep.",
Value: false,
Hidden: true,
}
) )
// devModeFlags holds list of flags that are set when development mode is on. // devModeFlags holds list of flags that are set when development mode is on.
@@ -272,6 +279,7 @@ var BeaconChainFlags = combinedFlags([]cli.Flag{
enableExperimentalAttestationPool, enableExperimentalAttestationPool,
forceHeadFlag, forceHeadFlag,
blacklistRoots, blacklistRoots,
lowValcountSweep,
}, deprecatedBeaconFlags, deprecatedFlags, upcomingDeprecation) }, deprecatedBeaconFlags, deprecatedFlags, upcomingDeprecation)
func combinedFlags(flags ...[]cli.Flag) []cli.Flag { func combinedFlags(flags ...[]cli.Flag) []cli.Flag {

View File

@@ -9,6 +9,7 @@ const (
RandaoMixesLength = 65536 // EPOCHS_PER_HISTORICAL_VECTOR RandaoMixesLength = 65536 // EPOCHS_PER_HISTORICAL_VECTOR
HistoricalRootsLength = 16777216 // HISTORICAL_ROOTS_LIMIT HistoricalRootsLength = 16777216 // HISTORICAL_ROOTS_LIMIT
ValidatorRegistryLimit = 1099511627776 // VALIDATOR_REGISTRY_LIMIT ValidatorRegistryLimit = 1099511627776 // VALIDATOR_REGISTRY_LIMIT
BuilderRegistryLimit = 1099511627776 // BUILDER_REGISTRY_LIMIT
Eth1DataVotesLength = 2048 // SLOTS_PER_ETH1_VOTING_PERIOD Eth1DataVotesLength = 2048 // SLOTS_PER_ETH1_VOTING_PERIOD
PreviousEpochAttestationsLength = 4096 // MAX_ATTESTATIONS * SLOTS_PER_EPOCH PreviousEpochAttestationsLength = 4096 // MAX_ATTESTATIONS * SLOTS_PER_EPOCH
CurrentEpochAttestationsLength = 4096 // MAX_ATTESTATIONS * SLOTS_PER_EPOCH CurrentEpochAttestationsLength = 4096 // MAX_ATTESTATIONS * SLOTS_PER_EPOCH

View File

@@ -9,6 +9,7 @@ const (
RandaoMixesLength = 64 // EPOCHS_PER_HISTORICAL_VECTOR RandaoMixesLength = 64 // EPOCHS_PER_HISTORICAL_VECTOR
HistoricalRootsLength = 16777216 // HISTORICAL_ROOTS_LIMIT HistoricalRootsLength = 16777216 // HISTORICAL_ROOTS_LIMIT
ValidatorRegistryLimit = 1099511627776 // VALIDATOR_REGISTRY_LIMIT ValidatorRegistryLimit = 1099511627776 // VALIDATOR_REGISTRY_LIMIT
BuilderRegistryLimit = 1099511627776 // BUILDER_REGISTRY_LIMIT
Eth1DataVotesLength = 32 // SLOTS_PER_ETH1_VOTING_PERIOD Eth1DataVotesLength = 32 // SLOTS_PER_ETH1_VOTING_PERIOD
PreviousEpochAttestationsLength = 1024 // MAX_ATTESTATIONS * SLOTS_PER_EPOCH PreviousEpochAttestationsLength = 1024 // MAX_ATTESTATIONS * SLOTS_PER_EPOCH
CurrentEpochAttestationsLength = 1024 // MAX_ATTESTATIONS * SLOTS_PER_EPOCH CurrentEpochAttestationsLength = 1024 // MAX_ATTESTATIONS * SLOTS_PER_EPOCH

View File

@@ -56,10 +56,12 @@ type BeaconChainConfig struct {
EffectiveBalanceIncrement uint64 `yaml:"EFFECTIVE_BALANCE_INCREMENT" spec:"true"` // EffectiveBalanceIncrement is used for converting the high balance into the low balance for validators. EffectiveBalanceIncrement uint64 `yaml:"EFFECTIVE_BALANCE_INCREMENT" spec:"true"` // EffectiveBalanceIncrement is used for converting the high balance into the low balance for validators.
// Initial value constants. // Initial value constants.
BLSWithdrawalPrefixByte byte `yaml:"BLS_WITHDRAWAL_PREFIX" spec:"true"` // BLSWithdrawalPrefixByte is used for BLS withdrawal and it's the first byte. BLSWithdrawalPrefixByte byte `yaml:"BLS_WITHDRAWAL_PREFIX" spec:"true"` // BLSWithdrawalPrefixByte is used for BLS withdrawal and it's the first byte.
ETH1AddressWithdrawalPrefixByte byte `yaml:"ETH1_ADDRESS_WITHDRAWAL_PREFIX" spec:"true"` // ETH1AddressWithdrawalPrefixByte is used for withdrawals and it's the first byte. ETH1AddressWithdrawalPrefixByte byte `yaml:"ETH1_ADDRESS_WITHDRAWAL_PREFIX" spec:"true"` // ETH1AddressWithdrawalPrefixByte is used for withdrawals and it's the first byte.
CompoundingWithdrawalPrefixByte byte `yaml:"COMPOUNDING_WITHDRAWAL_PREFIX" spec:"true"` // CompoundingWithdrawalPrefixByteByte is used for compounding withdrawals and it's the first byte. CompoundingWithdrawalPrefixByte byte `yaml:"COMPOUNDING_WITHDRAWAL_PREFIX" spec:"true"` // CompoundingWithdrawalPrefixByteByte is used for compounding withdrawals and it's the first byte.
ZeroHash [32]byte // ZeroHash is used to represent a zeroed out 32 byte array. BuilderWithdrawalPrefixByte byte `yaml:"BUILDER_WITHDRAWAL_PREFIX" spec:"true"` // BuilderWithdrawalPrefixByte is used for builder withdrawals and it's the first byte.
BuilderIndexSelfBuild primitives.BuilderIndex `yaml:"BUILDER_INDEX_SELF_BUILD" spec:"true"` // BuilderIndexSelfBuild indicates proposer self-built payloads.
ZeroHash [32]byte // ZeroHash is used to represent a zeroed out 32 byte array.
// Time parameters constants. // Time parameters constants.
GenesisDelay uint64 `yaml:"GENESIS_DELAY" spec:"true"` // GenesisDelay is the minimum number of seconds to delay starting the Ethereum Beacon Chain genesis. Must be at least 1 second. GenesisDelay uint64 `yaml:"GENESIS_DELAY" spec:"true"` // GenesisDelay is the minimum number of seconds to delay starting the Ethereum Beacon Chain genesis. Must be at least 1 second.
@@ -139,6 +141,7 @@ type BeaconChainConfig struct {
DomainApplicationMask [4]byte `yaml:"DOMAIN_APPLICATION_MASK" spec:"true"` // DomainApplicationMask defines the BLS signature domain for application mask. DomainApplicationMask [4]byte `yaml:"DOMAIN_APPLICATION_MASK" spec:"true"` // DomainApplicationMask defines the BLS signature domain for application mask.
DomainApplicationBuilder [4]byte `yaml:"DOMAIN_APPLICATION_BUILDER" spec:"true"` // DomainApplicationBuilder defines the BLS signature domain for application builder. DomainApplicationBuilder [4]byte `yaml:"DOMAIN_APPLICATION_BUILDER" spec:"true"` // DomainApplicationBuilder defines the BLS signature domain for application builder.
DomainBLSToExecutionChange [4]byte `yaml:"DOMAIN_BLS_TO_EXECUTION_CHANGE" spec:"true"` // DomainBLSToExecutionChange defines the BLS signature domain to change withdrawal addresses to ETH1 prefix DomainBLSToExecutionChange [4]byte `yaml:"DOMAIN_BLS_TO_EXECUTION_CHANGE" spec:"true"` // DomainBLSToExecutionChange defines the BLS signature domain to change withdrawal addresses to ETH1 prefix
DomainBeaconBuilder [4]byte `yaml:"DOMAIN_BEACON_BUILDER" spec:"true"` // DomainBeaconBuilder defines the BLS signature domain for beacon block builder.
// Prysm constants. // Prysm constants.
GenesisValidatorsRoot [32]byte // GenesisValidatorsRoot is the root hash of the genesis validators. GenesisValidatorsRoot [32]byte // GenesisValidatorsRoot is the root hash of the genesis validators.

View File

@@ -94,6 +94,8 @@ var mainnetBeaconConfig = &BeaconChainConfig{
BLSWithdrawalPrefixByte: byte(0), BLSWithdrawalPrefixByte: byte(0),
ETH1AddressWithdrawalPrefixByte: byte(1), ETH1AddressWithdrawalPrefixByte: byte(1),
CompoundingWithdrawalPrefixByte: byte(2), CompoundingWithdrawalPrefixByte: byte(2),
BuilderWithdrawalPrefixByte: byte(3),
BuilderIndexSelfBuild: primitives.BuilderIndex(math.MaxUint64),
ZeroHash: [32]byte{}, ZeroHash: [32]byte{},
// Time parameter constants. // Time parameter constants.
@@ -182,6 +184,7 @@ var mainnetBeaconConfig = &BeaconChainConfig{
DomainApplicationMask: bytesutil.Uint32ToBytes4(0x00000001), DomainApplicationMask: bytesutil.Uint32ToBytes4(0x00000001),
DomainApplicationBuilder: bytesutil.Uint32ToBytes4(0x00000001), DomainApplicationBuilder: bytesutil.Uint32ToBytes4(0x00000001),
DomainBLSToExecutionChange: bytesutil.Uint32ToBytes4(0x0A000000), DomainBLSToExecutionChange: bytesutil.Uint32ToBytes4(0x0A000000),
DomainBeaconBuilder: bytesutil.Uint32ToBytes4(0x1B000000),
// Prysm constants. // Prysm constants.
GenesisValidatorsRoot: [32]byte{75, 54, 61, 185, 78, 40, 97, 32, 215, 110, 185, 5, 52, 15, 221, 78, 84, 191, 233, 240, 107, 243, 63, 246, 207, 90, 210, 127, 81, 27, 254, 149}, GenesisValidatorsRoot: [32]byte{75, 54, 61, 185, 78, 40, 97, 32, 215, 110, 185, 5, 52, 15, 221, 78, 84, 191, 233, 240, 107, 243, 63, 246, 207, 90, 210, 127, 81, 27, 254, 149},
@@ -206,7 +209,7 @@ var mainnetBeaconConfig = &BeaconChainConfig{
BeaconStateDenebFieldCount: 28, BeaconStateDenebFieldCount: 28,
BeaconStateElectraFieldCount: 37, BeaconStateElectraFieldCount: 37,
BeaconStateFuluFieldCount: 38, BeaconStateFuluFieldCount: 38,
BeaconStateGloasFieldCount: 43, BeaconStateGloasFieldCount: 45,
// Slasher related values. // Slasher related values.
WeakSubjectivityPeriod: 54000, WeakSubjectivityPeriod: 54000,

View File

@@ -14,11 +14,13 @@ go_library(
"roblock.go", "roblock.go",
"rodatacolumn.go", "rodatacolumn.go",
"setters.go", "setters.go",
"signed_execution_bid.go",
"types.go", "types.go",
], ],
importpath = "github.com/OffchainLabs/prysm/v7/consensus-types/blocks", importpath = "github.com/OffchainLabs/prysm/v7/consensus-types/blocks",
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = [ deps = [
"//beacon-chain/core/signing:go_default_library",
"//beacon-chain/state/stateutil:go_default_library", "//beacon-chain/state/stateutil:go_default_library",
"//config/fieldparams:go_default_library", "//config/fieldparams:go_default_library",
"//config/params:go_default_library", "//config/params:go_default_library",
@@ -54,9 +56,11 @@ go_test(
"roblock_test.go", "roblock_test.go",
"rodatacolumn_test.go", "rodatacolumn_test.go",
"setters_test.go", "setters_test.go",
"signed_execution_bid_test.go",
], ],
embed = [":go_default_library"], embed = [":go_default_library"],
deps = [ deps = [
"//beacon-chain/core/signing:go_default_library",
"//config/fieldparams:go_default_library", "//config/fieldparams:go_default_library",
"//config/params:go_default_library", "//config/params:go_default_library",
"//consensus-types:go_default_library", "//consensus-types:go_default_library",

View File

@@ -641,6 +641,8 @@ func BuildSignedBeaconBlockFromExecutionPayload(blk interfaces.ReadOnlySignedBea
}, },
Signature: sig[:], Signature: sig[:],
} }
case version.Gloas:
return nil, errors.Wrap(errUnsupportedBeaconBlock, "gloas blocks are not supported in this function")
default: default:
return nil, errors.New("Block not of known type") return nil, errors.New("Block not of known type")
} }

View File

@@ -669,6 +669,7 @@ func hydrateBeaconBlockBodyGloas() *eth.BeaconBlockBodyGloas {
ParentBlockHash: make([]byte, fieldparams.RootLength), ParentBlockHash: make([]byte, fieldparams.RootLength),
ParentBlockRoot: make([]byte, fieldparams.RootLength), ParentBlockRoot: make([]byte, fieldparams.RootLength),
BlockHash: make([]byte, fieldparams.RootLength), BlockHash: make([]byte, fieldparams.RootLength),
PrevRandao: make([]byte, fieldparams.RootLength),
FeeRecipient: make([]byte, 20), FeeRecipient: make([]byte, 20),
BlobKzgCommitmentsRoot: make([]byte, fieldparams.RootLength), BlobKzgCommitmentsRoot: make([]byte, fieldparams.RootLength),
}, },

View File

@@ -0,0 +1,142 @@
package blocks
import (
"github.com/OffchainLabs/prysm/v7/beacon-chain/core/signing"
consensus_types "github.com/OffchainLabs/prysm/v7/consensus-types"
"github.com/OffchainLabs/prysm/v7/consensus-types/interfaces"
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
)
// signedExecutionPayloadBid wraps the protobuf signed execution payload bid
// and implements the ROSignedExecutionPayloadBid interface.
type signedExecutionPayloadBid struct {
bid *ethpb.SignedExecutionPayloadBid
}
// executionPayloadBidGloas wraps the protobuf execution payload bid for Gloas fork
// and implements the ROExecutionPayloadBidGloas interface.
type executionPayloadBidGloas struct {
payload *ethpb.ExecutionPayloadBid
}
// IsNil checks if the signed execution payload bid is nil or invalid.
func (s signedExecutionPayloadBid) IsNil() bool {
if s.bid == nil {
return true
}
if _, err := WrappedROExecutionPayloadBid(s.bid.Message); err != nil {
return true
}
return len(s.bid.Signature) != 96
}
// IsNil checks if the execution payload bid is nil or has invalid fields.
func (h executionPayloadBidGloas) IsNil() bool {
if h.payload == nil {
return true
}
if len(h.payload.ParentBlockHash) != 32 ||
len(h.payload.ParentBlockRoot) != 32 ||
len(h.payload.BlockHash) != 32 ||
len(h.payload.PrevRandao) != 32 ||
len(h.payload.BlobKzgCommitmentsRoot) != 32 ||
len(h.payload.FeeRecipient) != 20 {
return true
}
return false
}
// WrappedROSignedExecutionPayloadBid creates a new read-only signed execution payload bid
// wrapper from the given protobuf message.
func WrappedROSignedExecutionPayloadBid(pb *ethpb.SignedExecutionPayloadBid) (interfaces.ROSignedExecutionPayloadBid, error) {
wrapper := signedExecutionPayloadBid{bid: pb}
if wrapper.IsNil() {
return nil, consensus_types.ErrNilObjectWrapped
}
return wrapper, nil
}
// WrappedROExecutionPayloadBid creates a new read-only execution payload bid
// wrapper for the Gloas fork from the given protobuf message.
func WrappedROExecutionPayloadBid(pb *ethpb.ExecutionPayloadBid) (interfaces.ROExecutionPayloadBid, error) {
wrapper := executionPayloadBidGloas{payload: pb}
if wrapper.IsNil() {
return nil, consensus_types.ErrNilObjectWrapped
}
return wrapper, nil
}
// Bid returns the execution payload bid as a read-only interface.
func (s signedExecutionPayloadBid) Bid() (interfaces.ROExecutionPayloadBid, error) {
return WrappedROExecutionPayloadBid(s.bid.Message)
}
// SigningRoot computes the signing root for the execution payload bid with the given domain.
func (s signedExecutionPayloadBid) SigningRoot(domain []byte) ([32]byte, error) {
return signing.ComputeSigningRoot(s.bid.Message, domain)
}
// Signature returns the BLS signature as a 96-byte array.
func (s signedExecutionPayloadBid) Signature() [96]byte {
return [96]byte(s.bid.Signature)
}
// ParentBlockHash returns the hash of the parent execution block.
func (h executionPayloadBidGloas) ParentBlockHash() [32]byte {
return [32]byte(h.payload.ParentBlockHash)
}
// ParentBlockRoot returns the beacon block root of the parent block.
func (h executionPayloadBidGloas) ParentBlockRoot() [32]byte {
return [32]byte(h.payload.ParentBlockRoot)
}
// PrevRandao returns the previous randao value for the execution block.
func (h executionPayloadBidGloas) PrevRandao() [32]byte {
return [32]byte(h.payload.PrevRandao)
}
// BlockHash returns the hash of the execution block.
func (h executionPayloadBidGloas) BlockHash() [32]byte {
return [32]byte(h.payload.BlockHash)
}
// GasLimit returns the gas limit for the execution block.
func (h executionPayloadBidGloas) GasLimit() uint64 {
return h.payload.GasLimit
}
// BuilderIndex returns the validator index of the builder who created this bid.
func (h executionPayloadBidGloas) BuilderIndex() primitives.BuilderIndex {
return h.payload.BuilderIndex
}
// Slot returns the beacon chain slot for which this bid was created.
func (h executionPayloadBidGloas) Slot() primitives.Slot {
return h.payload.Slot
}
// Value returns the payment value offered by the builder in Gwei.
func (h executionPayloadBidGloas) Value() primitives.Gwei {
return primitives.Gwei(h.payload.Value)
}
// ExecutionPayment returns the execution payment offered by the builder.
func (h executionPayloadBidGloas) ExecutionPayment() primitives.Gwei {
return primitives.Gwei(h.payload.ExecutionPayment)
}
// BlobKzgCommitmentsRoot returns the root of the KZG commitments for blobs.
func (h executionPayloadBidGloas) BlobKzgCommitmentsRoot() [32]byte {
return [32]byte(h.payload.BlobKzgCommitmentsRoot)
}
// FeeRecipient returns the execution address that will receive the builder payment.
func (h executionPayloadBidGloas) FeeRecipient() [20]byte {
return [20]byte(h.payload.FeeRecipient)
}

View File

@@ -0,0 +1,127 @@
package blocks_test
import (
"bytes"
"testing"
"github.com/OffchainLabs/prysm/v7/beacon-chain/core/signing"
consensus_types "github.com/OffchainLabs/prysm/v7/consensus-types"
"github.com/OffchainLabs/prysm/v7/consensus-types/blocks"
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v7/testing/assert"
"github.com/OffchainLabs/prysm/v7/testing/require"
)
func validExecutionPayloadBid() *ethpb.ExecutionPayloadBid {
return &ethpb.ExecutionPayloadBid{
ParentBlockHash: bytes.Repeat([]byte{0x01}, 32),
ParentBlockRoot: bytes.Repeat([]byte{0x02}, 32),
BlockHash: bytes.Repeat([]byte{0x03}, 32),
PrevRandao: bytes.Repeat([]byte{0x04}, 32),
GasLimit: 123,
BuilderIndex: 5,
Slot: 6,
Value: 7,
ExecutionPayment: 8,
BlobKzgCommitmentsRoot: bytes.Repeat([]byte{0x05}, 32),
FeeRecipient: bytes.Repeat([]byte{0x06}, 20),
}
}
func TestWrappedROExecutionPayloadBid(t *testing.T) {
t.Run("returns error on invalid lengths", func(t *testing.T) {
testCases := []struct {
name string
mutate func(*ethpb.ExecutionPayloadBid)
}{
{
name: "parent block hash",
mutate: func(b *ethpb.ExecutionPayloadBid) { b.ParentBlockHash = []byte{0x01} },
},
{
name: "parent block root",
mutate: func(b *ethpb.ExecutionPayloadBid) { b.ParentBlockRoot = []byte{0x02} },
},
{
name: "block hash",
mutate: func(b *ethpb.ExecutionPayloadBid) { b.BlockHash = []byte{0x03} },
},
{
name: "prev randao",
mutate: func(b *ethpb.ExecutionPayloadBid) { b.PrevRandao = []byte{0x04} },
},
{
name: "blob kzg commitments root",
mutate: func(b *ethpb.ExecutionPayloadBid) { b.BlobKzgCommitmentsRoot = []byte{0x05} },
},
{
name: "fee recipient",
mutate: func(b *ethpb.ExecutionPayloadBid) { b.FeeRecipient = []byte{0x06} },
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
invalid := validExecutionPayloadBid()
tc.mutate(invalid)
_, err := blocks.WrappedROExecutionPayloadBid(invalid)
require.Equal(t, consensus_types.ErrNilObjectWrapped, err)
})
}
})
t.Run("wraps and exposes fields", func(t *testing.T) {
bid := validExecutionPayloadBid()
wrapped, err := blocks.WrappedROExecutionPayloadBid(bid)
require.NoError(t, err)
require.Equal(t, primitives.BuilderIndex(5), wrapped.BuilderIndex())
require.Equal(t, primitives.Slot(6), wrapped.Slot())
require.Equal(t, primitives.Gwei(7), wrapped.Value())
require.Equal(t, primitives.Gwei(8), wrapped.ExecutionPayment())
assert.DeepEqual(t, [32]byte(bytes.Repeat([]byte{0x01}, 32)), wrapped.ParentBlockHash())
assert.DeepEqual(t, [32]byte(bytes.Repeat([]byte{0x02}, 32)), wrapped.ParentBlockRoot())
assert.DeepEqual(t, [32]byte(bytes.Repeat([]byte{0x03}, 32)), wrapped.BlockHash())
assert.DeepEqual(t, [32]byte(bytes.Repeat([]byte{0x04}, 32)), wrapped.PrevRandao())
assert.DeepEqual(t, [32]byte(bytes.Repeat([]byte{0x05}, 32)), wrapped.BlobKzgCommitmentsRoot())
assert.DeepEqual(t, [20]byte(bytes.Repeat([]byte{0x06}, 20)), wrapped.FeeRecipient())
})
}
func TestWrappedROSignedExecutionPayloadBid(t *testing.T) {
t.Run("returns error for invalid signature length", func(t *testing.T) {
signed := &ethpb.SignedExecutionPayloadBid{
Message: validExecutionPayloadBid(),
Signature: bytes.Repeat([]byte{0xAA}, 95),
}
_, err := blocks.WrappedROSignedExecutionPayloadBid(signed)
require.Equal(t, consensus_types.ErrNilObjectWrapped, err)
})
t.Run("wraps and provides bid/signing data", func(t *testing.T) {
sig := bytes.Repeat([]byte{0xAB}, 96)
signed := &ethpb.SignedExecutionPayloadBid{
Message: validExecutionPayloadBid(),
Signature: sig,
}
wrapped, err := blocks.WrappedROSignedExecutionPayloadBid(signed)
require.NoError(t, err)
bid, err := wrapped.Bid()
require.NoError(t, err)
require.Equal(t, primitives.Gwei(8), bid.ExecutionPayment())
gotSig := wrapped.Signature()
assert.DeepEqual(t, [96]byte(sig), gotSig)
domain := bytes.Repeat([]byte{0xCC}, 32)
wantRoot, err := signing.ComputeSigningRoot(signed.Message, domain)
require.NoError(t, err)
gotRoot, err := wrapped.SigningRoot(domain)
require.NoError(t, err)
require.Equal(t, wantRoot, gotRoot)
})
}

View File

@@ -6,6 +6,7 @@ go_library(
"beacon_block.go", "beacon_block.go",
"error.go", "error.go",
"light_client.go", "light_client.go",
"signed_execution_payload_bid.go",
"utils.go", "utils.go",
"validator.go", "validator.go",
], ],

View File

@@ -0,0 +1,28 @@
package interfaces
import (
field_params "github.com/OffchainLabs/prysm/v7/config/fieldparams"
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
)
type ROSignedExecutionPayloadBid interface {
Bid() (ROExecutionPayloadBid, error)
Signature() [field_params.BLSSignatureLength]byte
SigningRoot([]byte) ([32]byte, error)
IsNil() bool
}
type ROExecutionPayloadBid interface {
ParentBlockHash() [32]byte
ParentBlockRoot() [32]byte
PrevRandao() [32]byte
BlockHash() [32]byte
GasLimit() uint64
BuilderIndex() primitives.BuilderIndex
Slot() primitives.Slot
Value() primitives.Gwei
ExecutionPayment() primitives.Gwei
BlobKzgCommitmentsRoot() [32]byte
FeeRecipient() [20]byte
IsNil() bool
}

2
go.mod
View File

@@ -96,6 +96,7 @@ require (
google.golang.org/grpc v1.71.0 google.golang.org/grpc v1.71.0
google.golang.org/protobuf v1.36.5 google.golang.org/protobuf v1.36.5
gopkg.in/d4l3k/messagediff.v1 v1.2.1 gopkg.in/d4l3k/messagediff.v1 v1.2.1
gopkg.in/natefinch/lumberjack.v2 v2.2.1
gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
honnef.co/go/tools v0.6.0 honnef.co/go/tools v0.6.0
@@ -273,7 +274,6 @@ require (
golang.org/x/tools/go/expect v0.1.1-deprecated // indirect golang.org/x/tools/go/expect v0.1.1-deprecated // indirect
gopkg.in/cenkalti/backoff.v1 v1.1.0 // indirect gopkg.in/cenkalti/backoff.v1 v1.1.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
lukechampine.com/blake3 v1.3.0 // indirect lukechampine.com/blake3 v1.3.0 // indirect
rsc.io/tmplfunc v0.0.3 // indirect rsc.io/tmplfunc v0.0.3 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect

View File

@@ -17,7 +17,9 @@ go_library(
"//io/file:go_default_library", "//io/file:go_default_library",
"//runtime/logging/logrus-prefixed-formatter:go_default_library", "//runtime/logging/logrus-prefixed-formatter:go_default_library",
"@com_github_hashicorp_golang_lru//:go_default_library", "@com_github_hashicorp_golang_lru//:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library",
"@in_gopkg_natefinch_lumberjack_v2//:go_default_library",
], ],
) )
@@ -28,5 +30,8 @@ go_test(
"stream_test.go", "stream_test.go",
], ],
embed = [":go_default_library"], embed = [":go_default_library"],
deps = ["//testing/require:go_default_library"], deps = [
"//testing/require:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
],
) )

View File

@@ -12,16 +12,25 @@ import (
"github.com/OffchainLabs/prysm/v7/config/params" "github.com/OffchainLabs/prysm/v7/config/params"
"github.com/OffchainLabs/prysm/v7/io/file" "github.com/OffchainLabs/prysm/v7/io/file"
prefixed "github.com/OffchainLabs/prysm/v7/runtime/logging/logrus-prefixed-formatter" prefixed "github.com/OffchainLabs/prysm/v7/runtime/logging/logrus-prefixed-formatter"
"github.com/pkg/errors"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"gopkg.in/natefinch/lumberjack.v2"
) )
var ephemeralLogFileVerbosity = logrus.DebugLevel
// SetLoggingLevel sets the base logging level for logrus.
func SetLoggingLevel(lvl logrus.Level) {
logrus.SetLevel(max(lvl, ephemeralLogFileVerbosity))
}
func addLogWriter(w io.Writer) { func addLogWriter(w io.Writer) {
mw := io.MultiWriter(logrus.StandardLogger().Out, w) mw := io.MultiWriter(logrus.StandardLogger().Out, w)
logrus.SetOutput(mw) logrus.SetOutput(mw)
} }
// ConfigurePersistentLogging adds a log-to-file writer. File content is identical to stdout. // ConfigurePersistentLogging adds a log-to-file writer. File content is identical to stdout.
func ConfigurePersistentLogging(logFileName string, format string) error { func ConfigurePersistentLogging(logFileName string, format string, lvl logrus.Level) error {
logrus.WithField("logFileName", logFileName).Info("Logs will be made persistent") logrus.WithField("logFileName", logFileName).Info("Logs will be made persistent")
if err := file.MkdirAll(filepath.Dir(logFileName)); err != nil { if err := file.MkdirAll(filepath.Dir(logFileName)); err != nil {
return err return err
@@ -47,14 +56,48 @@ func ConfigurePersistentLogging(logFileName string, format string) error {
formatter.DisableColors = true formatter.DisableColors = true
logrus.AddHook(&WriterHook{ logrus.AddHook(&WriterHook{
Formatter: formatter, Formatter: formatter,
Writer: f, Writer: f,
AllowedLevels: logrus.AllLevels[:lvl+1],
}) })
logrus.Info("File logging initialized") logrus.Info("File logging initialized")
return nil return nil
} }
// ConfigureEphemeralLogFile adds a log file that keeps 24 hours of logs with >debug verbosity.
func ConfigureEphemeralLogFile(datadirPath string, app string) error {
logFilePath := filepath.Join(datadirPath, "logs", app+".log")
if err := file.MkdirAll(filepath.Dir(logFilePath)); err != nil {
return errors.Wrap(err, "failed to create directory")
}
// Create formatter and writer hook
formatter := new(prefixed.TextFormatter)
formatter.TimestampFormat = "2006-01-02 15:04:05.00"
formatter.FullTimestamp = true
// If persistent log files are written - we disable the log messages coloring because
// the colors are ANSI codes and seen as gibberish in the log files.
formatter.DisableColors = true
// configure the lumberjack log writer to rotate logs every ~24 hours
debugWriter := &lumberjack.Logger{
Filename: logFilePath,
MaxSize: 250, // MB, to avoid unbounded growth
MaxBackups: 1, // one backup in case of size-based rotations
MaxAge: 1, // days; files older than this are removed
}
logrus.AddHook(&WriterHook{
Formatter: formatter,
Writer: debugWriter,
AllowedLevels: logrus.AllLevels[:ephemeralLogFileVerbosity+1],
})
logrus.Info("Ephemeral log file initialized")
return nil
}
// MaskCredentialsLogging masks the url credentials before logging for security purpose // MaskCredentialsLogging masks the url credentials before logging for security purpose
// [scheme:][//[userinfo@]host][/]path[?query][#fragment] --> [scheme:][//[***]host][/***][#***] // [scheme:][//[userinfo@]host][/]path[?query][#fragment] --> [scheme:][//[***]host][/***][#***]
// if the format is not matched nothing is done, string is returned as is. // if the format is not matched nothing is done, string is returned as is.

View File

@@ -6,6 +6,7 @@ import (
"testing" "testing"
"github.com/OffchainLabs/prysm/v7/testing/require" "github.com/OffchainLabs/prysm/v7/testing/require"
"github.com/sirupsen/logrus"
) )
var urltests = []struct { var urltests = []struct {
@@ -34,13 +35,13 @@ func TestConfigurePersistantLogging(t *testing.T) {
logFileName := "test.log" logFileName := "test.log"
existingDirectory := "test-1-existing-testing-dir" existingDirectory := "test-1-existing-testing-dir"
err := ConfigurePersistentLogging(fmt.Sprintf("%s/%s/%s", testParentDir, existingDirectory, logFileName), "text") err := ConfigurePersistentLogging(fmt.Sprintf("%s/%s/%s", testParentDir, existingDirectory, logFileName), "text", logrus.InfoLevel)
require.NoError(t, err) require.NoError(t, err)
// 2. Test creation of file along with parent directory // 2. Test creation of file along with parent directory
nonExistingDirectory := "test-2-non-existing-testing-dir" nonExistingDirectory := "test-2-non-existing-testing-dir"
err = ConfigurePersistentLogging(fmt.Sprintf("%s/%s/%s", testParentDir, nonExistingDirectory, logFileName), "text") err = ConfigurePersistentLogging(fmt.Sprintf("%s/%s/%s", testParentDir, nonExistingDirectory, logFileName), "text", logrus.InfoLevel)
require.NoError(t, err) require.NoError(t, err)
// 3. Test creation of file in an existing parent directory with a non-existing sub-directory // 3. Test creation of file in an existing parent directory with a non-existing sub-directory
@@ -51,7 +52,7 @@ func TestConfigurePersistantLogging(t *testing.T) {
return return
} }
err = ConfigurePersistentLogging(fmt.Sprintf("%s/%s/%s/%s", testParentDir, existingDirectory, nonExistingSubDirectory, logFileName), "text") err = ConfigurePersistentLogging(fmt.Sprintf("%s/%s/%s/%s", testParentDir, existingDirectory, nonExistingSubDirectory, logFileName), "text", logrus.InfoLevel)
require.NoError(t, err) require.NoError(t, err)
//4. Create log file in a directory without 700 permissions //4. Create log file in a directory without 700 permissions
@@ -61,3 +62,38 @@ func TestConfigurePersistantLogging(t *testing.T) {
return return
} }
} }
func TestConfigureEphemeralLogFile(t *testing.T) {
testParentDir := t.TempDir()
// 1. Test creation of file in an existing parent directory
existingDirectory := "test-1-existing-testing-dir"
err := ConfigureEphemeralLogFile(fmt.Sprintf("%s/%s", testParentDir, existingDirectory), "beacon-chain")
require.NoError(t, err)
// 2. Test creation of file along with parent directory
nonExistingDirectory := "test-2-non-existing-testing-dir"
err = ConfigureEphemeralLogFile(fmt.Sprintf("%s/%s", testParentDir, nonExistingDirectory), "beacon-chain")
require.NoError(t, err)
// 3. Test creation of file in an existing parent directory with a non-existing sub-directory
existingDirectory = "test-3-existing-testing-dir"
nonExistingSubDirectory := "test-3-non-existing-sub-dir"
err = os.Mkdir(fmt.Sprintf("%s/%s", testParentDir, existingDirectory), 0700)
if err != nil {
return
}
err = ConfigureEphemeralLogFile(fmt.Sprintf("%s/%s/%s", testParentDir, existingDirectory, nonExistingSubDirectory), "beacon-chain")
require.NoError(t, err)
//4. Create log file in a directory without 700 permissions
existingDirectory = "test-4-existing-testing-dir"
err = os.Mkdir(fmt.Sprintf("%s/%s", testParentDir, existingDirectory), 0750)
if err != nil {
return
}
err = ConfigureEphemeralLogFile(fmt.Sprintf("%s/%s/%s", testParentDir, existingDirectory, nonExistingSubDirectory), "beacon-chain")
require.NoError(t, err)
}

View File

@@ -35,6 +35,21 @@ func CopyValidator(val *Validator) *Validator {
} }
} }
// CopyBuilder copies the provided builder.
func CopyBuilder(builder *Builder) *Builder {
if builder == nil {
return nil
}
return &Builder{
Pubkey: bytesutil.SafeCopyBytes(builder.Pubkey),
Version: bytesutil.SafeCopyBytes(builder.Version),
ExecutionAddress: bytesutil.SafeCopyBytes(builder.ExecutionAddress),
Balance: builder.Balance,
DepositEpoch: builder.DepositEpoch,
WithdrawableEpoch: builder.WithdrawableEpoch,
}
}
// CopySyncCommitteeMessage copies the provided sync committee message object. // CopySyncCommitteeMessage copies the provided sync committee message object.
func CopySyncCommitteeMessage(s *SyncCommitteeMessage) *SyncCommitteeMessage { func CopySyncCommitteeMessage(s *SyncCommitteeMessage) *SyncCommitteeMessage {
if s == nil { if s == nil {
@@ -174,3 +189,28 @@ func copyBeaconBlockBodyGloas(body *BeaconBlockBodyGloas) *BeaconBlockBodyGloas
return copied return copied
} }
// CopyBuilderPendingPayment creates a deep copy of a builder pending payment.
func CopyBuilderPendingPayment(original *BuilderPendingPayment) *BuilderPendingPayment {
if original == nil {
return nil
}
return &BuilderPendingPayment{
Weight: original.Weight,
Withdrawal: CopyBuilderPendingWithdrawal(original.Withdrawal),
}
}
// CopyBuilderPendingWithdrawal creates a deep copy of a builder pending withdrawal.
func CopyBuilderPendingWithdrawal(original *BuilderPendingWithdrawal) *BuilderPendingWithdrawal {
if original == nil {
return nil
}
return &BuilderPendingWithdrawal{
FeeRecipient: bytesutil.SafeCopyBytes(original.FeeRecipient),
Amount: original.Amount,
BuilderIndex: original.BuilderIndex,
}
}

View File

@@ -1220,7 +1220,7 @@ func genExecutionPayloadBidGloas() *v1alpha1.ExecutionPayloadBid {
BlockHash: bytes(32), BlockHash: bytes(32),
FeeRecipient: bytes(20), FeeRecipient: bytes(20),
GasLimit: rand.Uint64(), GasLimit: rand.Uint64(),
BuilderIndex: primitives.ValidatorIndex(rand.Uint64()), BuilderIndex: primitives.BuilderIndex(rand.Uint64()),
Slot: primitives.Slot(rand.Uint64()), Slot: primitives.Slot(rand.Uint64()),
Value: primitives.Gwei(rand.Uint64()), Value: primitives.Gwei(rand.Uint64()),
BlobKzgCommitmentsRoot: bytes(32), BlobKzgCommitmentsRoot: bytes(32),
@@ -1246,3 +1246,89 @@ func genPayloadAttestations(num int) []*v1alpha1.PayloadAttestation {
} }
return pas return pas
} }
func TestCopyBuilderPendingWithdrawal(t *testing.T) {
t.Run("nil returns nil", func(t *testing.T) {
if got := v1alpha1.CopyBuilderPendingWithdrawal(nil); got != nil {
t.Fatalf("CopyBuilderPendingWithdrawal(nil) = %v, want nil", got)
}
})
t.Run("deep copy", func(t *testing.T) {
original := &v1alpha1.BuilderPendingWithdrawal{
FeeRecipient: []byte{0x01, 0x02},
Amount: primitives.Gwei(10),
BuilderIndex: primitives.BuilderIndex(3),
}
copied := v1alpha1.CopyBuilderPendingWithdrawal(original)
if copied == original {
t.Fatalf("expected new pointer for withdrawal copy")
}
if !reflect.DeepEqual(copied, original) {
t.Fatalf("CopyBuilderPendingWithdrawal() = %v, want %v", copied, original)
}
original.FeeRecipient[0] = 0xFF
original.Amount = primitives.Gwei(20)
original.BuilderIndex = primitives.BuilderIndex(9)
if copied.FeeRecipient[0] == original.FeeRecipient[0] {
t.Fatalf("fee recipient was not deep copied")
}
if copied.Amount != primitives.Gwei(10) {
t.Fatalf("amount mutated on copy: %d", copied.Amount)
}
if copied.BuilderIndex != primitives.BuilderIndex(3) {
t.Fatalf("builder index mutated on copy: %d", copied.BuilderIndex)
}
})
}
func TestCopyBuilderPendingPayment(t *testing.T) {
t.Run("nil returns nil", func(t *testing.T) {
if got := v1alpha1.CopyBuilderPendingPayment(nil); got != nil {
t.Fatalf("CopyBuilderPendingPayment(nil) = %v, want nil", got)
}
})
t.Run("deep copy", func(t *testing.T) {
original := &v1alpha1.BuilderPendingPayment{
Weight: primitives.Gwei(5),
Withdrawal: &v1alpha1.BuilderPendingWithdrawal{
FeeRecipient: []byte{0x0A, 0x0B},
Amount: primitives.Gwei(50),
BuilderIndex: primitives.BuilderIndex(7),
},
}
copied := v1alpha1.CopyBuilderPendingPayment(original)
if copied == original {
t.Fatalf("expected new pointer for payment copy")
}
if copied.Withdrawal == original.Withdrawal {
t.Fatalf("expected nested withdrawal to be deep copied")
}
if !reflect.DeepEqual(copied, original) {
t.Fatalf("CopyBuilderPendingPayment() = %v, want %v", copied, original)
}
original.Weight = primitives.Gwei(10)
original.Withdrawal.FeeRecipient[0] = 0xFF
original.Withdrawal.Amount = primitives.Gwei(75)
original.Withdrawal.BuilderIndex = primitives.BuilderIndex(9)
if copied.Weight != primitives.Gwei(5) {
t.Fatalf("weight mutated on copy: %d", copied.Weight)
}
if copied.Withdrawal.FeeRecipient[0] == original.Withdrawal.FeeRecipient[0] {
t.Fatalf("withdrawal fee recipient was not deep copied")
}
if copied.Withdrawal.Amount != primitives.Gwei(50) {
t.Fatalf("withdrawal amount mutated on copy: %d", copied.Withdrawal.Amount)
}
if copied.Withdrawal.BuilderIndex != primitives.BuilderIndex(7) {
t.Fatalf("withdrawal builder index mutated on copy: %d", copied.Withdrawal.BuilderIndex)
}
})
}

View File

@@ -13,11 +13,13 @@ func (header *ExecutionPayloadBid) Copy() *ExecutionPayloadBid {
ParentBlockHash: bytesutil.SafeCopyBytes(header.ParentBlockHash), ParentBlockHash: bytesutil.SafeCopyBytes(header.ParentBlockHash),
ParentBlockRoot: bytesutil.SafeCopyBytes(header.ParentBlockRoot), ParentBlockRoot: bytesutil.SafeCopyBytes(header.ParentBlockRoot),
BlockHash: bytesutil.SafeCopyBytes(header.BlockHash), BlockHash: bytesutil.SafeCopyBytes(header.BlockHash),
PrevRandao: bytesutil.SafeCopyBytes(header.PrevRandao),
FeeRecipient: bytesutil.SafeCopyBytes(header.FeeRecipient), FeeRecipient: bytesutil.SafeCopyBytes(header.FeeRecipient),
GasLimit: header.GasLimit, GasLimit: header.GasLimit,
BuilderIndex: header.BuilderIndex, BuilderIndex: header.BuilderIndex,
Slot: header.Slot, Slot: header.Slot,
Value: header.Value, Value: header.Value,
ExecutionPayment: header.ExecutionPayment,
BlobKzgCommitmentsRoot: bytesutil.SafeCopyBytes(header.BlobKzgCommitmentsRoot), BlobKzgCommitmentsRoot: bytesutil.SafeCopyBytes(header.BlobKzgCommitmentsRoot),
} }
} }
@@ -28,10 +30,9 @@ func (withdrawal *BuilderPendingWithdrawal) Copy() *BuilderPendingWithdrawal {
return nil return nil
} }
return &BuilderPendingWithdrawal{ return &BuilderPendingWithdrawal{
FeeRecipient: bytesutil.SafeCopyBytes(withdrawal.FeeRecipient), FeeRecipient: bytesutil.SafeCopyBytes(withdrawal.FeeRecipient),
Amount: withdrawal.Amount, Amount: withdrawal.Amount,
BuilderIndex: withdrawal.BuilderIndex, BuilderIndex: withdrawal.BuilderIndex,
WithdrawableEpoch: withdrawal.WithdrawableEpoch,
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -26,30 +26,37 @@ option go_package = "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1;eth";
// parent_block_hash: Hash32 // parent_block_hash: Hash32
// parent_block_root: Root // parent_block_root: Root
// block_hash: Hash32 // block_hash: Hash32
// prev_randao: Bytes32
// fee_recipient: ExecutionAddress // fee_recipient: ExecutionAddress
// gas_limit: uint64 // gas_limit: uint64
// builder_index: ValidatorIndex // builder_index: BuilderIndex
// slot: Slot // slot: Slot
// value: Gwei // value: Gwei
// execution_payment: Gwei
// blob_kzg_commitments_root: Root // blob_kzg_commitments_root: Root
message ExecutionPayloadBid { message ExecutionPayloadBid {
bytes parent_block_hash = 1 [ (ethereum.eth.ext.ssz_size) = "32" ]; bytes parent_block_hash = 1 [ (ethereum.eth.ext.ssz_size) = "32" ];
bytes parent_block_root = 2 [ (ethereum.eth.ext.ssz_size) = "32" ]; bytes parent_block_root = 2 [ (ethereum.eth.ext.ssz_size) = "32" ];
bytes block_hash = 3 [ (ethereum.eth.ext.ssz_size) = "32" ]; bytes block_hash = 3 [ (ethereum.eth.ext.ssz_size) = "32" ];
bytes fee_recipient = 4 [ (ethereum.eth.ext.ssz_size) = "20" ]; bytes prev_randao = 4 [ (ethereum.eth.ext.ssz_size) = "32" ];
uint64 gas_limit = 5; bytes fee_recipient = 5 [ (ethereum.eth.ext.ssz_size) = "20" ];
uint64 builder_index = 6 [ (ethereum.eth.ext.cast_type) = uint64 gas_limit = 6;
uint64 builder_index = 7 [ (ethereum.eth.ext.cast_type) =
"github.com/OffchainLabs/prysm/v7/" "github.com/OffchainLabs/prysm/v7/"
"consensus-types/primitives.ValidatorIndex" ]; "consensus-types/primitives.BuilderIndex" ];
uint64 slot = 7 [ uint64 slot = 8 [
(ethereum.eth.ext.cast_type) = (ethereum.eth.ext.cast_type) =
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives.Slot" "github.com/OffchainLabs/prysm/v7/consensus-types/primitives.Slot"
]; ];
uint64 value = 8 [ uint64 value = 9 [
(ethereum.eth.ext.cast_type) = (ethereum.eth.ext.cast_type) =
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives.Gwei" "github.com/OffchainLabs/prysm/v7/consensus-types/primitives.Gwei"
]; ];
bytes blob_kzg_commitments_root = 9 [ (ethereum.eth.ext.ssz_size) = "32" ]; uint64 execution_payment = 10 [
(ethereum.eth.ext.cast_type) =
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives.Gwei"
];
bytes blob_kzg_commitments_root = 11 [ (ethereum.eth.ext.ssz_size) = "32" ];
} }
// SignedExecutionPayloadBid wraps an execution payload bid with a signature. // SignedExecutionPayloadBid wraps an execution payload bid with a signature.
@@ -185,12 +192,15 @@ message SignedBeaconBlockGloas {
// [All previous fields from earlier forks] // [All previous fields from earlier forks]
// # Replaced existing latest execution header position // # Replaced existing latest execution header position
// latest_execution_payload_bid: ExecutionPayloadBid // latest_execution_payload_bid: ExecutionPayloadBid
// # New fields in Gloas:EIP7732 // builders: List[Builder, BUILDER_REGISTRY_LIMIT]
// # [New in Gloas:EIP7732]
// next_withdrawal_builder_index: BuilderIndex
// # [New in Gloas:EIP7732]
// execution_payload_availability: Bitvector[SLOTS_PER_HISTORICAL_ROOT] // execution_payload_availability: Bitvector[SLOTS_PER_HISTORICAL_ROOT]
// builder_pending_payments: Vector[BuilderPendingPayment, 2 * SLOTS_PER_EPOCH] // builder_pending_payments: Vector[BuilderPendingPayment, 2 * SLOTS_PER_EPOCH]
// builder_pending_withdrawals: List[BuilderPendingWithdrawal, BUILDER_PENDING_WITHDRAWALS_LIMIT] // builder_pending_withdrawals: List[BuilderPendingWithdrawal, BUILDER_PENDING_WITHDRAWALS_LIMIT]
// latest_block_hash: Hash32 // latest_block_hash: Hash32
// latest_withdrawals_root: Root // payload_expected_withdrawals: List[Withdrawal, MAX_WITHDRAWALS_PER_PAYLOAD]
message BeaconStateGloas { message BeaconStateGloas {
// Versioning [1001-2000] // Versioning [1001-2000]
uint64 genesis_time = 1001; uint64 genesis_time = 1001;
@@ -300,13 +310,20 @@ message BeaconStateGloas {
[ (ethereum.eth.ext.ssz_size) = "proposer_lookahead_size" ]; [ (ethereum.eth.ext.ssz_size) = "proposer_lookahead_size" ];
// Fields introduced in Gloas fork [14001-15000] // Fields introduced in Gloas fork [14001-15000]
bytes execution_payload_availability = 14001 [ repeated Builder builders = 14001
[ (ethereum.eth.ext.ssz_max) = "builder_registry_limit" ];
uint64 next_withdrawal_builder_index = 14002
[ (ethereum.eth.ext.cast_type) =
"github.com/OffchainLabs/prysm/v7/consensus-types/"
"primitives.BuilderIndex" ];
bytes execution_payload_availability = 14003 [
(ethereum.eth.ext.ssz_size) = "execution_payload_availability.size" (ethereum.eth.ext.ssz_size) = "execution_payload_availability.size"
]; ];
repeated BuilderPendingPayment builder_pending_payments = 14002 [(ethereum.eth.ext.ssz_size) = "builder_pending_payments.size"]; repeated BuilderPendingPayment builder_pending_payments = 14004 [(ethereum.eth.ext.ssz_size) = "builder_pending_payments.size"];
repeated BuilderPendingWithdrawal builder_pending_withdrawals = 14003 [(ethereum.eth.ext.ssz_max) = "1048576"]; repeated BuilderPendingWithdrawal builder_pending_withdrawals = 14005 [(ethereum.eth.ext.ssz_max) = "1048576"];
bytes latest_block_hash = 14004 [ (ethereum.eth.ext.ssz_size) = "32" ]; bytes latest_block_hash = 14006 [ (ethereum.eth.ext.ssz_size) = "32" ];
bytes latest_withdrawals_root = 14005 [ (ethereum.eth.ext.ssz_size) = "32" ]; repeated ethereum.engine.v1.Withdrawal payload_expected_withdrawals = 14007
[ (ethereum.eth.ext.ssz_max) = "withdrawal.size" ];
} }
// BuilderPendingPayment represents a pending payment to a builder. // BuilderPendingPayment represents a pending payment to a builder.
@@ -329,8 +346,7 @@ message BuilderPendingPayment {
// class BuilderPendingWithdrawal(Container): // class BuilderPendingWithdrawal(Container):
// fee_recipient: ExecutionAddress // fee_recipient: ExecutionAddress
// amount: Gwei // amount: Gwei
// builder_index: ValidatorIndex // builder_index: BuilderIndex
// withdrawable_epoch: Epoch
message BuilderPendingWithdrawal { message BuilderPendingWithdrawal {
bytes fee_recipient = 1 [ (ethereum.eth.ext.ssz_size) = "20" ]; bytes fee_recipient = 1 [ (ethereum.eth.ext.ssz_size) = "20" ];
uint64 amount = 2 [ uint64 amount = 2 [
@@ -340,11 +356,7 @@ message BuilderPendingWithdrawal {
uint64 builder_index = 3 uint64 builder_index = 3
[ (ethereum.eth.ext.cast_type) = [ (ethereum.eth.ext.cast_type) =
"github.com/OffchainLabs/prysm/v7/consensus-types/" "github.com/OffchainLabs/prysm/v7/consensus-types/"
"primitives.ValidatorIndex" ]; "primitives.BuilderIndex" ];
uint64 withdrawable_epoch = 4 [
(ethereum.eth.ext.cast_type) =
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives.Epoch"
];
} }
// DataColumnSidecarGloas represents a data column sidecar in the Gloas fork. // DataColumnSidecarGloas represents a data column sidecar in the Gloas fork.
@@ -387,7 +399,7 @@ message DataColumnSidecarGloas {
// class ExecutionPayloadEnvelope(Container): // class ExecutionPayloadEnvelope(Container):
// payload: ExecutionPayload // payload: ExecutionPayload
// execution_requests: ExecutionRequests // execution_requests: ExecutionRequests
// builder_index: ValidatorIndex // builder_index: BuilderIndex
// beacon_block_root: Root // beacon_block_root: Root
// slot: Slot // slot: Slot
// blob_kzg_commitments: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK] // blob_kzg_commitments: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK]
@@ -397,7 +409,7 @@ message ExecutionPayloadEnvelope {
ethereum.engine.v1.ExecutionRequests execution_requests = 2; ethereum.engine.v1.ExecutionRequests execution_requests = 2;
uint64 builder_index = 3 [ (ethereum.eth.ext.cast_type) = uint64 builder_index = 3 [ (ethereum.eth.ext.cast_type) =
"github.com/OffchainLabs/prysm/v7/" "github.com/OffchainLabs/prysm/v7/"
"consensus-types/primitives.ValidatorIndex" ]; "consensus-types/primitives.BuilderIndex" ];
bytes beacon_block_root = 4 [ (ethereum.eth.ext.ssz_size) = "32" ]; bytes beacon_block_root = 4 [ (ethereum.eth.ext.ssz_size) = "32" ];
uint64 slot = 5 [ uint64 slot = 5 [
(ethereum.eth.ext.cast_type) = (ethereum.eth.ext.cast_type) =
@@ -421,3 +433,31 @@ message SignedExecutionPayloadEnvelope {
ExecutionPayloadEnvelope message = 1; ExecutionPayloadEnvelope message = 1;
bytes signature = 2 [ (ethereum.eth.ext.ssz_size) = "96" ]; bytes signature = 2 [ (ethereum.eth.ext.ssz_size) = "96" ];
} }
// Builder represents a builder in the Gloas fork.
//
// Spec:
// class Builder(Container):
// pubkey: BLSPubkey
// version: uint8
// execution_address: ExecutionAddress
// balance: Gwei
// deposit_epoch: Epoch
// withdrawable_epoch: Epoch
message Builder {
bytes pubkey = 1 [ (ethereum.eth.ext.ssz_size) = "48" ];
bytes version = 2 [ (ethereum.eth.ext.ssz_size) = "1" ];
bytes execution_address = 3 [ (ethereum.eth.ext.ssz_size) = "20" ];
uint64 balance = 4 [
(ethereum.eth.ext.cast_type) =
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives.Gwei"
];
uint64 deposit_epoch = 5 [
(ethereum.eth.ext.cast_type) =
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives.Epoch"
];
uint64 withdrawable_epoch = 6 [
(ethereum.eth.ext.cast_type) =
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives.Epoch"
];
}

View File

@@ -37,26 +37,36 @@ func (e *ExecutionPayloadBid) MarshalSSZTo(buf []byte) (dst []byte, err error) {
} }
dst = append(dst, e.BlockHash...) dst = append(dst, e.BlockHash...)
// Field (3) 'FeeRecipient' // Field (3) 'PrevRandao'
if size := len(e.PrevRandao); size != 32 {
err = ssz.ErrBytesLengthFn("--.PrevRandao", size, 32)
return
}
dst = append(dst, e.PrevRandao...)
// Field (4) 'FeeRecipient'
if size := len(e.FeeRecipient); size != 20 { if size := len(e.FeeRecipient); size != 20 {
err = ssz.ErrBytesLengthFn("--.FeeRecipient", size, 20) err = ssz.ErrBytesLengthFn("--.FeeRecipient", size, 20)
return return
} }
dst = append(dst, e.FeeRecipient...) dst = append(dst, e.FeeRecipient...)
// Field (4) 'GasLimit' // Field (5) 'GasLimit'
dst = ssz.MarshalUint64(dst, e.GasLimit) dst = ssz.MarshalUint64(dst, e.GasLimit)
// Field (5) 'BuilderIndex' // Field (6) 'BuilderIndex'
dst = ssz.MarshalUint64(dst, uint64(e.BuilderIndex)) dst = ssz.MarshalUint64(dst, uint64(e.BuilderIndex))
// Field (6) 'Slot' // Field (7) 'Slot'
dst = ssz.MarshalUint64(dst, uint64(e.Slot)) dst = ssz.MarshalUint64(dst, uint64(e.Slot))
// Field (7) 'Value' // Field (8) 'Value'
dst = ssz.MarshalUint64(dst, uint64(e.Value)) dst = ssz.MarshalUint64(dst, uint64(e.Value))
// Field (8) 'BlobKzgCommitmentsRoot' // Field (9) 'ExecutionPayment'
dst = ssz.MarshalUint64(dst, uint64(e.ExecutionPayment))
// Field (10) 'BlobKzgCommitmentsRoot'
if size := len(e.BlobKzgCommitmentsRoot); size != 32 { if size := len(e.BlobKzgCommitmentsRoot); size != 32 {
err = ssz.ErrBytesLengthFn("--.BlobKzgCommitmentsRoot", size, 32) err = ssz.ErrBytesLengthFn("--.BlobKzgCommitmentsRoot", size, 32)
return return
@@ -70,7 +80,7 @@ func (e *ExecutionPayloadBid) MarshalSSZTo(buf []byte) (dst []byte, err error) {
func (e *ExecutionPayloadBid) UnmarshalSSZ(buf []byte) error { func (e *ExecutionPayloadBid) UnmarshalSSZ(buf []byte) error {
var err error var err error
size := uint64(len(buf)) size := uint64(len(buf))
if size != 180 { if size != 220 {
return ssz.ErrSize return ssz.ErrSize
} }
@@ -92,36 +102,45 @@ func (e *ExecutionPayloadBid) UnmarshalSSZ(buf []byte) error {
} }
e.BlockHash = append(e.BlockHash, buf[64:96]...) e.BlockHash = append(e.BlockHash, buf[64:96]...)
// Field (3) 'FeeRecipient' // Field (3) 'PrevRandao'
if cap(e.PrevRandao) == 0 {
e.PrevRandao = make([]byte, 0, len(buf[96:128]))
}
e.PrevRandao = append(e.PrevRandao, buf[96:128]...)
// Field (4) 'FeeRecipient'
if cap(e.FeeRecipient) == 0 { if cap(e.FeeRecipient) == 0 {
e.FeeRecipient = make([]byte, 0, len(buf[96:116])) e.FeeRecipient = make([]byte, 0, len(buf[128:148]))
} }
e.FeeRecipient = append(e.FeeRecipient, buf[96:116]...) e.FeeRecipient = append(e.FeeRecipient, buf[128:148]...)
// Field (4) 'GasLimit' // Field (5) 'GasLimit'
e.GasLimit = ssz.UnmarshallUint64(buf[116:124]) e.GasLimit = ssz.UnmarshallUint64(buf[148:156])
// Field (5) 'BuilderIndex' // Field (6) 'BuilderIndex'
e.BuilderIndex = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[124:132])) e.BuilderIndex = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.BuilderIndex(ssz.UnmarshallUint64(buf[156:164]))
// Field (6) 'Slot' // Field (7) 'Slot'
e.Slot = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[132:140])) e.Slot = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[164:172]))
// Field (7) 'Value' // Field (8) 'Value'
e.Value = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Gwei(ssz.UnmarshallUint64(buf[140:148])) e.Value = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Gwei(ssz.UnmarshallUint64(buf[172:180]))
// Field (8) 'BlobKzgCommitmentsRoot' // Field (9) 'ExecutionPayment'
e.ExecutionPayment = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Gwei(ssz.UnmarshallUint64(buf[180:188]))
// Field (10) 'BlobKzgCommitmentsRoot'
if cap(e.BlobKzgCommitmentsRoot) == 0 { if cap(e.BlobKzgCommitmentsRoot) == 0 {
e.BlobKzgCommitmentsRoot = make([]byte, 0, len(buf[148:180])) e.BlobKzgCommitmentsRoot = make([]byte, 0, len(buf[188:220]))
} }
e.BlobKzgCommitmentsRoot = append(e.BlobKzgCommitmentsRoot, buf[148:180]...) e.BlobKzgCommitmentsRoot = append(e.BlobKzgCommitmentsRoot, buf[188:220]...)
return err return err
} }
// SizeSSZ returns the ssz encoded size in bytes for the ExecutionPayloadBid object // SizeSSZ returns the ssz encoded size in bytes for the ExecutionPayloadBid object
func (e *ExecutionPayloadBid) SizeSSZ() (size int) { func (e *ExecutionPayloadBid) SizeSSZ() (size int) {
size = 180 size = 220
return return
} }
@@ -155,26 +174,36 @@ func (e *ExecutionPayloadBid) HashTreeRootWith(hh *ssz.Hasher) (err error) {
} }
hh.PutBytes(e.BlockHash) hh.PutBytes(e.BlockHash)
// Field (3) 'FeeRecipient' // Field (3) 'PrevRandao'
if size := len(e.PrevRandao); size != 32 {
err = ssz.ErrBytesLengthFn("--.PrevRandao", size, 32)
return
}
hh.PutBytes(e.PrevRandao)
// Field (4) 'FeeRecipient'
if size := len(e.FeeRecipient); size != 20 { if size := len(e.FeeRecipient); size != 20 {
err = ssz.ErrBytesLengthFn("--.FeeRecipient", size, 20) err = ssz.ErrBytesLengthFn("--.FeeRecipient", size, 20)
return return
} }
hh.PutBytes(e.FeeRecipient) hh.PutBytes(e.FeeRecipient)
// Field (4) 'GasLimit' // Field (5) 'GasLimit'
hh.PutUint64(e.GasLimit) hh.PutUint64(e.GasLimit)
// Field (5) 'BuilderIndex' // Field (6) 'BuilderIndex'
hh.PutUint64(uint64(e.BuilderIndex)) hh.PutUint64(uint64(e.BuilderIndex))
// Field (6) 'Slot' // Field (7) 'Slot'
hh.PutUint64(uint64(e.Slot)) hh.PutUint64(uint64(e.Slot))
// Field (7) 'Value' // Field (8) 'Value'
hh.PutUint64(uint64(e.Value)) hh.PutUint64(uint64(e.Value))
// Field (8) 'BlobKzgCommitmentsRoot' // Field (9) 'ExecutionPayment'
hh.PutUint64(uint64(e.ExecutionPayment))
// Field (10) 'BlobKzgCommitmentsRoot'
if size := len(e.BlobKzgCommitmentsRoot); size != 32 { if size := len(e.BlobKzgCommitmentsRoot); size != 32 {
err = ssz.ErrBytesLengthFn("--.BlobKzgCommitmentsRoot", size, 32) err = ssz.ErrBytesLengthFn("--.BlobKzgCommitmentsRoot", size, 32)
return return
@@ -216,7 +245,7 @@ func (s *SignedExecutionPayloadBid) MarshalSSZTo(buf []byte) (dst []byte, err er
func (s *SignedExecutionPayloadBid) UnmarshalSSZ(buf []byte) error { func (s *SignedExecutionPayloadBid) UnmarshalSSZ(buf []byte) error {
var err error var err error
size := uint64(len(buf)) size := uint64(len(buf))
if size != 276 { if size != 316 {
return ssz.ErrSize return ssz.ErrSize
} }
@@ -224,22 +253,22 @@ func (s *SignedExecutionPayloadBid) UnmarshalSSZ(buf []byte) error {
if s.Message == nil { if s.Message == nil {
s.Message = new(ExecutionPayloadBid) s.Message = new(ExecutionPayloadBid)
} }
if err = s.Message.UnmarshalSSZ(buf[0:180]); err != nil { if err = s.Message.UnmarshalSSZ(buf[0:220]); err != nil {
return err return err
} }
// Field (1) 'Signature' // Field (1) 'Signature'
if cap(s.Signature) == 0 { if cap(s.Signature) == 0 {
s.Signature = make([]byte, 0, len(buf[180:276])) s.Signature = make([]byte, 0, len(buf[220:316]))
} }
s.Signature = append(s.Signature, buf[180:276]...) s.Signature = append(s.Signature, buf[220:316]...)
return err return err
} }
// SizeSSZ returns the ssz encoded size in bytes for the SignedExecutionPayloadBid object // SizeSSZ returns the ssz encoded size in bytes for the SignedExecutionPayloadBid object
func (s *SignedExecutionPayloadBid) SizeSSZ() (size int) { func (s *SignedExecutionPayloadBid) SizeSSZ() (size int) {
size = 276 size = 316
return return
} }
@@ -713,7 +742,7 @@ func (b *BeaconBlockBodyGloas) MarshalSSZ() ([]byte, error) {
// MarshalSSZTo ssz marshals the BeaconBlockBodyGloas object to a target array // MarshalSSZTo ssz marshals the BeaconBlockBodyGloas object to a target array
func (b *BeaconBlockBodyGloas) MarshalSSZTo(buf []byte) (dst []byte, err error) { func (b *BeaconBlockBodyGloas) MarshalSSZTo(buf []byte) (dst []byte, err error) {
dst = buf dst = buf
offset := int(664) offset := int(704)
// Field (0) 'RandaoReveal' // Field (0) 'RandaoReveal'
if size := len(b.RandaoReveal); size != 96 { if size := len(b.RandaoReveal); size != 96 {
@@ -885,7 +914,7 @@ func (b *BeaconBlockBodyGloas) MarshalSSZTo(buf []byte) (dst []byte, err error)
func (b *BeaconBlockBodyGloas) UnmarshalSSZ(buf []byte) error { func (b *BeaconBlockBodyGloas) UnmarshalSSZ(buf []byte) error {
var err error var err error
size := uint64(len(buf)) size := uint64(len(buf))
if size < 664 { if size < 704 {
return ssz.ErrSize return ssz.ErrSize
} }
@@ -917,7 +946,7 @@ func (b *BeaconBlockBodyGloas) UnmarshalSSZ(buf []byte) error {
return ssz.ErrOffset return ssz.ErrOffset
} }
if o3 != 664 { if o3 != 704 {
return ssz.ErrInvalidVariableOffset return ssz.ErrInvalidVariableOffset
} }
@@ -958,12 +987,12 @@ func (b *BeaconBlockBodyGloas) UnmarshalSSZ(buf []byte) error {
if b.SignedExecutionPayloadBid == nil { if b.SignedExecutionPayloadBid == nil {
b.SignedExecutionPayloadBid = new(SignedExecutionPayloadBid) b.SignedExecutionPayloadBid = new(SignedExecutionPayloadBid)
} }
if err = b.SignedExecutionPayloadBid.UnmarshalSSZ(buf[384:660]); err != nil { if err = b.SignedExecutionPayloadBid.UnmarshalSSZ(buf[384:700]); err != nil {
return err return err
} }
// Offset (11) 'PayloadAttestations' // Offset (11) 'PayloadAttestations'
if o11 = ssz.ReadOffset(buf[660:664]); o11 > size || o9 > o11 { if o11 = ssz.ReadOffset(buf[700:704]); o11 > size || o9 > o11 {
return ssz.ErrOffset return ssz.ErrOffset
} }
@@ -1105,7 +1134,7 @@ func (b *BeaconBlockBodyGloas) UnmarshalSSZ(buf []byte) error {
// SizeSSZ returns the ssz encoded size in bytes for the BeaconBlockBodyGloas object // SizeSSZ returns the ssz encoded size in bytes for the BeaconBlockBodyGloas object
func (b *BeaconBlockBodyGloas) SizeSSZ() (size int) { func (b *BeaconBlockBodyGloas) SizeSSZ() (size int) {
size = 664 size = 704
// Field (3) 'ProposerSlashings' // Field (3) 'ProposerSlashings'
size += len(b.ProposerSlashings) * 416 size += len(b.ProposerSlashings) * 416
@@ -1408,7 +1437,7 @@ func (b *BeaconStateGloas) MarshalSSZ() ([]byte, error) {
// MarshalSSZTo ssz marshals the BeaconStateGloas object to a target array // MarshalSSZTo ssz marshals the BeaconStateGloas object to a target array
func (b *BeaconStateGloas) MarshalSSZTo(buf []byte) (dst []byte, err error) { func (b *BeaconStateGloas) MarshalSSZTo(buf []byte) (dst []byte, err error) {
dst = buf dst = buf
offset := int(2741821) offset := int(2741333)
// Field (0) 'GenesisTime' // Field (0) 'GenesisTime'
dst = ssz.MarshalUint64(dst, b.GenesisTime) dst = ssz.MarshalUint64(dst, b.GenesisTime)
@@ -1630,14 +1659,21 @@ func (b *BeaconStateGloas) MarshalSSZTo(buf []byte) (dst []byte, err error) {
dst = ssz.MarshalUint64(dst, b.ProposerLookahead[ii]) dst = ssz.MarshalUint64(dst, b.ProposerLookahead[ii])
} }
// Field (38) 'ExecutionPayloadAvailability' // Offset (38) 'Builders'
dst = ssz.WriteOffset(dst, offset)
offset += len(b.Builders) * 93
// Field (39) 'NextWithdrawalBuilderIndex'
dst = ssz.MarshalUint64(dst, uint64(b.NextWithdrawalBuilderIndex))
// Field (40) 'ExecutionPayloadAvailability'
if size := len(b.ExecutionPayloadAvailability); size != 1024 { if size := len(b.ExecutionPayloadAvailability); size != 1024 {
err = ssz.ErrBytesLengthFn("--.ExecutionPayloadAvailability", size, 1024) err = ssz.ErrBytesLengthFn("--.ExecutionPayloadAvailability", size, 1024)
return return
} }
dst = append(dst, b.ExecutionPayloadAvailability...) dst = append(dst, b.ExecutionPayloadAvailability...)
// Field (39) 'BuilderPendingPayments' // Field (41) 'BuilderPendingPayments'
if size := len(b.BuilderPendingPayments); size != 64 { if size := len(b.BuilderPendingPayments); size != 64 {
err = ssz.ErrVectorLengthFn("--.BuilderPendingPayments", size, 64) err = ssz.ErrVectorLengthFn("--.BuilderPendingPayments", size, 64)
return return
@@ -1648,23 +1684,20 @@ func (b *BeaconStateGloas) MarshalSSZTo(buf []byte) (dst []byte, err error) {
} }
} }
// Offset (40) 'BuilderPendingWithdrawals' // Offset (42) 'BuilderPendingWithdrawals'
dst = ssz.WriteOffset(dst, offset) dst = ssz.WriteOffset(dst, offset)
offset += len(b.BuilderPendingWithdrawals) * 44 offset += len(b.BuilderPendingWithdrawals) * 36
// Field (41) 'LatestBlockHash' // Field (43) 'LatestBlockHash'
if size := len(b.LatestBlockHash); size != 32 { if size := len(b.LatestBlockHash); size != 32 {
err = ssz.ErrBytesLengthFn("--.LatestBlockHash", size, 32) err = ssz.ErrBytesLengthFn("--.LatestBlockHash", size, 32)
return return
} }
dst = append(dst, b.LatestBlockHash...) dst = append(dst, b.LatestBlockHash...)
// Field (42) 'LatestWithdrawalsRoot' // Offset (44) 'PayloadExpectedWithdrawals'
if size := len(b.LatestWithdrawalsRoot); size != 32 { dst = ssz.WriteOffset(dst, offset)
err = ssz.ErrBytesLengthFn("--.LatestWithdrawalsRoot", size, 32) offset += len(b.PayloadExpectedWithdrawals) * 44
return
}
dst = append(dst, b.LatestWithdrawalsRoot...)
// Field (7) 'HistoricalRoots' // Field (7) 'HistoricalRoots'
if size := len(b.HistoricalRoots); size > 16777216 { if size := len(b.HistoricalRoots); size > 16777216 {
@@ -1777,7 +1810,18 @@ func (b *BeaconStateGloas) MarshalSSZTo(buf []byte) (dst []byte, err error) {
} }
} }
// Field (40) 'BuilderPendingWithdrawals' // Field (38) 'Builders'
if size := len(b.Builders); size > 1099511627776 {
err = ssz.ErrListTooBigFn("--.Builders", size, 1099511627776)
return
}
for ii := 0; ii < len(b.Builders); ii++ {
if dst, err = b.Builders[ii].MarshalSSZTo(dst); err != nil {
return
}
}
// Field (42) 'BuilderPendingWithdrawals'
if size := len(b.BuilderPendingWithdrawals); size > 1048576 { if size := len(b.BuilderPendingWithdrawals); size > 1048576 {
err = ssz.ErrListTooBigFn("--.BuilderPendingWithdrawals", size, 1048576) err = ssz.ErrListTooBigFn("--.BuilderPendingWithdrawals", size, 1048576)
return return
@@ -1788,6 +1832,17 @@ func (b *BeaconStateGloas) MarshalSSZTo(buf []byte) (dst []byte, err error) {
} }
} }
// Field (44) 'PayloadExpectedWithdrawals'
if size := len(b.PayloadExpectedWithdrawals); size > 16 {
err = ssz.ErrListTooBigFn("--.PayloadExpectedWithdrawals", size, 16)
return
}
for ii := 0; ii < len(b.PayloadExpectedWithdrawals); ii++ {
if dst, err = b.PayloadExpectedWithdrawals[ii].MarshalSSZTo(dst); err != nil {
return
}
}
return return
} }
@@ -1795,12 +1850,12 @@ func (b *BeaconStateGloas) MarshalSSZTo(buf []byte) (dst []byte, err error) {
func (b *BeaconStateGloas) UnmarshalSSZ(buf []byte) error { func (b *BeaconStateGloas) UnmarshalSSZ(buf []byte) error {
var err error var err error
size := uint64(len(buf)) size := uint64(len(buf))
if size < 2741821 { if size < 2741333 {
return ssz.ErrSize return ssz.ErrSize
} }
tail := buf tail := buf
var o7, o9, o11, o12, o15, o16, o21, o27, o34, o35, o36, o40 uint64 var o7, o9, o11, o12, o15, o16, o21, o27, o34, o35, o36, o38, o42, o44 uint64
// Field (0) 'GenesisTime' // Field (0) 'GenesisTime'
b.GenesisTime = ssz.UnmarshallUint64(buf[0:8]) b.GenesisTime = ssz.UnmarshallUint64(buf[0:8])
@@ -1853,7 +1908,7 @@ func (b *BeaconStateGloas) UnmarshalSSZ(buf []byte) error {
return ssz.ErrOffset return ssz.ErrOffset
} }
if o7 != 2741821 { if o7 != 2741333 {
return ssz.ErrInvalidVariableOffset return ssz.ErrInvalidVariableOffset
} }
@@ -1963,93 +2018,100 @@ func (b *BeaconStateGloas) UnmarshalSSZ(buf []byte) error {
if b.LatestExecutionPayloadBid == nil { if b.LatestExecutionPayloadBid == nil {
b.LatestExecutionPayloadBid = new(ExecutionPayloadBid) b.LatestExecutionPayloadBid = new(ExecutionPayloadBid)
} }
if err = b.LatestExecutionPayloadBid.UnmarshalSSZ(buf[2736629:2736809]); err != nil { if err = b.LatestExecutionPayloadBid.UnmarshalSSZ(buf[2736629:2736849]); err != nil {
return err return err
} }
// Field (25) 'NextWithdrawalIndex' // Field (25) 'NextWithdrawalIndex'
b.NextWithdrawalIndex = ssz.UnmarshallUint64(buf[2736809:2736817]) b.NextWithdrawalIndex = ssz.UnmarshallUint64(buf[2736849:2736857])
// Field (26) 'NextWithdrawalValidatorIndex' // Field (26) 'NextWithdrawalValidatorIndex'
b.NextWithdrawalValidatorIndex = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[2736817:2736825])) b.NextWithdrawalValidatorIndex = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[2736857:2736865]))
// Offset (27) 'HistoricalSummaries' // Offset (27) 'HistoricalSummaries'
if o27 = ssz.ReadOffset(buf[2736825:2736829]); o27 > size || o21 > o27 { if o27 = ssz.ReadOffset(buf[2736865:2736869]); o27 > size || o21 > o27 {
return ssz.ErrOffset return ssz.ErrOffset
} }
// Field (28) 'DepositRequestsStartIndex' // Field (28) 'DepositRequestsStartIndex'
b.DepositRequestsStartIndex = ssz.UnmarshallUint64(buf[2736829:2736837]) b.DepositRequestsStartIndex = ssz.UnmarshallUint64(buf[2736869:2736877])
// Field (29) 'DepositBalanceToConsume' // Field (29) 'DepositBalanceToConsume'
b.DepositBalanceToConsume = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Gwei(ssz.UnmarshallUint64(buf[2736837:2736845])) b.DepositBalanceToConsume = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Gwei(ssz.UnmarshallUint64(buf[2736877:2736885]))
// Field (30) 'ExitBalanceToConsume' // Field (30) 'ExitBalanceToConsume'
b.ExitBalanceToConsume = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Gwei(ssz.UnmarshallUint64(buf[2736845:2736853])) b.ExitBalanceToConsume = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Gwei(ssz.UnmarshallUint64(buf[2736885:2736893]))
// Field (31) 'EarliestExitEpoch' // Field (31) 'EarliestExitEpoch'
b.EarliestExitEpoch = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Epoch(ssz.UnmarshallUint64(buf[2736853:2736861])) b.EarliestExitEpoch = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Epoch(ssz.UnmarshallUint64(buf[2736893:2736901]))
// Field (32) 'ConsolidationBalanceToConsume' // Field (32) 'ConsolidationBalanceToConsume'
b.ConsolidationBalanceToConsume = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Gwei(ssz.UnmarshallUint64(buf[2736861:2736869])) b.ConsolidationBalanceToConsume = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Gwei(ssz.UnmarshallUint64(buf[2736901:2736909]))
// Field (33) 'EarliestConsolidationEpoch' // Field (33) 'EarliestConsolidationEpoch'
b.EarliestConsolidationEpoch = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Epoch(ssz.UnmarshallUint64(buf[2736869:2736877])) b.EarliestConsolidationEpoch = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Epoch(ssz.UnmarshallUint64(buf[2736909:2736917]))
// Offset (34) 'PendingDeposits' // Offset (34) 'PendingDeposits'
if o34 = ssz.ReadOffset(buf[2736877:2736881]); o34 > size || o27 > o34 { if o34 = ssz.ReadOffset(buf[2736917:2736921]); o34 > size || o27 > o34 {
return ssz.ErrOffset return ssz.ErrOffset
} }
// Offset (35) 'PendingPartialWithdrawals' // Offset (35) 'PendingPartialWithdrawals'
if o35 = ssz.ReadOffset(buf[2736881:2736885]); o35 > size || o34 > o35 { if o35 = ssz.ReadOffset(buf[2736921:2736925]); o35 > size || o34 > o35 {
return ssz.ErrOffset return ssz.ErrOffset
} }
// Offset (36) 'PendingConsolidations' // Offset (36) 'PendingConsolidations'
if o36 = ssz.ReadOffset(buf[2736885:2736889]); o36 > size || o35 > o36 { if o36 = ssz.ReadOffset(buf[2736925:2736929]); o36 > size || o35 > o36 {
return ssz.ErrOffset return ssz.ErrOffset
} }
// Field (37) 'ProposerLookahead' // Field (37) 'ProposerLookahead'
b.ProposerLookahead = ssz.ExtendUint64(b.ProposerLookahead, 64) b.ProposerLookahead = ssz.ExtendUint64(b.ProposerLookahead, 64)
for ii := 0; ii < 64; ii++ { for ii := 0; ii < 64; ii++ {
b.ProposerLookahead[ii] = ssz.UnmarshallUint64(buf[2736889:2737401][ii*8 : (ii+1)*8]) b.ProposerLookahead[ii] = ssz.UnmarshallUint64(buf[2736929:2737441][ii*8 : (ii+1)*8])
} }
// Field (38) 'ExecutionPayloadAvailability' // Offset (38) 'Builders'
if o38 = ssz.ReadOffset(buf[2737441:2737445]); o38 > size || o36 > o38 {
return ssz.ErrOffset
}
// Field (39) 'NextWithdrawalBuilderIndex'
b.NextWithdrawalBuilderIndex = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.BuilderIndex(ssz.UnmarshallUint64(buf[2737445:2737453]))
// Field (40) 'ExecutionPayloadAvailability'
if cap(b.ExecutionPayloadAvailability) == 0 { if cap(b.ExecutionPayloadAvailability) == 0 {
b.ExecutionPayloadAvailability = make([]byte, 0, len(buf[2737401:2738425])) b.ExecutionPayloadAvailability = make([]byte, 0, len(buf[2737453:2738477]))
} }
b.ExecutionPayloadAvailability = append(b.ExecutionPayloadAvailability, buf[2737401:2738425]...) b.ExecutionPayloadAvailability = append(b.ExecutionPayloadAvailability, buf[2737453:2738477]...)
// Field (39) 'BuilderPendingPayments' // Field (41) 'BuilderPendingPayments'
b.BuilderPendingPayments = make([]*BuilderPendingPayment, 64) b.BuilderPendingPayments = make([]*BuilderPendingPayment, 64)
for ii := 0; ii < 64; ii++ { for ii := 0; ii < 64; ii++ {
if b.BuilderPendingPayments[ii] == nil { if b.BuilderPendingPayments[ii] == nil {
b.BuilderPendingPayments[ii] = new(BuilderPendingPayment) b.BuilderPendingPayments[ii] = new(BuilderPendingPayment)
} }
if err = b.BuilderPendingPayments[ii].UnmarshalSSZ(buf[2738425:2741753][ii*52 : (ii+1)*52]); err != nil { if err = b.BuilderPendingPayments[ii].UnmarshalSSZ(buf[2738477:2741293][ii*44 : (ii+1)*44]); err != nil {
return err return err
} }
} }
// Offset (40) 'BuilderPendingWithdrawals' // Offset (42) 'BuilderPendingWithdrawals'
if o40 = ssz.ReadOffset(buf[2741753:2741757]); o40 > size || o36 > o40 { if o42 = ssz.ReadOffset(buf[2741293:2741297]); o42 > size || o38 > o42 {
return ssz.ErrOffset return ssz.ErrOffset
} }
// Field (41) 'LatestBlockHash' // Field (43) 'LatestBlockHash'
if cap(b.LatestBlockHash) == 0 { if cap(b.LatestBlockHash) == 0 {
b.LatestBlockHash = make([]byte, 0, len(buf[2741757:2741789])) b.LatestBlockHash = make([]byte, 0, len(buf[2741297:2741329]))
} }
b.LatestBlockHash = append(b.LatestBlockHash, buf[2741757:2741789]...) b.LatestBlockHash = append(b.LatestBlockHash, buf[2741297:2741329]...)
// Field (42) 'LatestWithdrawalsRoot' // Offset (44) 'PayloadExpectedWithdrawals'
if cap(b.LatestWithdrawalsRoot) == 0 { if o44 = ssz.ReadOffset(buf[2741329:2741333]); o44 > size || o42 > o44 {
b.LatestWithdrawalsRoot = make([]byte, 0, len(buf[2741789:2741821])) return ssz.ErrOffset
} }
b.LatestWithdrawalsRoot = append(b.LatestWithdrawalsRoot, buf[2741789:2741821]...)
// Field (7) 'HistoricalRoots' // Field (7) 'HistoricalRoots'
{ {
@@ -2209,7 +2271,7 @@ func (b *BeaconStateGloas) UnmarshalSSZ(buf []byte) error {
// Field (36) 'PendingConsolidations' // Field (36) 'PendingConsolidations'
{ {
buf = tail[o36:o40] buf = tail[o36:o38]
num, err := ssz.DivideInt2(len(buf), 16, 262144) num, err := ssz.DivideInt2(len(buf), 16, 262144)
if err != nil { if err != nil {
return err return err
@@ -2225,10 +2287,28 @@ func (b *BeaconStateGloas) UnmarshalSSZ(buf []byte) error {
} }
} }
// Field (40) 'BuilderPendingWithdrawals' // Field (38) 'Builders'
{ {
buf = tail[o40:] buf = tail[o38:o42]
num, err := ssz.DivideInt2(len(buf), 44, 1048576) num, err := ssz.DivideInt2(len(buf), 93, 1099511627776)
if err != nil {
return err
}
b.Builders = make([]*Builder, num)
for ii := 0; ii < num; ii++ {
if b.Builders[ii] == nil {
b.Builders[ii] = new(Builder)
}
if err = b.Builders[ii].UnmarshalSSZ(buf[ii*93 : (ii+1)*93]); err != nil {
return err
}
}
}
// Field (42) 'BuilderPendingWithdrawals'
{
buf = tail[o42:o44]
num, err := ssz.DivideInt2(len(buf), 36, 1048576)
if err != nil { if err != nil {
return err return err
} }
@@ -2237,7 +2317,25 @@ func (b *BeaconStateGloas) UnmarshalSSZ(buf []byte) error {
if b.BuilderPendingWithdrawals[ii] == nil { if b.BuilderPendingWithdrawals[ii] == nil {
b.BuilderPendingWithdrawals[ii] = new(BuilderPendingWithdrawal) b.BuilderPendingWithdrawals[ii] = new(BuilderPendingWithdrawal)
} }
if err = b.BuilderPendingWithdrawals[ii].UnmarshalSSZ(buf[ii*44 : (ii+1)*44]); err != nil { if err = b.BuilderPendingWithdrawals[ii].UnmarshalSSZ(buf[ii*36 : (ii+1)*36]); err != nil {
return err
}
}
}
// Field (44) 'PayloadExpectedWithdrawals'
{
buf = tail[o44:]
num, err := ssz.DivideInt2(len(buf), 44, 16)
if err != nil {
return err
}
b.PayloadExpectedWithdrawals = make([]*v1.Withdrawal, num)
for ii := 0; ii < num; ii++ {
if b.PayloadExpectedWithdrawals[ii] == nil {
b.PayloadExpectedWithdrawals[ii] = new(v1.Withdrawal)
}
if err = b.PayloadExpectedWithdrawals[ii].UnmarshalSSZ(buf[ii*44 : (ii+1)*44]); err != nil {
return err return err
} }
} }
@@ -2247,7 +2345,7 @@ func (b *BeaconStateGloas) UnmarshalSSZ(buf []byte) error {
// SizeSSZ returns the ssz encoded size in bytes for the BeaconStateGloas object // SizeSSZ returns the ssz encoded size in bytes for the BeaconStateGloas object
func (b *BeaconStateGloas) SizeSSZ() (size int) { func (b *BeaconStateGloas) SizeSSZ() (size int) {
size = 2741821 size = 2741333
// Field (7) 'HistoricalRoots' // Field (7) 'HistoricalRoots'
size += len(b.HistoricalRoots) * 32 size += len(b.HistoricalRoots) * 32
@@ -2282,8 +2380,14 @@ func (b *BeaconStateGloas) SizeSSZ() (size int) {
// Field (36) 'PendingConsolidations' // Field (36) 'PendingConsolidations'
size += len(b.PendingConsolidations) * 16 size += len(b.PendingConsolidations) * 16
// Field (40) 'BuilderPendingWithdrawals' // Field (38) 'Builders'
size += len(b.BuilderPendingWithdrawals) * 44 size += len(b.Builders) * 93
// Field (42) 'BuilderPendingWithdrawals'
size += len(b.BuilderPendingWithdrawals) * 36
// Field (44) 'PayloadExpectedWithdrawals'
size += len(b.PayloadExpectedWithdrawals) * 44
return return
} }
@@ -2637,14 +2741,33 @@ func (b *BeaconStateGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) {
hh.Merkleize(subIndx) hh.Merkleize(subIndx)
} }
// Field (38) 'ExecutionPayloadAvailability' // Field (38) 'Builders'
{
subIndx := hh.Index()
num := uint64(len(b.Builders))
if num > 1099511627776 {
err = ssz.ErrIncorrectListSize
return
}
for _, elem := range b.Builders {
if err = elem.HashTreeRootWith(hh); err != nil {
return
}
}
hh.MerkleizeWithMixin(subIndx, num, 1099511627776)
}
// Field (39) 'NextWithdrawalBuilderIndex'
hh.PutUint64(uint64(b.NextWithdrawalBuilderIndex))
// Field (40) 'ExecutionPayloadAvailability'
if size := len(b.ExecutionPayloadAvailability); size != 1024 { if size := len(b.ExecutionPayloadAvailability); size != 1024 {
err = ssz.ErrBytesLengthFn("--.ExecutionPayloadAvailability", size, 1024) err = ssz.ErrBytesLengthFn("--.ExecutionPayloadAvailability", size, 1024)
return return
} }
hh.PutBytes(b.ExecutionPayloadAvailability) hh.PutBytes(b.ExecutionPayloadAvailability)
// Field (39) 'BuilderPendingPayments' // Field (41) 'BuilderPendingPayments'
{ {
subIndx := hh.Index() subIndx := hh.Index()
for _, elem := range b.BuilderPendingPayments { for _, elem := range b.BuilderPendingPayments {
@@ -2655,7 +2778,7 @@ func (b *BeaconStateGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) {
hh.Merkleize(subIndx) hh.Merkleize(subIndx)
} }
// Field (40) 'BuilderPendingWithdrawals' // Field (42) 'BuilderPendingWithdrawals'
{ {
subIndx := hh.Index() subIndx := hh.Index()
num := uint64(len(b.BuilderPendingWithdrawals)) num := uint64(len(b.BuilderPendingWithdrawals))
@@ -2671,19 +2794,28 @@ func (b *BeaconStateGloas) HashTreeRootWith(hh *ssz.Hasher) (err error) {
hh.MerkleizeWithMixin(subIndx, num, 1048576) hh.MerkleizeWithMixin(subIndx, num, 1048576)
} }
// Field (41) 'LatestBlockHash' // Field (43) 'LatestBlockHash'
if size := len(b.LatestBlockHash); size != 32 { if size := len(b.LatestBlockHash); size != 32 {
err = ssz.ErrBytesLengthFn("--.LatestBlockHash", size, 32) err = ssz.ErrBytesLengthFn("--.LatestBlockHash", size, 32)
return return
} }
hh.PutBytes(b.LatestBlockHash) hh.PutBytes(b.LatestBlockHash)
// Field (42) 'LatestWithdrawalsRoot' // Field (44) 'PayloadExpectedWithdrawals'
if size := len(b.LatestWithdrawalsRoot); size != 32 { {
err = ssz.ErrBytesLengthFn("--.LatestWithdrawalsRoot", size, 32) subIndx := hh.Index()
return num := uint64(len(b.PayloadExpectedWithdrawals))
if num > 16 {
err = ssz.ErrIncorrectListSize
return
}
for _, elem := range b.PayloadExpectedWithdrawals {
if err = elem.HashTreeRootWith(hh); err != nil {
return
}
}
hh.MerkleizeWithMixin(subIndx, num, 16)
} }
hh.PutBytes(b.LatestWithdrawalsRoot)
hh.Merkleize(indx) hh.Merkleize(indx)
return return
@@ -2716,7 +2848,7 @@ func (b *BuilderPendingPayment) MarshalSSZTo(buf []byte) (dst []byte, err error)
func (b *BuilderPendingPayment) UnmarshalSSZ(buf []byte) error { func (b *BuilderPendingPayment) UnmarshalSSZ(buf []byte) error {
var err error var err error
size := uint64(len(buf)) size := uint64(len(buf))
if size != 52 { if size != 44 {
return ssz.ErrSize return ssz.ErrSize
} }
@@ -2727,7 +2859,7 @@ func (b *BuilderPendingPayment) UnmarshalSSZ(buf []byte) error {
if b.Withdrawal == nil { if b.Withdrawal == nil {
b.Withdrawal = new(BuilderPendingWithdrawal) b.Withdrawal = new(BuilderPendingWithdrawal)
} }
if err = b.Withdrawal.UnmarshalSSZ(buf[8:52]); err != nil { if err = b.Withdrawal.UnmarshalSSZ(buf[8:44]); err != nil {
return err return err
} }
@@ -2736,7 +2868,7 @@ func (b *BuilderPendingPayment) UnmarshalSSZ(buf []byte) error {
// SizeSSZ returns the ssz encoded size in bytes for the BuilderPendingPayment object // SizeSSZ returns the ssz encoded size in bytes for the BuilderPendingPayment object
func (b *BuilderPendingPayment) SizeSSZ() (size int) { func (b *BuilderPendingPayment) SizeSSZ() (size int) {
size = 52 size = 44
return return
} }
@@ -2783,9 +2915,6 @@ func (b *BuilderPendingWithdrawal) MarshalSSZTo(buf []byte) (dst []byte, err err
// Field (2) 'BuilderIndex' // Field (2) 'BuilderIndex'
dst = ssz.MarshalUint64(dst, uint64(b.BuilderIndex)) dst = ssz.MarshalUint64(dst, uint64(b.BuilderIndex))
// Field (3) 'WithdrawableEpoch'
dst = ssz.MarshalUint64(dst, uint64(b.WithdrawableEpoch))
return return
} }
@@ -2793,7 +2922,7 @@ func (b *BuilderPendingWithdrawal) MarshalSSZTo(buf []byte) (dst []byte, err err
func (b *BuilderPendingWithdrawal) UnmarshalSSZ(buf []byte) error { func (b *BuilderPendingWithdrawal) UnmarshalSSZ(buf []byte) error {
var err error var err error
size := uint64(len(buf)) size := uint64(len(buf))
if size != 44 { if size != 36 {
return ssz.ErrSize return ssz.ErrSize
} }
@@ -2807,17 +2936,14 @@ func (b *BuilderPendingWithdrawal) UnmarshalSSZ(buf []byte) error {
b.Amount = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Gwei(ssz.UnmarshallUint64(buf[20:28])) b.Amount = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Gwei(ssz.UnmarshallUint64(buf[20:28]))
// Field (2) 'BuilderIndex' // Field (2) 'BuilderIndex'
b.BuilderIndex = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[28:36])) b.BuilderIndex = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.BuilderIndex(ssz.UnmarshallUint64(buf[28:36]))
// Field (3) 'WithdrawableEpoch'
b.WithdrawableEpoch = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Epoch(ssz.UnmarshallUint64(buf[36:44]))
return err return err
} }
// SizeSSZ returns the ssz encoded size in bytes for the BuilderPendingWithdrawal object // SizeSSZ returns the ssz encoded size in bytes for the BuilderPendingWithdrawal object
func (b *BuilderPendingWithdrawal) SizeSSZ() (size int) { func (b *BuilderPendingWithdrawal) SizeSSZ() (size int) {
size = 44 size = 36
return return
} }
@@ -2843,9 +2969,6 @@ func (b *BuilderPendingWithdrawal) HashTreeRootWith(hh *ssz.Hasher) (err error)
// Field (2) 'BuilderIndex' // Field (2) 'BuilderIndex'
hh.PutUint64(uint64(b.BuilderIndex)) hh.PutUint64(uint64(b.BuilderIndex))
// Field (3) 'WithdrawableEpoch'
hh.PutUint64(uint64(b.WithdrawableEpoch))
hh.Merkleize(indx) hh.Merkleize(indx)
return return
} }
@@ -3218,7 +3341,7 @@ func (e *ExecutionPayloadEnvelope) UnmarshalSSZ(buf []byte) error {
} }
// Field (2) 'BuilderIndex' // Field (2) 'BuilderIndex'
e.BuilderIndex = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[8:16])) e.BuilderIndex = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.BuilderIndex(ssz.UnmarshallUint64(buf[8:16]))
// Field (3) 'BeaconBlockRoot' // Field (3) 'BeaconBlockRoot'
if cap(e.BeaconBlockRoot) == 0 { if cap(e.BeaconBlockRoot) == 0 {
@@ -3472,3 +3595,132 @@ func (s *SignedExecutionPayloadEnvelope) HashTreeRootWith(hh *ssz.Hasher) (err e
hh.Merkleize(indx) hh.Merkleize(indx)
return return
} }
// MarshalSSZ ssz marshals the Builder object
func (b *Builder) MarshalSSZ() ([]byte, error) {
return ssz.MarshalSSZ(b)
}
// MarshalSSZTo ssz marshals the Builder object to a target array
func (b *Builder) MarshalSSZTo(buf []byte) (dst []byte, err error) {
dst = buf
// Field (0) 'Pubkey'
if size := len(b.Pubkey); size != 48 {
err = ssz.ErrBytesLengthFn("--.Pubkey", size, 48)
return
}
dst = append(dst, b.Pubkey...)
// Field (1) 'Version'
if size := len(b.Version); size != 1 {
err = ssz.ErrBytesLengthFn("--.Version", size, 1)
return
}
dst = append(dst, b.Version...)
// Field (2) 'ExecutionAddress'
if size := len(b.ExecutionAddress); size != 20 {
err = ssz.ErrBytesLengthFn("--.ExecutionAddress", size, 20)
return
}
dst = append(dst, b.ExecutionAddress...)
// Field (3) 'Balance'
dst = ssz.MarshalUint64(dst, uint64(b.Balance))
// Field (4) 'DepositEpoch'
dst = ssz.MarshalUint64(dst, uint64(b.DepositEpoch))
// Field (5) 'WithdrawableEpoch'
dst = ssz.MarshalUint64(dst, uint64(b.WithdrawableEpoch))
return
}
// UnmarshalSSZ ssz unmarshals the Builder object
func (b *Builder) UnmarshalSSZ(buf []byte) error {
var err error
size := uint64(len(buf))
if size != 93 {
return ssz.ErrSize
}
// Field (0) 'Pubkey'
if cap(b.Pubkey) == 0 {
b.Pubkey = make([]byte, 0, len(buf[0:48]))
}
b.Pubkey = append(b.Pubkey, buf[0:48]...)
// Field (1) 'Version'
if cap(b.Version) == 0 {
b.Version = make([]byte, 0, len(buf[48:49]))
}
b.Version = append(b.Version, buf[48:49]...)
// Field (2) 'ExecutionAddress'
if cap(b.ExecutionAddress) == 0 {
b.ExecutionAddress = make([]byte, 0, len(buf[49:69]))
}
b.ExecutionAddress = append(b.ExecutionAddress, buf[49:69]...)
// Field (3) 'Balance'
b.Balance = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Gwei(ssz.UnmarshallUint64(buf[69:77]))
// Field (4) 'DepositEpoch'
b.DepositEpoch = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Epoch(ssz.UnmarshallUint64(buf[77:85]))
// Field (5) 'WithdrawableEpoch'
b.WithdrawableEpoch = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Epoch(ssz.UnmarshallUint64(buf[85:93]))
return err
}
// SizeSSZ returns the ssz encoded size in bytes for the Builder object
func (b *Builder) SizeSSZ() (size int) {
size = 93
return
}
// HashTreeRoot ssz hashes the Builder object
func (b *Builder) HashTreeRoot() ([32]byte, error) {
return ssz.HashWithDefaultHasher(b)
}
// HashTreeRootWith ssz hashes the Builder object with a hasher
func (b *Builder) HashTreeRootWith(hh *ssz.Hasher) (err error) {
indx := hh.Index()
// Field (0) 'Pubkey'
if size := len(b.Pubkey); size != 48 {
err = ssz.ErrBytesLengthFn("--.Pubkey", size, 48)
return
}
hh.PutBytes(b.Pubkey)
// Field (1) 'Version'
if size := len(b.Version); size != 1 {
err = ssz.ErrBytesLengthFn("--.Version", size, 1)
return
}
hh.PutBytes(b.Version)
// Field (2) 'ExecutionAddress'
if size := len(b.ExecutionAddress); size != 20 {
err = ssz.ErrBytesLengthFn("--.ExecutionAddress", size, 20)
return
}
hh.PutBytes(b.ExecutionAddress)
// Field (3) 'Balance'
hh.PutUint64(uint64(b.Balance))
// Field (4) 'DepositEpoch'
hh.PutUint64(uint64(b.DepositEpoch))
// Field (5) 'WithdrawableEpoch'
hh.PutUint64(uint64(b.WithdrawableEpoch))
hh.Merkleize(indx)
return
}

View File

@@ -26,10 +26,12 @@ func TestExecutionPayloadBid_Copy(t *testing.T) {
ParentBlockHash: []byte("parent_block_hash_32_bytes_long!"), ParentBlockHash: []byte("parent_block_hash_32_bytes_long!"),
ParentBlockRoot: []byte("parent_block_root_32_bytes_long!"), ParentBlockRoot: []byte("parent_block_root_32_bytes_long!"),
BlockHash: []byte("block_hash_32_bytes_are_long!!"), BlockHash: []byte("block_hash_32_bytes_are_long!!"),
PrevRandao: []byte("prev_randao_32_bytes_long!!!"),
FeeRecipient: []byte("fee_recipient_20_byt"), FeeRecipient: []byte("fee_recipient_20_byt"),
GasLimit: 15000000, GasLimit: 15000000,
BuilderIndex: primitives.ValidatorIndex(42), BuilderIndex: primitives.BuilderIndex(42),
Slot: primitives.Slot(12345), Slot: primitives.Slot(12345),
ExecutionPayment: 5645654,
Value: 1000000000000000000, Value: 1000000000000000000,
BlobKzgCommitmentsRoot: []byte("blob_kzg_commitments_32_bytes!!"), BlobKzgCommitmentsRoot: []byte("blob_kzg_commitments_32_bytes!!"),
}, },
@@ -76,10 +78,9 @@ func TestBuilderPendingWithdrawal_Copy(t *testing.T) {
{ {
name: "fully populated withdrawal", name: "fully populated withdrawal",
withdrawal: &BuilderPendingWithdrawal{ withdrawal: &BuilderPendingWithdrawal{
FeeRecipient: []byte("fee_recipient_20_byt"), FeeRecipient: []byte("fee_recipient_20_byt"),
Amount: primitives.Gwei(5000000000), Amount: primitives.Gwei(5000000000),
BuilderIndex: primitives.ValidatorIndex(123), BuilderIndex: primitives.BuilderIndex(123),
WithdrawableEpoch: primitives.Epoch(456),
}, },
}, },
} }
@@ -134,10 +135,9 @@ func TestBuilderPendingPayment_Copy(t *testing.T) {
payment: &BuilderPendingPayment{ payment: &BuilderPendingPayment{
Weight: primitives.Gwei(2500), Weight: primitives.Gwei(2500),
Withdrawal: &BuilderPendingWithdrawal{ Withdrawal: &BuilderPendingWithdrawal{
FeeRecipient: []byte("test_recipient_20byt"), FeeRecipient: []byte("test_recipient_20byt"),
Amount: primitives.Gwei(10000), Amount: primitives.Gwei(10000),
BuilderIndex: primitives.ValidatorIndex(789), BuilderIndex: primitives.BuilderIndex(789),
WithdrawableEpoch: primitives.Epoch(999),
}, },
}, },
}, },
@@ -166,3 +166,60 @@ func TestBuilderPendingPayment_Copy(t *testing.T) {
}) })
} }
} }
func TestCopyBuilder(t *testing.T) {
tests := []struct {
name string
builder *Builder
}{
{
name: "nil builder",
builder: nil,
},
{
name: "empty builder",
builder: &Builder{},
},
{
name: "fully populated builder",
builder: &Builder{
Pubkey: []byte("pubkey_48_bytes_long_pubkey_48_bytes_long_pubkey_48!"),
Version: []byte{'a'},
ExecutionAddress: []byte("execution_address_20"),
Balance: primitives.Gwei(12345),
DepositEpoch: primitives.Epoch(10),
WithdrawableEpoch: primitives.Epoch(20),
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
copied := CopyBuilder(tt.builder)
if tt.builder == nil {
if copied != nil {
t.Errorf("CopyBuilder() of nil should return nil, got %v", copied)
}
return
}
if !reflect.DeepEqual(tt.builder, copied) {
t.Errorf("CopyBuilder() = %v, want %v", copied, tt.builder)
}
if len(tt.builder.Pubkey) > 0 {
tt.builder.Pubkey[0] = 0xFF
if copied.Pubkey[0] == 0xFF {
t.Error("CopyBuilder() did not create deep copy of Pubkey")
}
}
if len(tt.builder.ExecutionAddress) > 0 {
tt.builder.ExecutionAddress[0] = 0xFF
if copied.ExecutionAddress[0] == 0xFF {
t.Error("CopyBuilder() did not create deep copy of ExecutionAddress")
}
}
})
}
}

View File

@@ -48,6 +48,7 @@ mainnet = {
"payload_attestation.size": "4", # Gloas: MAX_PAYLOAD_ATTESTATIONS defined in block body "payload_attestation.size": "4", # Gloas: MAX_PAYLOAD_ATTESTATIONS defined in block body
"execution_payload_availability.size": "1024", # Gloas: SLOTS_PER_HISTORICAL_ROOT "execution_payload_availability.size": "1024", # Gloas: SLOTS_PER_HISTORICAL_ROOT
"builder_pending_payments.size": "64", # Gloas: vector length (2 * SLOTS_PER_EPOCH) "builder_pending_payments.size": "64", # Gloas: vector length (2 * SLOTS_PER_EPOCH)
"builder_registry_limit": "1099511627776", # Gloas: BUILDER_REGISTRY_LIMIT (same for mainnet/minimal)
} }
minimal = { minimal = {
@@ -91,7 +92,8 @@ minimal = {
"ptc.type": "github.com/OffchainLabs/go-bitfield.Bitvector2", "ptc.type": "github.com/OffchainLabs/go-bitfield.Bitvector2",
"payload_attestation.size": "4", # Gloas: MAX_PAYLOAD_ATTESTATIONS defined in block body "payload_attestation.size": "4", # Gloas: MAX_PAYLOAD_ATTESTATIONS defined in block body
"execution_payload_availability.size": "8", # Gloas: SLOTS_PER_HISTORICAL_ROOT "execution_payload_availability.size": "8", # Gloas: SLOTS_PER_HISTORICAL_ROOT
"builder_pending_payments.size": "16" # Gloas: vector length (2 * SLOTS_PER_EPOCH) "builder_pending_payments.size": "16", # Gloas: vector length (2 * SLOTS_PER_EPOCH)
"builder_registry_limit": "1099511627776", # Gloas: BUILDER_REGISTRY_LIMIT (same for mainnet/minimal)
} }
###### Rules definitions ####### ###### Rules definitions #######

View File

@@ -200,6 +200,7 @@ go_test(
"fulu__sanity__blocks_test.go", "fulu__sanity__blocks_test.go",
"fulu__sanity__slots_test.go", "fulu__sanity__slots_test.go",
"fulu__ssz_static__ssz_static_test.go", "fulu__ssz_static__ssz_static_test.go",
"gloas__operations__execution_payload_header_test.go",
"gloas__ssz_static__ssz_static_test.go", "gloas__ssz_static__ssz_static_test.go",
"phase0__epoch_processing__effective_balance_updates_test.go", "phase0__epoch_processing__effective_balance_updates_test.go",
"phase0__epoch_processing__epoch_processing_test.go", "phase0__epoch_processing__epoch_processing_test.go",
@@ -278,6 +279,8 @@ go_test(
"//testing/spectest/shared/fulu/rewards:go_default_library", "//testing/spectest/shared/fulu/rewards:go_default_library",
"//testing/spectest/shared/fulu/sanity:go_default_library", "//testing/spectest/shared/fulu/sanity:go_default_library",
"//testing/spectest/shared/fulu/ssz_static:go_default_library", "//testing/spectest/shared/fulu/ssz_static:go_default_library",
"//testing/spectest/shared/gloas/operations:go_default_library",
"//testing/spectest/shared/gloas/ssz_static:go_default_library",
"//testing/spectest/shared/phase0/epoch_processing:go_default_library", "//testing/spectest/shared/phase0/epoch_processing:go_default_library",
"//testing/spectest/shared/phase0/finality:go_default_library", "//testing/spectest/shared/phase0/finality:go_default_library",
"//testing/spectest/shared/phase0/operations:go_default_library", "//testing/spectest/shared/phase0/operations:go_default_library",

View File

@@ -0,0 +1,11 @@
package mainnet
import (
"testing"
"github.com/OffchainLabs/prysm/v7/testing/spectest/shared/gloas/operations"
)
func TestMainnet_Gloas_Operations_ExecutionPayloadBid(t *testing.T) {
operations.RunExecutionPayloadBidTest(t, "mainnet")
}

View File

@@ -2,9 +2,10 @@ package mainnet
import ( import (
"testing" "testing"
"github.com/OffchainLabs/prysm/v7/testing/spectest/shared/gloas/ssz_static"
) )
func TestMainnet_Gloas_SSZStatic(t *testing.T) { func TestMainnet_Gloas_SSZStatic(t *testing.T) {
t.Skip("Gloas is not implemented") ssz_static.RunSSZStaticTests(t, "mainnet")
// ssz_static.RunSSZStaticTests(t, "mainnet")
} }

View File

@@ -206,6 +206,7 @@ go_test(
"fulu__sanity__blocks_test.go", "fulu__sanity__blocks_test.go",
"fulu__sanity__slots_test.go", "fulu__sanity__slots_test.go",
"fulu__ssz_static__ssz_static_test.go", "fulu__ssz_static__ssz_static_test.go",
"gloas__operations__execution_payload_bid_test.go",
"gloas__ssz_static__ssz_static_test.go", "gloas__ssz_static__ssz_static_test.go",
"phase0__epoch_processing__effective_balance_updates_test.go", "phase0__epoch_processing__effective_balance_updates_test.go",
"phase0__epoch_processing__epoch_processing_test.go", "phase0__epoch_processing__epoch_processing_test.go",
@@ -288,6 +289,8 @@ go_test(
"//testing/spectest/shared/fulu/rewards:go_default_library", "//testing/spectest/shared/fulu/rewards:go_default_library",
"//testing/spectest/shared/fulu/sanity:go_default_library", "//testing/spectest/shared/fulu/sanity:go_default_library",
"//testing/spectest/shared/fulu/ssz_static:go_default_library", "//testing/spectest/shared/fulu/ssz_static:go_default_library",
"//testing/spectest/shared/gloas/operations:go_default_library",
"//testing/spectest/shared/gloas/ssz_static:go_default_library",
"//testing/spectest/shared/phase0/epoch_processing:go_default_library", "//testing/spectest/shared/phase0/epoch_processing:go_default_library",
"//testing/spectest/shared/phase0/finality:go_default_library", "//testing/spectest/shared/phase0/finality:go_default_library",
"//testing/spectest/shared/phase0/operations:go_default_library", "//testing/spectest/shared/phase0/operations:go_default_library",

View File

@@ -0,0 +1,11 @@
package minimal
import (
"testing"
"github.com/OffchainLabs/prysm/v7/testing/spectest/shared/gloas/operations"
)
func TestMinimal_Gloas_Operations_ExecutionPayloadBid(t *testing.T) {
operations.RunExecutionPayloadBidTest(t, "minimal")
}

View File

@@ -2,9 +2,10 @@ package minimal
import ( import (
"testing" "testing"
"github.com/OffchainLabs/prysm/v7/testing/spectest/shared/gloas/ssz_static"
) )
func TestMinimal_Gloas_SSZStatic(t *testing.T) { func TestMinimal_Gloas_SSZStatic(t *testing.T) {
t.Skip("Gloas is not implemented") ssz_static.RunSSZStaticTests(t, "minimal")
// ssz_static.RunSSZStaticTests(t, "minimal")
} }

View File

@@ -12,6 +12,7 @@ go_library(
"deposit.go", "deposit.go",
"deposit_request.go", "deposit_request.go",
"execution_payload.go", "execution_payload.go",
"execution_payload_bid.go",
"proposer_slashing.go", "proposer_slashing.go",
"slashing.go", "slashing.go",
"sync_aggregate.go", "sync_aggregate.go",
@@ -26,6 +27,7 @@ go_library(
"//beacon-chain/core/altair:go_default_library", "//beacon-chain/core/altair:go_default_library",
"//beacon-chain/core/blocks:go_default_library", "//beacon-chain/core/blocks:go_default_library",
"//beacon-chain/core/electra:go_default_library", "//beacon-chain/core/electra:go_default_library",
"//beacon-chain/core/gloas:go_default_library",
"//beacon-chain/core/helpers:go_default_library", "//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/core/validators:go_default_library", "//beacon-chain/core/validators:go_default_library",
"//beacon-chain/state:go_default_library", "//beacon-chain/state:go_default_library",

View File

@@ -0,0 +1,47 @@
package operations
import (
"context"
"path"
"testing"
"github.com/OffchainLabs/prysm/v7/beacon-chain/core/gloas"
"github.com/OffchainLabs/prysm/v7/beacon-chain/core/helpers"
"github.com/OffchainLabs/prysm/v7/beacon-chain/state"
"github.com/OffchainLabs/prysm/v7/consensus-types/interfaces"
"github.com/OffchainLabs/prysm/v7/testing/require"
"github.com/OffchainLabs/prysm/v7/testing/spectest/utils"
"github.com/OffchainLabs/prysm/v7/testing/util"
"github.com/golang/snappy"
)
func runExecutionPayloadBidTest(t *testing.T, config string, fork string, objName string, block blockWithSSZObject, sszToState SSZToState, operationFn BlockOperation) {
require.NoError(t, utils.SetConfig(t, config))
testFolders, testsFolderPath := utils.TestFolders(t, config, fork, "operations/"+objName+"/pyspec_tests")
if len(testFolders) == 0 {
t.Fatalf("No test folders found for %s/%s/%s", config, fork, "operations/"+objName+"/pyspec_tests")
}
for _, folder := range testFolders {
t.Run(folder.Name(), func(t *testing.T) {
if folder.Name() != "process_execution_payload_bid_self_build_non_zero_value" {
t.Skip("skipping other tests for now")
}
helpers.ClearCache()
folderPath := path.Join(testsFolderPath, folder.Name())
blockFile, err := util.BazelFileBytes(folderPath, "block.ssz_snappy")
require.NoError(t, err)
blockSSZ, err := snappy.Decode(nil /* dst */, blockFile)
require.NoError(t, err, "Failed to decompress")
blk, err := block(blockSSZ)
require.NoError(t, err)
RunBlockOperationTest(t, folderPath, blk, sszToState, operationFn)
})
}
}
func RunExecutionPayloadBidTest(t *testing.T, config string, fork string, block blockWithSSZObject, sszToState SSZToState) {
runExecutionPayloadBidTest(t, config, fork, "execution_payload_bid", block, sszToState, func(ctx context.Context, s state.BeaconState, b interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) {
err := gloas.ProcessExecutionPayloadBid(s, b.Block())
return s, err
})
}

View File

@@ -0,0 +1,21 @@
load("@prysm//tools/go:def.bzl", "go_library")
go_library(
name = "go_default_library",
testonly = True,
srcs = [
"execution_payload_bid.go",
"helpers.go",
],
importpath = "github.com/OffchainLabs/prysm/v7/testing/spectest/shared/gloas/operations",
visibility = ["//visibility:public"],
deps = [
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/state-native:go_default_library",
"//consensus-types/blocks:go_default_library",
"//consensus-types/interfaces:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//runtime/version:go_default_library",
"//testing/spectest/shared/common/operations:go_default_library",
],
)

View File

@@ -0,0 +1,23 @@
package operations
import (
"testing"
"github.com/OffchainLabs/prysm/v7/consensus-types/blocks"
"github.com/OffchainLabs/prysm/v7/consensus-types/interfaces"
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v7/runtime/version"
common "github.com/OffchainLabs/prysm/v7/testing/spectest/shared/common/operations"
)
func blockWithSignedExecutionPayloadBid(blockSSZ []byte) (interfaces.SignedBeaconBlock, error) {
var block ethpb.BeaconBlockGloas
if err := block.UnmarshalSSZ(blockSSZ); err != nil {
return nil, err
}
return blocks.NewSignedBeaconBlock(&ethpb.SignedBeaconBlockGloas{Block: &block})
}
func RunExecutionPayloadBidTest(t *testing.T, config string) {
common.RunExecutionPayloadBidTest(t, config, version.String(version.Gloas), blockWithSignedExecutionPayloadBid, sszToState)
}

View File

@@ -0,0 +1,15 @@
package operations
import (
"github.com/OffchainLabs/prysm/v7/beacon-chain/state"
state_native "github.com/OffchainLabs/prysm/v7/beacon-chain/state/state-native"
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
)
func sszToState(b []byte) (state.BeaconState, error) {
base := &ethpb.BeaconStateGloas{}
if err := base.UnmarshalSSZ(b); err != nil {
return nil, err
}
return state_native.InitializeFromProtoGloas(base)
}

View File

@@ -6,6 +6,7 @@ import (
"testing" "testing"
state_native "github.com/OffchainLabs/prysm/v7/beacon-chain/state/state-native" state_native "github.com/OffchainLabs/prysm/v7/beacon-chain/state/state-native"
// enginev1 "github.com/OffchainLabs/prysm/v7/proto/engine/v1"
enginev1 "github.com/OffchainLabs/prysm/v7/proto/engine/v1" enginev1 "github.com/OffchainLabs/prysm/v7/proto/engine/v1"
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1" ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v7/testing/require" "github.com/OffchainLabs/prysm/v7/testing/require"
@@ -56,6 +57,8 @@ func unmarshalledSSZ(t *testing.T, serializedBytes []byte, folderName string) (a
obj = &ethpb.BeaconBlockBodyGloas{} obj = &ethpb.BeaconBlockBodyGloas{}
case "BeaconState": case "BeaconState":
obj = &ethpb.BeaconStateGloas{} obj = &ethpb.BeaconStateGloas{}
case "Builder":
obj = &ethpb.Builder{}
case "BuilderPendingPayment": case "BuilderPendingPayment":
obj = &ethpb.BuilderPendingPayment{} obj = &ethpb.BuilderPendingPayment{}
case "BuilderPendingWithdrawal": case "BuilderPendingWithdrawal":
@@ -70,6 +73,8 @@ func unmarshalledSSZ(t *testing.T, serializedBytes []byte, folderName string) (a
t.Skip("Not a consensus type") t.Skip("Not a consensus type")
case "DataColumnSidecar": case "DataColumnSidecar":
obj = &ethpb.DataColumnSidecarGloas{} obj = &ethpb.DataColumnSidecarGloas{}
case "SignedProposerPreferences", "ProposerPreferences":
t.Skip("p2p-only type; not part of the consensus state transition")
// Standard types that also exist in gloas // Standard types that also exist in gloas
case "ExecutionPayload": case "ExecutionPayload":

View File

@@ -10,6 +10,7 @@ go_library(
importpath = "github.com/OffchainLabs/prysm/v7/testing/spectest/utils", importpath = "github.com/OffchainLabs/prysm/v7/testing/spectest/utils",
visibility = ["//testing/spectest:__subpackages__"], visibility = ["//testing/spectest:__subpackages__"],
deps = [ deps = [
"//config/features:go_default_library",
"//config/params:go_default_library", "//config/params:go_default_library",
"//io/file:go_default_library", "//io/file:go_default_library",
"//testing/require:go_default_library", "//testing/require:go_default_library",

View File

@@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"testing" "testing"
"github.com/OffchainLabs/prysm/v7/config/features"
"github.com/OffchainLabs/prysm/v7/config/params" "github.com/OffchainLabs/prysm/v7/config/params"
) )
@@ -13,6 +14,12 @@ import (
// Provides reset function allowing to get back to the previous configuration at the end of a test. // Provides reset function allowing to get back to the previous configuration at the end of a test.
func SetConfig(t testing.TB, config string) error { func SetConfig(t testing.TB, config string) error {
params.SetupTestConfigCleanup(t) params.SetupTestConfigCleanup(t)
resetFeatures := features.InitWithReset(&features.Flags{
LowValcountSweep: true,
})
t.Cleanup(resetFeatures)
switch config { switch config {
case "minimal": case "minimal":
params.OverrideBeaconConfig(params.MinimalSpecConfig().Copy()) params.OverrideBeaconConfig(params.MinimalSpecConfig().Copy())

View File

@@ -71,7 +71,7 @@ func main() {
flag.Parse() flag.Parse()
if *logFileName != "" { if *logFileName != "" {
if err := logs.ConfigurePersistentLogging(*logFileName, "text"); err != nil { if err := logs.ConfigurePersistentLogging(*logFileName, "text", logrus.DebugLevel); err != nil {
log.WithError(err).Error("Failed to configuring logging to disk.") log.WithError(err).Error("Failed to configuring logging to disk.")
} }
} }

View File

@@ -75,13 +75,6 @@ func NewValidatorClient(cliCtx *cli.Context) (*ValidatorClient, error) {
return nil, err return nil, err
} }
verbosity := cliCtx.String(cmd.VerbosityFlag.Name)
level, err := logrus.ParseLevel(verbosity)
if err != nil {
return nil, err
}
logrus.SetLevel(level)
// Warn if user's platform is not supported // Warn if user's platform is not supported
prereqs.WarnIfPlatformNotSupported(cliCtx.Context) prereqs.WarnIfPlatformNotSupported(cliCtx.Context)