Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
e9f1b5b
[SSV-16,SSV-20] ssvsigner: Possible Local File Read + SSRF via Web3si…
nkryuchkov Jul 1, 2025
6ec55b9
Vouch acknowledgements (#2349) (#2351)
oleg-ssvlabs Jul 1, 2025
faaf805
[SSV-13] ssvsigner: fix remaining data races (#2368)
nkryuchkov Jul 3, 2025
68a75e4
[SSV-2] ssvsigner: error on empty fingerprints (#2366)
nkryuchkov Jul 3, 2025
8d2e9d8
[Main] hotfix/refactor: (VoluntaryExit) fetch header instead of block…
kchojn Jul 3, 2025
05220af
update 0NEinfra bootnode (#2377)
y0sher Jul 7, 2025
6b3b26e
Add stale bot (#2384)
zktaiga Jul 9, 2025
349d96f
Set global limits, increase operations (#2385)
zktaiga Jul 9, 2025
c86e05a
fix: update GasLimit36Epoch values for hoodi and mainnet configuratio…
y0sher Jul 9, 2025
38ee4d0
chore(audits): add ssv signer final report file. (#2387)
y0sher Jul 9, 2025
5d18975
fix(ssvsigner) tls load hostname from all cert data (#2383)
vaclav-ssvlabs Jul 10, 2025
0788e2d
fasttrack: gas-limit-36: enable on exact epoch configured (#2381)
iurii-ssv Jul 13, 2025
be2822a
Merge branch 'stage' into main+resolve-conflicts-20250714
nkryuchkov Jul 14, 2025
c817ead
align spec
nkryuchkov Jul 14, 2025
57fbe0f
audit: update ssvsigner final report file (#2396)
nkryuchkov Jul 15, 2025
aef843d
don't pass gas limit 36 epoch to validator registration runner
nkryuchkov Jul 15, 2025
cdf0071
Merge branch 'main' into main+resolve-conflicts-20250714
nkryuchkov Jul 15, 2025
454c995
Merge branch 'stage' into main+resolve-conflicts-20250714
nkryuchkov Jul 15, 2025
49ac9c0
feat(ssvsigner-e2e): implement mutual TLS for all E2E test connection…
olegshmuelov Jul 15, 2025
5c3351d
update differ
nkryuchkov Jul 15, 2025
aef57ca
Merge branch 'stage' into main+resolve-conflicts-20250714
nkryuchkov Jul 17, 2025
3620734
update differ config
nkryuchkov Jul 17, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .github/workflows/stale.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: 'Label and close stale PRs'
on:
schedule:
# Runs at 1:30 AM every day
- cron: '30 1 * * *'
workflow_dispatch: # Allows manual triggering

permissions:
actions: write
contents: read
issues: write
pull-requests: write

jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v9.1.0
with:
days-before-stale: 60
days-before-close: 30
stale-pr-message: 'This pull request has been marked as stale due to 60 days of inactivity. It will be closed in 30 days if there are no updates. Please comment if you would like to keep it open.'
close-pr-message: 'Closing this pull request as it has been inactive for 30 days after being marked stale. You are welcome to reopen it if you wish to continue.'
stale-issue-message: 'This issue has been marked as stale due to 60 days of inactivity. It will be closed in 30 days if there are no updates. Please comment if you would like to keep it open.'
close-issue-message: 'Closing this issue as it has been inactive for 30 days after being marked stale. You are welcome to reopen it if you wish to continue.'
stale-issue-label: 'stale'
stale-pr-label: 'stale'
operations-per-run: 100
# Enable statistics in the logs
enable-statistics: true
Binary file added audits/SSV_SIGNER_FINAL_REPORT.pdf
Binary file not shown.
5 changes: 0 additions & 5 deletions eth/eventsyncer/event_syncer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,6 @@ func TestEventSyncer(t *testing.T) {
ctx, cancel := context.WithTimeout(t.Context(), testTimeout)
defer cancel()

blockStream := make(chan []*ethtypes.Block)
defer close(blockStream)
done := make(chan struct{})
defer close(done)

// Create sim instance with a delay between block execution
sim := simTestBackend(testAddr)

Expand Down
13 changes: 0 additions & 13 deletions eth/executionclient/execution_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ type Provider interface {
FetchHistoricalLogs(ctx context.Context, fromBlock uint64) (logs <-chan BlockLogs, errors <-chan error, err error)
StreamLogs(ctx context.Context, fromBlock uint64) <-chan BlockLogs
Filterer() (*contract.ContractFilterer, error)
BlockByNumber(ctx context.Context, number *big.Int) (*ethtypes.Block, error)
HeaderByNumber(ctx context.Context, blockNumber *big.Int) (*ethtypes.Header, error)
ChainID(ctx context.Context) (*big.Int, error)
Healthy(ctx context.Context) error
Expand Down Expand Up @@ -395,18 +394,6 @@ func (ec *ExecutionClient) healthy(ctx context.Context) error {
return nil
}

func (ec *ExecutionClient) BlockByNumber(ctx context.Context, blockNumber *big.Int) (*ethtypes.Block, error) {
b, err := ec.client.BlockByNumber(ctx, blockNumber)
if err != nil {
ec.logger.Error(elResponseErrMsg,
zap.String("method", "eth_getBlockByNumber"),
zap.Error(err))
return nil, err
}

return b, nil
}

func (ec *ExecutionClient) HeaderByNumber(ctx context.Context, blockNumber *big.Int) (*ethtypes.Header, error) {
h, err := ec.client.HeaderByNumber(ctx, blockNumber)
if err != nil {
Expand Down
56 changes: 0 additions & 56 deletions eth/executionclient/execution_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1080,62 +1080,6 @@ func TestSubscribeFilterLogs(t *testing.T) {
})
}

// TestBlockByNumber tests the BlockByNumber method of the client.
func TestBlockByNumber(t *testing.T) {
logger := zaptest.NewLogger(t)

t.Run("successfully gets block by number", func(t *testing.T) {
env := setupTestEnv(t, 1*time.Second)

// Deploy the contract
_, err := env.deployCallableContract()
require.NoError(t, err)

// Create a client and connect to the simulator
err = env.createClient(WithLogger(logger))
require.NoError(t, err)

// Create some blocks
for i := 0; i < 5; i++ {
env.sim.Commit()
}

// Test the BlockByNumber method with specific block number
block, err := env.client.BlockByNumber(env.ctx, big.NewInt(2))
require.NoError(t, err)
require.NotNil(t, block)
require.Equal(t, uint64(2), block.NumberU64())

// Test the BlockByNumber method with nil (latest block)
latestBlock, err := env.client.BlockByNumber(env.ctx, nil)
require.NoError(t, err)
require.NotNil(t, latestBlock)
require.Equal(t, uint64(6), latestBlock.NumberU64()) // Genesis + 1 from deploy + 5 from loop
})

t.Run("error when BlockByNumber fails", func(t *testing.T) {
env := setupTestEnv(t, 1*time.Second)
_, err := env.deployCallableContract()
require.NoError(t, err)

// Create a client - connection should succeed initially
err = env.createClient(
WithLogger(logger),
WithConnectionTimeout(100*time.Millisecond),
)
require.NoError(t, err) // Connection is established initially

// Create a context with a very short timeout to ensure BlockByNumber fails
timeoutCtx, cancel := context.WithTimeout(env.ctx, 1*time.Nanosecond)
defer cancel()

// BlockByNumber should fail because of the short timeout
block, err := env.client.BlockByNumber(timeoutCtx, big.NewInt(1))
require.Error(t, err)
require.Nil(t, block)
})
}

// TestHeaderByNumber tests the HeaderByNumber method of the client.
func TestHeaderByNumber(t *testing.T) {
logger := zaptest.NewLogger(t)
Expand Down
30 changes: 0 additions & 30 deletions eth/executionclient/mocks.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 0 additions & 13 deletions eth/executionclient/multi_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -335,19 +335,6 @@ func (mc *MultiClient) Healthy(ctx context.Context) error {
return fmt.Errorf("no healthy clients: %w", err)
}

// BlockByNumber retrieves a block by its number.
func (mc *MultiClient) BlockByNumber(ctx context.Context, blockNumber *big.Int) (*ethtypes.Block, error) {
f := func(client SingleClientProvider) (any, error) {
return client.BlockByNumber(ctx, blockNumber)
}
res, err := mc.call(contextWithMethod(ctx, "BlockByNumber"), f, len(mc.clients))
if err != nil {
return nil, err
}

return res.(*ethtypes.Block), nil
}

// HeaderByNumber retrieves a block header by its number.
func (mc *MultiClient) HeaderByNumber(ctx context.Context, blockNumber *big.Int) (*ethtypes.Header, error) {
f := func(client SingleClientProvider) (any, error) {
Expand Down
59 changes: 4 additions & 55 deletions eth/executionclient/multi_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -919,57 +919,6 @@ func TestMultiClient_Healthy_AllClientsUnhealthy(t *testing.T) {
require.Contains(t, err.Error(), "client2 unhealthy")
}

func TestMultiClient_BlockByNumber(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

mockClient := NewMockSingleClientProvider(ctrl)

mockClient.
EXPECT().
BlockByNumber(gomock.Any(), big.NewInt(1234)).
Return(&ethtypes.Block{}, nil).
Times(1)

mc := &MultiClient{
nodeAddrs: []string{"mock1"},
clients: []SingleClientProvider{mockClient},
clientsMu: make([]sync.Mutex, 1),
logger: zap.NewNop(),
closed: make(chan struct{}),
}

blk, err := mc.BlockByNumber(t.Context(), big.NewInt(1234))
require.NoError(t, err)
require.NotNil(t, blk)
}

func TestMultiClient_BlockByNumber_Error(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

mockClient := NewMockSingleClientProvider(ctrl)

mockClient.
EXPECT().
BlockByNumber(gomock.Any(), big.NewInt(1234)).
Return((*ethtypes.Block)(nil), fmt.Errorf("block not found")).
Times(1)

mc := &MultiClient{
nodeAddrs: []string{"mock1"},
clients: []SingleClientProvider{mockClient},
clientsMu: make([]sync.Mutex, 1),
logger: zap.NewNop(),
closed: make(chan struct{}),
}

blk, err := mc.BlockByNumber(t.Context(), big.NewInt(1234))
require.Error(t, err)
require.Nil(t, blk)
require.Contains(t, err.Error(), "block not found")
}

func TestMultiClient_HeaderByNumber(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
Expand Down Expand Up @@ -1307,9 +1256,9 @@ func TestMultiClient_Call_Concurrency(t *testing.T) {

mockClient.
EXPECT().
BlockByNumber(gomock.Any(), gomock.Any()).
DoAndReturn(func(ctx context.Context, num *big.Int) (*ethtypes.Block, error) {
return &ethtypes.Block{}, nil
HeaderByNumber(gomock.Any(), gomock.Any()).
DoAndReturn(func(ctx context.Context, num *big.Int) (*ethtypes.Header, error) {
return &ethtypes.Header{}, nil
}).
Times(10)

Expand All @@ -1327,7 +1276,7 @@ func TestMultiClient_Call_Concurrency(t *testing.T) {
for i := 0; i < 10; i++ {
go func() {
defer wg.Done()
_, err := mc.BlockByNumber(t.Context(), big.NewInt(1234))
_, err := mc.HeaderByNumber(t.Context(), big.NewInt(1234))
require.NoError(t, err)
}()
}
Expand Down
2 changes: 1 addition & 1 deletion networkconfig/hoodi.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@ var HoodiSSV = &SSVConfig{
"enr:-Ja4QIKlyNFuFtTOnVoavqwmpgSJXfhSmhpdSDOUhf5-FBr7bBxQRvG6VrpUvlkr8MtpNNuMAkM33AseduSaOhd9IeWGAZWjRbnvgmlkgnY0gmlwhCNVVTCJc2VjcDI1NmsxoQNTTyiJPoZh502xOZpHSHAfR-94NaXLvi5J4CNHMh2tjoNzc3YBg3RjcIITioN1ZHCCD6I",
},
TotalEthereumValidators: 1107955, // active_validators from https://hoodi.beaconcha.in/index/data on Apr 18, 2025
GasLimit36Epoch: 0,
GasLimit36Epoch: 29000, // Jul-24-2025 09:30:00 AM UTC
}
7 changes: 2 additions & 5 deletions networkconfig/mainnet.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package networkconfig

import (
"math"
"math/big"

"github.com/attestantio/go-eth2-client/spec/phase0"
ethcommon "github.com/ethereum/go-ethereum/common"

spectypes "github.com/ssvlabs/ssv-spec/types"
Expand All @@ -22,7 +20,7 @@ var MainnetSSV = &SSVConfig{
"enr:-Ja4QAbDe5XANqJUDyJU1GmtS01qqMwDYx9JNZgymjBb55fMaha80E2HznRYoUGy6NFVSvs1u1cFqSM0MgJI-h1QKLeGAZKaTo7LgmlkgnY0gmlwhDQrfraJc2VjcDI1NmsxoQNEj0Pgq9-VxfeX83LPDOUPyWiTVzdI-DnfMdO1n468u4Nzc3YBg3RjcIITioN1ZHCCD6I",

// 0NEinfra bootnode
"enr:-Li4QDwrOuhEq5gBJBzFUPkezoYiy56SXZUwkSD7bxYo8RAhPnHyS0de0nOQrzl-cL47RY9Jg8k6Y_MgaUd9a5baYXeGAYnfZE76h2F0dG5ldHOIAAAAAAAAAACEZXRoMpD1pf1CAAAAAP__________gmlkgnY0gmlwhDaTS0mJc2VjcDI1NmsxoQMZzUHaN3eClRgF9NAqRNc-ilGpJDDJxdenfo4j-zWKKYN0Y3CCE4iDdWRwgg-g",
"enr:-Ja4QFpDBTMnLOykFvZsV8LnBibOQnhAgsN2SkOXApEcRbxyJNkHO9go3gonVUIREbUa0gHvzYdgzZ3U4ezmCyJrkI6GAZfeUw2QgmlkgnY0gmlwhId9yoSJc2VjcDI1NmsxoQMZzUHaN3eClRgF9NAqRNc-ilGpJDDJxdenfo4j-zWKKYNzc3YBg3RjcIITiIN1ZHCCD6A",

// Eridian (eridianalpha.com)
"enr:-Li4QIzHQ2H82twhvsu8EePZ6CA1gl0_B0WWsKaT07245TkHUqXay-MXEgObJB7BxMFl8TylFxfnKNxQyGTXh-2nAlOGAYuraxUEh2F0dG5ldHOIAAAAAAAAAACEZXRoMpD1pf1CAAAAAP__________gmlkgnY0gmlwhBKCzUSJc2VjcDI1NmsxoQNKskkQ6-mBdBWr_ORJfyHai5uD0vL6Fuw90X0sPwmRsoN0Y3CCE4iDdWRwgg-g",
Expand All @@ -31,6 +29,5 @@ var MainnetSSV = &SSVConfig{
"enr:-Li4QH7FwJcL8gJj0zHAITXqghMkG-A5bfWh2-3Q7vosy9D1BS8HZk-1ITuhK_rfzG3v_UtBDI6uNJZWpdcWfrQFCxKGAYnQ1DRCh2F0dG5ldHOIAAAAAAAAAACEZXRoMpD1pf1CAAAAAP__________gmlkgnY0gmlwhBLb3g2Jc2VjcDI1NmsxoQKeSDcZWSaY9FC723E9yYX1Li18bswhLNlxBZdLfgOKp4N0Y3CCE4mDdWRwgg-h",
},
TotalEthereumValidators: 1064860, // active_validators from https://mainnet.beaconcha.in/index/data on Apr 18, 2025
// TODO - set proper value for mainnet
GasLimit36Epoch: phase0.Epoch(math.MaxUint64),
GasLimit36Epoch: 385150, // Aug-09-2025 06:40:23 AM UTC
}
2 changes: 1 addition & 1 deletion operator/duties/scheduler.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ type BeaconNode interface {
}

type ExecutionClient interface {
BlockByNumber(ctx context.Context, blockNumber *big.Int) (*ethtypes.Block, error)
HeaderByNumber(ctx context.Context, blockNumber *big.Int) (*ethtypes.Header, error)
}

// ValidatorProvider represents the component that controls validators via the scheduler
Expand Down
14 changes: 7 additions & 7 deletions operator/duties/scheduler_mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions operator/duties/voluntary_exit.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,12 +144,12 @@ func (h *VoluntaryExitHandler) blockSlot(ctx context.Context, blockNumber uint64
return blockSlot, nil
}

block, err := h.executionClient.BlockByNumber(ctx, new(big.Int).SetUint64(blockNumber))
header, err := h.executionClient.HeaderByNumber(ctx, new(big.Int).SetUint64(blockNumber))
if err != nil {
return 0, err
}

blockSlot = h.beaconConfig.EstimatedSlotAtTime(time.Unix(int64(block.Time()), 0)) // #nosec G115
blockSlot = h.beaconConfig.EstimatedSlotAtTime(time.Unix(int64(header.Time), 0)) // #nosec G115

h.blockSlots[blockNumber] = blockSlot
for k, v := range h.blockSlots {
Expand Down
Loading