mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-06 22:23:56 -05:00
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
This commit is contained in:
@@ -273,7 +273,7 @@ filegroup(
|
||||
url = "https://github.com/ethereum/EIPs/archive/5480440fe51742ed23342b68cf106cefd427e39d.tar.gz",
|
||||
)
|
||||
|
||||
consensus_spec_version = "v1.6.0"
|
||||
consensus_spec_version = "v1.6.1"
|
||||
|
||||
load("@prysm//tools:download_spectests.bzl", "consensus_spec_tests")
|
||||
|
||||
@@ -281,8 +281,8 @@ consensus_spec_tests(
|
||||
name = "consensus_spec_tests",
|
||||
flavors = {
|
||||
"general": "sha256-54hTaUNF9nLg+hRr3oHoq0yjZpW3MNiiUUuCQu6Rajk=",
|
||||
"minimal": "sha256-1JHIGg3gVMjvcGYRHR5cwdDgOvX47oR/MWp6gyAeZfA=",
|
||||
"mainnet": "sha256-292h3W2Ffts0YExgDTyxYe9Os7R0bZIXuAaMO8P6kl4=",
|
||||
"minimal": "sha256-4dDJ3D0J+3SpizJMQLJYehfcVV5hSdP5dBYB//z0OQE=",
|
||||
"mainnet": "sha256-hAHFhwDEYRVNsgUMKpgq96yiWb0BbCGE7DnEVO328cU=",
|
||||
},
|
||||
version = consensus_spec_version,
|
||||
)
|
||||
@@ -298,7 +298,7 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
integrity = "sha256-VzBgrEokvYSMIIXVnSA5XS9I3m9oxpvToQGxC1N5lzw=",
|
||||
integrity = "sha256-/3o4CR7cClBh8V3qTy99LEel1UoPrFXS7+vF23gK4iM=",
|
||||
strip_prefix = "consensus-specs-" + consensus_spec_version[1:],
|
||||
url = "https://github.com/ethereum/consensus-specs/archive/refs/tags/%s.tar.gz" % consensus_spec_version,
|
||||
)
|
||||
|
||||
45
beacon-chain/core/gloas/BUILD.bazel
Normal file
45
beacon-chain/core/gloas/BUILD.bazel
Normal 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/params:go_default_library",
|
||||
"//consensus-types/blocks: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",
|
||||
"//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",
|
||||
],
|
||||
)
|
||||
256
beacon-chain/core/gloas/bid.go
Normal file
256
beacon-chain/core/gloas/bid.go
Normal file
@@ -0,0 +1,256 @@
|
||||
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"
|
||||
"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/consensus-types/primitives"
|
||||
"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.6.1 (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
|
||||
// builder = state.validators[builder_index]
|
||||
// amount = bid.value
|
||||
// if builder_index == block.proposer_index:
|
||||
// assert amount == 0
|
||||
// assert signed_bid.signature == G2_POINT_AT_INFINITY
|
||||
// else:
|
||||
// assert has_builder_withdrawal_credential(builder)
|
||||
// assert verify_execution_payload_bid_signature(state, signed_bid)
|
||||
// assert is_active_validator(builder, get_current_epoch(state))
|
||||
// assert not builder.slashed
|
||||
// assert amount == 0 or state.balances[builder_index] >= amount + pending_payments + pending_withdrawals + MIN_ACTIVATION_BALANCE
|
||||
// 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, withdrawable_epoch=FAR_FUTURE_EPOCH))
|
||||
// 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()
|
||||
proposerIndex := block.ProposerIndex()
|
||||
amount := bid.Value()
|
||||
|
||||
builder, err := st.ValidatorAtIndex(builderIndex)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get builder validator: %w", err)
|
||||
}
|
||||
|
||||
if builderIndex == proposerIndex {
|
||||
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 {
|
||||
if err := validateBuilderWithdrawalCredential(builder); err != nil {
|
||||
return fmt.Errorf("builder withdrawal credential validation failed: %w", err)
|
||||
}
|
||||
if err := validatePayloadBidSignature(st, wrappedBid); err != nil {
|
||||
return fmt.Errorf("bid signature validation failed: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := validateBuilderStatus(st, builder); err != nil {
|
||||
return fmt.Errorf("builder validation failed: %w", err)
|
||||
}
|
||||
|
||||
if err := validateBuilderHasEnoughBalance(st, builderIndex, amount); err != nil {
|
||||
return fmt.Errorf("builder financial capacity 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 := ðpb.BuilderPendingPayment{
|
||||
Weight: 0,
|
||||
Withdrawal: ðpb.BuilderPendingWithdrawal{
|
||||
FeeRecipient: feeRecipient[:],
|
||||
Amount: amount,
|
||||
BuilderIndex: builderIndex,
|
||||
WithdrawableEpoch: params.BeaconConfig().FarFutureEpoch,
|
||||
},
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
// validateBuilderStatus checks if the builder is active and not slashed.
|
||||
func validateBuilderStatus(st state.BeaconState, builder *ethpb.Validator) error {
|
||||
currentEpoch := slots.ToEpoch(st.Slot())
|
||||
if !helpers.IsActiveValidator(builder, currentEpoch) {
|
||||
return fmt.Errorf("builder is not active in epoch %d", currentEpoch)
|
||||
}
|
||||
|
||||
if builder.Slashed {
|
||||
return errors.New("builder is slashed")
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// validateBuilderWithdrawalCredential checks if the builder has the correct withdrawal credential prefix.
|
||||
func validateBuilderWithdrawalCredential(validator *ethpb.Validator) error {
|
||||
if len(validator.WithdrawalCredentials) != 32 {
|
||||
return fmt.Errorf("invalid withdrawal credential length: %d", len(validator.WithdrawalCredentials))
|
||||
}
|
||||
|
||||
if validator.WithdrawalCredentials[0] != params.BeaconConfig().BuilderWithdrawalPrefixByte {
|
||||
return fmt.Errorf("builder must have withdrawal credential prefix 0x%02x, got 0x%02x",
|
||||
params.BeaconConfig().BuilderWithdrawalPrefixByte,
|
||||
validator.WithdrawalCredentials[0])
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// validateBuilderHasEnoughBalance checks if the builder has sufficient funds for the bid.
|
||||
func validateBuilderHasEnoughBalance(st state.BeaconState, builderIndex primitives.ValidatorIndex, amount primitives.Gwei) error {
|
||||
if amount == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
builderBalance, err := st.BalanceAtIndex(builderIndex)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get builder balance: %w", err)
|
||||
}
|
||||
|
||||
pendingPayments, err := st.PendingPaymentSum(builderIndex)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to calculate pending payments: %w", err)
|
||||
}
|
||||
|
||||
pendingWithdrawals, err := st.PendingWithdrawalSum(builderIndex)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to calculate pending withdrawals: %w", err)
|
||||
}
|
||||
|
||||
minActivationBalance := params.BeaconConfig().MinActivationBalance
|
||||
requiredBalance := uint64(amount) + pendingPayments + pendingWithdrawals + minActivationBalance
|
||||
|
||||
if builderBalance < requiredBalance {
|
||||
return fmt.Errorf("builder %d has insufficient balance: has %d, needs %d (amount=%d, pending_payments=%d, pending_withdrawals=%d, min_activation=%d)",
|
||||
builderIndex, builderBalance, requiredBalance, amount, pendingPayments, pendingWithdrawals, minActivationBalance)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
builderPubkey := st.PubkeyAtIndex(bid.BuilderIndex())
|
||||
publicKey, err := bls.PublicKeyFromBytes(builderPubkey[:])
|
||||
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
|
||||
}
|
||||
293
beacon-chain/core/gloas/bid_test.go
Normal file
293
beacon-chain/core/gloas/bid_test.go
Normal file
@@ -0,0 +1,293 @@
|
||||
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, builderIdx primitives.ValidatorIndex, balance uint64, randao [32]byte, latestHash [32]byte, pubkeyBytes [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(builderIdx) + 1
|
||||
validators := make([]*ethpb.Validator, validatorCount)
|
||||
balances := make([]uint64, validatorCount)
|
||||
for i := range validatorCount {
|
||||
validators[i] = ðpb.Validator{
|
||||
PublicKey: pubkeyBytes[:],
|
||||
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] = ðpb.BuilderPendingPayment{Withdrawal: ðpb.BuilderPendingWithdrawal{}}
|
||||
}
|
||||
|
||||
stProto := ðpb.BeaconStateGloas{
|
||||
Slot: slot,
|
||||
GenesisValidatorsRoot: bytes.Repeat([]byte{0x11}, 32),
|
||||
Fork: ðpb.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{},
|
||||
}
|
||||
|
||||
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)
|
||||
builderIdx := primitives.ValidatorIndex(0)
|
||||
randao := [32]byte(bytes.Repeat([]byte{0xAA}, 32))
|
||||
latestHash := [32]byte(bytes.Repeat([]byte{0xBB}, 32))
|
||||
pubKey := [48]byte{}
|
||||
state := buildGloasState(t, slot, builderIdx, params.BeaconConfig().MinActivationBalance+1000, randao, latestHash, pubKey)
|
||||
|
||||
bid := ðpb.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 := ðpb.SignedExecutionPayloadBid{
|
||||
Message: bid,
|
||||
Signature: common.InfiniteSignature[:],
|
||||
}
|
||||
|
||||
block := stubBlock{
|
||||
slot: slot,
|
||||
proposer: builderIdx,
|
||||
parentRoot: bytesutil.ToBytes32(bid.ParentBlockRoot),
|
||||
body: stubBlockBody{signedBid: signed},
|
||||
v: version.Gloas,
|
||||
}
|
||||
|
||||
require.NoError(t, ProcessExecutionPayloadBid(state, block))
|
||||
sum, err := state.PendingPaymentSum(builderIdx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(0), sum)
|
||||
}
|
||||
|
||||
func TestProcessExecutionPayloadBid_SelfBuildNonZeroAmountFails(t *testing.T) {
|
||||
slot := primitives.Slot(2)
|
||||
builderIdx := primitives.ValidatorIndex(0)
|
||||
randao := [32]byte{}
|
||||
latestHash := [32]byte{1}
|
||||
state := buildGloasState(t, slot, builderIdx, params.BeaconConfig().MinActivationBalance+1000, randao, latestHash, [48]byte{})
|
||||
|
||||
bid := ðpb.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 := ðpb.SignedExecutionPayloadBid{
|
||||
Message: bid,
|
||||
Signature: common.InfiniteSignature[:],
|
||||
}
|
||||
block := stubBlock{
|
||||
slot: slot,
|
||||
proposer: builderIdx,
|
||||
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.ValidatorIndex(1)
|
||||
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, builderIdx, balance, randao, latestHash, pubKey)
|
||||
|
||||
bid := ðpb.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 := ðpb.SignedExecutionPayloadBid{
|
||||
Message: bid,
|
||||
Signature: sig[:],
|
||||
}
|
||||
|
||||
block := stubBlock{
|
||||
slot: slot,
|
||||
proposer: builderIdx + 1, // not self-build
|
||||
parentRoot: bytesutil.ToBytes32(bid.ParentBlockRoot),
|
||||
body: stubBlockBody{signedBid: signed},
|
||||
v: version.Gloas,
|
||||
}
|
||||
|
||||
require.NoError(t, ProcessExecutionPayloadBid(state, block))
|
||||
|
||||
paymentSum, err := state.PendingPaymentSum(builderIdx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(500_000), paymentSum)
|
||||
|
||||
gotBid, err := state.LatestExecutionPayloadBid()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, primitives.ValidatorIndex(1), gotBid.BuilderIndex())
|
||||
require.Equal(t, primitives.Gwei(500_000), gotBid.Value())
|
||||
}
|
||||
@@ -168,6 +168,7 @@ func TestGetSpec(t *testing.T) {
|
||||
config.BlobsidecarSubnetCount = 101
|
||||
config.BlobsidecarSubnetCountElectra = 102
|
||||
config.SyncMessageDueBPS = 103
|
||||
config.BuilderWithdrawalPrefixByte = byte('b')
|
||||
|
||||
var dbp [4]byte
|
||||
copy(dbp[:], []byte{'0', '0', '0', '1'})
|
||||
@@ -190,6 +191,9 @@ func TestGetSpec(t *testing.T) {
|
||||
var daap [4]byte
|
||||
copy(daap[:], []byte{'0', '0', '0', '7'})
|
||||
config.DomainAggregateAndProof = daap
|
||||
var dbb [4]byte
|
||||
copy(dbb[:], []byte{'0', '0', '0', '8'})
|
||||
config.DomainBeaconBuilder = dbb
|
||||
var dam [4]byte
|
||||
copy(dam[:], []byte{'1', '0', '0', '0'})
|
||||
config.DomainApplicationMask = dam
|
||||
@@ -205,7 +209,7 @@ func TestGetSpec(t *testing.T) {
|
||||
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), &resp))
|
||||
data, ok := resp.Data.(map[string]any)
|
||||
require.Equal(t, true, ok)
|
||||
assert.Equal(t, 175, len(data))
|
||||
assert.Equal(t, 177, len(data))
|
||||
for k, v := range data {
|
||||
t.Run(k, func(t *testing.T) {
|
||||
switch k {
|
||||
@@ -419,8 +423,12 @@ func TestGetSpec(t *testing.T) {
|
||||
assert.Equal(t, "0x0a000000", v)
|
||||
case "DOMAIN_APPLICATION_BUILDER":
|
||||
assert.Equal(t, "0x00000001", v)
|
||||
case "DOMAIN_BEACON_BUILDER":
|
||||
assert.Equal(t, "0x30303038", v)
|
||||
case "DOMAIN_BLOB_SIDECAR":
|
||||
assert.Equal(t, "0x00000000", v)
|
||||
case "BUILDER_WITHDRAWAL_PREFIX":
|
||||
assert.Equal(t, "0x62", v)
|
||||
case "TRANSITION_TOTAL_DIFFICULTY":
|
||||
assert.Equal(t, "0", v)
|
||||
case "TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH":
|
||||
|
||||
@@ -5,6 +5,7 @@ go_library(
|
||||
srcs = [
|
||||
"error.go",
|
||||
"interfaces.go",
|
||||
"interfaces_gloas.go",
|
||||
"prometheus.go",
|
||||
],
|
||||
importpath = "github.com/OffchainLabs/prysm/v7/beacon-chain/state",
|
||||
|
||||
@@ -63,6 +63,7 @@ type ReadOnlyBeaconState interface {
|
||||
ReadOnlyDeposits
|
||||
ReadOnlyConsolidations
|
||||
ReadOnlyProposerLookahead
|
||||
readOnlyGloasFields
|
||||
ToProtoUnsafe() any
|
||||
ToProto() any
|
||||
GenesisTime() time.Time
|
||||
@@ -98,6 +99,7 @@ type WriteOnlyBeaconState interface {
|
||||
WriteOnlyWithdrawals
|
||||
WriteOnlyDeposits
|
||||
WriteOnlyProposerLookahead
|
||||
writeOnlyGloasFields
|
||||
SetGenesisTime(val time.Time) error
|
||||
SetGenesisValidatorsRoot(val []byte) error
|
||||
SetSlot(val primitives.Slot) error
|
||||
|
||||
19
beacon-chain/state/interfaces_gloas.go
Normal file
19
beacon-chain/state/interfaces_gloas.go
Normal 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 {
|
||||
LatestBlockHash() ([32]byte, error)
|
||||
PendingPaymentSum(primitives.ValidatorIndex) (uint64, error)
|
||||
PendingWithdrawalSum(primitives.ValidatorIndex) (uint64, error)
|
||||
LatestExecutionPayloadBid() (interfaces.ROExecutionPayloadBid, error)
|
||||
}
|
||||
@@ -14,6 +14,7 @@ go_library(
|
||||
"getters_deposits.go",
|
||||
"getters_eth1.go",
|
||||
"getters_exit.go",
|
||||
"getters_gloas.go",
|
||||
"getters_misc.go",
|
||||
"getters_participation.go",
|
||||
"getters_payload_header.go",
|
||||
@@ -36,6 +37,7 @@ go_library(
|
||||
"setters_deposit_requests.go",
|
||||
"setters_deposits.go",
|
||||
"setters_eth1.go",
|
||||
"setters_gloas.go",
|
||||
"setters_misc.go",
|
||||
"setters_participation.go",
|
||||
"setters_payload_header.go",
|
||||
@@ -97,6 +99,7 @@ go_test(
|
||||
"getters_deposit_requests_test.go",
|
||||
"getters_deposits_test.go",
|
||||
"getters_exit_test.go",
|
||||
"getters_gloas_test.go",
|
||||
"getters_participation_test.go",
|
||||
"getters_setters_lookahead_test.go",
|
||||
"getters_test.go",
|
||||
@@ -113,6 +116,7 @@ go_test(
|
||||
"setters_deposit_requests_test.go",
|
||||
"setters_deposits_test.go",
|
||||
"setters_eth1_test.go",
|
||||
"setters_gloas_test.go",
|
||||
"setters_misc_test.go",
|
||||
"setters_participation_test.go",
|
||||
"setters_payload_header_test.go",
|
||||
|
||||
78
beacon-chain/state/state-native/getters_gloas.go
Normal file
78
beacon-chain/state/state-native/getters_gloas.go
Normal file
@@ -0,0 +1,78 @@
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"github.com/OffchainLabs/prysm/v7/consensus-types/blocks"
|
||||
"github.com/OffchainLabs/prysm/v7/consensus-types/interfaces"
|
||||
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
|
||||
"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
|
||||
}
|
||||
|
||||
// PendingPaymentSum returns the total pending payment amount for a builder.
|
||||
func (b *BeaconState) PendingPaymentSum(builderIndex primitives.ValidatorIndex) (uint64, error) {
|
||||
if b.version < version.Gloas {
|
||||
return 0, errNotSupported("PendingPaymentSum", b.version)
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
var total uint64
|
||||
for _, payment := range b.builderPendingPayments {
|
||||
if payment.Withdrawal.BuilderIndex == builderIndex {
|
||||
total += uint64(payment.Withdrawal.Amount)
|
||||
}
|
||||
}
|
||||
|
||||
return total, nil
|
||||
}
|
||||
|
||||
// PendingWithdrawalSum returns the total pending withdrawal amount for a builder.
|
||||
func (b *BeaconState) PendingWithdrawalSum(builderIndex primitives.ValidatorIndex) (uint64, error) {
|
||||
if b.version < version.Gloas {
|
||||
return 0, errNotSupported("PendingWithdrawalSum", b.version)
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
var total uint64
|
||||
for _, withdrawal := range b.builderPendingWithdrawals {
|
||||
if withdrawal.BuilderIndex == builderIndex {
|
||||
total += uint64(withdrawal.Amount)
|
||||
}
|
||||
}
|
||||
|
||||
return total, nil
|
||||
}
|
||||
|
||||
// LatestExecutionPayloadBid returns the cached latest execution payload bid for Gloas.
|
||||
func (b *BeaconState) LatestExecutionPayloadBid() (interfaces.ROExecutionPayloadBid, error) {
|
||||
if b.version < version.Gloas {
|
||||
return nil, errNotSupported("LatestExecutionPayloadBid", b.version)
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
if b.latestExecutionPayloadBid == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return blocks.WrappedROExecutionPayloadBid(b.latestExecutionPayloadBid.Copy())
|
||||
}
|
||||
171
beacon-chain/state/state-native/getters_gloas_test.go
Normal file
171
beacon-chain/state/state-native/getters_gloas_test.go
Normal file
@@ -0,0 +1,171 @@
|
||||
package state_native_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
state_native "github.com/OffchainLabs/prysm/v7/beacon-chain/state/state-native"
|
||||
"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(ðpb.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(ðpb.BeaconStateGloas{
|
||||
LatestBlockHash: hashBytes,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
got, err := st.LatestBlockHash()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, want, got)
|
||||
})
|
||||
}
|
||||
|
||||
func TestPendingPaymentSum(t *testing.T) {
|
||||
t.Run("returns error before gloas", func(t *testing.T) {
|
||||
st, _ := util.DeterministicGenesisState(t, 1)
|
||||
_, err := st.PendingPaymentSum(1)
|
||||
require.ErrorContains(t, "is not supported", err)
|
||||
})
|
||||
|
||||
t.Run("sums matching builder payments", func(t *testing.T) {
|
||||
const builder primitives.ValidatorIndex = 7
|
||||
st, err := state_native.InitializeFromProtoGloas(ðpb.BeaconStateGloas{
|
||||
BuilderPendingPayments: []*ethpb.BuilderPendingPayment{
|
||||
{
|
||||
Weight: 1,
|
||||
Withdrawal: ðpb.BuilderPendingWithdrawal{
|
||||
Amount: 10,
|
||||
BuilderIndex: builder,
|
||||
},
|
||||
},
|
||||
{
|
||||
Weight: 1,
|
||||
Withdrawal: ðpb.BuilderPendingWithdrawal{
|
||||
Amount: 20,
|
||||
BuilderIndex: 999,
|
||||
},
|
||||
},
|
||||
{
|
||||
Weight: 1,
|
||||
Withdrawal: ðpb.BuilderPendingWithdrawal{
|
||||
Amount: 30,
|
||||
BuilderIndex: builder,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
got, err := st.PendingPaymentSum(builder)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(40), got)
|
||||
|
||||
// No matching builder should return zero.
|
||||
got, err = st.PendingPaymentSum(primitives.ValidatorIndex(12345))
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(0), got)
|
||||
})
|
||||
}
|
||||
|
||||
func TestPendingWithdrawalSum(t *testing.T) {
|
||||
t.Run("returns error before gloas", func(t *testing.T) {
|
||||
st, _ := util.DeterministicGenesisState(t, 1)
|
||||
_, err := st.PendingWithdrawalSum(1)
|
||||
require.ErrorContains(t, "is not supported", err)
|
||||
})
|
||||
|
||||
t.Run("sums matching builder withdrawals", func(t *testing.T) {
|
||||
const builder primitives.ValidatorIndex = 3
|
||||
st, err := state_native.InitializeFromProtoGloas(ðpb.BeaconStateGloas{
|
||||
BuilderPendingWithdrawals: []*ethpb.BuilderPendingWithdrawal{
|
||||
{
|
||||
Amount: 5,
|
||||
BuilderIndex: builder,
|
||||
},
|
||||
{
|
||||
Amount: 7,
|
||||
BuilderIndex: 99,
|
||||
},
|
||||
{
|
||||
Amount: 11,
|
||||
BuilderIndex: builder,
|
||||
},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
got, err := st.PendingWithdrawalSum(builder)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(16), got)
|
||||
|
||||
got, err = st.PendingWithdrawalSum(primitives.ValidatorIndex(9999))
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(0), got)
|
||||
})
|
||||
}
|
||||
|
||||
func TestLatestExecutionPayloadBid(t *testing.T) {
|
||||
t.Run("returns error before gloas", func(t *testing.T) {
|
||||
st, _ := util.DeterministicGenesisState(t, 1)
|
||||
_, err := st.LatestExecutionPayloadBid()
|
||||
require.ErrorContains(t, "is not supported", err)
|
||||
})
|
||||
|
||||
t.Run("nil when unset", func(t *testing.T) {
|
||||
st, err := state_native.InitializeFromProtoGloas(ðpb.BeaconStateGloas{})
|
||||
require.NoError(t, err)
|
||||
|
||||
got, err := st.LatestExecutionPayloadBid()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, got == nil)
|
||||
})
|
||||
|
||||
t.Run("wraps stored bid", func(t *testing.T) {
|
||||
bid := ðpb.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: 1,
|
||||
BuilderIndex: 7,
|
||||
Slot: 9,
|
||||
Value: 11,
|
||||
ExecutionPayment: 12,
|
||||
BlobKzgCommitmentsRoot: bytes.Repeat([]byte{0x05}, 32),
|
||||
FeeRecipient: bytes.Repeat([]byte{0x06}, 20),
|
||||
}
|
||||
st, err := state_native.InitializeFromProtoGloas(ðpb.BeaconStateGloas{
|
||||
LatestExecutionPayloadBid: bid,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
got, err := st.LatestExecutionPayloadBid()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, primitives.ValidatorIndex(7), got.BuilderIndex())
|
||||
require.Equal(t, primitives.Gwei(11), got.Value())
|
||||
require.Equal(t, primitives.Gwei(12), got.ExecutionPayment())
|
||||
})
|
||||
}
|
||||
56
beacon-chain/state/state-native/setters_gloas.go
Normal file
56
beacon-chain/state/state-native/setters_gloas.go
Normal file
@@ -0,0 +1,56 @@
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"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"
|
||||
)
|
||||
|
||||
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 = ðpb.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()
|
||||
|
||||
b.builderPendingPayments[index] = ethpb.CopyBuilderPendingPayment(payment)
|
||||
|
||||
b.markFieldAsDirty(types.BuilderPendingPayments)
|
||||
return nil
|
||||
}
|
||||
127
beacon-chain/state/state-native/setters_gloas_test.go
Normal file
127
beacon-chain/state/state-native/setters_gloas_test.go
Normal file
@@ -0,0 +1,127 @@
|
||||
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.ValidatorIndex
|
||||
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.ValidatorIndex {
|
||||
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.ValidatorIndex(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, ðpb.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 := ðpb.BuilderPendingPayment{
|
||||
Weight: 2,
|
||||
Withdrawal: ðpb.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)
|
||||
})
|
||||
}
|
||||
3
changelog/ttsao_add-gloas-bid-processing.md
Normal file
3
changelog/ttsao_add-gloas-bid-processing.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Added
|
||||
|
||||
- Add Gloas latest execution bid processing
|
||||
@@ -59,6 +59,7 @@ type BeaconChainConfig struct {
|
||||
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.
|
||||
CompoundingWithdrawalPrefixByte byte `yaml:"COMPOUNDING_WITHDRAWAL_PREFIX" spec:"true"` // CompoundingWithdrawalPrefixByteByte is used for compounding withdrawals and it's the first byte.
|
||||
BuilderWithdrawalPrefixByte byte `yaml:"BUILDER_WITHDRAWAL_PREFIX" spec:"true"` // BuilderWithdrawalPrefixByte is used for builder withdrawals and it's the first byte.
|
||||
ZeroHash [32]byte // ZeroHash is used to represent a zeroed out 32 byte array.
|
||||
|
||||
// Time parameters constants.
|
||||
@@ -139,6 +140,7 @@ type BeaconChainConfig struct {
|
||||
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.
|
||||
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.
|
||||
GenesisValidatorsRoot [32]byte // GenesisValidatorsRoot is the root hash of the genesis validators.
|
||||
|
||||
@@ -94,6 +94,7 @@ var mainnetBeaconConfig = &BeaconChainConfig{
|
||||
BLSWithdrawalPrefixByte: byte(0),
|
||||
ETH1AddressWithdrawalPrefixByte: byte(1),
|
||||
CompoundingWithdrawalPrefixByte: byte(2),
|
||||
BuilderWithdrawalPrefixByte: byte(3),
|
||||
ZeroHash: [32]byte{},
|
||||
|
||||
// Time parameter constants.
|
||||
@@ -182,6 +183,7 @@ var mainnetBeaconConfig = &BeaconChainConfig{
|
||||
DomainApplicationMask: bytesutil.Uint32ToBytes4(0x00000001),
|
||||
DomainApplicationBuilder: bytesutil.Uint32ToBytes4(0x00000001),
|
||||
DomainBLSToExecutionChange: bytesutil.Uint32ToBytes4(0x0A000000),
|
||||
DomainBeaconBuilder: bytesutil.Uint32ToBytes4(0x1B000000),
|
||||
|
||||
// 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},
|
||||
|
||||
@@ -14,11 +14,13 @@ go_library(
|
||||
"roblock.go",
|
||||
"rodatacolumn.go",
|
||||
"setters.go",
|
||||
"signed_execution_bid.go",
|
||||
"types.go",
|
||||
],
|
||||
importpath = "github.com/OffchainLabs/prysm/v7/consensus-types/blocks",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//beacon-chain/core/signing:go_default_library",
|
||||
"//beacon-chain/state/stateutil:go_default_library",
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
@@ -54,9 +56,11 @@ go_test(
|
||||
"roblock_test.go",
|
||||
"rodatacolumn_test.go",
|
||||
"setters_test.go",
|
||||
"signed_execution_bid_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//beacon-chain/core/signing:go_default_library",
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types:go_default_library",
|
||||
|
||||
@@ -641,6 +641,8 @@ func BuildSignedBeaconBlockFromExecutionPayload(blk interfaces.ReadOnlySignedBea
|
||||
},
|
||||
Signature: sig[:],
|
||||
}
|
||||
case version.Gloas:
|
||||
return nil, errors.Wrap(errUnsupportedBeaconBlock, "gloas blocks are not supported in this function")
|
||||
default:
|
||||
return nil, errors.New("Block not of known type")
|
||||
}
|
||||
|
||||
@@ -669,6 +669,7 @@ func hydrateBeaconBlockBodyGloas() *eth.BeaconBlockBodyGloas {
|
||||
ParentBlockHash: make([]byte, fieldparams.RootLength),
|
||||
ParentBlockRoot: make([]byte, fieldparams.RootLength),
|
||||
BlockHash: make([]byte, fieldparams.RootLength),
|
||||
PrevRandao: make([]byte, fieldparams.RootLength),
|
||||
FeeRecipient: make([]byte, 20),
|
||||
BlobKzgCommitmentsRoot: make([]byte, fieldparams.RootLength),
|
||||
},
|
||||
|
||||
140
consensus-types/blocks/signed_execution_bid.go
Normal file
140
consensus-types/blocks/signed_execution_bid.go
Normal file
@@ -0,0 +1,140 @@
|
||||
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.BlobKzgCommitmentsRoot) != 32 {
|
||||
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.ValidatorIndex {
|
||||
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)
|
||||
}
|
||||
92
consensus-types/blocks/signed_execution_bid_test.go
Normal file
92
consensus-types/blocks/signed_execution_bid_test.go
Normal file
@@ -0,0 +1,92 @@
|
||||
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 ðpb.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) {
|
||||
invalid := validExecutionPayloadBid()
|
||||
invalid.ParentBlockHash = []byte{0x01}
|
||||
_, 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.ValidatorIndex(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 := ðpb.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 := ðpb.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)
|
||||
})
|
||||
}
|
||||
@@ -6,6 +6,7 @@ go_library(
|
||||
"beacon_block.go",
|
||||
"error.go",
|
||||
"light_client.go",
|
||||
"signed_execution_payload_bid.go",
|
||||
"utils.go",
|
||||
"validator.go",
|
||||
],
|
||||
|
||||
28
consensus-types/interfaces/signed_execution_payload_bid.go
Normal file
28
consensus-types/interfaces/signed_execution_payload_bid.go
Normal 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.ValidatorIndex
|
||||
Slot() primitives.Slot
|
||||
Value() primitives.Gwei
|
||||
ExecutionPayment() primitives.Gwei
|
||||
BlobKzgCommitmentsRoot() [32]byte
|
||||
FeeRecipient() [20]byte
|
||||
IsNil() bool
|
||||
}
|
||||
@@ -174,3 +174,29 @@ func copyBeaconBlockBodyGloas(body *BeaconBlockBodyGloas) *BeaconBlockBodyGloas
|
||||
|
||||
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,
|
||||
WithdrawableEpoch: original.WithdrawableEpoch,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1246,3 +1246,99 @@ func genPayloadAttestations(num int) []*v1alpha1.PayloadAttestation {
|
||||
}
|
||||
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.ValidatorIndex(3),
|
||||
WithdrawableEpoch: primitives.Epoch(4),
|
||||
}
|
||||
|
||||
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.ValidatorIndex(9)
|
||||
original.WithdrawableEpoch = primitives.Epoch(10)
|
||||
|
||||
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.ValidatorIndex(3) {
|
||||
t.Fatalf("builder index mutated on copy: %d", copied.BuilderIndex)
|
||||
}
|
||||
if copied.WithdrawableEpoch != primitives.Epoch(4) {
|
||||
t.Fatalf("withdrawable epoch mutated on copy: %d", copied.WithdrawableEpoch)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
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.ValidatorIndex(7),
|
||||
WithdrawableEpoch: primitives.Epoch(8),
|
||||
},
|
||||
}
|
||||
|
||||
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.ValidatorIndex(9)
|
||||
original.Withdrawal.WithdrawableEpoch = primitives.Epoch(11)
|
||||
|
||||
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.ValidatorIndex(7) {
|
||||
t.Fatalf("withdrawal builder index mutated on copy: %d", copied.Withdrawal.BuilderIndex)
|
||||
}
|
||||
if copied.Withdrawal.WithdrawableEpoch != primitives.Epoch(8) {
|
||||
t.Fatalf("withdrawal epoch mutated on copy: %d", copied.Withdrawal.WithdrawableEpoch)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -13,11 +13,13 @@ func (header *ExecutionPayloadBid) Copy() *ExecutionPayloadBid {
|
||||
ParentBlockHash: bytesutil.SafeCopyBytes(header.ParentBlockHash),
|
||||
ParentBlockRoot: bytesutil.SafeCopyBytes(header.ParentBlockRoot),
|
||||
BlockHash: bytesutil.SafeCopyBytes(header.BlockHash),
|
||||
PrevRandao: bytesutil.SafeCopyBytes(header.PrevRandao),
|
||||
FeeRecipient: bytesutil.SafeCopyBytes(header.FeeRecipient),
|
||||
GasLimit: header.GasLimit,
|
||||
BuilderIndex: header.BuilderIndex,
|
||||
Slot: header.Slot,
|
||||
Value: header.Value,
|
||||
ExecutionPayment: header.ExecutionPayment,
|
||||
BlobKzgCommitmentsRoot: bytesutil.SafeCopyBytes(header.BlobKzgCommitmentsRoot),
|
||||
}
|
||||
}
|
||||
|
||||
1040
proto/prysm/v1alpha1/gloas.pb.go
generated
1040
proto/prysm/v1alpha1/gloas.pb.go
generated
File diff suppressed because it is too large
Load Diff
@@ -26,30 +26,37 @@ option go_package = "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1;eth";
|
||||
// parent_block_hash: Hash32
|
||||
// parent_block_root: Root
|
||||
// block_hash: Hash32
|
||||
// prev_randao: Bytes32
|
||||
// fee_recipient: ExecutionAddress
|
||||
// gas_limit: uint64
|
||||
// builder_index: ValidatorIndex
|
||||
// slot: Slot
|
||||
// value: Gwei
|
||||
// execution_payment: Gwei
|
||||
// blob_kzg_commitments_root: Root
|
||||
message ExecutionPayloadBid {
|
||||
bytes parent_block_hash = 1 [ (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 fee_recipient = 4 [ (ethereum.eth.ext.ssz_size) = "20" ];
|
||||
uint64 gas_limit = 5;
|
||||
uint64 builder_index = 6 [ (ethereum.eth.ext.cast_type) =
|
||||
bytes prev_randao = 4 [ (ethereum.eth.ext.ssz_size) = "32" ];
|
||||
bytes fee_recipient = 5 [ (ethereum.eth.ext.ssz_size) = "20" ];
|
||||
uint64 gas_limit = 6;
|
||||
uint64 builder_index = 7 [ (ethereum.eth.ext.cast_type) =
|
||||
"github.com/OffchainLabs/prysm/v7/"
|
||||
"consensus-types/primitives.ValidatorIndex" ];
|
||||
uint64 slot = 7 [
|
||||
uint64 slot = 8 [
|
||||
(ethereum.eth.ext.cast_type) =
|
||||
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives.Slot"
|
||||
];
|
||||
uint64 value = 8 [
|
||||
uint64 value = 9 [
|
||||
(ethereum.eth.ext.cast_type) =
|
||||
"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.
|
||||
|
||||
@@ -37,26 +37,36 @@ func (e *ExecutionPayloadBid) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
||||
}
|
||||
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 {
|
||||
err = ssz.ErrBytesLengthFn("--.FeeRecipient", size, 20)
|
||||
return
|
||||
}
|
||||
dst = append(dst, e.FeeRecipient...)
|
||||
|
||||
// Field (4) 'GasLimit'
|
||||
// Field (5) 'GasLimit'
|
||||
dst = ssz.MarshalUint64(dst, e.GasLimit)
|
||||
|
||||
// Field (5) 'BuilderIndex'
|
||||
// Field (6) 'BuilderIndex'
|
||||
dst = ssz.MarshalUint64(dst, uint64(e.BuilderIndex))
|
||||
|
||||
// Field (6) 'Slot'
|
||||
// Field (7) 'Slot'
|
||||
dst = ssz.MarshalUint64(dst, uint64(e.Slot))
|
||||
|
||||
// Field (7) 'Value'
|
||||
// Field (8) '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 {
|
||||
err = ssz.ErrBytesLengthFn("--.BlobKzgCommitmentsRoot", size, 32)
|
||||
return
|
||||
@@ -70,7 +80,7 @@ func (e *ExecutionPayloadBid) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
||||
func (e *ExecutionPayloadBid) UnmarshalSSZ(buf []byte) error {
|
||||
var err error
|
||||
size := uint64(len(buf))
|
||||
if size != 180 {
|
||||
if size != 220 {
|
||||
return ssz.ErrSize
|
||||
}
|
||||
|
||||
@@ -92,36 +102,45 @@ func (e *ExecutionPayloadBid) UnmarshalSSZ(buf []byte) error {
|
||||
}
|
||||
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 {
|
||||
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'
|
||||
e.GasLimit = ssz.UnmarshallUint64(buf[116:124])
|
||||
// Field (5) 'GasLimit'
|
||||
e.GasLimit = ssz.UnmarshallUint64(buf[148:156])
|
||||
|
||||
// Field (5) 'BuilderIndex'
|
||||
e.BuilderIndex = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[124:132]))
|
||||
// Field (6) 'BuilderIndex'
|
||||
e.BuilderIndex = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[156:164]))
|
||||
|
||||
// Field (6) 'Slot'
|
||||
e.Slot = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[132:140]))
|
||||
// Field (7) 'Slot'
|
||||
e.Slot = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[164:172]))
|
||||
|
||||
// Field (7) 'Value'
|
||||
e.Value = github_com_OffchainLabs_prysm_v7_consensus_types_primitives.Gwei(ssz.UnmarshallUint64(buf[140:148]))
|
||||
// Field (8) 'Value'
|
||||
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 {
|
||||
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
|
||||
}
|
||||
|
||||
// SizeSSZ returns the ssz encoded size in bytes for the ExecutionPayloadBid object
|
||||
func (e *ExecutionPayloadBid) SizeSSZ() (size int) {
|
||||
size = 180
|
||||
size = 220
|
||||
return
|
||||
}
|
||||
|
||||
@@ -155,26 +174,36 @@ func (e *ExecutionPayloadBid) HashTreeRootWith(hh *ssz.Hasher) (err error) {
|
||||
}
|
||||
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 {
|
||||
err = ssz.ErrBytesLengthFn("--.FeeRecipient", size, 20)
|
||||
return
|
||||
}
|
||||
hh.PutBytes(e.FeeRecipient)
|
||||
|
||||
// Field (4) 'GasLimit'
|
||||
// Field (5) 'GasLimit'
|
||||
hh.PutUint64(e.GasLimit)
|
||||
|
||||
// Field (5) 'BuilderIndex'
|
||||
// Field (6) 'BuilderIndex'
|
||||
hh.PutUint64(uint64(e.BuilderIndex))
|
||||
|
||||
// Field (6) 'Slot'
|
||||
// Field (7) 'Slot'
|
||||
hh.PutUint64(uint64(e.Slot))
|
||||
|
||||
// Field (7) 'Value'
|
||||
// Field (8) '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 {
|
||||
err = ssz.ErrBytesLengthFn("--.BlobKzgCommitmentsRoot", size, 32)
|
||||
return
|
||||
@@ -216,7 +245,7 @@ func (s *SignedExecutionPayloadBid) MarshalSSZTo(buf []byte) (dst []byte, err er
|
||||
func (s *SignedExecutionPayloadBid) UnmarshalSSZ(buf []byte) error {
|
||||
var err error
|
||||
size := uint64(len(buf))
|
||||
if size != 276 {
|
||||
if size != 316 {
|
||||
return ssz.ErrSize
|
||||
}
|
||||
|
||||
@@ -224,22 +253,22 @@ func (s *SignedExecutionPayloadBid) UnmarshalSSZ(buf []byte) error {
|
||||
if s.Message == nil {
|
||||
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
|
||||
}
|
||||
|
||||
// Field (1) 'Signature'
|
||||
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
|
||||
}
|
||||
|
||||
// SizeSSZ returns the ssz encoded size in bytes for the SignedExecutionPayloadBid object
|
||||
func (s *SignedExecutionPayloadBid) SizeSSZ() (size int) {
|
||||
size = 276
|
||||
size = 316
|
||||
return
|
||||
}
|
||||
|
||||
@@ -713,7 +742,7 @@ func (b *BeaconBlockBodyGloas) MarshalSSZ() ([]byte, error) {
|
||||
// MarshalSSZTo ssz marshals the BeaconBlockBodyGloas object to a target array
|
||||
func (b *BeaconBlockBodyGloas) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
||||
dst = buf
|
||||
offset := int(664)
|
||||
offset := int(704)
|
||||
|
||||
// Field (0) 'RandaoReveal'
|
||||
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 {
|
||||
var err error
|
||||
size := uint64(len(buf))
|
||||
if size < 664 {
|
||||
if size < 704 {
|
||||
return ssz.ErrSize
|
||||
}
|
||||
|
||||
@@ -917,7 +946,7 @@ func (b *BeaconBlockBodyGloas) UnmarshalSSZ(buf []byte) error {
|
||||
return ssz.ErrOffset
|
||||
}
|
||||
|
||||
if o3 != 664 {
|
||||
if o3 != 704 {
|
||||
return ssz.ErrInvalidVariableOffset
|
||||
}
|
||||
|
||||
@@ -958,12 +987,12 @@ func (b *BeaconBlockBodyGloas) UnmarshalSSZ(buf []byte) error {
|
||||
if b.SignedExecutionPayloadBid == nil {
|
||||
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
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
@@ -1105,7 +1134,7 @@ func (b *BeaconBlockBodyGloas) UnmarshalSSZ(buf []byte) error {
|
||||
|
||||
// SizeSSZ returns the ssz encoded size in bytes for the BeaconBlockBodyGloas object
|
||||
func (b *BeaconBlockBodyGloas) SizeSSZ() (size int) {
|
||||
size = 664
|
||||
size = 704
|
||||
|
||||
// Field (3) 'ProposerSlashings'
|
||||
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
|
||||
func (b *BeaconStateGloas) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
||||
dst = buf
|
||||
offset := int(2741821)
|
||||
offset := int(2741861)
|
||||
|
||||
// Field (0) 'GenesisTime'
|
||||
dst = ssz.MarshalUint64(dst, b.GenesisTime)
|
||||
@@ -1795,7 +1824,7 @@ func (b *BeaconStateGloas) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
||||
func (b *BeaconStateGloas) UnmarshalSSZ(buf []byte) error {
|
||||
var err error
|
||||
size := uint64(len(buf))
|
||||
if size < 2741821 {
|
||||
if size < 2741861 {
|
||||
return ssz.ErrSize
|
||||
}
|
||||
|
||||
@@ -1853,7 +1882,7 @@ func (b *BeaconStateGloas) UnmarshalSSZ(buf []byte) error {
|
||||
return ssz.ErrOffset
|
||||
}
|
||||
|
||||
if o7 != 2741821 {
|
||||
if o7 != 2741861 {
|
||||
return ssz.ErrInvalidVariableOffset
|
||||
}
|
||||
|
||||
@@ -1963,65 +1992,65 @@ func (b *BeaconStateGloas) UnmarshalSSZ(buf []byte) error {
|
||||
if b.LatestExecutionPayloadBid == nil {
|
||||
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
|
||||
}
|
||||
|
||||
// Field (25) 'NextWithdrawalIndex'
|
||||
b.NextWithdrawalIndex = ssz.UnmarshallUint64(buf[2736809:2736817])
|
||||
b.NextWithdrawalIndex = ssz.UnmarshallUint64(buf[2736849:2736857])
|
||||
|
||||
// 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'
|
||||
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
|
||||
}
|
||||
|
||||
// Field (28) 'DepositRequestsStartIndex'
|
||||
b.DepositRequestsStartIndex = ssz.UnmarshallUint64(buf[2736829:2736837])
|
||||
b.DepositRequestsStartIndex = ssz.UnmarshallUint64(buf[2736869:2736877])
|
||||
|
||||
// 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'
|
||||
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'
|
||||
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'
|
||||
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'
|
||||
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'
|
||||
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
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// Field (37) 'ProposerLookahead'
|
||||
b.ProposerLookahead = ssz.ExtendUint64(b.ProposerLookahead, 64)
|
||||
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'
|
||||
if cap(b.ExecutionPayloadAvailability) == 0 {
|
||||
b.ExecutionPayloadAvailability = make([]byte, 0, len(buf[2737401:2738425]))
|
||||
b.ExecutionPayloadAvailability = make([]byte, 0, len(buf[2737441:2738465]))
|
||||
}
|
||||
b.ExecutionPayloadAvailability = append(b.ExecutionPayloadAvailability, buf[2737401:2738425]...)
|
||||
b.ExecutionPayloadAvailability = append(b.ExecutionPayloadAvailability, buf[2737441:2738465]...)
|
||||
|
||||
// Field (39) 'BuilderPendingPayments'
|
||||
b.BuilderPendingPayments = make([]*BuilderPendingPayment, 64)
|
||||
@@ -2029,27 +2058,27 @@ func (b *BeaconStateGloas) UnmarshalSSZ(buf []byte) error {
|
||||
if b.BuilderPendingPayments[ii] == nil {
|
||||
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[2738465:2741793][ii*52 : (ii+1)*52]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Offset (40) 'BuilderPendingWithdrawals'
|
||||
if o40 = ssz.ReadOffset(buf[2741753:2741757]); o40 > size || o36 > o40 {
|
||||
if o40 = ssz.ReadOffset(buf[2741793:2741797]); o40 > size || o36 > o40 {
|
||||
return ssz.ErrOffset
|
||||
}
|
||||
|
||||
// Field (41) 'LatestBlockHash'
|
||||
if cap(b.LatestBlockHash) == 0 {
|
||||
b.LatestBlockHash = make([]byte, 0, len(buf[2741757:2741789]))
|
||||
b.LatestBlockHash = make([]byte, 0, len(buf[2741797:2741829]))
|
||||
}
|
||||
b.LatestBlockHash = append(b.LatestBlockHash, buf[2741757:2741789]...)
|
||||
b.LatestBlockHash = append(b.LatestBlockHash, buf[2741797:2741829]...)
|
||||
|
||||
// Field (42) 'LatestWithdrawalsRoot'
|
||||
if cap(b.LatestWithdrawalsRoot) == 0 {
|
||||
b.LatestWithdrawalsRoot = make([]byte, 0, len(buf[2741789:2741821]))
|
||||
b.LatestWithdrawalsRoot = make([]byte, 0, len(buf[2741829:2741861]))
|
||||
}
|
||||
b.LatestWithdrawalsRoot = append(b.LatestWithdrawalsRoot, buf[2741789:2741821]...)
|
||||
b.LatestWithdrawalsRoot = append(b.LatestWithdrawalsRoot, buf[2741829:2741861]...)
|
||||
|
||||
// Field (7) 'HistoricalRoots'
|
||||
{
|
||||
@@ -2247,7 +2276,7 @@ func (b *BeaconStateGloas) UnmarshalSSZ(buf []byte) error {
|
||||
|
||||
// SizeSSZ returns the ssz encoded size in bytes for the BeaconStateGloas object
|
||||
func (b *BeaconStateGloas) SizeSSZ() (size int) {
|
||||
size = 2741821
|
||||
size = 2741861
|
||||
|
||||
// Field (7) 'HistoricalRoots'
|
||||
size += len(b.HistoricalRoots) * 32
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
version: v1.6.0
|
||||
version: v1.6.1
|
||||
style: full
|
||||
|
||||
specrefs:
|
||||
@@ -358,7 +358,6 @@ exceptions:
|
||||
- process_proposer_slashing#gloas
|
||||
- process_slot#gloas
|
||||
- process_withdrawals#gloas
|
||||
- remove_flag#gloas
|
||||
- should_extend_payload#gloas
|
||||
- update_latest_messages#gloas
|
||||
- upgrade_to_gloas#gloas
|
||||
|
||||
@@ -200,6 +200,7 @@ go_test(
|
||||
"fulu__sanity__blocks_test.go",
|
||||
"fulu__sanity__slots_test.go",
|
||||
"fulu__ssz_static__ssz_static_test.go",
|
||||
"gloas__operations__execution_payload_header_test.go",
|
||||
"gloas__ssz_static__ssz_static_test.go",
|
||||
"phase0__epoch_processing__effective_balance_updates_test.go",
|
||||
"phase0__epoch_processing__epoch_processing_test.go",
|
||||
@@ -278,6 +279,7 @@ go_test(
|
||||
"//testing/spectest/shared/fulu/rewards:go_default_library",
|
||||
"//testing/spectest/shared/fulu/sanity: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/finality:go_default_library",
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package mainnet
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/OffchainLabs/prysm/v7/testing/spectest/shared/gloas/operations"
|
||||
)
|
||||
|
||||
func TestMainnet_Gloas_Operations_ExecutionPayloadHeader(t *testing.T) {
|
||||
operations.RunExecutionPayloadBidTest(t, "mainnet")
|
||||
}
|
||||
@@ -206,6 +206,7 @@ go_test(
|
||||
"fulu__sanity__blocks_test.go",
|
||||
"fulu__sanity__slots_test.go",
|
||||
"fulu__ssz_static__ssz_static_test.go",
|
||||
"gloas__operations__execution_payload_bid_test.go",
|
||||
"gloas__ssz_static__ssz_static_test.go",
|
||||
"phase0__epoch_processing__effective_balance_updates_test.go",
|
||||
"phase0__epoch_processing__epoch_processing_test.go",
|
||||
@@ -288,6 +289,7 @@ go_test(
|
||||
"//testing/spectest/shared/fulu/rewards:go_default_library",
|
||||
"//testing/spectest/shared/fulu/sanity: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/finality:go_default_library",
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package minimal
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/OffchainLabs/prysm/v7/testing/spectest/shared/gloas/operations"
|
||||
)
|
||||
|
||||
func TestMinimal_Gloas_Operations_ExecutionPayloadHeader(t *testing.T) {
|
||||
operations.RunExecutionPayloadBidTest(t, "minimal")
|
||||
}
|
||||
@@ -12,6 +12,7 @@ go_library(
|
||||
"deposit.go",
|
||||
"deposit_request.go",
|
||||
"execution_payload.go",
|
||||
"execution_payload_bid.go",
|
||||
"proposer_slashing.go",
|
||||
"slashing.go",
|
||||
"sync_aggregate.go",
|
||||
@@ -26,6 +27,7 @@ go_library(
|
||||
"//beacon-chain/core/altair:go_default_library",
|
||||
"//beacon-chain/core/blocks: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/validators:go_default_library",
|
||||
"//beacon-chain/state:go_default_library",
|
||||
|
||||
@@ -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
|
||||
})
|
||||
}
|
||||
21
testing/spectest/shared/gloas/operations/BUILD.bazel
Normal file
21
testing/spectest/shared/gloas/operations/BUILD.bazel
Normal 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",
|
||||
],
|
||||
)
|
||||
@@ -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(ðpb.SignedBeaconBlockGloas{Block: &block})
|
||||
}
|
||||
|
||||
func RunExecutionPayloadBidTest(t *testing.T, config string) {
|
||||
common.RunExecutionPayloadBidTest(t, config, version.String(version.Gloas), blockWithSignedExecutionPayloadBid, sszToState)
|
||||
}
|
||||
15
testing/spectest/shared/gloas/operations/helpers.go
Normal file
15
testing/spectest/shared/gloas/operations/helpers.go
Normal 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 := ðpb.BeaconStateGloas{}
|
||||
if err := base.UnmarshalSSZ(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return state_native.InitializeFromProtoGloas(base)
|
||||
}
|
||||
Reference in New Issue
Block a user