Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
4d866ab
draft
olegshmuelov Apr 20, 2025
aa46e71
refactor(execution_client.go): rename logs channel to logsCh for clar…
kchojn Apr 28, 2025
58c07af
update [skip ci]
kchojn Apr 29, 2025
f8a1592
refactor(common_test.go, event_handler_test.go, defaults.go, executio…
kchojn Apr 29, 2025
837c45d
refactor(execution_client.go): remove unused reconnect method and rel…
kchojn Apr 29, 2025
4d230e7
refactor(node.go): remove unused reconnection interval options to sim…
kchojn Apr 29, 2025
879875b
merge stage [skip ci]
kchojn May 1, 2025
476f4e3
fix(execution_client.go): update logging method names to improve clar…
kchojn May 1, 2025
1c2db05
clean up
kchojn May 1, 2025
7b7507c
test(execution_client_test.go): update test case for chain reorganiza…
kchojn May 4, 2025
e0429a5
refactor(common_test.go): rename followDistance to finalityBlocks for…
kchojn May 4, 2025
f66bb36
feat(executionclient): add DefaultFinalityDistance constant with valu…
kchojn May 5, 2025
5fd0b41
Update eth/executionclient/defaults.go
kchojn May 5, 2025
ffe54fb
Update eth/executionclient/execution_client.go
kchojn May 5, 2025
fe53254
support finalized blocks
kchojn May 5, 2025
309eb63
lint
kchojn May 5, 2025
0a1bc18
feat(executionclient): introduce SlotsPerEpoch constant to improve re…
kchojn May 6, 2025
7b19564
improve tests
kchojn May 6, 2025
0d35334
improve docs + timeouts
kchojn May 6, 2025
4ee20a4
restore followDistance logic back TODO: update tests [skip ci]
kchojn May 6, 2025
a8e9311
Merge remote-tracking branch 'origin/stage' into finality-sync
kchojn May 7, 2025
209fcd7
feat(eth/executionclient): add tests for IsFinalityActive function
kchojn May 7, 2025
e26a0f2
small cleanup [skip ci]
kchojn May 7, 2025
41846bc
fork support
kchojn May 7, 2025
4440124
feat(multi_client_test.go): add support for follow distance and final…
kchojn May 7, 2025
dc3a03c
refactor(event_handler_test.go): add executionclient.WithFinalityFork…
kchojn May 7, 2025
d2faa93
refactor(execution_client.go): improve comments and add clarity to th…
kchojn May 7, 2025
c7a9a50
Update eth/executionclient/multi_client_test.go
kchojn May 7, 2025
804ef76
refactor
kchojn May 7, 2025
54a08d9
refactor(execution_client.go): refactor IsPreFinalityFork function to…
kchojn May 7, 2025
826dd7a
refactor(execution_client.go): improve variable naming and add atomic…
kchojn May 8, 2025
488546b
remove old stuff
kchojn May 8, 2025
211ed9c
checkpoint [skip ci]
kchojn May 8, 2025
c7feb03
fix too old block, TODO: refactor, optimize rpc calls
kchojn May 8, 2025
d21c706
feat(event_syncer_test.go): add tests for finalized fork scenarios in…
kchojn May 8, 2025
f165470
refactor(execution_client.go): improve logic for determining target b…
kchojn May 9, 2025
9ee2a15
refactor(execution_client.go): refactor logging in streamLogsToChan m…
kchojn May 9, 2025
61e1ba2
refactor(event_syncer.go): improve readability by extracting lastBloc…
kchojn May 9, 2025
f4cca05
move fork stuff to networkconfig
kchojn May 19, 2025
cf357f7
feat(executionclient): add support for phase0.Epoch type in Config st…
kchojn May 21, 2025
d11f46b
refactor(executionclient): update Config struct to use GetFinalityCon…
kchojn May 21, 2025
20f68fb
refactor(config.go): refactor NetworkName method to use active fork n…
kchojn May 21, 2025
663f796
refactor(ssv_forks.go): rename Fork type to SSVForkName for clarity a…
kchojn May 21, 2025
d73cb19
some tests
kchojn May 21, 2025
d2fb9be
NewConfigFromNetworkConfig
kchojn May 27, 2025
fae6bd1
Merge remote-tracking branch 'origin/stage' into finality-sync
kchojn May 27, 2025
2baf05b
feat(common_test.go): add support for finalityEpoch variable to confi…
kchojn May 27, 2025
c65d07c
merge stage
kchojn May 28, 2025
3a1c0c2
merge stage, TODOs
kchojn Jun 3, 2025
66ddc51
post merge cleanup
kchojn Jun 4, 2025
b3dbbcb
pr comments fixes
kchojn Jun 4, 2025
4ae6ada
refactor(event_syncer.go): simplify staleness threshold comparison in…
kchojn Jun 4, 2025
d6dc4de
refactor(execution_client_test.go): extract copyNetworkConfig functio…
kchojn Jun 4, 2025
73e7976
refactor(execution_client_test.go): remove unnecessary copyNetworkCon…
kchojn Jun 4, 2025
17171c6
refactor(execution_client.go): remove logging statement for finality …
kchojn Jun 4, 2025
503cc9c
refactor(event_syncer.go): improve comments and error messages for be…
kchojn Jun 4, 2025
82cd6ca
merge stage
kchojn Jun 5, 2025
7d85ef2
mock
kchojn Jun 5, 2025
860b9bd
Merge branch 'stage' into finality-sync
kchojn Jun 26, 2025
dbc9e09
adapt gas-limit: default to 36 #2307
kchojn Jun 26, 2025
67f3024
Merge branch 'stage' into finality-sync
kchojn Jun 26, 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
10 changes: 3 additions & 7 deletions cli/operator/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -320,13 +320,11 @@
if len(executionAddrList) == 1 {
ec, err := executionclient.New(
cmd.Context(),
networkConfig,

Check warning on line 323 in cli/operator/node.go

View check run for this annotation

Codecov / codecov/patch

cli/operator/node.go#L323

Added line #L323 was not covered by tests
executionAddrList[0],
ssvNetworkConfig.RegistryContractAddr,
executionclient.WithLogger(logger),
executionclient.WithFollowDistance(executionclient.DefaultFollowDistance),
executionclient.WithConnectionTimeout(cfg.ExecutionClient.ConnectionTimeout),
executionclient.WithReconnectionInitialInterval(executionclient.DefaultReconnectionInitialInterval),
executionclient.WithReconnectionMaxInterval(executionclient.DefaultReconnectionMaxInterval),
executionclient.WithHealthInvalidationInterval(executionclient.DefaultHealthInvalidationInterval),
executionclient.WithSyncDistanceTolerance(cfg.ExecutionClient.SyncDistanceTolerance),
)
Expand All @@ -338,13 +336,11 @@
} else {
ec, err := executionclient.NewMulti(
cmd.Context(),
networkConfig,

Check warning on line 339 in cli/operator/node.go

View check run for this annotation

Codecov / codecov/patch

cli/operator/node.go#L339

Added line #L339 was not covered by tests
executionAddrList,
ssvNetworkConfig.RegistryContractAddr,
executionclient.WithLoggerMulti(logger),
executionclient.WithFollowDistanceMulti(executionclient.DefaultFollowDistance),
executionclient.WithConnectionTimeoutMulti(cfg.ExecutionClient.ConnectionTimeout),
executionclient.WithReconnectionInitialIntervalMulti(executionclient.DefaultReconnectionInitialInterval),
executionclient.WithReconnectionMaxIntervalMulti(executionclient.DefaultReconnectionMaxInterval),
executionclient.WithHealthInvalidationIntervalMulti(executionclient.DefaultHealthInvalidationInterval),
executionclient.WithSyncDistanceToleranceMulti(cfg.ExecutionClient.SyncDistanceTolerance),
)
Expand Down Expand Up @@ -403,7 +399,7 @@
nodeStorage,
dutyStore,
signatureVerifier,
networkConfig.Forks[spec.DataVersionElectra].Epoch,
networkConfig.BeaconConfig.Forks[spec.DataVersionElectra].Epoch,

Check warning on line 402 in cli/operator/node.go

View check run for this annotation

Codecov / codecov/patch

cli/operator/node.go#L402

Added line #L402 was not covered by tests
validation.WithLogger(logger),
)

Expand Down
41 changes: 27 additions & 14 deletions eth/ethtest/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,18 @@ import (
"net/http/httptest"
"strings"
"testing"
"time"

"github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
ethcommon "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rpc"
"go.uber.org/mock/gomock"
"go.uber.org/zap/zaptest"

"github.com/ssvlabs/ssv/networkconfig"

"github.com/ssvlabs/ssv/eth/eventsyncer"
"github.com/ssvlabs/ssv/eth/executionclient"
"github.com/ssvlabs/ssv/eth/simulator"
Expand Down Expand Up @@ -64,7 +68,8 @@ type TestEnv struct {
httpSrv *httptest.Server
validatorCtrl *mocks.MockController
mockCtrl *gomock.Controller
followDistance *uint64
networkConfig networkconfig.NetworkConfig
followDistance uint64
}

func (e *TestEnv) shutdown() {
Expand All @@ -88,12 +93,24 @@ func (e *TestEnv) setup(
testAddresses []*ethcommon.Address,
validatorsCount uint64,
operatorsCount uint64,
useFinalityFork bool,
) error {
if e.followDistance == nil {
e.SetDefaultFollowDistance()
}
logger := zaptest.NewLogger(t)

// Set up network config with recent genesis time to avoid high epoch calculations
e.networkConfig = networkconfig.TestNetwork
e.networkConfig.GenesisTime = time.Now().Add(-1 * time.Minute) // Recent genesis

if useFinalityFork {
e.followDistance = 0
e.networkConfig.SSVConfig.Forks.Forks[1].Epoch = phase0.Epoch(1)
e.networkConfig.GenesisTime = time.Now().Add(-10 * time.Hour) // A bit earlier genesis time
} else {
e.followDistance = executionclient.DefaultFollowDistance
e.networkConfig.SSVConfig.Forks.Forks[1].Epoch = phase0.Epoch(1000000)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Extra empty line should be removed for consistency with code formatting.

Suggested change
e.networkConfig.SSVConfig.Forks.Forks[1].Epoch = phase0.Epoch(1000000)

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Prompt To Fix With AI
This is a comment left during a code review.
Path: eth/ethtest/common_test.go
Line: 111:111

Comment:
**style:** Extra empty line should be removed for consistency with code formatting.

```suggestion
e.networkConfig.SSVConfig.Forks.Forks[1].Epoch = phase0.Epoch(1000000)
```

<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>

How can I resolve this? If you propose a fix, please make it concise.

}

// Create operators RSA keys
ops, err := createOperators(operatorsCount, 0)
if err != nil {
Expand Down Expand Up @@ -167,13 +184,13 @@ func (e *TestEnv) setup(
return fmt.Errorf("contractCode is empty")
}

// Create a client and connect to the simulator
e.execClient, err = executionclient.New(
ctx,
e.networkConfig,
addr,
contractAddr,
executionclient.WithLogger(logger),
executionclient.WithFollowDistance(*e.followDistance),
executionclient.WithFollowDistance(e.followDistance),
)
if err != nil {
return err
Expand Down Expand Up @@ -206,18 +223,14 @@ func (e *TestEnv) setup(
return nil
}

func (e *TestEnv) SetDefaultFollowDistance() {
// 8 is current production offset
value := uint64(8)
e.followDistance = &value
}

func (e *TestEnv) CloseFollowDistance(blockNum *uint64) {
for i := uint64(0); i < *e.followDistance; i++ {
// MineAndFinalize mines enough blocks to ensure finality.
func (e *TestEnv) MineAndFinalize(blockNum *uint64) {
for i := uint64(0); i < e.networkConfig.SlotsPerEpoch*2; i++ {
commitBlock(e.sim, blockNum)
}
}

// commitBlock creates a new block and increments block counter.
func commitBlock(sim *simulator.Backend, blockNum *uint64) {
sim.Commit()
*blockNum++
Expand Down
63 changes: 46 additions & 17 deletions eth/ethtest/eth_e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ package ethtest

import (
"context"
"fmt"
"math/big"
"testing"
"time"

ethcommon "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rpc"
"github.com/stretchr/testify/require"
"go.uber.org/mock/gomock"

Expand All @@ -25,8 +25,20 @@ var (
testAddrBob = crypto.PubkeyToAddress(testKeyBob.PublicKey)
)

// E2E tests for ETH package
func TestEthExecLayer(t *testing.T) {
// TestEthExecLayer_PreFork tests ETH package with follow distance approach (pre-fork).
// TODO: use the correct name when we know the name of the fork.
func TestEthExecLayer_PreFork(t *testing.T) {
runTestEthExecLayer(t, false)
}

// TestEthExecLayer_PostFork tests ETH package with finality approach (post-fork)
// TODO: use the correct name when we know the name of the fork.
func TestEthExecLayer_PostFork(t *testing.T) {
runTestEthExecLayer(t, true)
}

// E2E tests for ETH package with configurable finality approach
func runTestEthExecLayer(t *testing.T, useFinalityFork bool) {
ctx, cancel := context.WithCancel(t.Context())
defer cancel()

Expand All @@ -45,10 +57,10 @@ func TestEthExecLayer(t *testing.T) {
expectedNonce := registrystorage.Nonce(0)

testEnv := TestEnv{}
testEnv.SetDefaultFollowDistance()

defer testEnv.shutdown()
err := testEnv.setup(t, ctx, testAddresses, 7, 4)

err := testEnv.setup(t, ctx, testAddresses, 7, 4, useFinalityFork)
require.NoError(t, err)

var (
Expand Down Expand Up @@ -83,7 +95,7 @@ func TestEthExecLayer(t *testing.T) {
opAddedInput.prepare(ops, auth)
opAddedInput.produce()

testEnv.CloseFollowDistance(&blockNum)
testEnv.MineAndFinalize(&blockNum)
}

// BLOCK 3: VALIDATOR ADDED:
Expand All @@ -96,15 +108,32 @@ func TestEthExecLayer(t *testing.T) {
valAddInput := NewTestValidatorRegisteredInput(common)
valAddInput.prepare(validators, shares, ops, auth, &expectedNonce, []uint32{0, 1})
valAddInput.produce()
testEnv.CloseFollowDistance(&blockNum)
testEnv.MineAndFinalize(&blockNum)

// Check how the EventSyncer determines which blocks to process
var expectedLastHandledBlock uint64

if useFinalityFork {
// When using finality fork, check the finalized block number
finalizedBlock, err := testEnv.sim.Client().HeaderByNumber(ctx, big.NewInt(rpc.FinalizedBlockNumber.Int64()))
require.NoError(t, err)
expectedLastHandledBlock = finalizedBlock.Number.Uint64()
} else {
// When using follow distance, the last handled block is the current block minus follow distance
currentBlock, err := testEnv.sim.Client().BlockNumber(ctx)
t.Logf("Current block number: %d", currentBlock)
require.NoError(t, err)
expectedLastHandledBlock = currentBlock - testEnv.followDistance
t.Logf("Expected last handled block: %d", expectedLastHandledBlock)
}

// Run SyncHistory
lastHandledBlockNum, err = eventSyncer.SyncHistory(ctx, lastHandledBlockNum)
t.Logf("Last handled block number after SyncHistory: %d", lastHandledBlockNum)
require.NoError(t, err)

//check all the events were handled correctly and block number was increased
require.Equal(t, blockNum-*testEnv.followDistance, lastHandledBlockNum)
fmt.Println("lastHandledBlockNum", lastHandledBlockNum)
// Check that the last handled block number matches our expectation
require.Equal(t, expectedLastHandledBlock, lastHandledBlockNum)

// Check that operators were successfully registered
operators, err := nodeStorage.ListOperators(nil, 0, 10)
Expand Down Expand Up @@ -154,7 +183,7 @@ func TestEthExecLayer(t *testing.T) {
valAddInput := NewTestValidatorRegisteredInput(common)
valAddInput.prepare(validators, shares, ops, auth, &expectedNonce, []uint32{2, 3, 4, 5, 6})
valAddInput.produce()
testEnv.CloseFollowDistance(&blockNum)
testEnv.MineAndFinalize(&blockNum)

// Wait until the state is changed
time.Sleep(time.Millisecond * 5000)
Expand Down Expand Up @@ -185,7 +214,7 @@ func TestEthExecLayer(t *testing.T) {
cluster,
)
valExit.produce()
testEnv.CloseFollowDistance(&blockNum)
testEnv.MineAndFinalize(&blockNum)

// Wait to make sure the state is not changed
time.Sleep(time.Millisecond * 500)
Expand All @@ -210,7 +239,7 @@ func TestEthExecLayer(t *testing.T) {
cluster,
)
valRemove.produce()
testEnv.CloseFollowDistance(&blockNum)
testEnv.MineAndFinalize(&blockNum)

// Wait until the state is changed
time.Sleep(time.Millisecond * 500)
Expand Down Expand Up @@ -240,7 +269,7 @@ func TestEthExecLayer(t *testing.T) {
},
})
clusterLiquidate.produce()
testEnv.CloseFollowDistance(&blockNum)
testEnv.MineAndFinalize(&blockNum)

// Wait until the state is changed
time.Sleep(time.Millisecond * 300)
Expand Down Expand Up @@ -280,7 +309,7 @@ func TestEthExecLayer(t *testing.T) {
},
})
clusterReactivated.produce()
testEnv.CloseFollowDistance(&blockNum)
testEnv.MineAndFinalize(&blockNum)

// Wait until the state is changed
time.Sleep(time.Millisecond * 300)
Expand All @@ -303,7 +332,7 @@ func TestEthExecLayer(t *testing.T) {
opRemoved := NewOperatorRemovedEventInput(common)
opRemoved.prepare([]uint64{1, 2}, auth)
opRemoved.produce()
testEnv.CloseFollowDistance(&blockNum)
testEnv.MineAndFinalize(&blockNum)

// TODO: this should be adjusted when eth/eventhandler/handlers.go#L109 is resolved
}
Expand All @@ -317,7 +346,7 @@ func TestEthExecLayer(t *testing.T) {
{auth, &testAddrBob},
})
setFeeRecipient.produce()
testEnv.CloseFollowDistance(&blockNum)
testEnv.MineAndFinalize(&blockNum)

// Wait until the state is changed
time.Sleep(time.Millisecond * 300)
Expand Down
Loading