Skip to content

Commit 20eb1bc

Browse files
authored
feat: Support mainnet for Lido CSM setup
* feat: Add contract addresses for mainnet * style: Update Grafana lido dashboard * tests: Add test cases for mainnet * docs: Update docs with lido mainnet testnet
1 parent 4c7e63e commit 20eb1bc

File tree

17 files changed

+476
-30
lines changed

17 files changed

+476
-30
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
##Added
11+
- Support Mainnet for Lido CSM setup.
12+
1013
## [v1.6.0] - 2024-10-18
1114

1215
### Added

cli/cli_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ func TestCli(t *testing.T) {
3939
// Silence logger
4040
log.SetOutput(io.Discard)
4141

42-
mevboostRelayListUris, _ := mevboostrelaylist.RelaysURI("mainnet")
42+
mainnetMevboostRelayListUris, _ := mevboostrelaylist.RelaysURI("mainnet")
4343
holeskyMevboostRelayListUris, _ := mevboostrelaylist.RelaysURI("holesky")
4444

4545
ETHClients := map[string][]string{
@@ -527,7 +527,7 @@ func TestCli(t *testing.T) {
527527
},
528528
},
529529
{
530-
name: "full node with Lido",
530+
name: "full node with Lido, mainnet",
531531
setup: func(t *testing.T, sedgeActions *sedge_mocks.MockSedgeActions, prompter *sedge_mocks.MockPrompter, depsMgr *sedge_mocks.MockDependenciesManager) {
532532
generationPath := t.TempDir()
533533
genData := generate.GenData{
@@ -555,7 +555,7 @@ func TestCli(t *testing.T) {
555555
VLStartGracePeriod: 840,
556556
Mev: true,
557557
MevImage: "flashbots/mev-boost:latest",
558-
RelayURLs: mevboostRelayListUris,
558+
RelayURLs: mainnetMevboostRelayListUris,
559559
ContainerTag: "tag",
560560
JWTSecretPath: filepath.Join(generationPath, "jwtsecret"),
561561
}

cli/lidoStatus_test.go

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,11 @@ func TestLidoStatusCmd(t *testing.T) {
100100
{
101101
name: "Valid node ID, Holesky",
102102
flags: flags{
103-
networkName: "holesky",
104-
nodeIDInt: 1,
103+
rewardAddress: "0x22bA5CaFB5E26E6Fe51f330294209034013A5A4c", // rewardAddress should be ignored
104+
networkName: "holesky",
105+
nodeIDInt: 1,
105106
},
106-
isErr: true,
107+
isErr: false,
107108
},
108109
{
109110
name: "Invalid: negative node ID, Holesky",
@@ -113,6 +114,56 @@ func TestLidoStatusCmd(t *testing.T) {
113114
},
114115
isErr: true,
115116
},
117+
{
118+
name: "Invalid: missing address, Mainnet",
119+
flags: flags{
120+
networkName: "mainnet",
121+
},
122+
isErr: true,
123+
},
124+
{
125+
name: "Invalid: incorrect address, Mainnet",
126+
flags: flags{
127+
rewardAddress: "0xC870Fd10dd",
128+
networkName: "mainnet",
129+
},
130+
isErr: true,
131+
},
132+
{
133+
name: "Invalid: address missing 0x prefix, Mainnet",
134+
flags: flags{
135+
rewardAddress: "bA99F374C20A3475De737B466ee68Ad9C38c26AF",
136+
networkName: "mainnet",
137+
},
138+
isErr: true,
139+
},
140+
// {
141+
// name: "Valid node ID, Mainnet",
142+
// flags: flags{
143+
// rewardAddress: "0x22bA5CaFB5E26E6Fe51f330294209034013A5A4c", // rewardAddress should be ignored
144+
// networkName: "mainnet",
145+
// nodeIDInt: 1,
146+
// },
147+
// isErr: false,
148+
// },
149+
// {
150+
// name: "Valid node ID with long description, Mainnet",
151+
// flags: flags{
152+
// rewardAddress: "0x22bA5CaFB5E26E6Fe51f330294209034013A5A4c", // rewardAddress should be ignored
153+
// networkName: "mainnet",
154+
// nodeIDInt: 1,
155+
// longDescriptions: true,
156+
// },
157+
// isErr: false,
158+
// },
159+
{
160+
name: "Invalid: negative node ID, Mainnet",
161+
flags: flags{
162+
networkName: "mainnet",
163+
nodeIDInt: -14,
164+
},
165+
isErr: true,
166+
},
116167
}
117168

118169
for _, tc := range tcs {

cli/monitoring_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,31 @@ func TestMonitoringCmd(t *testing.T) {
9191
},
9292
isErr: true,
9393
},
94+
{
95+
name: "valid monitoring init: lido, Mainnet",
96+
flags: []string{"init", "lido", "--node-operator-id", "1", "--network", "mainnet"},
97+
mocker: func(t *testing.T, ctrl *gomock.Controller) *sedge_mocks.MockMonitoringManager {
98+
mockManager := sedge_mocks.NewMockMonitoringManager(ctrl)
99+
gomock.InOrder(
100+
mockManager.EXPECT().InstallationStatus().Return(common.NotInstalled, nil).AnyTimes(),
101+
mockManager.EXPECT().InstallStack().Return(nil).AnyTimes(),
102+
mockManager.EXPECT().Status().Return(common.Created, nil).AnyTimes(),
103+
mockManager.EXPECT().Run().Return(nil).AnyTimes(),
104+
mockManager.EXPECT().Init().Return(nil).AnyTimes(),
105+
mockManager.EXPECT().AddService(gomock.Any()).Return(nil).AnyTimes(),
106+
)
107+
return mockManager
108+
},
109+
isErr: false,
110+
},
111+
{
112+
name: "invalid monitoring init: lido, no nodeID or reward address, Mainnet",
113+
flags: []string{"init", "lido", "--network", "mainnet"},
114+
mocker: func(t *testing.T, ctrl *gomock.Controller) *sedge_mocks.MockMonitoringManager {
115+
return sedge_mocks.NewMockMonitoringManager(ctrl)
116+
},
117+
isErr: true,
118+
},
94119
}
95120

96121
for _, tc := range tcs {

docs/docs/commands/generate.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ Use "sedge generate [command] --help" for more information about a command.
5252

5353
### Lido Flow
5454

55-
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.
55+
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.
5656

5757
It will include in the configuration of the selected node:
5858
- Lido Withdrawal Credentials

docs/docs/quickstart/lido.mdx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@ If you are interested in becoming a Lido node operator, make sure to read the [N
2121

2222
:::info
2323

24-
Lido CSM is **[currently live and permissionless on the Holesky testnet](https://operatorportal.lido.fi/modules/community-staking-module)**.
25-
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/).
24+
Lido CSM is **[currently live and permissionless on the Holesky and Mainnet testnet](https://operatorportal.lido.fi/modules/community-staking-module)**.
2625

2726
:::
2827

e2e/lido-exporter/args_test.go

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,3 +537,149 @@ func TestE2E_InvalidArgs_NegativeNodeID(t *testing.T) {
537537
// Run test case
538538
e2eTest.run()
539539
}
540+
541+
func TestE2E_ValidArgs_NodeOperatorID_Mainnet(t *testing.T) {
542+
// t.Parallel()
543+
// Test context
544+
var (
545+
cmd *exec.Cmd
546+
)
547+
// Build test case
548+
e2eTest := newE2ELidoExporterTestCase(
549+
t,
550+
// Arrange
551+
nil,
552+
// Act
553+
func(t *testing.T, binaryPath string) *exec.Cmd {
554+
cmd = base.RunCommandCMD(t, binaryPath, "lido-exporter", "lido-exporter", "--node-operator-id", "1", "--network", "mainnet", "--port", "9980")
555+
time.Sleep(2 * time.Second)
556+
return cmd
557+
},
558+
// Assert
559+
func(t *testing.T) {
560+
checkPrometheusServerUp(t, 9980)
561+
checkMetrics(t, 9980)
562+
563+
cmd.Process.Signal(os.Interrupt)
564+
565+
// Wait for the process to exit with a timeout
566+
done := make(chan error, 1)
567+
go func() {
568+
done <- cmd.Wait()
569+
}()
570+
571+
select {
572+
case err := <-done:
573+
assert.NoError(t, err)
574+
case <-time.After(5 * time.Second):
575+
t.Error("Process did not exit within the timeout period")
576+
cmd.Process.Kill() // Force kill if it doesn't exit
577+
}
578+
},
579+
)
580+
// Run test case
581+
e2eTest.run()
582+
}
583+
584+
func TestE2E_ValidEnv_All_Mainnet(t *testing.T) {
585+
// t.Parallel()
586+
// Test context
587+
var (
588+
cmd *exec.Cmd
589+
)
590+
// Build test case
591+
e2eTest := newE2ELidoExporterTestCase(
592+
t,
593+
// Arrange
594+
func(t *testing.T, binaryPath string) (map[string]string, error) {
595+
return map[string]string{
596+
"LIDO_EXPORTER_RPC_ENDPOINTS": "'https://eth.llamarpc.com','https://eth-pokt.nodies.app','https://rpc.mevblocker.io'",
597+
"LIDO_EXPORTER_WS_ENDPOINTS": "'wss://ethereum-rpc.publicnode.com'",
598+
"LIDO_EXPORTER_PORT": "9990",
599+
"LIDO_EXPORTER_SCRAPE_TIME": "2s",
600+
"LIDO_EXPORTER_NETWORK": "mainnet",
601+
"LIDO_EXPORTER_NODE_OPERATOR_ID": "1",
602+
}, nil
603+
},
604+
// Act
605+
func(t *testing.T, binaryPath string) *exec.Cmd {
606+
cmd = base.RunCommandCMD(t, binaryPath, "lido-exporter", "lido-exporter")
607+
time.Sleep(2 * time.Second)
608+
return cmd
609+
},
610+
// Assert
611+
func(t *testing.T) {
612+
checkPrometheusServerUp(t, 9990)
613+
checkMetrics(t, 9990)
614+
615+
cmd.Process.Signal(os.Interrupt)
616+
617+
// Wait for the process to exit with a timeout
618+
done := make(chan error, 1)
619+
go func() {
620+
done <- cmd.Wait()
621+
}()
622+
623+
select {
624+
case err := <-done:
625+
assert.NoError(t, err)
626+
case <-time.After(5 * time.Second):
627+
t.Error("Process did not exit within the timeout period")
628+
cmd.Process.Kill() // Force kill if it doesn't exit
629+
}
630+
},
631+
)
632+
// Run test case
633+
e2eTest.run()
634+
}
635+
636+
func TestE2E_ValidFlags_All_Mainnet(t *testing.T) {
637+
// t.Parallel()
638+
// Test context
639+
var (
640+
cmd *exec.Cmd
641+
)
642+
// Build test case
643+
e2eTest := newE2ELidoExporterTestCase(
644+
t,
645+
// Arrange
646+
nil,
647+
// Act
648+
func(t *testing.T, binaryPath string) *exec.Cmd {
649+
cmd = base.RunCommandCMD(t, binaryPath, "lido-exporter", "lido-exporter",
650+
"--rpc-endpoints", "https://eth.llamarpc.com", "https://eth-pokt.nodies.app", "https://rpc.mevblocker.io",
651+
"--ws-endpoints", "wss://ethereum-rpc.publicnode.com", // https endpoint should be ignored
652+
"--port", "9989",
653+
"--scrape-time", "1s",
654+
"--network", "mainnet",
655+
"--node-operator-id", "1", // should be prioritized over reward address
656+
"--reward-address", "0x22bA5CaFB5E26E6Fe51f330294209034013A5A4c",
657+
)
658+
time.Sleep(2 * time.Second)
659+
return cmd
660+
},
661+
// Assert
662+
func(t *testing.T) {
663+
checkPrometheusServerUp(t, 9989)
664+
checkMetrics(t, 9989)
665+
666+
cmd.Process.Signal(os.Interrupt)
667+
668+
// Wait for the process to exit with a timeout
669+
done := make(chan error, 1)
670+
go func() {
671+
done <- cmd.Wait()
672+
}()
673+
674+
select {
675+
case err := <-done:
676+
assert.NoError(t, err)
677+
case <-time.After(5 * time.Second):
678+
t.Error("Process did not exit within the timeout period")
679+
cmd.Process.Kill() // Force kill if it doesn't exit
680+
}
681+
},
682+
)
683+
// Run test case
684+
e2eTest.run()
685+
}

e2e/sedge/lidoStatus_test.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,3 +161,73 @@ func TestE2E_LidoStatus_InvalidZeroRewardAddress(t *testing.T) {
161161
// Run test case
162162
e2eTest.run()
163163
}
164+
165+
// func TestE2E_LidoStatus_ValidNodeID_Mainnet(t *testing.T) {
166+
// // Test context
167+
// var (
168+
// runErr error
169+
// )
170+
// // Build test case
171+
// e2eTest := newE2ESedgeTestCase(
172+
// t,
173+
// // Arrange
174+
// nil,
175+
// // Act
176+
// func(t *testing.T, binaryPath string, dataDirPath string) {
177+
// runErr = base.RunCommand(t, binaryPath, "sedge", "lido-status", "--nodeID", "1", "--l", "--network", "mainnet")
178+
// },
179+
// // Assert
180+
// func(t *testing.T, dataDirPath string) {
181+
// assert.NoError(t, runErr, "lido status command should succeed with the given arguments")
182+
// },
183+
// )
184+
// // Run test case
185+
// e2eTest.run()
186+
// }
187+
188+
func TestE2E_LidoStatus_InvalidNodeID_Mainnet(t *testing.T) {
189+
// Test context
190+
var (
191+
runErr error
192+
)
193+
// Build test case
194+
e2eTest := newE2ESedgeTestCase(
195+
t,
196+
// Arrange
197+
nil,
198+
// Act
199+
func(t *testing.T, binaryPath string, dataDirPath string) {
200+
runErr = base.RunCommand(t, binaryPath, "sedge", "lido-status", "--nodeID", "-30", "--l", "--network", "mainnet")
201+
},
202+
// Assert
203+
func(t *testing.T, dataDirPath string) {
204+
// Node ID can't be a negative value
205+
assert.Error(t, runErr, "lido status command should fail")
206+
},
207+
)
208+
// Run test case
209+
e2eTest.run()
210+
}
211+
212+
func TestE2E_LidoStatus_InvalidRewardAddress_Mainnet(t *testing.T) {
213+
// Test context
214+
var (
215+
runErr error
216+
)
217+
// Build test case
218+
e2eTest := newE2ESedgeTestCase(
219+
t,
220+
// Arrange
221+
nil,
222+
// Act
223+
func(t *testing.T, binaryPath string, dataDirPath string) {
224+
runErr = base.RunCommand(t, binaryPath, "sedge", "lido-status", "0xccbhk45", "--network", "mainnet")
225+
},
226+
// Assert
227+
func(t *testing.T, dataDirPath string) {
228+
assert.Error(t, runErr, "lido status command should fail")
229+
},
230+
)
231+
// Run test case
232+
e2eTest.run()
233+
}

0 commit comments

Comments
 (0)