gloas: add new execution payload bid processing#15638
Conversation
db6c8de to
2344512
Compare
2344512 to
24afb03
Compare
9b74781 to
1f182f1
Compare
7fdffad to
62b5aba
Compare
| return fmt.Errorf("invalid signature format: %w", err) | ||
| } | ||
|
|
||
| currentEpoch := slots.ToEpoch(bid.Slot()) |
There was a problem hiding this comment.
should this be from the bid or form the state slot? or do they need to be checked against each other?
There was a problem hiding this comment.
we verified bid.Slot() == block.Slot() and in process_block_header, we also verified state.Slot() == block.Slot() so they all are consistent
| if amount != 0 { | ||
| return fmt.Errorf("self-build amount must be zero, got %d", amount) | ||
| } | ||
| if wrappedBid.Signature() != common.InfiniteSignature { |
There was a problem hiding this comment.
I think this should be !bytes.Equal(wrappedBid.Signature(),common.InfiniteSignature)
There was a problem hiding this comment.
both of them are [96]byte..
wrappedBid.Signature() != common.InfiniteSignature wouldn't work?
There was a problem hiding this comment.
yeah actually i'm probably wrong on this i just usually see bytes.Equal when comparing bytes but checked myself that this should be fine
| if err != nil { | ||
| return fmt.Errorf("failed to get randao mix: %w", err) | ||
| } | ||
| if bid.PrevRandao() != [32]byte(randaoMix) { |
There was a problem hiding this comment.
what about doing something like
bidPrevRandao := bid.PrevRandao()
if !bytes.Equal(bidPrevRandao[:], randaoMix) {
There was a problem hiding this comment.
any real concern with casting? at this point we know randaoMix is 32 bytes and casting is a bit easier to read / very marginally faster, we also use this [32]byte cast in a bunch of places in prysm already
There was a problem hiding this comment.
I think similiar to the previous one I was just more used to seeing bytes.Equal comparison because most were slices vs arrays for bytes. but as a follow up when do we [32]byte cast this way vs using bytesutil.ToBytes32( I think we usually use the latter
| }, | ||
| } | ||
| slotIndex := params.BeaconConfig().SlotsPerEpoch + (bid.Slot() % params.BeaconConfig().SlotsPerEpoch) | ||
| if err := st.SetBuilderPendingPayment(slotIndex, pendingPayment); err != nil { |
There was a problem hiding this comment.
since the underlying value is a slice when you set builder pending payment, do we need any safety checks on slotIndex so that it's not some out of bound index compared to the underlying slice
There was a problem hiding this comment.
i think it makes sense to bound check in SetBuilderPendingPayment
There was a problem hiding this comment.
I don't think i see a bounds check added for this one yet
| } | ||
|
|
||
| // CopyBuilderPendingPayment creates a deep copy of a builder pending payment. | ||
| func CopyBuilderPendingPayment(original *BuilderPendingPayment) *BuilderPendingPayment { |
There was a problem hiding this comment.
not sure if it's part of another pr but some stuff is missing maybe due to updated gloas proto?
- copySignedExecutionPayloadBid missing PrevRandao and ExecutionPayment
- copyPayloadAttestation shallow-copies AggregationBits
- genExecutionPayloadBidGloas test helper missing those same fields
There was a problem hiding this comment.
we'll do them in later prs
|
|
||
| builderIndex := bid.BuilderIndex() | ||
| proposerIndex := block.ProposerIndex() | ||
| amount := bid.Value() |
There was a problem hiding this comment.
What's the difference between value and executionPayment?
There was a problem hiding this comment.
one is in protocol, through consensus,
one is out of protocol, optional
62b5aba to
34a4aa4
Compare
00fc4a7 to
0816f23
Compare
40a2e53 to
ec80c47
Compare
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
ec80c47 to
3343ce7
Compare
| return true | ||
| } | ||
|
|
||
| if len(h.payload.ParentBlockHash) != 32 || |
There was a problem hiding this comment.
checks for prev randao and feerecipient are missing here
james-prysm
left a comment
There was a problem hiding this comment.
all my comments have been addressed
e6eec11 to
3dd766f
Compare
potuz
left a comment
There was a problem hiding this comment.
The model likes fmt.Errorf("my error %w", err) when most of our code likes errors.Wrap.
Left a few comments about unnecessary copies in getters in the state. We should try to avoid these early in the fork to avoid piling performance issues.
| 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) |
There was a problem hiding this comment.
Why not wrapping the error instead?
There was a problem hiding this comment.
%w in fmt.Errorf wraps an error
| 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") |
There was a problem hiding this comment.
| return errors.New("self-build signature must be point at infinity") | |
| return errors.New("self-build signature must be the point at infinity") |
| b.lock.RLock() | ||
| defer b.lock.RUnlock() | ||
|
|
||
| builder, err := b.builderAtIndex(builderIndex) |
There was a problem hiding this comment.
I don't like that this is an internal beacon state getter that is copying a builder when it doesn't. This applies to others in the state package, even away from Gloas.
There was a problem hiding this comment.
in particular I think we should stick to non exported methods to NOT copy the structure or at least agree on a common convention.
| b.lock.RLock() | ||
| defer b.lock.RUnlock() | ||
|
|
||
| builder, err := b.builderAtIndex(builderIndex) |
potuz
left a comment
There was a problem hiding this comment.
Second pass, looks good to me, need a last pass on the last files.
| } | ||
| func (s stubBlock) HashTreeRootWith(*fastssz.Hasher) error { return nil } | ||
|
|
||
| func buildGloasState(t *testing.T, slot primitives.Slot, proposerIdx primitives.ValidatorIndex, builderIdx primitives.BuilderIndex, balance uint64, randao [32]byte, latestHash [32]byte, builderPubkey [48]byte) *state_native.BeaconState { |
There was a problem hiding this comment.
Why do we have these functions here? we typically have a deterministic state builder for tests in the testing package.
There was a problem hiding this comment.
I find that hand crafting the block and state is a better exercise than using a deterministic state. Doing it by hand forces you to think carefully about which fields are required and which are not, rather than taking everything for granted. That said, I may revert back to a deterministic since this is a lot of work
| 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) { |
There was a problem hiding this comment.
The intention is that stubBlock and stubBlockBody satisfy the right interfaces? in this case perhaps it's good to add an assert right here that they do.
| return false, nil | ||
| } | ||
|
|
||
| return balance-minBalance >= uint64(bidAmount), nil |
There was a problem hiding this comment.
I'm surprised this passes the linter, I thought gofmt would write this as balance - minBalance
There was a problem hiding this comment.
i wrote balance - minBalance and they changed back to balance-minBalance
| ) | ||
|
|
||
| func blockWithSignedExecutionPayloadBid(blockSSZ []byte) (interfaces.SignedBeaconBlock, error) { | ||
| var block ethpb.BeaconBlockGloas |
There was a problem hiding this comment.
The next two functions have either var block ethpb.BeaconBlockGloas or block := ðpb.BeaconBlockGloas{}. Why the difference?
There was a problem hiding this comment.
No reason, i didnt care too much about being consistent and nit in test, I can stick to one if you want, but i think that's hard to enforce across prysm with different authors
| 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") |
There was a problem hiding this comment.
Why is this? are there no more bid processing tests?
There was a problem hiding this comment.
No, i wanted to debug one test and forgot to uncomment to test the rest
This PR implements [process_execution_payload_bid](https://github.com/ethereum/consensus-specs/blob/master/specs/gloas/beacon-chain.md#new-process_execution_payload_bid) and spec tests
This PR implements process_execution_payload_bid and spec tests