mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-25 21:07:18 +00:00
d17996f8b0
* Update V3 from V4 * Fix build v3 -> v4 * Update ssz * Update beacon_chain.pb.go * Fix formatter import * Update update-mockgen.sh comment to v4 * Fix conflicts. Pass build and tests * Fix test
261 lines
7.9 KiB
Go
261 lines
7.9 KiB
Go
package execution
|
|
|
|
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/v4/beacon-chain/blockchain/testing"
|
|
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/feed"
|
|
statefeed "github.com/prysmaticlabs/prysm/v4/beacon-chain/core/feed/state"
|
|
mocks "github.com/prysmaticlabs/prysm/v4/beacon-chain/execution/testing"
|
|
fieldparams "github.com/prysmaticlabs/prysm/v4/config/fieldparams"
|
|
"github.com/prysmaticlabs/prysm/v4/config/params"
|
|
"github.com/prysmaticlabs/prysm/v4/consensus-types/blocks"
|
|
pb "github.com/prysmaticlabs/prysm/v4/proto/engine/v1"
|
|
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
|
|
"github.com/prysmaticlabs/prysm/v4/testing/require"
|
|
logTest "github.com/sirupsen/logrus/hooks/test"
|
|
"google.golang.org/protobuf/proto"
|
|
)
|
|
|
|
func Test_checkTransitionConfiguration(t *testing.T) {
|
|
params.SetupTestConfigCleanup(t)
|
|
cfg := params.BeaconConfig().Copy()
|
|
cfg.BellatrixForkEpoch = 0
|
|
params.OverrideBeaconConfig(cfg)
|
|
hook := logTest.NewGlobal()
|
|
|
|
t.Run("context canceled", func(t *testing.T) {
|
|
ctx := context.Background()
|
|
m := &mocks.EngineClient{}
|
|
m.Err = errors.New("something went wrong")
|
|
|
|
srv := setupTransitionConfigTest(t)
|
|
srv.cfg.stateNotifier = &mockChain.MockStateNotifier{}
|
|
checkTransitionPollingInterval = time.Millisecond
|
|
ctx, cancel := context.WithCancel(ctx)
|
|
go srv.checkTransitionConfiguration(ctx, make(chan *feed.Event, 1))
|
|
<-time.After(100 * time.Millisecond)
|
|
cancel()
|
|
require.LogsContain(t, hook, "Could not check configuration values")
|
|
})
|
|
|
|
t.Run("block containing execution payload exits routine", func(t *testing.T) {
|
|
ctx := context.Background()
|
|
m := &mocks.EngineClient{}
|
|
m.Err = errors.New("something went wrong")
|
|
srv := setupTransitionConfigTest(t)
|
|
srv.cfg.stateNotifier = &mockChain.MockStateNotifier{}
|
|
|
|
checkTransitionPollingInterval = time.Millisecond
|
|
ctx, cancel := context.WithCancel(ctx)
|
|
exit := make(chan bool)
|
|
notification := make(chan *feed.Event)
|
|
go func() {
|
|
srv.checkTransitionConfiguration(ctx, notification)
|
|
exit <- true
|
|
}()
|
|
payload := emptyPayload()
|
|
payload.GasUsed = 21000
|
|
wrappedBlock, err := blocks.NewSignedBeaconBlock(ðpb.SignedBeaconBlockBellatrix{
|
|
Block: ðpb.BeaconBlockBellatrix{
|
|
Body: ðpb.BeaconBlockBodyBellatrix{
|
|
ExecutionPayload: payload,
|
|
},
|
|
}},
|
|
)
|
|
require.NoError(t, err)
|
|
notification <- &feed.Event{
|
|
Data: &statefeed.BlockProcessedData{
|
|
SignedBlock: wrappedBlock,
|
|
},
|
|
Type: statefeed.BlockProcessed,
|
|
}
|
|
<-exit
|
|
cancel()
|
|
require.LogsContain(t, hook, "PoS transition is complete, no longer checking")
|
|
})
|
|
}
|
|
|
|
func TestService_handleExchangeConfigurationError(t *testing.T) {
|
|
hook := logTest.NewGlobal()
|
|
t.Run("clears existing service error", func(t *testing.T) {
|
|
srv := setupTransitionConfigTest(t)
|
|
srv.isRunning = true
|
|
srv.runError = ErrConfigMismatch
|
|
srv.handleExchangeConfigurationError(nil)
|
|
require.Equal(t, true, srv.Status() == nil)
|
|
})
|
|
t.Run("does not clear existing service error if wrong kind", func(t *testing.T) {
|
|
srv := setupTransitionConfigTest(t)
|
|
srv.isRunning = true
|
|
err := errors.New("something else went wrong")
|
|
srv.runError = err
|
|
srv.handleExchangeConfigurationError(nil)
|
|
require.ErrorIs(t, err, srv.Status())
|
|
})
|
|
t.Run("sets service error on config mismatch", func(t *testing.T) {
|
|
srv := setupTransitionConfigTest(t)
|
|
srv.isRunning = true
|
|
srv.handleExchangeConfigurationError(ErrConfigMismatch)
|
|
require.Equal(t, ErrConfigMismatch, srv.Status())
|
|
require.LogsContain(t, hook, configMismatchLog)
|
|
})
|
|
t.Run("does not set service error if unrelated problem", func(t *testing.T) {
|
|
srv := setupTransitionConfigTest(t)
|
|
srv.isRunning = true
|
|
srv.handleExchangeConfigurationError(errors.New("foo"))
|
|
require.Equal(t, true, srv.Status() == nil)
|
|
require.LogsContain(t, hook, "Could not check configuration values")
|
|
})
|
|
}
|
|
|
|
func setupTransitionConfigTest(t testing.TB) *Service {
|
|
fix := fixtures()
|
|
request, ok := fix["TransitionConfiguration"].(*pb.TransitionConfiguration)
|
|
require.Equal(t, true, ok)
|
|
resp, ok := proto.Clone(request).(*pb.TransitionConfiguration)
|
|
require.Equal(t, true, ok)
|
|
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
defer func() {
|
|
require.NoError(t, r.Body.Close())
|
|
}()
|
|
|
|
// Change the terminal block hash.
|
|
h := common.BytesToHash([]byte("foo"))
|
|
resp.TerminalBlockHash = h[:]
|
|
respJSON := map[string]interface{}{
|
|
"jsonrpc": "2.0",
|
|
"id": 1,
|
|
"result": resp,
|
|
}
|
|
require.NoError(t, json.NewEncoder(w).Encode(respJSON))
|
|
}))
|
|
defer srv.Close()
|
|
|
|
rpcClient, err := rpc.DialHTTP(srv.URL)
|
|
require.NoError(t, err)
|
|
defer rpcClient.Close()
|
|
|
|
service := &Service{
|
|
cfg: &config{},
|
|
}
|
|
service.rpcClient = rpcClient
|
|
return service
|
|
}
|
|
|
|
func TestService_logTtdStatus(t *testing.T) {
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
defer func() {
|
|
require.NoError(t, r.Body.Close())
|
|
}()
|
|
|
|
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,
|
|
"result": resp,
|
|
}
|
|
require.NoError(t, json.NewEncoder(w).Encode(respJSON))
|
|
}))
|
|
defer srv.Close()
|
|
|
|
rpcClient, err := rpc.DialHTTP(srv.URL)
|
|
require.NoError(t, err)
|
|
defer rpcClient.Close()
|
|
|
|
service := &Service{
|
|
cfg: &config{},
|
|
}
|
|
service.rpcClient = rpcClient
|
|
|
|
ttd := new(uint256.Int)
|
|
reached, err := service.logTtdStatus(context.Background(), ttd.SetUint64(24343))
|
|
require.NoError(t, err)
|
|
require.Equal(t, true, reached)
|
|
|
|
reached, err = service.logTtdStatus(context.Background(), ttd.SetUint64(323423484))
|
|
require.NoError(t, err)
|
|
require.Equal(t, false, reached)
|
|
}
|
|
|
|
func TestService_logTtdStatus_NotSyncedClient(t *testing.T) {
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
defer func() {
|
|
require.NoError(t, r.Body.Close())
|
|
}()
|
|
|
|
resp := (*pb.ExecutionBlock)(nil) // Nil response when a client is not synced
|
|
respJSON := map[string]interface{}{
|
|
"jsonrpc": "2.0",
|
|
"id": 1,
|
|
"result": resp,
|
|
}
|
|
require.NoError(t, json.NewEncoder(w).Encode(respJSON))
|
|
}))
|
|
defer srv.Close()
|
|
|
|
rpcClient, err := rpc.DialHTTP(srv.URL)
|
|
require.NoError(t, err)
|
|
defer rpcClient.Close()
|
|
|
|
service := &Service{
|
|
cfg: &config{},
|
|
}
|
|
service.rpcClient = rpcClient
|
|
|
|
ttd := new(uint256.Int)
|
|
reached, err := service.logTtdStatus(context.Background(), ttd.SetUint64(24343))
|
|
require.ErrorContains(t, "missing required field 'parentHash' for Header", err)
|
|
require.Equal(t, false, reached)
|
|
}
|
|
|
|
func emptyPayload() *pb.ExecutionPayload {
|
|
return &pb.ExecutionPayload{
|
|
ParentHash: make([]byte, fieldparams.RootLength),
|
|
FeeRecipient: make([]byte, fieldparams.FeeRecipientLength),
|
|
StateRoot: make([]byte, fieldparams.RootLength),
|
|
ReceiptsRoot: make([]byte, fieldparams.RootLength),
|
|
LogsBloom: make([]byte, fieldparams.LogsBloomLength),
|
|
PrevRandao: make([]byte, fieldparams.RootLength),
|
|
BaseFeePerGas: make([]byte, fieldparams.RootLength),
|
|
BlockHash: make([]byte, fieldparams.RootLength),
|
|
Transactions: make([][]byte, 0),
|
|
ExtraData: make([]byte, 0),
|
|
}
|
|
}
|