mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 21:38:05 -05:00
Compare commits
9 Commits
json-block
...
item
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1f403fd57f | ||
|
|
b67c885995 | ||
|
|
60ed488428 | ||
|
|
2f0e2886b4 | ||
|
|
2d53ae79df | ||
|
|
ce277cb388 | ||
|
|
c9a366c36a | ||
|
|
3a957c567f | ||
|
|
77a63f871d |
@@ -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.
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
@@ -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 := ðpb.SignedBeaconBlockBellatrix{
|
||||
Block: ðpb.BeaconBlockBellatrix{
|
||||
Body: ðpb.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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 := ðpb.SignedBeaconBlockBellatrix{
|
||||
@@ -133,18 +140,18 @@ func Test_validateMergeBlock(t *testing.T) {
|
||||
Slot: 1,
|
||||
Body: ðpb.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[:])
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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'},
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
114
beacon-chain/powchain/engine_client_fuzz_test.go
Normal file
114
beacon-chain/powchain/engine_client_fuzz_test.go
Normal 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)
|
||||
})
|
||||
}
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
)
|
||||
|
||||
@@ -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\"]}")
|
||||
@@ -0,0 +1,2 @@
|
||||
go test fuzz v1
|
||||
[]byte("{\"BAseFeePerGAs\":\"0X0\"}")
|
||||
@@ -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\"]}")
|
||||
@@ -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\"]}")
|
||||
@@ -0,0 +1,2 @@
|
||||
go test fuzz v1
|
||||
[]byte("{\"pArentHAsh\":\"\",\"feeReCipient\":\"\",\"stAteRoot\":\"\",\"reCeiptsRoot\":\"\",\"logsBloom\":\"\",\"prevRAndAo\":\"\",\"eXtrADAtA\":\"\",\"BAseFeePerGAs\":\"0X0\",\"BloCkHAsh\":\"\",\"trAnsACtions\":[]}")
|
||||
@@ -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\"]}")
|
||||
@@ -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\"]}")
|
||||
@@ -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\"]}")
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -80,6 +80,7 @@ var appFlags = []cli.Flag{
|
||||
flags.SuggestedFeeRecipientFlag,
|
||||
flags.ProposerSettingsURLFlag,
|
||||
flags.ProposerSettingsFlag,
|
||||
flags.EnableValidatorRegistrationFlag,
|
||||
////////////////////
|
||||
cmd.DisableMonitoringFlag,
|
||||
cmd.MonitoringHostFlag,
|
||||
|
||||
@@ -114,6 +114,7 @@ var appHelpFlagGroups = []flagGroup{
|
||||
flags.ProposerSettingsFlag,
|
||||
flags.ProposerSettingsURLFlag,
|
||||
flags.SuggestedFeeRecipientFlag,
|
||||
flags.EnableValidatorRegistrationFlag,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
],
|
||||
)
|
||||
|
||||
229
proto/engine/v1/execution_engine.pb.go
generated
229
proto/engine/v1/execution_engine.pb.go
generated
@@ -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
|
||||
|
||||
@@ -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"];
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
1836
proto/prysm/v1alpha1/beacon_chain.pb.go
generated
1836
proto/prysm/v1alpha1/beacon_chain.pb.go
generated
File diff suppressed because it is too large
Load Diff
@@ -434,6 +434,9 @@ message BeaconBlockContainer {
|
||||
|
||||
// Representing an bellatrix block.
|
||||
SignedBeaconBlockBellatrix bellatrix_block = 5;
|
||||
|
||||
// Representing a blinded bellatrix block.
|
||||
SignedBlindedBeaconBlockBellatrix blinded_bellatrix_block = 6;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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"],
|
||||
|
||||
@@ -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)
|
||||
|
||||
44
testing/endtoend/minimal_slashing_e2e_test.go
Normal file
44
testing/endtoend/minimal_slashing_e2e_test.go
Normal 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()
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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, ðpb.ValidatorRegistrationV1{
|
||||
FeeRecipient: feeRecipient[:],
|
||||
GasLimit: gasLimit,
|
||||
Timestamp: uint64(time.Now().UTC().Unix()),
|
||||
Pubkey: pubkeys[i][:],
|
||||
})
|
||||
|
||||
if enableValidatorRegistration {
|
||||
registerValidatorRequests = append(registerValidatorRequests, ðpb.ValidatorRegistrationV1{
|
||||
FeeRecipient: feeRecipient[:],
|
||||
GasLimit: gasLimit,
|
||||
Timestamp: uint64(time.Now().UTC().Unix()),
|
||||
Pubkey: pubkeys[i][:],
|
||||
})
|
||||
}
|
||||
}
|
||||
return validatorToFeeRecipients, registerValidatorRequests, nil
|
||||
}
|
||||
|
||||
@@ -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
|
||||
ðpb.ValidatorIndexRequest{PublicKey: keys[0][:]},
|
||||
).Return(ðpb.ValidatorIndexResponse{
|
||||
Index: 1,
|
||||
}, nil)
|
||||
client.EXPECT().ValidatorIndex(
|
||||
ctx, // ctx
|
||||
ðpb.ValidatorIndexRequest{PublicKey: keys[1][:]},
|
||||
).Return(ðpb.ValidatorIndexResponse{
|
||||
Index: 2,
|
||||
}, nil)
|
||||
client.EXPECT().PrepareBeaconProposer(gomock.Any(), ðpb.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
|
||||
ðpb.ValidatorIndexRequest{PublicKey: keys[0][:]},
|
||||
).Return(ðpb.ValidatorIndexResponse{
|
||||
Index: 1,
|
||||
}, nil)
|
||||
client.EXPECT().SubmitValidatorRegistration(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(&empty.Empty{}, nil)
|
||||
client.EXPECT().PrepareBeaconProposer(gomock.Any(), ðpb.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
|
||||
ðpb.ValidatorIndexRequest{PublicKey: keys[0][:]},
|
||||
).Return(ðpb.ValidatorIndexResponse{
|
||||
Index: 1,
|
||||
}, nil)
|
||||
|
||||
client.EXPECT().SubmitValidatorRegistration(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(&empty.Empty{}, nil)
|
||||
client.EXPECT().PrepareBeaconProposer(gomock.Any(), ðpb.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(ðpb.ValidatorIndexResponse{
|
||||
Index: 1,
|
||||
}, nil)
|
||||
client.EXPECT().PrepareBeaconProposer(gomock.Any(), ðpb.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(), ðpb.PrepareBeaconProposerRequest{
|
||||
Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{
|
||||
{FeeRecipient: common.HexToAddress("0x0").Bytes(), ValidatorIndex: 1},
|
||||
},
|
||||
}).Return(nil, nil)
|
||||
client.EXPECT().SubmitValidatorRegistration(
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
|
||||
@@ -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(), ðpb.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(), ðpb.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(), ðpb.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(), ðpb.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(), ðpb.PrepareBeaconProposerRequest{
|
||||
Recipients: []*ethpb.PrepareBeaconProposerRequest_FeeRecipientContainer{
|
||||
{FeeRecipient: common.HexToAddress("0x046Fb65722E7b2455043BFEBf6177F1D2e9738D9").Bytes(), ValidatorIndex: 2},
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 != "" {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user