Skip to content

Commit

Permalink
feat: Support mainnet for Lido CSM setup
Browse files Browse the repository at this point in the history
* feat: Add contract addresses for mainnet

* style: Update Grafana lido dashboard

* tests: Add test cases for mainnet

* docs: Update docs with lido mainnet testnet
  • Loading branch information
khalifaa55 authored Oct 23, 2024
1 parent 4c7e63e commit 20eb1bc
Show file tree
Hide file tree
Showing 17 changed files with 476 additions and 30 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

##Added
- Support Mainnet for Lido CSM setup.

## [v1.6.0] - 2024-10-18

### Added
Expand Down
6 changes: 3 additions & 3 deletions cli/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func TestCli(t *testing.T) {
// Silence logger
log.SetOutput(io.Discard)

mevboostRelayListUris, _ := mevboostrelaylist.RelaysURI("mainnet")
mainnetMevboostRelayListUris, _ := mevboostrelaylist.RelaysURI("mainnet")
holeskyMevboostRelayListUris, _ := mevboostrelaylist.RelaysURI("holesky")

ETHClients := map[string][]string{
Expand Down Expand Up @@ -527,7 +527,7 @@ func TestCli(t *testing.T) {
},
},
{
name: "full node with Lido",
name: "full node with Lido, mainnet",
setup: func(t *testing.T, sedgeActions *sedge_mocks.MockSedgeActions, prompter *sedge_mocks.MockPrompter, depsMgr *sedge_mocks.MockDependenciesManager) {
generationPath := t.TempDir()
genData := generate.GenData{
Expand Down Expand Up @@ -555,7 +555,7 @@ func TestCli(t *testing.T) {
VLStartGracePeriod: 840,
Mev: true,
MevImage: "flashbots/mev-boost:latest",
RelayURLs: mevboostRelayListUris,
RelayURLs: mainnetMevboostRelayListUris,
ContainerTag: "tag",
JWTSecretPath: filepath.Join(generationPath, "jwtsecret"),
}
Expand Down
57 changes: 54 additions & 3 deletions cli/lidoStatus_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,11 @@ func TestLidoStatusCmd(t *testing.T) {
{
name: "Valid node ID, Holesky",
flags: flags{
networkName: "holesky",
nodeIDInt: 1,
rewardAddress: "0x22bA5CaFB5E26E6Fe51f330294209034013A5A4c", // rewardAddress should be ignored
networkName: "holesky",
nodeIDInt: 1,
},
isErr: true,
isErr: false,
},
{
name: "Invalid: negative node ID, Holesky",
Expand All @@ -113,6 +114,56 @@ func TestLidoStatusCmd(t *testing.T) {
},
isErr: true,
},
{
name: "Invalid: missing address, Mainnet",
flags: flags{
networkName: "mainnet",
},
isErr: true,
},
{
name: "Invalid: incorrect address, Mainnet",
flags: flags{
rewardAddress: "0xC870Fd10dd",
networkName: "mainnet",
},
isErr: true,
},
{
name: "Invalid: address missing 0x prefix, Mainnet",
flags: flags{
rewardAddress: "bA99F374C20A3475De737B466ee68Ad9C38c26AF",
networkName: "mainnet",
},
isErr: true,
},
// {
// name: "Valid node ID, Mainnet",
// flags: flags{
// rewardAddress: "0x22bA5CaFB5E26E6Fe51f330294209034013A5A4c", // rewardAddress should be ignored
// networkName: "mainnet",
// nodeIDInt: 1,
// },
// isErr: false,
// },
// {
// name: "Valid node ID with long description, Mainnet",
// flags: flags{
// rewardAddress: "0x22bA5CaFB5E26E6Fe51f330294209034013A5A4c", // rewardAddress should be ignored
// networkName: "mainnet",
// nodeIDInt: 1,
// longDescriptions: true,
// },
// isErr: false,
// },
{
name: "Invalid: negative node ID, Mainnet",
flags: flags{
networkName: "mainnet",
nodeIDInt: -14,
},
isErr: true,
},
}

for _, tc := range tcs {
Expand Down
25 changes: 25 additions & 0 deletions cli/monitoring_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,31 @@ func TestMonitoringCmd(t *testing.T) {
},
isErr: true,
},
{
name: "valid monitoring init: lido, Mainnet",
flags: []string{"init", "lido", "--node-operator-id", "1", "--network", "mainnet"},
mocker: func(t *testing.T, ctrl *gomock.Controller) *sedge_mocks.MockMonitoringManager {
mockManager := sedge_mocks.NewMockMonitoringManager(ctrl)
gomock.InOrder(
mockManager.EXPECT().InstallationStatus().Return(common.NotInstalled, nil).AnyTimes(),
mockManager.EXPECT().InstallStack().Return(nil).AnyTimes(),
mockManager.EXPECT().Status().Return(common.Created, nil).AnyTimes(),
mockManager.EXPECT().Run().Return(nil).AnyTimes(),
mockManager.EXPECT().Init().Return(nil).AnyTimes(),
mockManager.EXPECT().AddService(gomock.Any()).Return(nil).AnyTimes(),
)
return mockManager
},
isErr: false,
},
{
name: "invalid monitoring init: lido, no nodeID or reward address, Mainnet",
flags: []string{"init", "lido", "--network", "mainnet"},
mocker: func(t *testing.T, ctrl *gomock.Controller) *sedge_mocks.MockMonitoringManager {
return sedge_mocks.NewMockMonitoringManager(ctrl)
},
isErr: true,
},
}

for _, tc := range tcs {
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/commands/generate.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ Use "sedge generate [command] --help" for more information about a command.

### Lido Flow

With the `--lido` flag, you can generate a Lido CSM node. This will generate a full node, a execution, a consensus, a validator o a mev-boost node with the Lido CSM configuration.
With the `--lido` flag, you can generate a Lido CSM node. This will generate a full node, a execution, a consensus, a validator or a mev-boost node with the Lido CSM configuration.

It will include in the configuration of the selected node:
- Lido Withdrawal Credentials
Expand Down
3 changes: 1 addition & 2 deletions docs/docs/quickstart/lido.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ If you are interested in becoming a Lido node operator, make sure to read the [N

:::info

Lido CSM is **[currently live and permissionless on the Holesky testnet](https://operatorportal.lido.fi/modules/community-staking-module)**.
The Mainnet launch is expected soon. You can check your eligibility for the Early Adoption program on Mainnet [here](https://lidofinance.github.io/csm-ea-checker/).
Lido CSM is **[currently live and permissionless on the Holesky and Mainnet testnet](https://operatorportal.lido.fi/modules/community-staking-module)**.

:::

Expand Down
146 changes: 146 additions & 0 deletions e2e/lido-exporter/args_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -537,3 +537,149 @@ func TestE2E_InvalidArgs_NegativeNodeID(t *testing.T) {
// Run test case
e2eTest.run()
}

func TestE2E_ValidArgs_NodeOperatorID_Mainnet(t *testing.T) {
// t.Parallel()
// Test context
var (
cmd *exec.Cmd
)
// Build test case
e2eTest := newE2ELidoExporterTestCase(
t,
// Arrange
nil,
// Act
func(t *testing.T, binaryPath string) *exec.Cmd {
cmd = base.RunCommandCMD(t, binaryPath, "lido-exporter", "lido-exporter", "--node-operator-id", "1", "--network", "mainnet", "--port", "9980")
time.Sleep(2 * time.Second)
return cmd
},
// Assert
func(t *testing.T) {
checkPrometheusServerUp(t, 9980)
checkMetrics(t, 9980)

cmd.Process.Signal(os.Interrupt)

// Wait for the process to exit with a timeout
done := make(chan error, 1)
go func() {
done <- cmd.Wait()
}()

select {
case err := <-done:
assert.NoError(t, err)
case <-time.After(5 * time.Second):
t.Error("Process did not exit within the timeout period")
cmd.Process.Kill() // Force kill if it doesn't exit
}
},
)
// Run test case
e2eTest.run()
}

func TestE2E_ValidEnv_All_Mainnet(t *testing.T) {
// t.Parallel()
// Test context
var (
cmd *exec.Cmd
)
// Build test case
e2eTest := newE2ELidoExporterTestCase(
t,
// Arrange
func(t *testing.T, binaryPath string) (map[string]string, error) {
return map[string]string{
"LIDO_EXPORTER_RPC_ENDPOINTS": "'https://eth.llamarpc.com','https://eth-pokt.nodies.app','https://rpc.mevblocker.io'",
"LIDO_EXPORTER_WS_ENDPOINTS": "'wss://ethereum-rpc.publicnode.com'",
"LIDO_EXPORTER_PORT": "9990",
"LIDO_EXPORTER_SCRAPE_TIME": "2s",
"LIDO_EXPORTER_NETWORK": "mainnet",
"LIDO_EXPORTER_NODE_OPERATOR_ID": "1",
}, nil
},
// Act
func(t *testing.T, binaryPath string) *exec.Cmd {
cmd = base.RunCommandCMD(t, binaryPath, "lido-exporter", "lido-exporter")
time.Sleep(2 * time.Second)
return cmd
},
// Assert
func(t *testing.T) {
checkPrometheusServerUp(t, 9990)
checkMetrics(t, 9990)

cmd.Process.Signal(os.Interrupt)

// Wait for the process to exit with a timeout
done := make(chan error, 1)
go func() {
done <- cmd.Wait()
}()

select {
case err := <-done:
assert.NoError(t, err)
case <-time.After(5 * time.Second):
t.Error("Process did not exit within the timeout period")
cmd.Process.Kill() // Force kill if it doesn't exit
}
},
)
// Run test case
e2eTest.run()
}

func TestE2E_ValidFlags_All_Mainnet(t *testing.T) {
// t.Parallel()
// Test context
var (
cmd *exec.Cmd
)
// Build test case
e2eTest := newE2ELidoExporterTestCase(
t,
// Arrange
nil,
// Act
func(t *testing.T, binaryPath string) *exec.Cmd {
cmd = base.RunCommandCMD(t, binaryPath, "lido-exporter", "lido-exporter",
"--rpc-endpoints", "https://eth.llamarpc.com", "https://eth-pokt.nodies.app", "https://rpc.mevblocker.io",
"--ws-endpoints", "wss://ethereum-rpc.publicnode.com", // https endpoint should be ignored
"--port", "9989",
"--scrape-time", "1s",
"--network", "mainnet",
"--node-operator-id", "1", // should be prioritized over reward address
"--reward-address", "0x22bA5CaFB5E26E6Fe51f330294209034013A5A4c",
)
time.Sleep(2 * time.Second)
return cmd
},
// Assert
func(t *testing.T) {
checkPrometheusServerUp(t, 9989)
checkMetrics(t, 9989)

cmd.Process.Signal(os.Interrupt)

// Wait for the process to exit with a timeout
done := make(chan error, 1)
go func() {
done <- cmd.Wait()
}()

select {
case err := <-done:
assert.NoError(t, err)
case <-time.After(5 * time.Second):
t.Error("Process did not exit within the timeout period")
cmd.Process.Kill() // Force kill if it doesn't exit
}
},
)
// Run test case
e2eTest.run()
}
70 changes: 70 additions & 0 deletions e2e/sedge/lidoStatus_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,3 +161,73 @@ func TestE2E_LidoStatus_InvalidZeroRewardAddress(t *testing.T) {
// Run test case
e2eTest.run()
}

// func TestE2E_LidoStatus_ValidNodeID_Mainnet(t *testing.T) {
// // Test context
// var (
// runErr error
// )
// // Build test case
// e2eTest := newE2ESedgeTestCase(
// t,
// // Arrange
// nil,
// // Act
// func(t *testing.T, binaryPath string, dataDirPath string) {
// runErr = base.RunCommand(t, binaryPath, "sedge", "lido-status", "--nodeID", "1", "--l", "--network", "mainnet")
// },
// // Assert
// func(t *testing.T, dataDirPath string) {
// assert.NoError(t, runErr, "lido status command should succeed with the given arguments")
// },
// )
// // Run test case
// e2eTest.run()
// }

func TestE2E_LidoStatus_InvalidNodeID_Mainnet(t *testing.T) {
// Test context
var (
runErr error
)
// Build test case
e2eTest := newE2ESedgeTestCase(
t,
// Arrange
nil,
// Act
func(t *testing.T, binaryPath string, dataDirPath string) {
runErr = base.RunCommand(t, binaryPath, "sedge", "lido-status", "--nodeID", "-30", "--l", "--network", "mainnet")
},
// Assert
func(t *testing.T, dataDirPath string) {
// Node ID can't be a negative value
assert.Error(t, runErr, "lido status command should fail")
},
)
// Run test case
e2eTest.run()
}

func TestE2E_LidoStatus_InvalidRewardAddress_Mainnet(t *testing.T) {
// Test context
var (
runErr error
)
// Build test case
e2eTest := newE2ESedgeTestCase(
t,
// Arrange
nil,
// Act
func(t *testing.T, binaryPath string, dataDirPath string) {
runErr = base.RunCommand(t, binaryPath, "sedge", "lido-status", "0xccbhk45", "--network", "mainnet")
},
// Assert
func(t *testing.T, dataDirPath string) {
assert.Error(t, runErr, "lido status command should fail")
},
)
// Run test case
e2eTest.run()
}
Loading

0 comments on commit 20eb1bc

Please sign in to comment.