Compare commits

...

9 Commits

Author SHA1 Message Date
Raul Jordan
1f403fd57f add 2022-07-07 11:29:15 -04:00
Raul Jordan
b67c885995 Major Simplification of JSON Handling for Execution Blocks (#10993)
* no more execution block custom type

* simpler json rpc data unmarshaling

* simplicify

* included hash and txs fix

* all tests

* pass

* build

* mock fix

* attempt build

* builds

* build

* builds

* pass

* pass

* build

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2022-07-06 22:06:00 +00:00
james-prysm
60ed488428 changing gaslimit to validator registration (#10992)
* changing gaslimit to validator registration

* adding new flag to enable validator registration for suggested fee recipient

* making sure default gaslimit is set

* Update cmd/validator/flags/flags.go

Co-authored-by: terencechain <terence@prysmaticlabs.com>

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: terencechain <terence@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2022-07-06 18:42:21 +00:00
Potuz
2f0e2886b4 Do not error if the LVH is bogus (#10996)
* Do not error if the LVH is bogus

* add tests and mark the regression PR

* dead code

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2022-07-06 17:37:15 +00:00
terencechain
2d53ae79df Cleanups to pulltips (#10984)
* Minor cleanups to pulltips

* Feedbacks

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2022-07-06 16:55:17 +00:00
Nishant Das
ce277cb388 Add Fuzzing For JSON Marshalling/Unmarshalling Methods (#10995)
* modify it

* add gaz

* revert

* deps

* revert change

* fix it
2022-07-06 15:15:14 +00:00
Raul Jordan
c9a366c36a Revert "Move Slasher E2E To Scenario Test" (#10986)
This reverts commit 65900115fc.

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2022-07-06 13:03:30 +00:00
terencechain
3a957c567f Handle invalid_block_hash error from ee (#10991)
* Handle invalid_block_hash error from ee

* Update beacon-chain/blockchain/error.go

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>

* Remove invalid block and state

* Revert "Remove invalid block and state"

This reverts commit 9ca011b8ce.

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
2022-07-06 00:22:12 +00:00
Raul Jordan
77a63f871d Included Blinded Beacon Block in V1alpha1 Protobuf (#10989)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
2022-07-05 21:03:14 +00:00
66 changed files with 1990 additions and 1713 deletions

View File

@@ -4,7 +4,9 @@ import "github.com/pkg/errors"
var (
// ErrInvalidPayload is returned when the payload is invalid
ErrInvalidPayload = errors.New("recevied an INVALID payload from execution engine")
ErrInvalidPayload = errors.New("received an INVALID payload from execution engine")
// ErrInvalidBlockHashPayloadStatus is returned when the payload has invalid block hash.
ErrInvalidBlockHashPayloadStatus = errors.New("received an INVALID_BLOCK_HASH payload from execution engine")
// ErrUndefinedExecutionEngineError is returned when the execution engine returns an error that is not defined
ErrUndefinedExecutionEngineError = errors.New("received an undefined ee error")
// errNilFinalizedInStore is returned when a nil finalized checkpt is returned from store.

View File

@@ -213,6 +213,9 @@ func (s *Service) notifyNewPayload(ctx context.Context, postStateVersion int,
"invalidCount": len(invalidRoots),
}).Warn("Pruned invalid blocks")
return false, invalidBlock{ErrInvalidPayload}
case powchain.ErrInvalidBlockHashPayloadStatus:
newPayloadInvalidNodeCount.Inc()
return false, invalidBlock{ErrInvalidBlockHashPayloadStatus}
default:
return false, errors.WithMessage(ErrUndefinedExecutionEngineError, err.Error())
}

View File

@@ -6,6 +6,7 @@ import (
"time"
"github.com/ethereum/go-ethereum/common"
gethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
@@ -673,16 +674,40 @@ func Test_NotifyNewPayload(t *testing.T) {
newPayloadErr: ErrUndefinedExecutionEngineError,
errString: ErrUndefinedExecutionEngineError.Error(),
},
{
name: "invalid block hash error from ee",
postState: bellatrixState,
blk: func() interfaces.SignedBeaconBlock {
blk := &ethpb.SignedBeaconBlockBellatrix{
Block: &ethpb.BeaconBlockBellatrix{
Body: &ethpb.BeaconBlockBodyBellatrix{
ExecutionPayload: &v1.ExecutionPayload{
ParentHash: bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength),
},
},
},
}
b, err := wrapper.WrappedSignedBeaconBlock(blk)
require.NoError(t, err)
return b
}(),
newPayloadErr: ErrInvalidBlockHashPayloadStatus,
errString: ErrInvalidBlockHashPayloadStatus.Error(),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
e := &mockPOW.EngineClient{ErrNewPayload: tt.newPayloadErr, BlockByHashMap: map[[32]byte]*v1.ExecutionBlock{}}
e.BlockByHashMap[[32]byte{'a'}] = &v1.ExecutionBlock{
ParentHash: bytesutil.PadTo([]byte{'b'}, fieldparams.RootLength),
Header: gethtypes.Header{
ParentHash: common.BytesToHash([]byte("b")),
},
TotalDifficulty: "0x2",
}
e.BlockByHashMap[[32]byte{'b'}] = &v1.ExecutionBlock{
ParentHash: bytesutil.PadTo([]byte{'3'}, fieldparams.RootLength),
Header: gethtypes.Header{
ParentHash: common.BytesToHash([]byte("3")),
},
TotalDifficulty: "0x1",
}
service.cfg.ExecutionEngineCaller = e
@@ -735,11 +760,15 @@ func Test_NotifyNewPayload_SetOptimisticToValid(t *testing.T) {
require.NoError(t, err)
e := &mockPOW.EngineClient{BlockByHashMap: map[[32]byte]*v1.ExecutionBlock{}}
e.BlockByHashMap[[32]byte{'a'}] = &v1.ExecutionBlock{
ParentHash: bytesutil.PadTo([]byte{'b'}, fieldparams.RootLength),
Header: gethtypes.Header{
ParentHash: common.BytesToHash([]byte("b")),
},
TotalDifficulty: "0x2",
}
e.BlockByHashMap[[32]byte{'b'}] = &v1.ExecutionBlock{
ParentHash: bytesutil.PadTo([]byte{'3'}, fieldparams.RootLength),
Header: gethtypes.Header{
ParentHash: common.BytesToHash([]byte("3")),
},
TotalDifficulty: "0x1",
}
service.cfg.ExecutionEngineCaller = e

View File

@@ -100,7 +100,7 @@ func (s *Service) getBlkParentHashAndTD(ctx context.Context, blkHash []byte) ([]
if overflows {
return nil, nil, errors.New("total difficulty overflows")
}
return blk.ParentHash, blkTDUint256, nil
return blk.ParentHash[:], blkTDUint256, nil
}
// validateTerminalBlockHash validates if the merge block is a valid terminal PoW block.

View File

@@ -6,12 +6,12 @@ import (
"math/big"
"testing"
gethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/holiman/uint256"
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
"github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/protoarray"
mocks "github.com/prysmaticlabs/prysm/beacon-chain/powchain/testing"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
"github.com/prysmaticlabs/prysm/config/params"
"github.com/prysmaticlabs/prysm/consensus-types/wrapper"
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
@@ -120,12 +120,19 @@ func Test_validateMergeBlock(t *testing.T) {
engine := &mocks.EngineClient{BlockByHashMap: map[[32]byte]*enginev1.ExecutionBlock{}}
service.cfg.ExecutionEngineCaller = engine
engine.BlockByHashMap[[32]byte{'a'}] = &enginev1.ExecutionBlock{
ParentHash: bytesutil.PadTo([]byte{'b'}, fieldparams.RootLength),
a := [32]byte{'a'}
b := [32]byte{'b'}
mergeBlockParentHash := [32]byte{'3'}
engine.BlockByHashMap[a] = &enginev1.ExecutionBlock{
Header: gethtypes.Header{
ParentHash: b,
},
TotalDifficulty: "0x2",
}
engine.BlockByHashMap[[32]byte{'b'}] = &enginev1.ExecutionBlock{
ParentHash: bytesutil.PadTo([]byte{'3'}, fieldparams.RootLength),
engine.BlockByHashMap[b] = &enginev1.ExecutionBlock{
Header: gethtypes.Header{
ParentHash: mergeBlockParentHash,
},
TotalDifficulty: "0x1",
}
blk := &ethpb.SignedBeaconBlockBellatrix{
@@ -133,18 +140,18 @@ func Test_validateMergeBlock(t *testing.T) {
Slot: 1,
Body: &ethpb.BeaconBlockBodyBellatrix{
ExecutionPayload: &enginev1.ExecutionPayload{
ParentHash: bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength),
ParentHash: a[:],
},
},
},
}
b, err := wrapper.WrappedSignedBeaconBlock(blk)
bk, err := wrapper.WrappedSignedBeaconBlock(blk)
require.NoError(t, err)
require.NoError(t, service.validateMergeBlock(ctx, b))
require.NoError(t, service.validateMergeBlock(ctx, bk))
cfg.TerminalTotalDifficulty = "1"
params.OverrideBeaconConfig(cfg)
err = service.validateMergeBlock(ctx, b)
err = service.validateMergeBlock(ctx, bk)
require.ErrorContains(t, "invalid TTD, configTTD: 1, currentTTD: 2, parentTTD: 1", err)
require.Equal(t, true, IsInvalidBlock(err))
}
@@ -167,7 +174,9 @@ func Test_getBlkParentHashAndTD(t *testing.T) {
p := [32]byte{'b'}
td := "0x1"
engine.BlockByHashMap[h] = &enginev1.ExecutionBlock{
ParentHash: p[:],
Header: gethtypes.Header{
ParentHash: p,
},
TotalDifficulty: td,
}
parentHash, totalDifficulty, err := service.getBlkParentHashAndTD(ctx, h[:])
@@ -183,14 +192,18 @@ func Test_getBlkParentHashAndTD(t *testing.T) {
require.ErrorContains(t, "pow block is nil", err)
engine.BlockByHashMap[h] = &enginev1.ExecutionBlock{
ParentHash: p[:],
Header: gethtypes.Header{
ParentHash: p,
},
TotalDifficulty: "1",
}
_, _, err = service.getBlkParentHashAndTD(ctx, h[:])
require.ErrorContains(t, "could not decode merge block total difficulty: hex string without 0x prefix", err)
engine.BlockByHashMap[h] = &enginev1.ExecutionBlock{
ParentHash: p[:],
Header: gethtypes.Header{
ParentHash: p,
},
TotalDifficulty: "0XFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
}
_, _, err = service.getBlkParentHashAndTD(ctx, h[:])

View File

@@ -9,6 +9,8 @@ import (
"testing"
"time"
"github.com/ethereum/go-ethereum/common"
gethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/pkg/errors"
mock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
@@ -1527,6 +1529,9 @@ func Test_validateMergeTransitionBlock(t *testing.T) {
service, err := NewService(ctx, opts...)
require.NoError(t, err)
aHash := common.BytesToHash([]byte("a"))
bHash := common.BytesToHash([]byte("b"))
tests := []struct {
name string
stateVersion int
@@ -1557,7 +1562,7 @@ func Test_validateMergeTransitionBlock(t *testing.T) {
name: "state older than Bellatrix, non empty payload",
stateVersion: 1,
payload: &enginev1.ExecutionPayload{
ParentHash: bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength),
ParentHash: aHash[:],
},
},
{
@@ -1583,7 +1588,7 @@ func Test_validateMergeTransitionBlock(t *testing.T) {
name: "state is Bellatrix, non empty payload, empty header",
stateVersion: 2,
payload: &enginev1.ExecutionPayload{
ParentHash: bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength),
ParentHash: aHash[:],
},
header: &enginev1.ExecutionPayloadHeader{
ParentHash: make([]byte, fieldparams.RootLength),
@@ -1601,7 +1606,7 @@ func Test_validateMergeTransitionBlock(t *testing.T) {
name: "state is Bellatrix, non empty payload, non empty header",
stateVersion: 2,
payload: &enginev1.ExecutionPayload{
ParentHash: bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength),
ParentHash: aHash[:],
},
header: &enginev1.ExecutionPayloadHeader{
BlockNumber: 1,
@@ -1611,7 +1616,7 @@ func Test_validateMergeTransitionBlock(t *testing.T) {
name: "state is Bellatrix, non empty payload, nil header",
stateVersion: 2,
payload: &enginev1.ExecutionPayload{
ParentHash: bytesutil.PadTo([]byte{'a'}, fieldparams.RootLength),
ParentHash: aHash[:],
},
errString: "nil header or block body",
},
@@ -1619,12 +1624,16 @@ func Test_validateMergeTransitionBlock(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
e := &mockPOW.EngineClient{BlockByHashMap: map[[32]byte]*enginev1.ExecutionBlock{}}
e.BlockByHashMap[[32]byte{'a'}] = &enginev1.ExecutionBlock{
ParentHash: bytesutil.PadTo([]byte{'b'}, fieldparams.RootLength),
e.BlockByHashMap[aHash] = &enginev1.ExecutionBlock{
Header: gethtypes.Header{
ParentHash: bHash,
},
TotalDifficulty: "0x2",
}
e.BlockByHashMap[[32]byte{'b'}] = &enginev1.ExecutionBlock{
ParentHash: bytesutil.PadTo([]byte{'3'}, fieldparams.RootLength),
e.BlockByHashMap[bHash] = &enginev1.ExecutionBlock{
Header: gethtypes.Header{
ParentHash: common.BytesToHash([]byte("3")),
},
TotalDifficulty: "0x1",
}
service.cfg.ExecutionEngineCaller = e

View File

@@ -1,8 +1,6 @@
package precompute
import (
"context"
"github.com/pkg/errors"
"github.com/prysmaticlabs/go-bitfield"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
@@ -17,7 +15,7 @@ var errNilState = errors.New("nil state")
// UnrealizedCheckpoints returns the justification and finalization checkpoints of the
// given state as if it was progressed with empty slots until the next epoch.
func UnrealizedCheckpoints(ctx context.Context, st state.BeaconState) (*ethpb.Checkpoint, *ethpb.Checkpoint, error) {
func UnrealizedCheckpoints(st state.BeaconState) (*ethpb.Checkpoint, *ethpb.Checkpoint, error) {
if st == nil || st.IsNil() {
return nil, nil, errNilState
}

View File

@@ -243,7 +243,7 @@ func TestUnrealizedCheckpoints(t *testing.T) {
_, _, err = altair.InitializePrecomputeValidators(context.Background(), state)
require.NoError(t, err)
jc, fc, err := precompute.UnrealizedCheckpoints(context.Background(), state)
jc, fc, err := precompute.UnrealizedCheckpoints(state)
require.NoError(t, err)
require.DeepEqual(t, test.expectedJustified, jc.Epoch)
require.DeepEqual(t, test.expectedFinalized, fc.Epoch)

View File

@@ -8,7 +8,6 @@ var errInvalidProposerBoostRoot = errors.New("invalid proposer boost root")
var errUnknownFinalizedRoot = errors.New("unknown finalized root")
var errUnknownJustifiedRoot = errors.New("unknown justified root")
var errInvalidOptimisticStatus = errors.New("invalid optimistic status")
var errUnknownPayloadHash = errors.New("unknown payload hash")
var errInvalidNilCheckpoint = errors.New("invalid nil checkpoint")
var errInvalidUnrealizedJustifiedEpoch = errors.New("invalid unrealized justified epoch")
var errInvalidUnrealizedFinalizedEpoch = errors.New("invalid unrealized finalized epoch")

View File

@@ -150,8 +150,8 @@ func (f *ForkChoice) InsertNode(ctx context.Context, state state.BeaconState, ro
return err
}
if features.Get().PullTips {
jc, fc = f.store.pullTips(ctx, state, node, jc, fc)
if features.Get().EnablePullTips {
jc, fc = f.store.pullTips(state, node, jc, fc)
}
return f.updateCheckpoints(ctx, jc, fc)
}

View File

@@ -65,8 +65,8 @@ func (f *ForkChoice) NewSlot(ctx context.Context, slot types.Slot) error {
f.store.justifiedCheckpoint = bjcp
}
}
if features.Get().PullTips {
f.UpdateUnrealizedCheckpoints()
if features.Get().EnablePullTips {
f.updateUnrealizedCheckpoints()
}
return nil
}

View File

@@ -32,12 +32,6 @@ func (s *Store) setOptimisticToInvalid(ctx context.Context, root, parentRoot, pa
return invalidRoots, errInvalidParentRoot
}
}
// Check if last valid hash is an ancestor of the passed node.
lastValid, ok := s.nodeByPayload[payloadHash]
if !ok || lastValid == nil {
s.nodesLock.Unlock()
return invalidRoots, errUnknownPayloadHash
}
firstInvalid := node
for ; firstInvalid.parent != nil && firstInvalid.parent.payloadHash != payloadHash; firstInvalid = firstInvalid.parent {
if ctx.Err() != nil {

View File

@@ -30,6 +30,23 @@ func TestPruneInvalid(t *testing.T) {
wantedRoots [][32]byte
wantedErr error
}{
{ // Bogus LVH, root not in forkchoice
[32]byte{'x'},
[32]byte{'i'},
[32]byte{'R'},
13,
[][32]byte{},
nil,
},
{
// Bogus LVH
[32]byte{'i'},
[32]byte{'h'},
[32]byte{'R'},
12,
[][32]byte{{'i'}},
nil,
},
{
[32]byte{'j'},
[32]byte{'b'},

View File

@@ -1,8 +1,6 @@
package doublylinkedtree
import (
"context"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute"
forkchoicetypes "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/types"
@@ -44,20 +42,19 @@ func (s *Store) setUnrealizedFinalizedEpoch(root [32]byte, epoch types.Epoch) er
return nil
}
// UpdateUnrealizedCheckpoints "realizes" the unrealized justified and finalized
// epochs stored within nodes. It should be called at the beginning of each
// epoch
func (f *ForkChoice) UpdateUnrealizedCheckpoints() {
// updateUnrealizedCheckpoints "realizes" the unrealized justified and finalized
// epochs stored within nodes. It should be called at the beginning of each epoch.
func (f *ForkChoice) updateUnrealizedCheckpoints() {
f.store.nodesLock.Lock()
defer f.store.nodesLock.Unlock()
for _, node := range f.store.nodeByRoot {
node.justifiedEpoch = node.unrealizedJustifiedEpoch
node.finalizedEpoch = node.unrealizedFinalizedEpoch
if node.justifiedEpoch > f.store.justifiedCheckpoint.Epoch {
f.store.justifiedCheckpoint = f.store.unrealizedJustifiedCheckpoint
if node.justifiedEpoch > f.store.bestJustifiedCheckpoint.Epoch {
f.store.bestJustifiedCheckpoint = f.store.unrealizedJustifiedCheckpoint
}
f.store.justifiedCheckpoint = f.store.unrealizedJustifiedCheckpoint
}
if node.finalizedEpoch > f.store.finalizedCheckpoint.Epoch {
f.store.justifiedCheckpoint = f.store.unrealizedJustifiedCheckpoint
@@ -66,33 +63,37 @@ func (f *ForkChoice) UpdateUnrealizedCheckpoints() {
}
}
func (s *Store) pullTips(ctx context.Context, state state.BeaconState, node *Node, jc, fc *ethpb.Checkpoint) (*ethpb.Checkpoint, *ethpb.Checkpoint) {
func (s *Store) pullTips(state state.BeaconState, node *Node, jc, fc *ethpb.Checkpoint) (*ethpb.Checkpoint, *ethpb.Checkpoint) {
s.nodesLock.Lock()
defer s.nodesLock.Unlock()
if node.parent == nil { // Nothing to do if the parent is nil.
return jc, fc
}
s.checkpointsLock.Lock()
defer s.checkpointsLock.Unlock()
var uj, uf *ethpb.Checkpoint
currentSlot := slots.CurrentSlot(s.genesisTime)
currentEpoch := slots.ToEpoch(currentSlot)
currentEpoch := slots.ToEpoch(slots.CurrentSlot(s.genesisTime))
stateSlot := state.Slot()
stateEpoch := slots.ToEpoch(stateSlot)
if node.parent == nil {
return jc, fc
}
currJustified := node.parent.unrealizedJustifiedEpoch == currentEpoch
prevJustified := node.parent.unrealizedJustifiedEpoch+1 == currentEpoch
tooEarlyForCurr := slots.SinceEpochStarts(stateSlot)*3 < params.BeaconConfig().SlotsPerEpoch*2
// Exit early if it's justified or too early to be justified.
if currJustified || (stateEpoch == currentEpoch && prevJustified && tooEarlyForCurr) {
node.unrealizedJustifiedEpoch = node.parent.unrealizedJustifiedEpoch
node.unrealizedFinalizedEpoch = node.parent.unrealizedFinalizedEpoch
return jc, fc
}
uj, uf, err := precompute.UnrealizedCheckpoints(ctx, state)
uj, uf, err := precompute.UnrealizedCheckpoints(state)
if err != nil {
log.WithError(err).Debug("could not compute unrealized checkpoints")
uj, uf = jc, fc
}
node.unrealizedJustifiedEpoch, node.unrealizedFinalizedEpoch = uj.Epoch, uf.Epoch
// Update store's unrealized checkpoints.
if uj.Epoch > s.unrealizedJustifiedCheckpoint.Epoch {
s.unrealizedJustifiedCheckpoint = &forkchoicetypes.Checkpoint{
Epoch: uj.Epoch, Root: bytesutil.ToBytes32(uj.Root),
@@ -107,6 +108,8 @@ func (s *Store) pullTips(ctx context.Context, state state.BeaconState, node *Nod
}
}
// Update node's checkpoints.
node.unrealizedJustifiedEpoch, node.unrealizedFinalizedEpoch = uj.Epoch, uf.Epoch
if stateEpoch < currentEpoch {
jc, fc = uj, uf
node.justifiedEpoch = uj.Epoch

View File

@@ -98,7 +98,7 @@ func TestStore_LongFork(t *testing.T) {
require.Equal(t, uint64(100), f.store.nodeByRoot[[32]byte{'c'}].weight)
// Update unrealized justification, c becomes head
f.UpdateUnrealizedCheckpoints()
f.updateUnrealizedCheckpoints()
headRoot, err = f.Head(ctx, []uint64{100})
require.NoError(t, err)
require.Equal(t, [32]byte{'c'}, headRoot)
@@ -179,7 +179,7 @@ func TestStore_NoDeadLock(t *testing.T) {
require.Equal(t, types.Epoch(0), f.FinalizedCheckpoint().Epoch)
// Realized Justified checkpoints, H becomes head
f.UpdateUnrealizedCheckpoints()
f.updateUnrealizedCheckpoints()
headRoot, err = f.Head(ctx, []uint64{100})
require.NoError(t, err)
require.Equal(t, [32]byte{'h'}, headRoot)
@@ -240,7 +240,7 @@ func TestStore_ForkNextEpoch(t *testing.T) {
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
require.NoError(t, f.store.setUnrealizedJustifiedEpoch([32]byte{'d'}, 1))
f.store.unrealizedJustifiedCheckpoint = &forkchoicetypes.Checkpoint{Epoch: 1}
f.UpdateUnrealizedCheckpoints()
f.updateUnrealizedCheckpoints()
headRoot, err = f.Head(ctx, []uint64{100})
require.NoError(t, err)
require.Equal(t, [32]byte{'d'}, headRoot)
@@ -251,7 +251,7 @@ func TestStore_ForkNextEpoch(t *testing.T) {
func TestStore_PullTips_Heuristics(t *testing.T) {
resetCfg := features.InitWithReset(&features.Flags{
PullTips: true,
EnablePullTips: true,
})
defer resetCfg()
ctx := context.Background()

View File

@@ -17,3 +17,4 @@ var errInvalidNilCheckpoint = errors.New("invalid nil checkpoint")
var errInvalidUnrealizedJustifiedEpoch = errors.New("invalid unrealized justified epoch")
var errInvalidUnrealizedFinalizedEpoch = errors.New("invalid unrealized finalized epoch")
var errNilBlockHeader = errors.New("invalid nil block header")
var errInvalidParentRoot = errors.New("invalid parent root")

View File

@@ -65,7 +65,7 @@ func (f *ForkChoice) NewSlot(ctx context.Context, slot types.Slot) error {
f.store.justifiedCheckpoint = bjcp
}
}
if features.Get().PullTips {
if features.Get().EnablePullTips {
f.UpdateUnrealizedCheckpoints()
}
return nil

View File

@@ -56,8 +56,8 @@ func (f *ForkChoice) SetOptimisticToInvalid(ctx context.Context, root, parentRoo
defer f.store.nodesLock.Unlock()
invalidRoots := make([][32]byte, 0)
lastValidIndex, ok := f.store.payloadIndices[payloadHash]
if !ok || lastValidIndex == NonExistentNode {
return invalidRoots, errInvalidFinalizedNode
if !ok {
lastValidIndex = uint64(len(f.store.nodes))
}
invalidIndex, ok := f.store.nodesIndices[root]

View File

@@ -385,8 +385,6 @@ func TestSetOptimisticToInvalid_InvalidRoots(t *testing.T) {
require.NoError(t, f.InsertNode(ctx, state, blkRoot))
_, err = f.SetOptimisticToInvalid(ctx, [32]byte{'p'}, [32]byte{'p'}, [32]byte{'B'})
require.ErrorIs(t, ErrUnknownNodeRoot, err)
_, err = f.SetOptimisticToInvalid(ctx, [32]byte{'a'}, [32]byte{}, [32]byte{'p'})
require.ErrorIs(t, errInvalidFinalizedNode, err)
}
// This is a regression test (10445)
@@ -417,3 +415,40 @@ func TestSetOptimisticToInvalid_ProposerBoost(t *testing.T) {
require.DeepEqual(t, params.BeaconConfig().ZeroHash, f.store.previousProposerBoostRoot)
f.store.proposerBoostLock.RUnlock()
}
// This is a regression test (10996)
func TestSetOptimisticToInvalid_BogusLVH(t *testing.T) {
ctx := context.Background()
f := setup(1, 1)
state, root, err := prepareForkchoiceState(ctx, 1, [32]byte{'a'}, [32]byte{}, [32]byte{'A'}, 1, 1)
require.NoError(t, err)
require.NoError(t, f.InsertNode(ctx, state, root))
state, root, err = prepareForkchoiceState(ctx, 2, [32]byte{'b'}, [32]byte{'a'}, [32]byte{'B'}, 1, 1)
require.NoError(t, err)
require.NoError(t, f.InsertNode(ctx, state, root))
invalidRoots, err := f.SetOptimisticToInvalid(ctx, [32]byte{'b'}, [32]byte{'a'}, [32]byte{'R'})
require.NoError(t, err)
require.Equal(t, 1, len(invalidRoots))
require.Equal(t, [32]byte{'b'}, invalidRoots[0])
}
// This is a regression test (10996)
func TestSetOptimisticToInvalid_BogusLVH_RotNotImported(t *testing.T) {
ctx := context.Background()
f := setup(1, 1)
state, root, err := prepareForkchoiceState(ctx, 1, [32]byte{'a'}, [32]byte{}, [32]byte{'A'}, 1, 1)
require.NoError(t, err)
require.NoError(t, f.InsertNode(ctx, state, root))
state, root, err = prepareForkchoiceState(ctx, 2, [32]byte{'b'}, [32]byte{'a'}, [32]byte{'B'}, 1, 1)
require.NoError(t, err)
require.NoError(t, f.InsertNode(ctx, state, root))
invalidRoots, err := f.SetOptimisticToInvalid(ctx, [32]byte{'c'}, [32]byte{'b'}, [32]byte{'R'})
require.NoError(t, err)
require.Equal(t, 0, len(invalidRoots))
}

View File

@@ -155,8 +155,8 @@ func (f *ForkChoice) InsertNode(ctx context.Context, state state.BeaconState, ro
return err
}
if features.Get().PullTips {
jc, fc = f.store.pullTips(ctx, state, node, jc, fc)
if features.Get().EnablePullTips {
jc, fc = f.store.pullTips(state, node, jc, fc)
}
return f.updateCheckpoints(ctx, jc, fc)
}

View File

@@ -1,8 +1,6 @@
package protoarray
import (
"context"
"github.com/prysmaticlabs/prysm/beacon-chain/core/epoch/precompute"
forkchoicetypes "github.com/prysmaticlabs/prysm/beacon-chain/forkchoice/types"
"github.com/prysmaticlabs/prysm/beacon-chain/state"
@@ -77,16 +75,18 @@ func (f *ForkChoice) UpdateUnrealizedCheckpoints() {
}
}
func (s *Store) pullTips(ctx context.Context, state state.BeaconState, node *Node, jc, fc *ethpb.Checkpoint) (*ethpb.Checkpoint, *ethpb.Checkpoint) {
var uj, uf *ethpb.Checkpoint
func (s *Store) pullTips(state state.BeaconState, node *Node, jc, fc *ethpb.Checkpoint) (*ethpb.Checkpoint, *ethpb.Checkpoint) {
s.nodesLock.Lock()
defer s.nodesLock.Unlock()
currentSlot := slots.CurrentSlot(s.genesisTime)
currentEpoch := slots.ToEpoch(currentSlot)
stateSlot := state.Slot()
stateEpoch := slots.ToEpoch(stateSlot)
if node.parent == NonExistentNode {
if node.parent == NonExistentNode { // Nothing to do if the parent is nil.
return jc, fc
}
currentEpoch := slots.ToEpoch(slots.CurrentSlot(s.genesisTime))
stateSlot := state.Slot()
stateEpoch := slots.ToEpoch(stateSlot)
parent := s.nodes[node.parent]
currJustified := parent.unrealizedJustifiedEpoch == currentEpoch
prevJustified := parent.unrealizedJustifiedEpoch+1 == currentEpoch
@@ -97,12 +97,13 @@ func (s *Store) pullTips(ctx context.Context, state state.BeaconState, node *Nod
return jc, fc
}
uj, uf, err := precompute.UnrealizedCheckpoints(ctx, state)
uj, uf, err := precompute.UnrealizedCheckpoints(state)
if err != nil {
log.WithError(err).Debug("could not compute unrealized checkpoints")
uj, uf = jc, fc
}
node.unrealizedJustifiedEpoch, node.unrealizedFinalizedEpoch = uj.Epoch, uf.Epoch
// Update store's unrealized checkpoints.
s.checkpointsLock.Lock()
if uj.Epoch > s.unrealizedJustifiedCheckpoint.Epoch {
s.unrealizedJustifiedCheckpoint = &forkchoicetypes.Checkpoint{
@@ -117,12 +118,15 @@ func (s *Store) pullTips(ctx context.Context, state state.BeaconState, node *Nod
Epoch: uf.Epoch, Root: bytesutil.ToBytes32(uf.Root),
}
}
s.checkpointsLock.Unlock()
// Update node's checkpoints.
node.unrealizedJustifiedEpoch, node.unrealizedFinalizedEpoch = uj.Epoch, uf.Epoch
if stateEpoch < currentEpoch {
jc, fc = uj, uf
node.justifiedEpoch = uj.Epoch
node.finalizedEpoch = uf.Epoch
}
s.checkpointsLock.Unlock()
return jc, fc
}

View File

@@ -252,7 +252,7 @@ func TestStore_ForkNextEpoch(t *testing.T) {
func TestStore_PullTips_Heuristics(t *testing.T) {
resetCfg := features.InitWithReset(&features.Flags{
PullTips: true,
EnablePullTips: true,
})
defer resetCfg()
ctx := context.Background()

View File

@@ -77,6 +77,7 @@ go_test(
"block_reader_test.go",
"check_transition_config_test.go",
"deposit_test.go",
"engine_client_fuzz_test.go",
"engine_client_test.go",
"init_test.go",
"log_processing_test.go",
@@ -85,6 +86,7 @@ go_test(
"provider_test.go",
"service_test.go",
],
data = glob(["testdata/**"]),
embed = [":go_default_library"],
deps = [
"//async/event:go_default_library",
@@ -121,6 +123,7 @@ go_test(
"@com_github_ethereum_go_ethereum//accounts/abi/bind/backends:go_default_library",
"@com_github_ethereum_go_ethereum//common:go_default_library",
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
"@com_github_ethereum_go_ethereum//core/beacon:go_default_library",
"@com_github_ethereum_go_ethereum//core/types:go_default_library",
"@com_github_ethereum_go_ethereum//rpc:go_default_library",
"@com_github_ethereum_go_ethereum//trie:go_default_library",

View File

@@ -4,12 +4,14 @@ import (
"context"
"encoding/json"
"errors"
"math/big"
"net/http"
"net/http/httptest"
"testing"
"time"
"github.com/ethereum/go-ethereum/common"
gethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rpc"
"github.com/holiman/uint256"
mockChain "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
@@ -161,7 +163,27 @@ func TestService_logTtdStatus(t *testing.T) {
require.NoError(t, r.Body.Close())
}()
resp := &pb.ExecutionBlock{TotalDifficulty: "0x12345678"}
resp := &pb.ExecutionBlock{
Header: gethtypes.Header{
ParentHash: common.Hash{},
UncleHash: common.Hash{},
Coinbase: common.Address{},
Root: common.Hash{},
TxHash: common.Hash{},
ReceiptHash: common.Hash{},
Bloom: gethtypes.Bloom{},
Difficulty: big.NewInt(1),
Number: big.NewInt(2),
GasLimit: 3,
GasUsed: 4,
Time: 5,
Extra: nil,
MixDigest: common.Hash{},
Nonce: gethtypes.BlockNonce{},
BaseFee: big.NewInt(6),
},
TotalDifficulty: "0x12345678",
}
respJSON := map[string]interface{}{
"jsonrpc": "2.0",
"id": 1,

View File

@@ -80,7 +80,7 @@ func (s *Service) NewPayload(ctx context.Context, payload *pb.ExecutionPayload)
switch result.Status {
case pb.PayloadStatus_INVALID_BLOCK_HASH:
return nil, fmt.Errorf("could not validate block hash: %v", result.ValidationError)
return nil, ErrInvalidBlockHashPayloadStatus
case pb.PayloadStatus_ACCEPTED, pb.PayloadStatus_SYNCING:
return nil, ErrAcceptedSyncingPayloadStatus
case pb.PayloadStatus_INVALID:
@@ -228,8 +228,8 @@ func (s *Service) GetTerminalBlockHash(ctx context.Context) ([]byte, bool, error
}
blockReachedTTD := currentTotalDifficulty.Cmp(terminalTotalDifficulty) >= 0
parentHash := bytesutil.ToBytes32(blk.ParentHash)
if len(blk.ParentHash) == 0 || parentHash == params.BeaconConfig().ZeroHash {
parentHash := blk.ParentHash
if parentHash == params.BeaconConfig().ZeroHash {
return nil, false, nil
}
parentBlk, err := s.ExecutionBlockByHash(ctx, parentHash)
@@ -248,12 +248,12 @@ func (s *Service) GetTerminalBlockHash(ctx context.Context) ([]byte, bool, error
if !parentReachedTTD {
log.WithFields(logrus.Fields{
"number": blk.Number,
"hash": fmt.Sprintf("%#x", bytesutil.Trunc(blk.Hash)),
"hash": fmt.Sprintf("%#x", bytesutil.Trunc(blk.Hash[:])),
"td": blk.TotalDifficulty,
"parentTd": parentBlk.TotalDifficulty,
"ttd": terminalTotalDifficulty,
}).Info("Retrieved terminal block hash")
return blk.Hash, true, nil
return blk.Hash[:], true, nil
}
} else {
return nil, false, nil

View File

@@ -0,0 +1,114 @@
//go:build go1.18
// +build go1.18
package powchain_test
import (
"encoding/json"
"fmt"
"math"
"math/big"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/beacon"
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
pb "github.com/prysmaticlabs/prysm/proto/engine/v1"
"github.com/prysmaticlabs/prysm/testing/assert"
)
func FuzzForkChoiceResponse(f *testing.F) {
valHash := common.Hash([32]byte{0xFF, 0x01})
payloadID := beacon.PayloadID([8]byte{0x01, 0xFF, 0xAA, 0x00, 0xEE, 0xFE, 0x00, 0x00})
valErr := "asjajshjahsaj"
seed := &beacon.ForkChoiceResponse{
PayloadStatus: beacon.PayloadStatusV1{
Status: "INVALID_TERMINAL_BLOCK",
LatestValidHash: &valHash,
ValidationError: &valErr,
},
PayloadID: &payloadID,
}
output, err := json.Marshal(seed)
assert.NoError(f, err)
f.Add(output)
f.Fuzz(func(t *testing.T, jsonBlob []byte) {
gethResp := &beacon.ForkChoiceResponse{}
prysmResp := &powchain.ForkchoiceUpdatedResponse{}
gethErr := json.Unmarshal(jsonBlob, gethResp)
prysmErr := json.Unmarshal(jsonBlob, prysmResp)
assert.Equal(t, gethErr != nil, prysmErr != nil, fmt.Sprintf("geth and prysm unmarshaller return inconsistent errors. %v and %v", gethErr, prysmErr))
// Nothing to marshal if we have an error.
if gethErr != nil {
return
}
gethBlob, gethErr := json.Marshal(gethResp)
prysmBlob, prysmErr := json.Marshal(prysmResp)
assert.Equal(t, gethErr != nil, prysmErr != nil, "geth and prysm unmarshaller return inconsistent errors")
newGethResp := &beacon.ForkChoiceResponse{}
newGethErr := json.Unmarshal(prysmBlob, newGethResp)
assert.NoError(t, newGethErr)
if newGethResp.PayloadStatus.Status == "UNKNOWN" {
return
}
newGethResp2 := &beacon.ForkChoiceResponse{}
newGethErr = json.Unmarshal(gethBlob, newGethResp2)
assert.NoError(t, newGethErr)
assert.DeepEqual(t, newGethResp.PayloadID, newGethResp2.PayloadID)
assert.DeepEqual(t, newGethResp.PayloadStatus.Status, newGethResp2.PayloadStatus.Status)
assert.DeepEqual(t, newGethResp.PayloadStatus.LatestValidHash, newGethResp2.PayloadStatus.LatestValidHash)
isNilOrEmpty := newGethResp.PayloadStatus.ValidationError == nil || (*newGethResp.PayloadStatus.ValidationError == "")
isNilOrEmpty2 := newGethResp2.PayloadStatus.ValidationError == nil || (*newGethResp2.PayloadStatus.ValidationError == "")
assert.DeepEqual(t, isNilOrEmpty, isNilOrEmpty2)
if !isNilOrEmpty {
assert.DeepEqual(t, *newGethResp.PayloadStatus.ValidationError, *newGethResp2.PayloadStatus.ValidationError)
}
})
}
func FuzzExecutionPayload(f *testing.F) {
logsBloom := [256]byte{'j', 'u', 'n', 'k'}
execData := &beacon.ExecutableDataV1{
ParentHash: common.Hash([32]byte{0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01}),
FeeRecipient: common.Address([20]byte{0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF}),
StateRoot: common.Hash([32]byte{0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01}),
ReceiptsRoot: common.Hash([32]byte{0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01}),
LogsBloom: logsBloom[:],
Random: common.Hash([32]byte{0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01}),
Number: math.MaxUint64,
GasLimit: math.MaxUint64,
GasUsed: math.MaxUint64,
Timestamp: 100,
ExtraData: nil,
BaseFeePerGas: big.NewInt(math.MaxInt),
BlockHash: common.Hash([32]byte{0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01}),
Transactions: [][]byte{{0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01}, {0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01}, {0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01}, {0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01}},
}
output, err := json.Marshal(execData)
assert.NoError(f, err)
f.Add(output)
f.Fuzz(func(t *testing.T, jsonBlob []byte) {
gethResp := &beacon.ExecutableDataV1{}
prysmResp := &pb.ExecutionPayload{}
gethErr := json.Unmarshal(jsonBlob, gethResp)
prysmErr := json.Unmarshal(jsonBlob, prysmResp)
assert.Equal(t, gethErr != nil, prysmErr != nil, fmt.Sprintf("geth and prysm unmarshaller return inconsistent errors. %v and %v", gethErr, prysmErr))
// Nothing to marshal if we have an error.
if gethErr != nil {
return
}
gethBlob, gethErr := json.Marshal(gethResp)
prysmBlob, prysmErr := json.Marshal(prysmResp)
assert.Equal(t, gethErr != nil, prysmErr != nil, "geth and prysm unmarshaller return inconsistent errors")
newGethResp := &beacon.ExecutableDataV1{}
newGethErr := json.Unmarshal(prysmBlob, newGethResp)
assert.NoError(t, newGethErr)
newGethResp2 := &beacon.ExecutableDataV1{}
newGethErr = json.Unmarshal(gethBlob, newGethResp2)
assert.NoError(t, newGethErr)
assert.DeepEqual(t, newGethResp.LogsBloom, newGethResp2.LogsBloom)
})
}

View File

@@ -12,6 +12,7 @@ import (
"testing"
"github.com/ethereum/go-ethereum/common"
gethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rpc"
"github.com/holiman/uint256"
"github.com/pkg/errors"
@@ -250,7 +251,7 @@ func TestClient_HTTP(t *testing.T) {
// We call the RPC method via HTTP and expect a proper result.
resp, err := client.NewPayload(ctx, execPayload)
require.ErrorContains(t, "could not validate block hash", err)
require.ErrorIs(t, ErrInvalidBlockHashPayloadStatus, err)
require.DeepEqual(t, []uint8(nil), resp)
})
t.Run(NewPayloadMethod+" INVALID status", func(t *testing.T) {
@@ -416,7 +417,7 @@ func TestServer_getPowBlockHashAtTerminalTotalDifficulty(t *testing.T) {
name: "current execution block invalid TD",
paramsTd: "1",
currentPowBlock: &pb.ExecutionBlock{
Hash: []byte{'a'},
Hash: common.BytesToHash([]byte("a")),
TotalDifficulty: "1115792089237316195423570985008687907853269984665640564039457584007913129638912",
},
errString: "could not convert total difficulty to uint256",
@@ -425,8 +426,10 @@ func TestServer_getPowBlockHashAtTerminalTotalDifficulty(t *testing.T) {
name: "current execution block has zero hash parent",
paramsTd: "2",
currentPowBlock: &pb.ExecutionBlock{
Hash: []byte{'a'},
ParentHash: params.BeaconConfig().ZeroHash[:],
Hash: common.BytesToHash([]byte("a")),
Header: gethtypes.Header{
ParentHash: common.BytesToHash(params.BeaconConfig().ZeroHash[:]),
},
TotalDifficulty: "0x3",
},
},
@@ -434,8 +437,10 @@ func TestServer_getPowBlockHashAtTerminalTotalDifficulty(t *testing.T) {
name: "could not get parent block",
paramsTd: "2",
currentPowBlock: &pb.ExecutionBlock{
Hash: []byte{'a'},
ParentHash: []byte{'b'},
Hash: common.BytesToHash([]byte("a")),
Header: gethtypes.Header{
ParentHash: common.BytesToHash([]byte("b")),
},
TotalDifficulty: "0x3",
},
errString: "could not get parent execution block",
@@ -444,13 +449,17 @@ func TestServer_getPowBlockHashAtTerminalTotalDifficulty(t *testing.T) {
name: "parent execution block invalid TD",
paramsTd: "2",
currentPowBlock: &pb.ExecutionBlock{
Hash: []byte{'a'},
ParentHash: []byte{'b'},
Hash: common.BytesToHash([]byte("a")),
Header: gethtypes.Header{
ParentHash: common.BytesToHash([]byte("b")),
},
TotalDifficulty: "0x3",
},
parentPowBlock: &pb.ExecutionBlock{
Hash: []byte{'b'},
ParentHash: []byte{'c'},
Hash: common.BytesToHash([]byte("b")),
Header: gethtypes.Header{
ParentHash: common.BytesToHash([]byte("c")),
},
TotalDifficulty: "1",
},
errString: "could not convert total difficulty to uint256",
@@ -459,29 +468,37 @@ func TestServer_getPowBlockHashAtTerminalTotalDifficulty(t *testing.T) {
name: "happy case",
paramsTd: "2",
currentPowBlock: &pb.ExecutionBlock{
Hash: []byte{'a'},
ParentHash: []byte{'b'},
Hash: common.BytesToHash([]byte("a")),
Header: gethtypes.Header{
ParentHash: common.BytesToHash([]byte("b")),
},
TotalDifficulty: "0x3",
},
parentPowBlock: &pb.ExecutionBlock{
Hash: []byte{'b'},
ParentHash: []byte{'c'},
Hash: common.BytesToHash([]byte("b")),
Header: gethtypes.Header{
ParentHash: common.BytesToHash([]byte("c")),
},
TotalDifficulty: "0x1",
},
wantExists: true,
wantTerminalBlockHash: []byte{'a'},
wantTerminalBlockHash: common.BytesToHash([]byte("a")).Bytes(),
},
{
name: "ttd not reached",
paramsTd: "3",
currentPowBlock: &pb.ExecutionBlock{
Hash: []byte{'a'},
ParentHash: []byte{'b'},
Hash: common.BytesToHash([]byte("a")),
Header: gethtypes.Header{
ParentHash: common.BytesToHash([]byte("b")),
},
TotalDifficulty: "0x2",
},
parentPowBlock: &pb.ExecutionBlock{
Hash: []byte{'b'},
ParentHash: []byte{'c'},
Hash: common.BytesToHash([]byte("b")),
Header: gethtypes.Header{
ParentHash: common.BytesToHash([]byte("c")),
},
TotalDifficulty: "0x1",
},
},
@@ -494,7 +511,7 @@ func TestServer_getPowBlockHashAtTerminalTotalDifficulty(t *testing.T) {
var m map[[32]byte]*pb.ExecutionBlock
if tt.parentPowBlock != nil {
m = map[[32]byte]*pb.ExecutionBlock{
bytesutil.ToBytes32(tt.parentPowBlock.Hash): tt.parentPowBlock,
tt.parentPowBlock.Hash: tt.parentPowBlock,
}
}
client := mocks.EngineClient{
@@ -749,8 +766,6 @@ func fixtures() map[string]interface{} {
BlockHash: foo[:],
Transactions: [][]byte{foo[:]},
}
number := bytesutil.PadTo([]byte("100"), fieldparams.RootLength)
hash := bytesutil.PadTo([]byte("hash"), fieldparams.RootLength)
parent := bytesutil.PadTo([]byte("parentHash"), fieldparams.RootLength)
sha3Uncles := bytesutil.PadTo([]byte("sha3Uncles"), fieldparams.RootLength)
miner := bytesutil.PadTo([]byte("miner"), fieldparams.FeeRecipientLength)
@@ -759,25 +774,24 @@ func fixtures() map[string]interface{} {
receiptsRoot := bytesutil.PadTo([]byte("receiptsRoot"), fieldparams.RootLength)
logsBloom := bytesutil.PadTo([]byte("logs"), fieldparams.LogsBloomLength)
executionBlock := &pb.ExecutionBlock{
Number: number,
Hash: hash,
ParentHash: parent,
Sha3Uncles: sha3Uncles,
Miner: miner,
StateRoot: stateRoot,
TransactionsRoot: transactionsRoot,
ReceiptsRoot: receiptsRoot,
LogsBloom: logsBloom,
Difficulty: bytesutil.PadTo([]byte("1"), fieldparams.RootLength),
TotalDifficulty: "2",
GasLimit: 3,
GasUsed: 4,
Timestamp: 5,
Size: bytesutil.PadTo([]byte("6"), fieldparams.RootLength),
ExtraData: bytesutil.PadTo([]byte("extraData"), fieldparams.RootLength),
BaseFeePerGas: bytesutil.PadTo([]byte("baseFeePerGas"), fieldparams.RootLength),
Transactions: [][]byte{foo[:]},
Uncles: [][]byte{foo[:]},
Header: gethtypes.Header{
ParentHash: common.BytesToHash(parent),
UncleHash: common.BytesToHash(sha3Uncles),
Coinbase: common.BytesToAddress(miner),
Root: common.BytesToHash(stateRoot),
TxHash: common.BytesToHash(transactionsRoot),
ReceiptHash: common.BytesToHash(receiptsRoot),
Bloom: gethtypes.BytesToBloom(logsBloom),
Difficulty: big.NewInt(1),
Number: big.NewInt(2),
GasLimit: 3,
GasUsed: 4,
Time: 5,
Extra: []byte("extra"),
MixDigest: common.BytesToHash([]byte("mix")),
Nonce: gethtypes.EncodeNonce(6),
BaseFee: big.NewInt(7),
},
}
status := &pb.PayloadStatus{
Status: pb.PayloadStatus_VALID,
@@ -806,7 +820,7 @@ func fixtures() map[string]interface{} {
forkChoiceInvalidResp := &ForkchoiceUpdatedResponse{
Status: &pb.PayloadStatus{
Status: pb.PayloadStatus_INVALID,
LatestValidHash: []byte("latestValidHash"),
LatestValidHash: bytesutil.PadTo([]byte("latestValidHash"), 32),
},
PayloadId: &id,
}

View File

@@ -30,6 +30,8 @@ var (
ErrAcceptedSyncingPayloadStatus = errors.New("payload status is SYNCING or ACCEPTED")
// ErrInvalidPayloadStatus when the status of the payload is invalid.
ErrInvalidPayloadStatus = errors.New("payload status is INVALID")
// ErrInvalidBlockHashPayloadStatus when the status of the payload fails to validate block hash.
ErrInvalidBlockHashPayloadStatus = errors.New("payload status is INVALID_BLOCK_HASH")
// ErrNilResponse when the response is nil.
ErrNilResponse = errors.New("nil response")
)

View File

@@ -0,0 +1,2 @@
go test fuzz v1
[]byte("{\"parentHash\":\"0xff01ff01ff01ff01ff01ff01ff01ff0100000000000000000000000000000000\",\"feeRecipient\":\"0xff01ff01ff01ff01ffff01ff01ff01ff01ff0000\",\"stateRoot\":\"0xff01ff01ff01ff01ff01ff01ff01ff0100000000000000000000000000000000\",\"receiptsRoot\":\"0xff01ff01ff01ff01ff01ff01ff01ff01000000fffffff0000000000000000000\",\"logsBloom\":\"0x6a756e6b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"prevRandao\":\"0xff01ff01ff01ff01ff01ff01ff01ff0100000000000000000000000000000000\",\"blockNumber\":\"0xffffffffffffffff\",\"gasLimit\":\"0xffffffffffffffff\",\"gasUsed\":\"0xffffffffffffffff\",\"timestamp\":\"0x64\",\"extraData\":\"0x\",\"baseFeePerGas\":\"0x7fffff0000000fff\",\"blockHash\":\"0xff01ff01ff01ff01ff01ff01ff0100000000000000000000000000000000\",\"transactions\":[\"0xff01ff01ff01ff01ff01ff01ff01ff01\",\"0xff01ff01ff01ff01ff01ff01ff01ff01\",\"0xff01ff01ff01ff01ff01ff01ff01ff01\",\"0xff01ff01ff01ff01ff01ff01ff01ff01\"]}")

View File

@@ -0,0 +1,2 @@
go test fuzz v1
[]byte("{\"BAseFeePerGAs\":\"0X0\"}")

View File

@@ -0,0 +1,2 @@
go test fuzz v1
[]byte("{\"parentHash\":\"0xff01ff01ff01ff01ff01ff01ff01ff0100000000000000000000000000000000\",\"feeRecipient\":\"0xff01ff01ff01ff01ffff01ff01ff0000\",\"stateRoot\":\"0xff01ff01ff01ff01ff01ff01ff01ff0100000000000000000000000000000000\",\"receiptsRoot\":\"0xff01ff01ff01ff01ff01ff01ff01ff0100000000000000000000000000000000\",\"logsBloom\":\"0x6a756e6b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"prevRandao\":\"0xff01ff01ff01ff01ff01ff000000ff0100000000000000000000000000000000\",\"blockNumber\":\"0xffffffffffffffff\",\"gasLimit\":\"0xffffffffffffffff\",\"gasUsed\":\"0xffffffffffffffff\",\"timestamp\":\"0x64\",\"extraData\":\"0x\",\"baseFeePerGas\":\"0x7f0fffffffffffff\",\"blockHash\":\"0xff01ff01ff01ff01ff01ff01ff01ff0100000000000000000000000000000000\",\"transactions\":[\"0xff01ff01ff01ff01ff01ff01ff01ff01\",\"0xff01ff01ff01ff01ff01ff01ff01ff01\",\"0xff01ff01ff01ff01ff01ff01ff01ff01\",\"0xff01ff01ff01ff01ff01ff01ff01ff01\"]}")

View File

@@ -0,0 +1,2 @@
go test fuzz v1
[]byte("{\"parentHash\":\"0xff01Ff01ff01ff01ff01ff01ff01ff0100000000000000000000000000000000\",\"feeRecipient\":\"0xff01ff01ff01ff01ffff01ff01ff01ff01ff0000\",\"stateRoot\":\"0xff01ff01ff0fff01ff01ff01ff01ff0100000000000000000000000000000000\",\"receiptsRoot\":\"0xff01ff01ff01ff01ff01ff01ff01ff0100000000000000000000000000000000\",\"logsBloom\":\"0x6a756e6b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"prevRandao\":\"0xff01ff01ff01ff01ff011f01ff01ff0100000000000000000000000000000000\",\"blockNumber\":\"0xffffffffffffffff\",\"gasLimit\":\"0xffffffffffffffff\",\"gasUsed\":\"0xffffffffffffffff\",\"timestamp\":\"0x64\",\"extraData\":\"0x\",\"baseFeePerGas\":\"0x7fffffffffffffff\",\"blockHash\":\"0xff01ff01ff01ff01ff01ff01ff01ff0100000000000000000000000000000000\",\"transactions\":[\"0xff01ff01ff01ff01ff01ff01ff01ff01\",\"0xff01ff01ff01ff01ff01ff01ff01ff01\",\"0xff01ff01ff01ff01ff01ff01ff01ff01\",\"0xff01ff01ff01ff01ff01ff01ff01ff01\"]}")

View File

@@ -0,0 +1,2 @@
go test fuzz v1
[]byte("{\"pArentHAsh\":\"\",\"feeReCipient\":\"\",\"stAteRoot\":\"\",\"reCeiptsRoot\":\"\",\"logsBloom\":\"\",\"prevRAndAo\":\"\",\"eXtrADAtA\":\"\",\"BAseFeePerGAs\":\"0X0\",\"BloCkHAsh\":\"\",\"trAnsACtions\":[]}")

View File

@@ -0,0 +1,2 @@
go test fuzz v1
[]byte("{\"parentHash\":\"0xff01ff01ff01ff01ff01ff01ff01ff0100000000000000000000000000000000\",\"feeRecipient\":\"0xff01ff01ff01ff01ffff01ff01ff01ff01ff0000\",\"stateRoot\":\"0xff01ff01ff01ff01ff01ff01ff01ff0100000000000000000000000000000000\",\"receiptsRoot\":\"0xff01ff01ff01ff01ff01ff01ff01ff01000000fffffff0000000000000000000\",\"logsBloom\":\"0x6a756e6b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"prevRandao\":\"0xff01ff01ff01ff01ff01ff01ff01ff0100000000000000000000000000000000\",\"blockNumber\":\"0xffffffffffffffff\",\"gasLimit\":\"0xffffffffffffffff\",\"gasUsed\":\"0xffffffffffffffff\",\"t\xc1\xc1\xc1\xc1\xc1\xc1\xc1\xc1\":\"0x64\",\"extraData\":\"0x\",\"baseFeePerGas\":\"0x7fffff0000000fff\",\"blockHash\":\"0xff01ff01ff01ff01ff01ff01ff01ff0100000000000000000000000000000000\",\"transactions\":[\"0xff01ff01ff01ff01ff01ff01ff01ff01\",\"0xff01ff01ff01ff01ff01ff01ff01ff01\",\"0xff01ff01ff01ff01ff01ff01ff01ff01\",\"0xff01ff01ff01ff01ff01ff01ff01ff01\"]}")

View File

@@ -0,0 +1,2 @@
go test fuzz v1
[]byte("{\"parentHash\":\"0xff01ff01ff01ff01ff01ff01ff01ff0100000000000000000000000000000000\",\"feeRecipient\":\"0xff01ff01ff01ff01ffff01ff01ff01ff01ff0000\",\"stateRoot\":\"0xff01ff01ff01ff01ff01ff01ff01ff0100000000000000000000000000000000\",\"receiptsRoot\":\"0xff01ff01ff01ff01ff01ff01ff01ff01000000fffffff0000000000000000000\",\"logsBloom\":\"0x6a756e6b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"prevRandao\":\"0xff01ff01ff01ff01ff01ff01ff01ff0100000000000000000000000000000000\",\"blockNumber\":\"0xffffffffffffffff\",\"gasLimit\":\"0xffffffffffffffff\",\"gasUsed\":\"0xffffffffffffffff\",\"timestamp\":\"0x64\",\"extraData\":\"0x\",\"baseFeePerGas\":\"0x7fffff0000000fff0000000\",\"blockHash\":\"0xff01ff01ff01ff01ff01ff01ff01ff0100000000000000000000000000000000\",\"transactions\":[\"0xff01ff01ff01ff01ff01ff01ff01ff01\",\"0xff01ff01ff01ff01ff01ff01ff01ff01\",\"0xff01ff010ff1ff01ff01ff01ff01ff01\",\"0xff01ff01ff01ff01ff01ff01ff01ff01\"]}")

View File

@@ -0,0 +1,2 @@
go test fuzz v1
[]byte("{\"parentHash\":\"0xff01ff01ff01ff01ff01ff01ff01ff0100000000000000000000000000000000\",\"feeRecipient\":\"0xff01ff01ff01ff01ffff01ff01ff01ff01ff0000\",\"stateRoot\":\"0xff01ff01ff01ff01ff01ff01ff01ff0100000000000000000000000000000000\",\"receiptsRoot\":\"0xff01ff01ff01ff01ff01ff01ff01ff01000000fffffff0000000000000000000\",\"logsBloom\":\"0x6a756e6b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\",\"prevRandao\":\"0xff01ff01ff01ff01ff01ff01ff01ff0100000000000000000000000000000000\",\"blockNu0000000mber\":\"0xffffffffffffffff\",\"gasLimit\":\"0xffffffffffffffff\",\"gasUsed\":\"0xffffffffffffffff\",\"timestamp\":\"0x64\",\"extraData\":\"0x\",\"baseFeePerGas\":\"0x7fffff0000000fff\",\"blockHash\":\"0xff01ff01ff01ff01ff01ff01ff01ff0100000000000000000000000000000000\",\"transactions\":[\"0xff01ff01ff01ff01ff01ff01ff01ff01\",\"0xff01ff01ff01ff01ff01ff01ff01ff01\",\"0xff01ff01ff01ff01ff01ff01ff01ff01\",\"0xff01ff01ff01ff01ff01ff01ff01ff01\"]}")

View File

@@ -94,8 +94,8 @@ func (e *EngineClient) GetTerminalBlockHash(ctx context.Context) ([]byte, bool,
currentTotalDifficulty, _ := uint256.FromBig(b)
blockReachedTTD := currentTotalDifficulty.Cmp(terminalTotalDifficulty) >= 0
parentHash := bytesutil.ToBytes32(blk.ParentHash)
if len(blk.ParentHash) == 0 || parentHash == params.BeaconConfig().ZeroHash {
parentHash := blk.ParentHash
if parentHash == params.BeaconConfig().ZeroHash {
return nil, false, nil
}
parentBlk, err := e.ExecutionBlockByHash(ctx, parentHash)
@@ -110,7 +110,7 @@ func (e *EngineClient) GetTerminalBlockHash(ctx context.Context) ([]byte, bool,
parentTotalDifficulty, _ := uint256.FromBig(b)
parentReachedTTD := parentTotalDifficulty.Cmp(terminalTotalDifficulty) >= 0
if !parentReachedTTD {
return blk.Hash, true, nil
return blk.Hash[:], true, nil
}
} else {
return nil, false, nil

View File

@@ -165,6 +165,7 @@ go_test(
"//time/slots:go_default_library",
"@com_github_d4l3k_messagediff//:go_default_library",
"@com_github_ethereum_go_ethereum//common:go_default_library",
"@com_github_ethereum_go_ethereum//core/types:go_default_library",
"@com_github_golang_mock//gomock:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",

View File

@@ -6,6 +6,7 @@ import (
"testing"
"github.com/ethereum/go-ethereum/common"
gethtypes "github.com/ethereum/go-ethereum/core/types"
chainMock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
dbTest "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
@@ -203,7 +204,7 @@ func TestServer_getTerminalBlockHashIfExists(t *testing.T) {
}{
{
name: "use terminal block hash, doesn't exist",
paramsTerminalHash: []byte{'a'},
paramsTerminalHash: common.BytesToHash([]byte("a")).Bytes(),
errString: "could not fetch height for hash",
},
{
@@ -218,17 +219,21 @@ func TestServer_getTerminalBlockHashIfExists(t *testing.T) {
name: "use terminal total difficulty",
paramsTd: "2",
currentPowBlock: &pb.ExecutionBlock{
Hash: []byte{'a'},
ParentHash: []byte{'b'},
Hash: common.BytesToHash([]byte("a")),
Header: gethtypes.Header{
ParentHash: common.BytesToHash([]byte("b")),
},
TotalDifficulty: "0x3",
},
parentPowBlock: &pb.ExecutionBlock{
Hash: []byte{'b'},
ParentHash: []byte{'c'},
Hash: common.BytesToHash([]byte("b")),
Header: gethtypes.Header{
ParentHash: common.BytesToHash([]byte("c")),
},
TotalDifficulty: "0x1",
},
wantExists: true,
wantTerminalBlockHash: []byte{'a'},
wantTerminalBlockHash: common.BytesToHash([]byte("a")).Bytes(),
},
}
for _, tt := range tests {
@@ -240,7 +245,7 @@ func TestServer_getTerminalBlockHashIfExists(t *testing.T) {
var m map[[32]byte]*pb.ExecutionBlock
if tt.parentPowBlock != nil {
m = map[[32]byte]*pb.ExecutionBlock{
bytesutil.ToBytes32(tt.parentPowBlock.Hash): tt.parentPowBlock,
tt.parentPowBlock.Hash: tt.parentPowBlock,
}
}
c := powtesting.NewPOWChain()

View File

@@ -358,6 +358,13 @@ var (
" For additional setting overrides use the --" + ProposerSettingsFlag.Name + " or --" + ProposerSettingsURLFlag.Name + " Flags. ",
Value: params.BeaconConfig().EthBurnAddressHex,
}
// EnableValidatorRegistrationFlag enables the periodic validator registration API calls that will update the custom builder with validator settings.
EnableValidatorRegistrationFlag = &cli.StringFlag{
Name: "enable-validator-registration",
Usage: "Enables validator registration APIs (MEV Builder APIs) for the validator client to update settings such as fee recipient and gas limit",
Value: "",
}
)
// DefaultValidatorDir returns OS-specific default validator directory.

View File

@@ -80,6 +80,7 @@ var appFlags = []cli.Flag{
flags.SuggestedFeeRecipientFlag,
flags.ProposerSettingsURLFlag,
flags.ProposerSettingsFlag,
flags.EnableValidatorRegistrationFlag,
////////////////////
cmd.DisableMonitoringFlag,
cmd.MonitoringHostFlag,

View File

@@ -114,6 +114,7 @@ var appHelpFlagGroups = []flagGroup{
flags.ProposerSettingsFlag,
flags.ProposerSettingsURLFlag,
flags.SuggestedFeeRecipientFlag,
flags.EnableValidatorRegistrationFlag,
},
},
{

View File

@@ -61,7 +61,7 @@ type Flags struct {
EnableSlashingProtectionPruning bool
EnableNativeState bool // EnableNativeState defines whether the beacon state will be represented as a pure Go struct or a Go struct that wraps a proto struct.
PullTips bool // Experimental disable of boundary checks
EnablePullTips bool // EnablePullTips enables experimental disabling of boundary checks.
EnableVectorizedHTR bool // EnableVectorizedHTR specifies whether the beacon state will use the optimized sha256 routines.
EnableForkChoiceDoublyLinkedTree bool // EnableForkChoiceDoublyLinkedTree specifies whether fork choice store will use a doubly linked tree.
EnableBatchGossipAggregation bool // EnableBatchGossipAggregation specifies whether to further aggregate our gossip batches before verifying them.
@@ -212,9 +212,9 @@ func ConfigureBeaconChain(ctx *cli.Context) error {
logDisabled(disableNativeState)
cfg.EnableNativeState = false
}
if ctx.Bool(pullTips.Name) {
logEnabled(pullTips)
cfg.PullTips = true
if ctx.Bool(enablePullTips.Name) {
logEnabled(enablePullTips)
cfg.EnablePullTips = true
}
if ctx.Bool(enableVecHTR.Name) {
logEnabled(enableVecHTR)

View File

@@ -106,7 +106,7 @@ var (
Usage: "Disables representing the beacon state as a pure Go struct.",
}
pullTips = &cli.BoolFlag{
enablePullTips = &cli.BoolFlag{
Name: "experimental-disable-boundary-checks",
Usage: "Experimental disable of boundary checks, useful for debugging, may cause bad votes.",
}
@@ -169,7 +169,7 @@ var BeaconChainFlags = append(deprecatedFlags, []cli.Flag{
enableSlasherFlag,
enableHistoricalSpaceRepresentation,
disableNativeState,
pullTips,
enablePullTips,
enableVecHTR,
enableForkChoiceDoublyLinkedTree,
enableGossipBatchAggregation,

View File

@@ -16,10 +16,16 @@ type ProposerSettingsPayload struct {
// ProposerOptionPayload is the struct representation of the JSON config file set in the validator through the CLI.
// FeeRecipient is set to an eth address in hex string format with 0x prefix.
// GasLimit is a number set to help the network decide on the maximum gas in each block.
type ProposerOptionPayload struct {
FeeRecipient string `json:"fee_recipient" yaml:"fee_recipient"`
GasLimit uint64 `json:"gas_limit,omitempty" yaml:"gas_limit,omitempty"`
FeeRecipient string `json:"fee_recipient" yaml:"fee_recipient"`
ValidatorRegistration *ValidatorRegistration `json:"validator_registration" yaml:"validator_registration"`
}
// ValidatorRegistration is the struct representation of the JSON config file set in the validator through the CLI.
// GasLimit is a number set to help the network decide on the maximum gas in each block.
type ValidatorRegistration struct {
Enable bool `json:"enable" yaml:"enable"`
GasLimit uint64 `json:"gas_limit,omitempty" yaml:"gas_limit,omitempty"`
}
// ProposerSettings is a Prysm internal representation of the fee recipient config on the validator client.
@@ -31,14 +37,14 @@ type ProposerSettings struct {
// ProposerOption is a Prysm internal representation of the ProposerOptionPayload on the validator client in bytes format instead of hex.
type ProposerOption struct {
FeeRecipient common.Address
GasLimit uint64
FeeRecipient common.Address
ValidatorRegistration *ValidatorRegistration
}
// DefaultProposerOption returns a Proposer Option with defaults filled
func DefaultProposerOption() ProposerOption {
return ProposerOption{
FeeRecipient: params.BeaconConfig().DefaultFeeRecipient,
GasLimit: params.BeaconConfig().DefaultBuilderGasLimit,
FeeRecipient: params.BeaconConfig().DefaultFeeRecipient,
ValidatorRegistration: nil,
}
}

View File

@@ -46,11 +46,11 @@ go_proto_library(
proto = ":proto",
visibility = ["//visibility:public"],
deps = [
"//proto/eth/ext:go_default_library",
"@io_bazel_rules_go//proto/wkt:descriptor_go_proto",
"@com_github_golang_protobuf//proto:go_default_library",
"//consensus-types/primitives:go_default_library",
"//proto/eth/ext:go_default_library",
"@com_github_golang_protobuf//proto:go_default_library",
"@go_googleapis//google/api:annotations_go_proto",
"@io_bazel_rules_go//proto/wkt:descriptor_go_proto",
"@org_golang_google_protobuf//reflect/protoreflect:go_default_library",
"@org_golang_google_protobuf//runtime/protoimpl:go_default_library",
],
@@ -68,19 +68,22 @@ go_library(
importpath = "github.com/prysmaticlabs/prysm/proto/engine/v1",
visibility = ["//visibility:public"],
deps = [
"//config/fieldparams:go_default_library",
"//config/params:go_default_library",
"//encoding/bytesutil:go_default_library",
"//proto/eth/ext:go_default_library",
"@io_bazel_rules_go//proto/wkt:descriptor_go_proto",
"@com_github_golang_protobuf//proto:go_default_library",
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
"@com_github_ethereum_go_ethereum//common:go_default_library",
"@com_github_ethereum_go_ethereum//core/types:go_default_library",
"@io_bazel_rules_go//proto/wkt:timestamp_go_proto",
"@go_googleapis//google/api:annotations_go_proto",
"@com_github_golang_protobuf//proto:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_prysmaticlabs_fastssz//:go_default_library",
"@io_bazel_rules_go//proto/wkt:descriptor_go_proto",
"@org_golang_google_protobuf//encoding/protojson:go_default_library",
"@org_golang_google_protobuf//reflect/protoreflect:go_default_library",
"@org_golang_google_protobuf//runtime/protoimpl:go_default_library",
"@com_github_prysmaticlabs_fastssz//:go_default_library",
"//encoding/bytesutil:go_default_library",
"//config/fieldparams:go_default_library",
"//config/params:go_default_library",
], # keep
)
@@ -91,10 +94,12 @@ go_test(
],
deps = [
":go_default_library",
"//config/fieldparams:go_default_library",
"//config/params:go_default_library",
"//encoding/bytesutil:go_default_library",
"//testing/require:go_default_library",
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
"//config/fieldparams:go_default_library",
"//config/params:go_default_library",
"@com_github_ethereum_go_ethereum//common:go_default_library",
"@com_github_ethereum_go_ethereum//core/types:go_default_library",
],
)

View File

@@ -80,213 +80,6 @@ func (PayloadStatus_Status) EnumDescriptor() ([]byte, []int) {
return file_proto_engine_v1_execution_engine_proto_rawDescGZIP(), []int{5, 0}
}
type ExecutionBlock struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Number []byte `protobuf:"bytes,1,opt,name=number,proto3" json:"number,omitempty"`
Hash []byte `protobuf:"bytes,2,opt,name=hash,proto3" json:"hash,omitempty"`
ParentHash []byte `protobuf:"bytes,3,opt,name=parent_hash,json=parentHash,proto3" json:"parent_hash,omitempty"`
Sha3Uncles []byte `protobuf:"bytes,4,opt,name=sha3_uncles,json=sha3Uncles,proto3" json:"sha3_uncles,omitempty"`
Miner []byte `protobuf:"bytes,5,opt,name=miner,proto3" json:"miner,omitempty"`
StateRoot []byte `protobuf:"bytes,6,opt,name=state_root,json=stateRoot,proto3" json:"state_root,omitempty"`
TransactionsRoot []byte `protobuf:"bytes,7,opt,name=transactions_root,json=transactionsRoot,proto3" json:"transactions_root,omitempty"`
ReceiptsRoot []byte `protobuf:"bytes,8,opt,name=receipts_root,json=receiptsRoot,proto3" json:"receipts_root,omitempty"`
LogsBloom []byte `protobuf:"bytes,9,opt,name=logs_bloom,json=logsBloom,proto3" json:"logs_bloom,omitempty"`
Difficulty []byte `protobuf:"bytes,10,opt,name=difficulty,proto3" json:"difficulty,omitempty"`
TotalDifficulty string `protobuf:"bytes,11,opt,name=total_difficulty,json=totalDifficulty,proto3" json:"total_difficulty,omitempty"`
GasLimit uint64 `protobuf:"varint,12,opt,name=gas_limit,json=gasLimit,proto3" json:"gas_limit,omitempty"`
GasUsed uint64 `protobuf:"varint,13,opt,name=gas_used,json=gasUsed,proto3" json:"gas_used,omitempty"`
BaseFeePerGas []byte `protobuf:"bytes,14,opt,name=base_fee_per_gas,json=baseFeePerGas,proto3" json:"base_fee_per_gas,omitempty"`
Size []byte `protobuf:"bytes,15,opt,name=size,proto3" json:"size,omitempty"`
Timestamp uint64 `protobuf:"varint,16,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
ExtraData []byte `protobuf:"bytes,17,opt,name=extra_data,json=extraData,proto3" json:"extra_data,omitempty"`
MixHash []byte `protobuf:"bytes,18,opt,name=mix_hash,json=mixHash,proto3" json:"mix_hash,omitempty"`
Nonce []byte `protobuf:"bytes,19,opt,name=nonce,proto3" json:"nonce,omitempty"`
Transactions [][]byte `protobuf:"bytes,20,rep,name=transactions,proto3" json:"transactions,omitempty"`
Uncles [][]byte `protobuf:"bytes,21,rep,name=uncles,proto3" json:"uncles,omitempty"`
}
func (x *ExecutionBlock) Reset() {
*x = ExecutionBlock{}
if protoimpl.UnsafeEnabled {
mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ExecutionBlock) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ExecutionBlock) ProtoMessage() {}
func (x *ExecutionBlock) ProtoReflect() protoreflect.Message {
mi := &file_proto_engine_v1_execution_engine_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ExecutionBlock.ProtoReflect.Descriptor instead.
func (*ExecutionBlock) Descriptor() ([]byte, []int) {
return file_proto_engine_v1_execution_engine_proto_rawDescGZIP(), []int{0}
}
func (x *ExecutionBlock) GetNumber() []byte {
if x != nil {
return x.Number
}
return nil
}
func (x *ExecutionBlock) GetHash() []byte {
if x != nil {
return x.Hash
}
return nil
}
func (x *ExecutionBlock) GetParentHash() []byte {
if x != nil {
return x.ParentHash
}
return nil
}
func (x *ExecutionBlock) GetSha3Uncles() []byte {
if x != nil {
return x.Sha3Uncles
}
return nil
}
func (x *ExecutionBlock) GetMiner() []byte {
if x != nil {
return x.Miner
}
return nil
}
func (x *ExecutionBlock) GetStateRoot() []byte {
if x != nil {
return x.StateRoot
}
return nil
}
func (x *ExecutionBlock) GetTransactionsRoot() []byte {
if x != nil {
return x.TransactionsRoot
}
return nil
}
func (x *ExecutionBlock) GetReceiptsRoot() []byte {
if x != nil {
return x.ReceiptsRoot
}
return nil
}
func (x *ExecutionBlock) GetLogsBloom() []byte {
if x != nil {
return x.LogsBloom
}
return nil
}
func (x *ExecutionBlock) GetDifficulty() []byte {
if x != nil {
return x.Difficulty
}
return nil
}
func (x *ExecutionBlock) GetTotalDifficulty() string {
if x != nil {
return x.TotalDifficulty
}
return ""
}
func (x *ExecutionBlock) GetGasLimit() uint64 {
if x != nil {
return x.GasLimit
}
return 0
}
func (x *ExecutionBlock) GetGasUsed() uint64 {
if x != nil {
return x.GasUsed
}
return 0
}
func (x *ExecutionBlock) GetBaseFeePerGas() []byte {
if x != nil {
return x.BaseFeePerGas
}
return nil
}
func (x *ExecutionBlock) GetSize() []byte {
if x != nil {
return x.Size
}
return nil
}
func (x *ExecutionBlock) GetTimestamp() uint64 {
if x != nil {
return x.Timestamp
}
return 0
}
func (x *ExecutionBlock) GetExtraData() []byte {
if x != nil {
return x.ExtraData
}
return nil
}
func (x *ExecutionBlock) GetMixHash() []byte {
if x != nil {
return x.MixHash
}
return nil
}
func (x *ExecutionBlock) GetNonce() []byte {
if x != nil {
return x.Nonce
}
return nil
}
func (x *ExecutionBlock) GetTransactions() [][]byte {
if x != nil {
return x.Transactions
}
return nil
}
func (x *ExecutionBlock) GetUncles() [][]byte {
if x != nil {
return x.Uncles
}
return nil
}
type ExecutionPayload struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -1066,18 +859,6 @@ func file_proto_engine_v1_execution_engine_proto_init() {
}
if !protoimpl.UnsafeEnabled {
file_proto_engine_v1_execution_engine_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ExecutionBlock); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_proto_engine_v1_execution_engine_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ExecutionPayload); i {
case 0:
return &v.state
@@ -1089,7 +870,7 @@ func file_proto_engine_v1_execution_engine_proto_init() {
return nil
}
}
file_proto_engine_v1_execution_engine_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
file_proto_engine_v1_execution_engine_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ExecutionPayloadHeader); i {
case 0:
return &v.state
@@ -1101,7 +882,7 @@ func file_proto_engine_v1_execution_engine_proto_init() {
return nil
}
}
file_proto_engine_v1_execution_engine_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
file_proto_engine_v1_execution_engine_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*TransitionConfiguration); i {
case 0:
return &v.state
@@ -1113,7 +894,7 @@ func file_proto_engine_v1_execution_engine_proto_init() {
return nil
}
}
file_proto_engine_v1_execution_engine_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
file_proto_engine_v1_execution_engine_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*PayloadAttributes); i {
case 0:
return &v.state
@@ -1125,7 +906,7 @@ func file_proto_engine_v1_execution_engine_proto_init() {
return nil
}
}
file_proto_engine_v1_execution_engine_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
file_proto_engine_v1_execution_engine_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*PayloadStatus); i {
case 0:
return &v.state
@@ -1137,7 +918,7 @@ func file_proto_engine_v1_execution_engine_proto_init() {
return nil
}
}
file_proto_engine_v1_execution_engine_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
file_proto_engine_v1_execution_engine_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ForkchoiceState); i {
case 0:
return &v.state

View File

@@ -24,30 +24,6 @@ option java_outer_classname = "ExecutionEngineProto";
option java_package = "org.ethereum.engine.v1";
option php_namespace = "Ethereum\\Engine\\v1";
message ExecutionBlock {
bytes number = 1;
bytes hash = 2;
bytes parent_hash = 3;
bytes sha3_uncles = 4;
bytes miner = 5;
bytes state_root = 6;
bytes transactions_root = 7;
bytes receipts_root = 8;
bytes logs_bloom = 9;
bytes difficulty = 10;
string total_difficulty = 11;
uint64 gas_limit = 12;
uint64 gas_used = 13;
bytes base_fee_per_gas = 14;
bytes size = 15;
uint64 timestamp = 16;
bytes extra_data = 17;
bytes mix_hash = 18;
bytes nonce = 19;
repeated bytes transactions = 20;
repeated bytes uncles = 21;
}
message ExecutionPayload {
bytes parent_hash = 1 [(ethereum.eth.ext.ssz_size) = "32"];
bytes fee_recipient = 2 [(ethereum.eth.ext.ssz_size) = "20"];

View File

@@ -4,7 +4,10 @@ import (
"encoding/json"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
gethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/pkg/errors"
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
)
@@ -18,6 +21,73 @@ func (b PayloadIDBytes) MarshalJSON() ([]byte, error) {
return json.Marshal(hexutil.Bytes(b[:]))
}
// ExecutionBlock is the response kind received by the eth_getBlockByHash and
// eth_getBlockByNumber endpoints via JSON-RPC.
type ExecutionBlock struct {
gethtypes.Header
Hash common.Hash `json:"hash"`
Transactions []*gethtypes.Transaction `json:"transactions"`
TotalDifficulty string `json:"totalDifficulty"`
}
func (e *ExecutionBlock) MarshalJSON() ([]byte, error) {
decoded := make(map[string]interface{})
encodedHeader, err := e.Header.MarshalJSON()
if err != nil {
return nil, err
}
if err := json.Unmarshal(encodedHeader, &decoded); err != nil {
return nil, err
}
encodedTxs, err := json.Marshal(e.Transactions)
if err != nil {
return nil, err
}
decoded["hash"] = e.Hash.String()
decoded["transactions"] = string(encodedTxs)
decoded["totalDifficulty"] = e.TotalDifficulty
return json.Marshal(decoded)
}
func (e *ExecutionBlock) UnmarshalJSON(enc []byte) error {
if err := e.Header.UnmarshalJSON(enc); err != nil {
return err
}
decoded := make(map[string]interface{})
if err := json.Unmarshal(enc, &decoded); err != nil {
return err
}
blockHashStr, ok := decoded["hash"].(string)
if !ok {
return errors.New("expected `hash` field in JSON response")
}
e.Hash = common.HexToHash(blockHashStr)
e.TotalDifficulty, ok = decoded["totalDifficulty"].(string)
if !ok {
return errors.New("expected `totalDifficulty` field in JSON response")
}
txsList, ok := decoded["transactions"].([]interface{})
if !ok {
return nil
}
// If the block contains a list of transactions, we JSON unmarshal
// them into a list of geth transaction objects.
txs := make([]*gethtypes.Transaction, len(txsList))
for i, tx := range txsList {
t := &gethtypes.Transaction{}
encodedTx, err := json.Marshal(tx)
if err != nil {
return errors.Wrapf(err, "could not marshal tx %v", tx)
}
if err := json.Unmarshal(encodedTx, &t); err != nil {
return errors.Wrapf(err, "could not marshal tx %s", string(encodedTx))
}
txs[i] = t
}
e.Transactions = txs
return nil
}
// UnmarshalJSON --
func (b *PayloadIDBytes) UnmarshalJSON(enc []byte) error {
hexBytes := hexutil.Bytes(make([]byte, 0))
@@ -30,147 +100,20 @@ func (b *PayloadIDBytes) UnmarshalJSON(enc []byte) error {
return nil
}
type executionBlockJSON struct {
Number string `json:"number"`
Hash hexutil.Bytes `json:"hash"`
ParentHash hexutil.Bytes `json:"parentHash"`
Sha3Uncles hexutil.Bytes `json:"sha3Uncles"`
Miner hexutil.Bytes `json:"miner"`
StateRoot hexutil.Bytes `json:"stateRoot"`
TransactionsRoot hexutil.Bytes `json:"transactionsRoot"`
ReceiptsRoot hexutil.Bytes `json:"receiptsRoot"`
LogsBloom hexutil.Bytes `json:"logsBloom"`
Difficulty string `json:"difficulty"`
TotalDifficulty string `json:"totalDifficulty"`
GasLimit hexutil.Uint64 `json:"gasLimit"`
GasUsed hexutil.Uint64 `json:"gasUsed"`
Timestamp hexutil.Uint64 `json:"timestamp"`
BaseFeePerGas string `json:"baseFeePerGas"`
ExtraData hexutil.Bytes `json:"extraData"`
MixHash hexutil.Bytes `json:"mixHash"`
Nonce hexutil.Bytes `json:"nonce"`
Size string `json:"size"`
Transactions []hexutil.Bytes `json:"transactions"`
Uncles []hexutil.Bytes `json:"uncles"`
}
// MarshalJSON defines a custom json.Marshaler interface implementation
// that uses custom json.Marshalers for the hexutil.Bytes and hexutil.Uint64 types.
func (e *ExecutionBlock) MarshalJSON() ([]byte, error) {
transactions := make([]hexutil.Bytes, len(e.Transactions))
for i, tx := range e.Transactions {
transactions[i] = tx
}
uncles := make([]hexutil.Bytes, len(e.Uncles))
for i, ucl := range e.Uncles {
uncles[i] = ucl
}
num := new(big.Int).SetBytes(e.Number)
numHex := hexutil.EncodeBig(num)
diff := new(big.Int).SetBytes(e.Difficulty)
diffHex := hexutil.EncodeBig(diff)
size := new(big.Int).SetBytes(e.Size)
sizeHex := hexutil.EncodeBig(size)
baseFee := new(big.Int).SetBytes(bytesutil.ReverseByteOrder(e.BaseFeePerGas))
baseFeeHex := hexutil.EncodeBig(baseFee)
return json.Marshal(executionBlockJSON{
Number: numHex,
Hash: e.Hash,
ParentHash: e.ParentHash,
Sha3Uncles: e.Sha3Uncles,
Miner: e.Miner,
StateRoot: e.StateRoot,
TransactionsRoot: e.TransactionsRoot,
ReceiptsRoot: e.ReceiptsRoot,
LogsBloom: e.LogsBloom,
Difficulty: diffHex,
TotalDifficulty: e.TotalDifficulty,
GasLimit: hexutil.Uint64(e.GasLimit),
GasUsed: hexutil.Uint64(e.GasUsed),
Timestamp: hexutil.Uint64(e.Timestamp),
ExtraData: e.ExtraData,
MixHash: e.MixHash,
Nonce: e.Nonce,
Size: sizeHex,
BaseFeePerGas: baseFeeHex,
Transactions: transactions,
Uncles: uncles,
})
}
// UnmarshalJSON defines a custom json.Unmarshaler interface implementation
// that uses custom json.Unmarshalers for the hexutil.Bytes and hexutil.Uint64 types.
func (e *ExecutionBlock) UnmarshalJSON(enc []byte) error {
dec := executionBlockJSON{}
if err := json.Unmarshal(enc, &dec); err != nil {
return err
}
*e = ExecutionBlock{}
num, err := hexutil.DecodeBig(dec.Number)
if err != nil {
return err
}
e.Number = num.Bytes()
e.Hash = dec.Hash
e.ParentHash = dec.ParentHash
e.Sha3Uncles = dec.Sha3Uncles
e.Miner = dec.Miner
e.StateRoot = dec.StateRoot
e.TransactionsRoot = dec.TransactionsRoot
e.ReceiptsRoot = dec.ReceiptsRoot
e.LogsBloom = dec.LogsBloom
diff, err := hexutil.DecodeBig(dec.Difficulty)
if err != nil {
return err
}
e.Difficulty = diff.Bytes()
e.TotalDifficulty = dec.TotalDifficulty
e.GasLimit = uint64(dec.GasLimit)
e.GasUsed = uint64(dec.GasUsed)
e.Timestamp = uint64(dec.Timestamp)
e.ExtraData = dec.ExtraData
e.MixHash = dec.MixHash
e.Nonce = dec.Nonce
size, err := hexutil.DecodeBig(dec.Size)
if err != nil {
return err
}
e.Size = size.Bytes()
baseFee, err := hexutil.DecodeBig(dec.BaseFeePerGas)
if err != nil {
return err
}
e.BaseFeePerGas = bytesutil.PadTo(bytesutil.ReverseByteOrder(baseFee.Bytes()), fieldparams.RootLength)
transactions := make([][]byte, len(dec.Transactions))
for i, tx := range dec.Transactions {
transactions[i] = tx
}
e.Transactions = transactions
uncles := make([][]byte, len(dec.Uncles))
for i, ucl := range dec.Uncles {
uncles[i] = ucl
}
e.Uncles = uncles
return nil
}
type executionPayloadJSON struct {
ParentHash hexutil.Bytes `json:"parentHash"`
FeeRecipient hexutil.Bytes `json:"feeRecipient"`
StateRoot hexutil.Bytes `json:"stateRoot"`
ReceiptsRoot hexutil.Bytes `json:"receiptsRoot"`
LogsBloom hexutil.Bytes `json:"logsBloom"`
PrevRandao hexutil.Bytes `json:"prevRandao"`
BlockNumber hexutil.Uint64 `json:"blockNumber"`
GasLimit hexutil.Uint64 `json:"gasLimit"`
GasUsed hexutil.Uint64 `json:"gasUsed"`
Timestamp hexutil.Uint64 `json:"timestamp"`
ParentHash *common.Hash `json:"parentHash"`
FeeRecipient *common.Address `json:"feeRecipient"`
StateRoot *common.Hash `json:"stateRoot"`
ReceiptsRoot *common.Hash `json:"receiptsRoot"`
LogsBloom *hexutil.Bytes `json:"logsBloom"`
PrevRandao *common.Hash `json:"prevRandao"`
BlockNumber *hexutil.Uint64 `json:"blockNumber"`
GasLimit *hexutil.Uint64 `json:"gasLimit"`
GasUsed *hexutil.Uint64 `json:"gasUsed"`
Timestamp *hexutil.Uint64 `json:"timestamp"`
ExtraData hexutil.Bytes `json:"extraData"`
BaseFeePerGas string `json:"baseFeePerGas"`
BlockHash hexutil.Bytes `json:"blockHash"`
BlockHash *common.Hash `json:"blockHash"`
Transactions []hexutil.Bytes `json:"transactions"`
}
@@ -182,20 +125,31 @@ func (e *ExecutionPayload) MarshalJSON() ([]byte, error) {
}
baseFee := new(big.Int).SetBytes(bytesutil.ReverseByteOrder(e.BaseFeePerGas))
baseFeeHex := hexutil.EncodeBig(baseFee)
pHash := common.BytesToHash(e.ParentHash)
sRoot := common.BytesToHash(e.StateRoot)
recRoot := common.BytesToHash(e.ReceiptsRoot)
prevRan := common.BytesToHash(e.PrevRandao)
bHash := common.BytesToHash(e.BlockHash)
blockNum := hexutil.Uint64(e.BlockNumber)
gasLimit := hexutil.Uint64(e.GasLimit)
gasUsed := hexutil.Uint64(e.GasUsed)
timeStamp := hexutil.Uint64(e.Timestamp)
recipient := common.BytesToAddress(e.FeeRecipient)
logsBloom := hexutil.Bytes(e.LogsBloom)
return json.Marshal(executionPayloadJSON{
ParentHash: e.ParentHash,
FeeRecipient: e.FeeRecipient,
StateRoot: e.StateRoot,
ReceiptsRoot: e.ReceiptsRoot,
LogsBloom: e.LogsBloom,
PrevRandao: e.PrevRandao,
BlockNumber: hexutil.Uint64(e.BlockNumber),
GasLimit: hexutil.Uint64(e.GasLimit),
GasUsed: hexutil.Uint64(e.GasUsed),
Timestamp: hexutil.Uint64(e.Timestamp),
ParentHash: &pHash,
FeeRecipient: &recipient,
StateRoot: &sRoot,
ReceiptsRoot: &recRoot,
LogsBloom: &logsBloom,
PrevRandao: &prevRan,
BlockNumber: &blockNum,
GasLimit: &gasLimit,
GasUsed: &gasUsed,
Timestamp: &timeStamp,
ExtraData: e.ExtraData,
BaseFeePerGas: baseFeeHex,
BlockHash: e.BlockHash,
BlockHash: &bHash,
Transactions: transactions,
})
}
@@ -206,24 +160,65 @@ func (e *ExecutionPayload) UnmarshalJSON(enc []byte) error {
if err := json.Unmarshal(enc, &dec); err != nil {
return err
}
if dec.ParentHash == nil {
return errors.New("missing required field 'parentHash' for ExecutionPayload")
}
if dec.FeeRecipient == nil {
return errors.New("missing required field 'feeRecipient' for ExecutionPayload")
}
if dec.StateRoot == nil {
return errors.New("missing required field 'stateRoot' for ExecutionPayload")
}
if dec.ReceiptsRoot == nil {
return errors.New("missing required field 'receiptsRoot' for ExecutableDataV1")
}
if dec.LogsBloom == nil {
return errors.New("missing required field 'logsBloom' for ExecutionPayload")
}
if dec.PrevRandao == nil {
return errors.New("missing required field 'prevRandao' for ExecutionPayload")
}
if dec.ExtraData == nil {
return errors.New("missing required field 'extraData' for ExecutionPayload")
}
if dec.BlockHash == nil {
return errors.New("missing required field 'blockHash' for ExecutionPayload")
}
if dec.Transactions == nil {
return errors.New("missing required field 'transactions' for ExecutionPayload")
}
if dec.BlockNumber == nil {
return errors.New("missing required field 'blockNumber' for ExecutionPayload")
}
if dec.Timestamp == nil {
return errors.New("missing required field 'timestamp' for ExecutionPayload")
}
if dec.GasUsed == nil {
return errors.New("missing required field 'gasUsed' for ExecutionPayload")
}
if dec.GasLimit == nil {
return errors.New("missing required field 'gasLimit' for ExecutionPayload")
}
*e = ExecutionPayload{}
e.ParentHash = bytesutil.PadTo(dec.ParentHash, fieldparams.RootLength)
e.FeeRecipient = bytesutil.PadTo(dec.FeeRecipient, fieldparams.FeeRecipientLength)
e.StateRoot = bytesutil.PadTo(dec.StateRoot, fieldparams.RootLength)
e.ReceiptsRoot = bytesutil.PadTo(dec.ReceiptsRoot, fieldparams.RootLength)
e.LogsBloom = bytesutil.PadTo(dec.LogsBloom, fieldparams.LogsBloomLength)
e.PrevRandao = bytesutil.PadTo(dec.PrevRandao, fieldparams.RootLength)
e.BlockNumber = uint64(dec.BlockNumber)
e.GasLimit = uint64(dec.GasLimit)
e.GasUsed = uint64(dec.GasUsed)
e.Timestamp = uint64(dec.Timestamp)
e.ParentHash = dec.ParentHash.Bytes()
e.FeeRecipient = dec.FeeRecipient.Bytes()
e.StateRoot = dec.StateRoot.Bytes()
e.ReceiptsRoot = dec.ReceiptsRoot.Bytes()
e.LogsBloom = *dec.LogsBloom
e.PrevRandao = dec.PrevRandao.Bytes()
e.BlockNumber = uint64(*dec.BlockNumber)
e.GasLimit = uint64(*dec.GasLimit)
e.GasUsed = uint64(*dec.GasUsed)
e.Timestamp = uint64(*dec.Timestamp)
e.ExtraData = dec.ExtraData
baseFee, err := hexutil.DecodeBig(dec.BaseFeePerGas)
if err != nil {
return err
}
e.BaseFeePerGas = bytesutil.PadTo(bytesutil.ReverseByteOrder(baseFee.Bytes()), fieldparams.RootLength)
e.BlockHash = bytesutil.PadTo(dec.BlockHash, fieldparams.RootLength)
e.BlockHash = dec.BlockHash.Bytes()
transactions := make([][]byte, len(dec.Transactions))
for i, tx := range dec.Transactions {
transactions[i] = tx
@@ -261,16 +256,20 @@ func (p *PayloadAttributes) UnmarshalJSON(enc []byte) error {
}
type payloadStatusJSON struct {
LatestValidHash *hexutil.Bytes `json:"latestValidHash"`
Status string `json:"status"`
ValidationError *string `json:"validationError"`
LatestValidHash *common.Hash `json:"latestValidHash"`
Status string `json:"status"`
ValidationError *string `json:"validationError"`
}
// MarshalJSON --
func (p *PayloadStatus) MarshalJSON() ([]byte, error) {
hash := p.LatestValidHash
var latestHash *common.Hash
if p.LatestValidHash != nil {
hash := common.Hash(bytesutil.ToBytes32(p.LatestValidHash))
latestHash = (*common.Hash)(&hash)
}
return json.Marshal(payloadStatusJSON{
LatestValidHash: (*hexutil.Bytes)(&hash),
LatestValidHash: latestHash,
Status: p.Status.String(),
ValidationError: &p.ValidationError,
})
@@ -284,7 +283,7 @@ func (p *PayloadStatus) UnmarshalJSON(enc []byte) error {
}
*p = PayloadStatus{}
if dec.LatestValidHash != nil {
p.LatestValidHash = *dec.LatestValidHash
p.LatestValidHash = dec.LatestValidHash[:]
}
p.Status = PayloadStatus_Status(PayloadStatus_Status_value[dec.Status])
if dec.ValidationError != nil {

View File

@@ -5,7 +5,8 @@ import (
"math/big"
"testing"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common"
gethtypes "github.com/ethereum/go-ethereum/core/types"
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
"github.com/prysmaticlabs/prysm/config/params"
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
@@ -125,61 +126,58 @@ func TestJsonMarshalUnmarshal(t *testing.T) {
})
t.Run("execution block", func(t *testing.T) {
baseFeePerGas := big.NewInt(1770307273)
jsonPayload := &enginev1.ExecutionBlock{
Number: []byte("100"),
Hash: []byte("hash"),
ParentHash: []byte("parent"),
Sha3Uncles: []byte("sha3Uncles"),
Miner: []byte("miner"),
StateRoot: []byte("stateRoot"),
TransactionsRoot: []byte("txRoot"),
ReceiptsRoot: []byte("receiptsRoot"),
LogsBloom: []byte("logsBloom"),
Difficulty: []byte("1"),
TotalDifficulty: "2",
GasLimit: 3,
GasUsed: 4,
Timestamp: 5,
BaseFeePerGas: baseFeePerGas.Bytes(),
Size: []byte("7"),
ExtraData: []byte("extraData"),
MixHash: []byte("mixHash"),
Nonce: []byte("nonce"),
Transactions: [][]byte{[]byte("hi")},
Uncles: [][]byte{[]byte("bye")},
want := &gethtypes.Header{
Number: big.NewInt(1),
ParentHash: common.BytesToHash([]byte("parent")),
UncleHash: common.BytesToHash([]byte("uncle")),
Coinbase: common.BytesToAddress([]byte("coinbase")),
Root: common.BytesToHash([]byte("uncle")),
TxHash: common.BytesToHash([]byte("txHash")),
ReceiptHash: common.BytesToHash([]byte("receiptHash")),
Bloom: gethtypes.BytesToBloom([]byte("bloom")),
Difficulty: big.NewInt(2),
GasLimit: 3,
GasUsed: 4,
Time: 5,
BaseFee: baseFeePerGas,
Extra: []byte("extraData"),
MixDigest: common.BytesToHash([]byte("mix")),
Nonce: gethtypes.EncodeNonce(6),
}
enc, err := json.Marshal(jsonPayload)
enc, err := json.Marshal(want)
require.NoError(t, err)
payloadPb := &enginev1.ExecutionBlock{}
require.NoError(t, json.Unmarshal(enc, payloadPb))
require.DeepEqual(t, []byte("100"), payloadPb.Number)
require.DeepEqual(t, []byte("hash"), payloadPb.Hash)
require.DeepEqual(t, []byte("parent"), payloadPb.ParentHash)
require.DeepEqual(t, []byte("sha3Uncles"), payloadPb.Sha3Uncles)
require.DeepEqual(t, []byte("miner"), payloadPb.Miner)
require.DeepEqual(t, []byte("stateRoot"), payloadPb.StateRoot)
require.DeepEqual(t, []byte("txRoot"), payloadPb.TransactionsRoot)
require.DeepEqual(t, []byte("receiptsRoot"), payloadPb.ReceiptsRoot)
require.DeepEqual(t, []byte("logsBloom"), payloadPb.LogsBloom)
require.DeepEqual(t, []byte("1"), payloadPb.Difficulty)
require.DeepEqual(t, "2", payloadPb.TotalDifficulty)
require.DeepEqual(t, uint64(3), payloadPb.GasLimit)
require.DeepEqual(t, uint64(4), payloadPb.GasUsed)
require.DeepEqual(t, uint64(5), payloadPb.Timestamp)
require.DeepEqual(t, bytesutil.PadTo(baseFeePerGas.Bytes(), fieldparams.RootLength), payloadPb.BaseFeePerGas)
require.DeepEqual(t, []byte("7"), payloadPb.Size)
require.DeepEqual(t, []byte("extraData"), payloadPb.ExtraData)
require.DeepEqual(t, []byte("mixHash"), payloadPb.MixHash)
require.DeepEqual(t, []byte("nonce"), payloadPb.Nonce)
require.DeepEqual(t, [][]byte{[]byte("hi")}, payloadPb.Transactions)
require.DeepEqual(t, [][]byte{[]byte("bye")}, payloadPb.Uncles)
})
t.Run("nil execution block", func(t *testing.T) {
jsonPayload := (*enginev1.ExecutionBlock)(nil)
enc, err := json.Marshal(jsonPayload)
payloadItems := make(map[string]interface{})
require.NoError(t, json.Unmarshal(enc, &payloadItems))
blockHash := want.Hash()
payloadItems["hash"] = blockHash.String()
payloadItems["totalDifficulty"] = "0x393a2e53de197c"
encodedPayloadItems, err := json.Marshal(payloadItems)
require.NoError(t, err)
payloadPb := &enginev1.ExecutionBlock{}
require.ErrorIs(t, hexutil.ErrEmptyString, json.Unmarshal(enc, payloadPb))
require.NoError(t, json.Unmarshal(encodedPayloadItems, payloadPb))
require.DeepEqual(t, blockHash, payloadPb.Hash)
require.DeepEqual(t, want.Number, payloadPb.Number)
require.DeepEqual(t, want.ParentHash, payloadPb.ParentHash)
require.DeepEqual(t, want.UncleHash, payloadPb.UncleHash)
require.DeepEqual(t, want.Coinbase, payloadPb.Coinbase)
require.DeepEqual(t, want.Root, payloadPb.Root)
require.DeepEqual(t, want.TxHash, payloadPb.TxHash)
require.DeepEqual(t, want.ReceiptHash, payloadPb.ReceiptHash)
require.DeepEqual(t, want.Bloom, payloadPb.Bloom)
require.DeepEqual(t, want.Difficulty, payloadPb.Difficulty)
require.DeepEqual(t, payloadItems["totalDifficulty"], payloadPb.TotalDifficulty)
require.DeepEqual(t, want.GasUsed, payloadPb.GasUsed)
require.DeepEqual(t, want.GasLimit, payloadPb.GasLimit)
require.DeepEqual(t, want.Time, payloadPb.Time)
require.DeepEqual(t, want.BaseFee, payloadPb.BaseFee)
require.DeepEqual(t, want.Extra, payloadPb.Extra)
require.DeepEqual(t, want.MixDigest, payloadPb.MixDigest)
require.DeepEqual(t, want.Nonce, payloadPb.Nonce)
})
}

File diff suppressed because it is too large Load Diff

View File

@@ -434,6 +434,9 @@ message BeaconBlockContainer {
// Representing an bellatrix block.
SignedBeaconBlockBellatrix bellatrix_block = 5;
// Representing a blinded bellatrix block.
SignedBlindedBeaconBlockBellatrix blinded_bellatrix_block = 6;
}
}

View File

@@ -52,6 +52,7 @@ go_test(
"endtoend_setup_test.go",
"endtoend_test.go",
"minimal_e2e_test.go",
"minimal_slashing_e2e_test.go",
"slasher_simulator_e2e_test.go",
],
args = ["-test.v"],

View File

@@ -3,7 +3,6 @@ package endtoend
import (
"testing"
ev "github.com/prysmaticlabs/prysm/testing/endtoend/evaluators"
"github.com/prysmaticlabs/prysm/testing/endtoend/types"
)
@@ -19,20 +18,6 @@ func TestEndToEnd_MinimalConfig_Web3Signer(t *testing.T) {
e2eMinimal(t, types.WithRemoteSigner()).run()
}
func TestEndToEnd_MinimalConfig_Slasher(t *testing.T) {
e2eMinimal(
t,
types.WithSlasher(
ev.PeersConnect,
ev.HealthzCheck,
ev.ValidatorsSlashedAfterEpoch(4),
ev.SlashedValidatorsLoseBalanceAfterEpoch(4),
ev.InjectDoubleVoteOnEpoch(2),
ev.InjectDoubleBlockOnEpoch(2),
),
).run()
}
func TestEndToEnd_ScenarioRun_EEOffline(t *testing.T) {
t.Skip("TODO(#10242) Prysm is current unable to handle an offline e2e")
runner := e2eMinimal(t)

View File

@@ -0,0 +1,44 @@
package endtoend
import (
"fmt"
"testing"
"github.com/prysmaticlabs/prysm/config/params"
ev "github.com/prysmaticlabs/prysm/testing/endtoend/evaluators"
e2eParams "github.com/prysmaticlabs/prysm/testing/endtoend/params"
"github.com/prysmaticlabs/prysm/testing/endtoend/types"
"github.com/prysmaticlabs/prysm/testing/require"
)
func TestEndToEnd_Slasher_MinimalConfig(t *testing.T) {
params.SetupTestConfigCleanup(t)
params.OverrideBeaconConfig(params.E2ETestConfig().Copy())
require.NoError(t, e2eParams.Init(t, e2eParams.StandardBeaconCount))
tracingPort := e2eParams.TestParams.Ports.JaegerTracingPort
tracingEndpoint := fmt.Sprintf("127.0.0.1:%d", tracingPort)
testConfig := &types.E2EConfig{
BeaconFlags: []string{
"--slasher",
},
ValidatorFlags: []string{},
EpochsToRun: 4,
TestSync: false,
TestFeature: false,
TestDeposits: false,
Evaluators: []types.Evaluator{
ev.PeersConnect,
ev.HealthzCheck,
ev.ValidatorsSlashedAfterEpoch(4),
ev.SlashedValidatorsLoseBalanceAfterEpoch(4),
ev.InjectDoubleVoteOnEpoch(2),
ev.InjectDoubleBlockOnEpoch(2),
},
EvalInterceptor: defaultInterceptor,
TracingSinkEndpoint: tracingEndpoint,
}
newTestRunner(t, testConfig).run()
}

View File

@@ -23,14 +23,6 @@ func WithRemoteSigner() E2EConfigOpt {
}
}
func WithSlasher(evs ...Evaluator) E2EConfigOpt {
return func(cfg *E2EConfig) {
cfg.UseSlasher = true
cfg.Evaluators = evs
cfg.BeaconFlags = append(cfg.BeaconFlags, "--slasher")
}
}
func WithCheckpointSync() E2EConfigOpt {
return func(cfg *E2EConfig) {
cfg.TestCheckpointSync = true
@@ -45,7 +37,6 @@ type E2EConfig struct {
UsePrysmShValidator bool
UsePprof bool
UseWeb3RemoteSigner bool
UseSlasher bool
TestDeposits bool
UseFixedPeerIDs bool
UseValidatorCrossClient bool

View File

@@ -40,6 +40,7 @@ go_library(
"//testing/util:go_default_library",
"@com_github_ethereum_go_ethereum//common:go_default_library",
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
"@com_github_ethereum_go_ethereum//core/types:go_default_library",
"@com_github_golang_snappy//:go_default_library",
],
)

View File

@@ -7,6 +7,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
gethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain"
mock "github.com/prysmaticlabs/prysm/beacon-chain/blockchain/testing"
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
@@ -96,9 +97,11 @@ func (m *engineMock) ExecutionBlockByHash(_ context.Context, hash common.Hash) (
td := new(big.Int).SetBytes(bytesutil.ReverseByteOrder(b.TotalDifficulty))
tdHex := hexutil.EncodeBig(td)
return &pb.ExecutionBlock{
ParentHash: b.ParentHash,
Header: gethtypes.Header{
ParentHash: common.BytesToHash(b.ParentHash),
},
TotalDifficulty: tdHex,
Hash: b.BlockHash,
Hash: common.BytesToHash(b.BlockHash),
}, nil
}

View File

@@ -994,6 +994,7 @@ func (v *validator) buildProposerSettingsRequests(ctx context.Context, pubkeys [
var registerValidatorRequests []*ethpb.ValidatorRegistrationV1
// need to check for pubkey to validator index mappings
for i, key := range pubkeys {
var enableValidatorRegistration bool
skipAppendToFeeRecipientArray := false
feeRecipient := common.HexToAddress(params.BeaconConfig().EthBurnAddressHex)
gasLimit := params.BeaconConfig().DefaultBuilderGasLimit
@@ -1012,14 +1013,25 @@ func (v *validator) buildProposerSettingsRequests(ctx context.Context, pubkeys [
}
if v.ProposerSettings.DefaultConfig != nil {
feeRecipient = v.ProposerSettings.DefaultConfig.FeeRecipient
gasLimit = v.ProposerSettings.DefaultConfig.GasLimit
vr := v.ProposerSettings.DefaultConfig.ValidatorRegistration
if vr != nil && vr.Enable {
gasLimit = vr.GasLimit
enableValidatorRegistration = true
}
}
if v.ProposerSettings.ProposeConfig != nil {
option, ok := v.ProposerSettings.ProposeConfig[key]
if ok && option != nil {
// override the default if a proposeconfig is set
feeRecipient = option.FeeRecipient
gasLimit = option.GasLimit
vr := option.ValidatorRegistration
if vr != nil && vr.Enable {
gasLimit = vr.GasLimit
enableValidatorRegistration = true
} else {
enableValidatorRegistration = false
}
}
}
if hexutil.Encode(feeRecipient.Bytes()) == params.BeaconConfig().EthBurnAddressHex {
@@ -1031,13 +1043,14 @@ func (v *validator) buildProposerSettingsRequests(ctx context.Context, pubkeys [
FeeRecipient: feeRecipient[:],
})
}
registerValidatorRequests = append(registerValidatorRequests, &ethpb.ValidatorRegistrationV1{
FeeRecipient: feeRecipient[:],
GasLimit: gasLimit,
Timestamp: uint64(time.Now().UTC().Unix()),
Pubkey: pubkeys[i][:],
})
if enableValidatorRegistration {
registerValidatorRequests = append(registerValidatorRequests, &ethpb.ValidatorRegistrationV1{
FeeRecipient: feeRecipient[:],
GasLimit: gasLimit,
Timestamp: uint64(time.Now().UTC().Unix()),
Pubkey: pubkeys[i][:],
})
}
}
return validatorToFeeRecipients, registerValidatorRequests, nil
}

View File

@@ -378,6 +378,10 @@ func TestWaitMultipleActivation_LogsActivationEpochOK(t *testing.T) {
ProposeConfig: nil,
DefaultConfig: &validatorserviceconfig.ProposerOption{
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
ValidatorRegistration: &validatorserviceconfig.ValidatorRegistration{
Enable: true,
GasLimit: uint64(40000000),
},
},
},
}
@@ -435,6 +439,10 @@ func TestWaitActivation_NotAllValidatorsActivatedOK(t *testing.T) {
ProposeConfig: nil,
DefaultConfig: &validatorserviceconfig.ProposerOption{
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
ValidatorRegistration: &validatorserviceconfig.ValidatorRegistration{
Enable: true,
GasLimit: uint64(40000000),
},
},
},
}
@@ -1546,19 +1554,25 @@ func TestValidator_PushProposerSettings(t *testing.T) {
}).Return(nil, nil)
config[keys[0]] = &validatorserviceconfig.ProposerOption{
FeeRecipient: common.HexToAddress("0x055Fb65722E7b2455043BFEBf6177F1D2e9738D9"),
GasLimit: uint64(40000000),
ValidatorRegistration: &validatorserviceconfig.ValidatorRegistration{
Enable: true,
GasLimit: uint64(40000000),
},
}
v.ProposerSettings = &validatorserviceconfig.ProposerSettings{
ProposeConfig: config,
DefaultConfig: &validatorserviceconfig.ProposerOption{
FeeRecipient: common.HexToAddress(defaultFeeHex),
GasLimit: uint64(35000000),
ValidatorRegistration: &validatorserviceconfig.ValidatorRegistration{
Enable: true,
GasLimit: uint64(35000000),
},
},
}
client.EXPECT().SubmitValidatorRegistration(
gomock.Any(),
gomock.Any(),
).Times(2).Return(&empty.Empty{}, nil)
).Return(&empty.Empty{}, nil)
return &v
},
feeRecipientMap: map[types.ValidatorIndex]string{
@@ -1577,6 +1591,81 @@ func TestValidator_PushProposerSettings(t *testing.T) {
},
},
},
{
name: " Happy Path default doesn't send validator registration",
validatorSetter: func(t *testing.T) *validator {
v := validator{
validatorClient: client,
node: nodeClient,
db: db,
pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]types.ValidatorIndex),
useWeb: false,
interopKeysConfig: &local.InteropKeymanagerConfig{
NumValidatorKeys: 2,
Offset: 1,
},
}
err := v.WaitForKeymanagerInitialization(ctx)
require.NoError(t, err)
config := make(map[[fieldparams.BLSPubkeyLength]byte]*validatorserviceconfig.ProposerOption)
km, err := v.Keymanager()
require.NoError(t, err)
keys, err := km.FetchValidatingPublicKeys(ctx)
require.NoError(t, err)
client.EXPECT().ValidatorIndex(
ctx, // ctx
&ethpb.ValidatorIndexRequest{PublicKey: keys[0][:]},
).Return(&ethpb.ValidatorIndexResponse{
Index: 1,
}, nil)
client.EXPECT().ValidatorIndex(
ctx, // ctx
&ethpb.ValidatorIndexRequest{PublicKey: keys[1][:]},
).Return(&ethpb.ValidatorIndexResponse{
Index: 2,
}, nil)
client.EXPECT().PrepareBeaconProposer(gomock.Any(), &ethpb.PrepareBeaconProposerRequest{
Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{
{FeeRecipient: common.HexToAddress("0x055Fb65722E7b2455043BFEBf6177F1D2e9738D9").Bytes(), ValidatorIndex: 1},
{FeeRecipient: common.HexToAddress(defaultFeeHex).Bytes(), ValidatorIndex: 2},
},
}).Return(nil, nil)
config[keys[0]] = &validatorserviceconfig.ProposerOption{
FeeRecipient: common.HexToAddress("0x055Fb65722E7b2455043BFEBf6177F1D2e9738D9"),
ValidatorRegistration: &validatorserviceconfig.ValidatorRegistration{
Enable: true,
GasLimit: uint64(40000000),
},
}
v.ProposerSettings = &validatorserviceconfig.ProposerSettings{
ProposeConfig: config,
DefaultConfig: &validatorserviceconfig.ProposerOption{
FeeRecipient: common.HexToAddress(defaultFeeHex),
ValidatorRegistration: &validatorserviceconfig.ValidatorRegistration{
Enable: false,
GasLimit: uint64(35000000),
},
},
}
client.EXPECT().SubmitValidatorRegistration(
gomock.Any(),
gomock.Any(),
).Return(&empty.Empty{}, nil)
return &v
},
feeRecipientMap: map[types.ValidatorIndex]string{
1: "0x055Fb65722E7b2455043BFEBf6177F1D2e9738D9",
2: defaultFeeHex,
},
mockExpectedRequests: []ExpectedValidatorRegistration{
{
FeeRecipient: common.HexToAddress("0x055Fb65722E7b2455043BFEBf6177F1D2e9738D9").Bytes(),
GasLimit: uint64(40000000),
},
},
},
{
name: " Happy Path",
validatorSetter: func(t *testing.T) *validator {
@@ -1605,7 +1694,10 @@ func TestValidator_PushProposerSettings(t *testing.T) {
ProposeConfig: nil,
DefaultConfig: &validatorserviceconfig.ProposerOption{
FeeRecipient: common.HexToAddress(defaultFeeHex),
GasLimit: params.BeaconConfig().DefaultBuilderGasLimit,
ValidatorRegistration: &validatorserviceconfig.ValidatorRegistration{
Enable: true,
GasLimit: params.BeaconConfig().DefaultBuilderGasLimit,
},
},
}
client.EXPECT().ValidatorIndex(
@@ -1636,6 +1728,64 @@ func TestValidator_PushProposerSettings(t *testing.T) {
},
},
},
{
name: " Happy Path validator index not found in cache",
validatorSetter: func(t *testing.T) *validator {
v := validator{
validatorClient: client,
node: nodeClient,
db: db,
pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]types.ValidatorIndex),
useWeb: false,
interopKeysConfig: &local.InteropKeymanagerConfig{
NumValidatorKeys: 1,
Offset: 1,
},
}
err := v.WaitForKeymanagerInitialization(ctx)
require.NoError(t, err)
v.ProposerSettings = &validatorserviceconfig.ProposerSettings{
ProposeConfig: nil,
DefaultConfig: &validatorserviceconfig.ProposerOption{
FeeRecipient: common.HexToAddress(defaultFeeHex),
ValidatorRegistration: &validatorserviceconfig.ValidatorRegistration{
Enable: true,
GasLimit: uint64(40000000),
},
},
}
km, err := v.Keymanager()
require.NoError(t, err)
keys, err := km.FetchValidatingPublicKeys(ctx)
require.NoError(t, err)
client.EXPECT().ValidatorIndex(
ctx, // ctx
&ethpb.ValidatorIndexRequest{PublicKey: keys[0][:]},
).Return(&ethpb.ValidatorIndexResponse{
Index: 1,
}, nil)
client.EXPECT().SubmitValidatorRegistration(
gomock.Any(),
gomock.Any(),
).Return(&empty.Empty{}, nil)
client.EXPECT().PrepareBeaconProposer(gomock.Any(), &ethpb.PrepareBeaconProposerRequest{
Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{
{FeeRecipient: common.HexToAddress(defaultFeeHex).Bytes(), ValidatorIndex: 1},
},
}).Return(nil, nil)
return &v
},
feeRecipientMap: map[types.ValidatorIndex]string{
1: defaultFeeHex,
},
mockExpectedRequests: []ExpectedValidatorRegistration{
{
FeeRecipient: byteValueAddress,
GasLimit: params.BeaconConfig().DefaultBuilderGasLimit,
},
},
},
{
name: " Skip if no config",
validatorSetter: func(t *testing.T) *validator {
@@ -1655,61 +1805,6 @@ func TestValidator_PushProposerSettings(t *testing.T) {
return &v
},
},
{
name: " Happy Path validator index not found in cache",
validatorSetter: func(t *testing.T) *validator {
v := validator{
validatorClient: client,
node: nodeClient,
db: db,
pubkeyToValidatorIndex: make(map[[fieldparams.BLSPubkeyLength]byte]types.ValidatorIndex),
useWeb: false,
interopKeysConfig: &local.InteropKeymanagerConfig{
NumValidatorKeys: 1,
Offset: 1,
},
}
err := v.WaitForKeymanagerInitialization(ctx)
require.NoError(t, err)
v.ProposerSettings = &validatorserviceconfig.ProposerSettings{
ProposeConfig: nil,
DefaultConfig: &validatorserviceconfig.ProposerOption{
FeeRecipient: common.HexToAddress(defaultFeeHex),
},
}
km, err := v.Keymanager()
require.NoError(t, err)
keys, err := km.FetchValidatingPublicKeys(ctx)
require.NoError(t, err)
client.EXPECT().ValidatorIndex(
ctx, // ctx
&ethpb.ValidatorIndexRequest{PublicKey: keys[0][:]},
).Return(&ethpb.ValidatorIndexResponse{
Index: 1,
}, nil)
client.EXPECT().SubmitValidatorRegistration(
gomock.Any(),
gomock.Any(),
).Return(&empty.Empty{}, nil)
client.EXPECT().PrepareBeaconProposer(gomock.Any(), &ethpb.PrepareBeaconProposerRequest{
Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{
{FeeRecipient: common.HexToAddress(defaultFeeHex).Bytes(), ValidatorIndex: 1},
},
}).Return(nil, nil)
return &v
},
feeRecipientMap: map[types.ValidatorIndex]string{
1: defaultFeeHex,
},
mockExpectedRequests: []ExpectedValidatorRegistration{
{
FeeRecipient: byteValueAddress,
GasLimit: params.BeaconConfig().DefaultBuilderGasLimit,
},
},
},
{
name: " proposer config not nil but fee recipient empty",
validatorSetter: func(t *testing.T) *validator {
@@ -1814,7 +1909,6 @@ func TestValidator_PushProposerSettings(t *testing.T) {
{
name: "register validator batch failed",
validatorSetter: func(t *testing.T) *validator {
v := validator{
validatorClient: client,
node: nodeClient,
@@ -1839,21 +1933,29 @@ func TestValidator_PushProposerSettings(t *testing.T) {
).Return(&ethpb.ValidatorIndexResponse{
Index: 1,
}, nil)
client.EXPECT().PrepareBeaconProposer(gomock.Any(), &ethpb.PrepareBeaconProposerRequest{
Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{
{FeeRecipient: common.HexToAddress("0x0").Bytes(), ValidatorIndex: 1},
},
}).Return(nil, nil)
config[keys[0]] = &validatorserviceconfig.ProposerOption{
FeeRecipient: common.Address{},
ValidatorRegistration: &validatorserviceconfig.ValidatorRegistration{
Enable: true,
GasLimit: uint64(40000000),
},
}
v.ProposerSettings = &validatorserviceconfig.ProposerSettings{
ProposeConfig: config,
DefaultConfig: &validatorserviceconfig.ProposerOption{
FeeRecipient: common.HexToAddress(defaultFeeHex),
ValidatorRegistration: &validatorserviceconfig.ValidatorRegistration{
Enable: true,
GasLimit: uint64(40000000),
},
},
}
client.EXPECT().PrepareBeaconProposer(gomock.Any(), &ethpb.PrepareBeaconProposerRequest{
Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{
{FeeRecipient: common.HexToAddress("0x0").Bytes(), ValidatorIndex: 1},
},
}).Return(nil, nil)
client.EXPECT().SubmitValidatorRegistration(
gomock.Any(),
gomock.Any(),

View File

@@ -8,7 +8,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/golang/mock/gomock"
"github.com/golang/protobuf/ptypes/empty"
"github.com/pkg/errors"
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
validatorserviceconfig "github.com/prysmaticlabs/prysm/config/validator/service"
@@ -106,11 +105,6 @@ func TestWaitActivation_StreamSetupFails_AttemptsToReconnect(t *testing.T) {
resp := generateMockStatusResponse([][]byte{pubKey[:]})
resp.Statuses[0].Status.Status = ethpb.ValidatorStatus_ACTIVE
clientStream.EXPECT().Recv().Return(resp, nil)
client.EXPECT().SubmitValidatorRegistration(
gomock.Any(),
gomock.Any(),
).Return(&empty.Empty{}, nil)
assert.NoError(t, v.WaitForActivation(context.Background(), nil))
}
@@ -160,11 +154,6 @@ func TestWaitForActivation_ReceiveErrorFromStream_AttemptsReconnection(t *testin
nil,
errors.New("fails"),
).Return(resp, nil)
client.EXPECT().SubmitValidatorRegistration(
gomock.Any(),
gomock.Any(),
).Return(&empty.Empty{}, nil)
assert.NoError(t, v.WaitForActivation(context.Background(), nil))
}
@@ -210,11 +199,6 @@ func TestWaitActivation_LogsActivationEpochOK(t *testing.T) {
resp,
nil,
)
client.EXPECT().SubmitValidatorRegistration(
gomock.Any(),
gomock.Any(),
).Return(&empty.Empty{}, nil)
client.EXPECT().PrepareBeaconProposer(gomock.Any(), &ethpb.PrepareBeaconProposerRequest{
Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{
{FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9").Bytes(), ValidatorIndex: 1},
@@ -265,11 +249,6 @@ func TestWaitForActivation_Exiting(t *testing.T) {
resp,
nil,
)
client.EXPECT().SubmitValidatorRegistration(
gomock.Any(),
gomock.Any(),
).Return(&empty.Empty{}, nil)
client.EXPECT().PrepareBeaconProposer(gomock.Any(), &ethpb.PrepareBeaconProposerRequest{
Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{
{FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9").Bytes(), ValidatorIndex: 1},
@@ -327,10 +306,6 @@ func TestWaitForActivation_RefetchKeys(t *testing.T) {
resp,
nil)
client.EXPECT().SubmitValidatorRegistration(
gomock.Any(),
gomock.Any(),
).Return(&empty.Empty{}, nil)
client.EXPECT().PrepareBeaconProposer(gomock.Any(), &ethpb.PrepareBeaconProposerRequest{
Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{
{FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9").Bytes(), ValidatorIndex: 1},
@@ -412,11 +387,6 @@ func TestWaitForActivation_AccountsChanged(t *testing.T) {
nil,
)
client.EXPECT().SubmitValidatorRegistration(
gomock.Any(),
gomock.Any(),
).Times(1).Return(&empty.Empty{}, nil)
go func() {
// We add the active key into the keymanager and simulate a key refresh.
time.Sleep(time.Second * 1)
@@ -507,11 +477,6 @@ func TestWaitForActivation_AccountsChanged(t *testing.T) {
nil,
)
client.EXPECT().SubmitValidatorRegistration(
gomock.Any(),
gomock.Any(),
).Times(1).Return(&empty.Empty{}, nil)
channel := make(chan [][fieldparams.BLSPubkeyLength]byte)
go func() {
// We add the active key into the keymanager and simulate a key refresh.
@@ -588,10 +553,6 @@ func TestWaitForActivation_RemoteKeymanager(t *testing.T) {
PublicKeys: [][]byte{inactiveKey[:], activeKey[:]},
},
).Return(resp, nil /* err */)
client.EXPECT().SubmitValidatorRegistration(
gomock.Any(),
gomock.Any(),
).Times(1).Return(&empty.Empty{}, nil)
client.EXPECT().PrepareBeaconProposer(gomock.Any(), &ethpb.PrepareBeaconProposerRequest{
Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{
{FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9").Bytes(), ValidatorIndex: 2},
@@ -677,11 +638,6 @@ func TestWaitForActivation_RemoteKeymanager(t *testing.T) {
PublicKeys: [][]byte{inactiveKey[:], activeKey[:]},
},
).Return(resp2, nil /* err */)
client.EXPECT().SubmitValidatorRegistration(
gomock.Any(),
gomock.Any(),
).Times(1).Return(&empty.Empty{}, nil)
client.EXPECT().PrepareBeaconProposer(gomock.Any(), &ethpb.PrepareBeaconProposerRequest{
Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{
{FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9").Bytes(), ValidatorIndex: 2},

View File

@@ -486,13 +486,22 @@ func proposerSettings(cliCtx *cli.Context) (*validatorServiceConfig.ProposerSett
}
// is overridden by file and URL flags
if cliCtx.IsSet(flags.SuggestedFeeRecipientFlag.Name) {
if cliCtx.IsSet(flags.SuggestedFeeRecipientFlag.Name) &&
!cliCtx.IsSet(flags.ProposerSettingsFlag.Name) &&
!cliCtx.IsSet(flags.ProposerSettingsURLFlag.Name) {
suggestedFee := cliCtx.String(flags.SuggestedFeeRecipientFlag.Name)
var vr *validatorServiceConfig.ValidatorRegistration
if cliCtx.Bool(flags.EnableValidatorRegistrationFlag.Name) {
vr = &validatorServiceConfig.ValidatorRegistration{
Enable: true,
GasLimit: reviewGasLimit(params.BeaconConfig().DefaultBuilderGasLimit),
}
}
fileConfig = &validatorServiceConfig.ProposerSettingsPayload{
ProposerConfig: nil,
DefaultConfig: &validatorServiceConfig.ProposerOptionPayload{
FeeRecipient: suggestedFee,
GasLimit: params.BeaconConfig().DefaultBuilderGasLimit,
FeeRecipient: suggestedFee,
ValidatorRegistration: vr,
},
}
}
@@ -525,7 +534,7 @@ func proposerSettings(cliCtx *cli.Context) (*validatorServiceConfig.ProposerSett
// default fileConfig is mandatory
if fileConfig.DefaultConfig == nil {
return nil, errors.New("default fileConfig is required")
return nil, errors.New("default fileConfig is required, proposer settings file is either empty or an incorrect format")
}
if !common.IsHexAddress(fileConfig.DefaultConfig.FeeRecipient) {
return nil, errors.New("default fileConfig fee recipient is not a valid eth1 address")
@@ -534,8 +543,11 @@ func proposerSettings(cliCtx *cli.Context) (*validatorServiceConfig.ProposerSett
return nil, err
}
vpSettings.DefaultConfig = &validatorServiceConfig.ProposerOption{
FeeRecipient: common.HexToAddress(fileConfig.DefaultConfig.FeeRecipient),
GasLimit: reviewGasLimit(fileConfig.DefaultConfig.GasLimit),
FeeRecipient: common.HexToAddress(fileConfig.DefaultConfig.FeeRecipient),
ValidatorRegistration: fileConfig.DefaultConfig.ValidatorRegistration,
}
if vpSettings.DefaultConfig.ValidatorRegistration != nil {
vpSettings.DefaultConfig.ValidatorRegistration.GasLimit = reviewGasLimit(vpSettings.DefaultConfig.ValidatorRegistration.GasLimit)
}
if fileConfig.ProposerConfig != nil {
@@ -557,10 +569,14 @@ func proposerSettings(cliCtx *cli.Context) (*validatorServiceConfig.ProposerSett
if err := warnNonChecksummedAddress(option.FeeRecipient); err != nil {
return nil, err
}
vpSettings.ProposeConfig[bytesutil.ToBytes48(decodedKey)] = &validatorServiceConfig.ProposerOption{
FeeRecipient: common.HexToAddress(option.FeeRecipient),
GasLimit: reviewGasLimit(option.GasLimit),
if option.ValidatorRegistration != nil {
option.ValidatorRegistration.GasLimit = reviewGasLimit(option.ValidatorRegistration.GasLimit)
}
vpSettings.ProposeConfig[bytesutil.ToBytes48(decodedKey)] = &validatorServiceConfig.ProposerOption{
FeeRecipient: common.HexToAddress(option.FeeRecipient),
ValidatorRegistration: option.ValidatorRegistration,
}
}
}

View File

@@ -205,12 +205,13 @@ func TestProposerSettings(t *testing.T) {
proposerSettingsFlagValues *proposerSettingsFlag
}
tests := []struct {
name string
args args
want func() *validatorserviceconfig.ProposerSettings
urlResponse string
wantErr string
wantLog string
name string
args args
want func() *validatorserviceconfig.ProposerSettings
urlResponse string
wantErr string
wantLog string
validatorRegistrationEnabled bool
}{
{
name: "Happy Path Config file File, bad checksum",
@@ -228,12 +229,10 @@ func TestProposerSettings(t *testing.T) {
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*validatorserviceconfig.ProposerOption{
bytesutil.ToBytes48(key1): {
FeeRecipient: common.HexToAddress("0xae967917c465db8578ca9024c205720b1a3651A9"),
GasLimit: params.BeaconConfig().DefaultBuilderGasLimit,
},
},
DefaultConfig: &validatorserviceconfig.ProposerOption{
FeeRecipient: common.HexToAddress("0xae967917c465db8578ca9024c205720b1a3651A9"),
GasLimit: params.BeaconConfig().DefaultBuilderGasLimit,
},
}
},
@@ -258,16 +257,25 @@ func TestProposerSettings(t *testing.T) {
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*validatorserviceconfig.ProposerOption{
bytesutil.ToBytes48(key1): {
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
GasLimit: params.BeaconConfig().DefaultBuilderGasLimit,
ValidatorRegistration: &validatorserviceconfig.ValidatorRegistration{
Enable: true,
GasLimit: params.BeaconConfig().DefaultBuilderGasLimit,
},
},
bytesutil.ToBytes48(key2): {
FeeRecipient: common.HexToAddress("0x60155530FCE8a85ec7055A5F8b2bE214B3DaeFd4"),
GasLimit: params.BeaconConfig().DefaultBuilderGasLimit,
ValidatorRegistration: &validatorserviceconfig.ValidatorRegistration{
Enable: true,
GasLimit: params.BeaconConfig().DefaultBuilderGasLimit,
},
},
},
DefaultConfig: &validatorserviceconfig.ProposerOption{
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
GasLimit: params.BeaconConfig().DefaultBuilderGasLimit,
ValidatorRegistration: &validatorserviceconfig.ValidatorRegistration{
Enable: true,
GasLimit: params.BeaconConfig().DefaultBuilderGasLimit,
},
},
}
},
@@ -289,12 +297,10 @@ func TestProposerSettings(t *testing.T) {
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*validatorserviceconfig.ProposerOption{
bytesutil.ToBytes48(key1): {
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
GasLimit: params.BeaconConfig().DefaultBuilderGasLimit,
},
},
DefaultConfig: &validatorserviceconfig.ProposerOption{
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
GasLimit: params.BeaconConfig().DefaultBuilderGasLimit,
},
}
},
@@ -316,19 +322,25 @@ func TestProposerSettings(t *testing.T) {
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*validatorserviceconfig.ProposerOption{
bytesutil.ToBytes48(key1): {
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
GasLimit: uint64(40000000),
ValidatorRegistration: &validatorserviceconfig.ValidatorRegistration{
Enable: true,
GasLimit: uint64(40000000),
},
},
},
DefaultConfig: &validatorserviceconfig.ProposerOption{
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
GasLimit: uint64(45000000),
ValidatorRegistration: &validatorserviceconfig.ValidatorRegistration{
Enable: false,
GasLimit: params.BeaconConfig().DefaultBuilderGasLimit,
},
},
}
},
wantErr: "",
},
{
name: "Happy Path Suggested Fee File",
name: "Happy Path Suggested Fee ",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "",
@@ -341,12 +353,35 @@ func TestProposerSettings(t *testing.T) {
ProposeConfig: nil,
DefaultConfig: &validatorserviceconfig.ProposerOption{
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
GasLimit: params.BeaconConfig().DefaultBuilderGasLimit,
},
}
},
wantErr: "",
},
{
name: "Happy Path Suggested Fee , validator registration enabled",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "",
url: "",
defaultfee: "0x6e35733c5af9B61374A128e6F85f553aF09ff89A",
},
},
want: func() *validatorserviceconfig.ProposerSettings {
return &validatorserviceconfig.ProposerSettings{
ProposeConfig: nil,
DefaultConfig: &validatorserviceconfig.ProposerOption{
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
ValidatorRegistration: &validatorserviceconfig.ValidatorRegistration{
Enable: true,
GasLimit: params.BeaconConfig().DefaultBuilderGasLimit,
},
},
}
},
wantErr: "",
validatorRegistrationEnabled: true,
},
{
name: "Suggested Fee does not Override Config",
args: args{
@@ -363,17 +398,41 @@ func TestProposerSettings(t *testing.T) {
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*validatorserviceconfig.ProposerOption{
bytesutil.ToBytes48(key1): {
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
GasLimit: params.BeaconConfig().DefaultBuilderGasLimit,
},
},
DefaultConfig: &validatorserviceconfig.ProposerOption{
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
GasLimit: params.BeaconConfig().DefaultBuilderGasLimit,
},
}
},
wantErr: "",
},
{
name: "Suggested Fee with validator registration does not Override Config",
args: args{
proposerSettingsFlagValues: &proposerSettingsFlag{
dir: "./testdata/good-prepare-beacon-proposer-config.json",
url: "",
defaultfee: "0x6e35733c5af9B61374A128e6F85f553aF09ff89B",
},
},
want: func() *validatorserviceconfig.ProposerSettings {
key1, err := hexutil.Decode("0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a")
require.NoError(t, err)
return &validatorserviceconfig.ProposerSettings{
ProposeConfig: map[[fieldparams.BLSPubkeyLength]byte]*validatorserviceconfig.ProposerOption{
bytesutil.ToBytes48(key1): {
FeeRecipient: common.HexToAddress("0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"),
},
},
DefaultConfig: &validatorserviceconfig.ProposerOption{
FeeRecipient: common.HexToAddress("0x6e35733c5af9B61374A128e6F85f553aF09ff89A"),
},
}
},
wantErr: "",
validatorRegistrationEnabled: true,
},
{
name: "No flags set means empty config",
args: args{
@@ -443,6 +502,9 @@ func TestProposerSettings(t *testing.T) {
set.String(flags.SuggestedFeeRecipientFlag.Name, tt.args.proposerSettingsFlagValues.defaultfee, "")
require.NoError(t, set.Set(flags.SuggestedFeeRecipientFlag.Name, tt.args.proposerSettingsFlagValues.defaultfee))
}
if tt.validatorRegistrationEnabled {
set.Bool(flags.EnableValidatorRegistrationFlag.Name, true, "")
}
cliCtx := cli.NewContext(&app, set, nil)
got, err := proposerSettings(cliCtx)
if tt.wantErr != "" {

View File

@@ -1,13 +1,25 @@
{
"proposer_config": {
"0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a": {
"fee_recipient": "0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3"
"fee_recipient": "0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3",
"validator_registration": {
"enable": true,
"gas_limit": 30000000
}
},
"0xb057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7b": {
"fee_recipient": "0x60155530FCE8a85ec7055A5F8b2bE214B3DaeFd4"
"fee_recipient": "0x60155530FCE8a85ec7055A5F8b2bE214B3DaeFd4",
"validator_registration": {
"enable": true,
"gas_limit": 30000000
}
}
},
"default_config": {
"fee_recipient": "0x6e35733c5af9B61374A128e6F85f553aF09ff89A"
"fee_recipient": "0x6e35733c5af9B61374A128e6F85f553aF09ff89A",
"validator_registration": {
"enable": true,
"gas_limit": 30000000
}
}
}

View File

@@ -2,7 +2,11 @@
proposer_config:
'0xa057816155ad77931185101128655c0191bd0214c201ca48ed887f6c4c6adf334070efcd75140eada5ac83a92506dd7a':
fee_recipient: '0x50155530FCE8a85ec7055A5F8b2bE214B3DaeFd3'
gas_limit: 40000000
validator_registration:
enable: true
gas_limit: 40000000
default_config:
fee_recipient: '0x6e35733c5af9B61374A128e6F85f553aF09ff89A'
gas_limit: 45000000
validator_registration:
enable: false
gas_limit: 30000000

View File

@@ -455,6 +455,7 @@ func (s *Server) SetFeeRecipientByPubkey(ctx context.Context, req *ethpbservice.
DefaultConfig: &defaultOption,
}
case s.validatorService.ProposerSettings.ProposeConfig == nil:
pOption.ValidatorRegistration = s.validatorService.ProposerSettings.DefaultConfig.ValidatorRegistration
s.validatorService.ProposerSettings.ProposeConfig = map[[fieldparams.BLSPubkeyLength]byte]*validatorServiceConfig.ProposerOption{
bytesutil.ToBytes48(validatorKey): &pOption,
}
@@ -463,6 +464,7 @@ func (s *Server) SetFeeRecipientByPubkey(ctx context.Context, req *ethpbservice.
if found {
proposerOption.FeeRecipient = common.BytesToAddress(req.Ethaddress)
} else {
pOption.ValidatorRegistration = s.validatorService.ProposerSettings.DefaultConfig.ValidatorRegistration
s.validatorService.ProposerSettings.ProposeConfig[bytesutil.ToBytes48(validatorKey)] = &pOption
}
}