Skip to content

Commit

Permalink
Merge branch 'develop' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
sugh01 authored Jul 8, 2024
2 parents bb7d95f + 74604f5 commit df81a46
Show file tree
Hide file tree
Showing 19 changed files with 465 additions and 154 deletions.
45 changes: 45 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/go
{
"name": "Go",
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
"image": "mcr.microsoft.com/devcontainers/go:1-1.22-bookworm",
"features": {
"ghcr.io/devcontainers/features/docker-in-docker:2": {},
"ghcr.io/devcontainers-contrib/features/curl-apt-get:1": {}
},
"customizations": {
"vscode": {
"extensions": [
"GitHub.copilot",
"streetsidesoftware.code-spell-checker",
"ms-azuretools.vscode-docker",
"dbaeumer.vscode-eslint",
"donjayamanne.githistory",
"GitHub.copilot-chat",
"GitHub.vscode-pull-request-github",
"golang.go",
"yzhang.markdown-all-in-one",
"DavidAnson.vscode-markdownlint",
"unifiedjs.vscode-mdx",
"redhat.vscode-yaml",
"eamodio.gitlens"
]
}
}

// Features to add to the dev container. More info: https://containers.dev/features.
// "features": {},

// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],

// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "go version",

// Configure tool-specific properties.
// "customizations": {},

// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
// "remoteUser": "root"
}
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- Add support for MEV-boost on Holesky.

### Changed

- Update client images to Dencun-ready versions.
Expand Down
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,12 +174,12 @@ Users acknowledge that no warranty is being made of a successful installation. S

### CL clients with Mev-Boost

| Client | Mev-Boost | Networks |
| ---------- | --------- |--------------------------|
| Lighthouse | yes | Mainnet, Sepolia |
| Lodestar | yes | Mainnet, Sepolia |
| Prysm | yes | Mainnet, Sepolia |
| Teku | yes | Mainnet, Sepolia |
| Client | Mev-Boost | Networks |
| ---------- | --------- |---------------------------|
| Lighthouse | yes | Mainnet, Sepolia, Holesky |
| Lodestar | yes | Mainnet, Sepolia, Holesky |
| Prysm | yes | Mainnet, Sepolia, Holesky |
| Teku | yes | Mainnet, Sepolia, Holesky |

## Supported Linux flavours for dependency installation

Expand Down
2 changes: 2 additions & 0 deletions cli/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,7 @@ func TestCli(t *testing.T) {
MapAllPorts: false,
ExecutionApiUrl: "http://execution:5051",
ExecutionAuthUrl: "http://execution:5051",
MevBoostEndpoint: "http://mev-boost:3030",
ContainerTag: "tag",
JWTSecretPath: filepath.Join(generationPath, "jwtsecret"),
}
Expand All @@ -383,6 +384,7 @@ func TestCli(t *testing.T) {
prompter.EXPECT().Input("Container tag, sedge will add to each container and the network, a suffix with the tag", "", false, nil).Return("tag", nil),
prompter.EXPECT().Select("Select consensus client", "", ETHClients["consensus"]).Return(3, nil),
prompter.EXPECT().InputURL("Checkpoint sync URL", configs.NetworksConfigs()[genData.Network].CheckpointSyncURL, false).Return("https://checkpoint-sync.holesky.ethpandaops.io/", nil),
prompter.EXPECT().InputURL("Mev-Boost endpoint", "", false).Return("http://mev-boost:3030", nil),
prompter.EXPECT().InputURL("Execution API URL", "", true).Return("http://execution:5051", nil),
prompter.EXPECT().InputURL("Execution Auth API URL", "", true).Return("http://execution:5051", nil),
prompter.EXPECT().EthAddress("Please enter the Fee Recipient address (press enter to skip it)", "", false).Return("0x2d07a21ebadde0c13e8b91022a7e5732eb6bf5d5", nil),
Expand Down
32 changes: 24 additions & 8 deletions cli/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/NethermindEth/sedge/internal/pkg/commands"
"github.com/NethermindEth/sedge/internal/pkg/keystores"
"github.com/NethermindEth/sedge/internal/ui"
"github.com/NethermindEth/sedge/internal/utils"
eth2 "github.com/protolambda/zrnt/eth2/configs"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
Expand Down Expand Up @@ -83,6 +84,10 @@ func KeysCmd(cmdRunner commands.CommandRunner, p ui.Prompter) *cobra.Command {
if err := configs.NetworkCheck(flags.network); err != nil {
log.Fatal(err.Error())
}
// Validate fee recipient
if flags.eth1WithdrawalAddress != "" && !utils.IsAddress(flags.eth1WithdrawalAddress) {
log.Fatal(configs.ErrInvalidWithdrawalAddr)
}
// Ensure that path is absolute
log.Debugf("Path to keystore folder: %s", flags.path)
absPath, err := filepath.Abs(flags.path)
Expand All @@ -93,7 +98,10 @@ func KeysCmd(cmdRunner commands.CommandRunner, p ui.Prompter) *cobra.Command {
return nil
},
Run: func(cmd *cobra.Command, args []string) {
// TODO: allow usage of withdrawal address
// Warn about withdrawal address
if flags.eth1WithdrawalAddress != "" {
log.Warn(configs.WithdrawalAddressDefinedWarning)
}
// Get keystore passphrase
if !flags.randomPassphrase && flags.passphrasePath != "" {
content, err := readFileContent(flags.passphrasePath)
Expand Down Expand Up @@ -153,14 +161,22 @@ func KeysCmd(cmdRunner commands.CommandRunner, p ui.Prompter) *cobra.Command {
flags.numberVal = numberVal
}

keystorePath := filepath.Join(flags.path, "keystore")

var withdrawalAddress string
if flags.eth1WithdrawalAddress != "" {
withdrawalAddress = flags.eth1WithdrawalAddress[2:]
}

data := keystores.ValidatorKeysGenData{
Mnemonic: mnemonic,
Passphrase: passphrase,
OutputPath: keystorePath,
MinIndex: uint64(flags.existingVal),
MaxIndex: uint64(flags.existingVal) + uint64(flags.numberVal),
NetworkName: flags.network,
ForkVersion: configs.NetworksConfigs()[flags.network].GenesisForkVersion,
Mnemonic: mnemonic,
Passphrase: passphrase,
OutputPath: keystorePath,
MinIndex: uint64(flags.existingVal),
MaxIndex: uint64(flags.existingVal) + uint64(flags.numberVal),
NetworkName: flags.network,
ForkVersion: configs.NetworksConfigs()[flags.network].GenesisForkVersion,
WithdrawalAddress: withdrawalAddress,
// Constants
UseUniquePassphrase: true,
Insecure: false,
Expand Down
137 changes: 70 additions & 67 deletions configs/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,71 +17,74 @@ package configs

// All the strings that are needed for error logging.
const (
ReadingInstructionError = "failed to read instructions from file %s"
IncorrectClientError = "incorrect %s client name \"%s\". Please provide correct client name. Use 'clients' command to see the list of supported clients"
ClosingFileError = "failed to close file %s"
ScriptIsNotRunningError = "services of docker-compose script provided are not running. Error: %v"
GettingLogsError = "failed to get logs for services %s. Error: %v"
DockerComposePsReturnedEmptyError = "'docker compose ps --services' returned empty string"
InvalidVolumePathError = "invalid path provided: %s. If you intended to pass a host directory, use absolute path"
ZipError = "all lists must have the same size"
CommandError = "command '%s' throws error: %v"
DistroInfoError = "failed to get linux distribution info. Error: %v"
EmptyClientMapError = "is not possible to select a random element from an empty collection"
NoSupportedClientsError = "collection of clients given for random choice doesn't have any supported client. Check the target network (flag --network). Use 'clients' command to see the list of supported clients for every supported network"
NetworkValidationFailedError = "'network' flag validation failed. Error: %v"
UnknownNetworkError = "unknown network \"%s\". Please provide correct network name. Use 'networks' command to see the list of supported networks"
GenerateJWTSecretError = "JWT secret generation failed. Error: %v"
GetPWDError = "something failed trying to get current working directory. Error: %v"
EmptyFeeRecipientError = "you should provide an Ethereum address for the Fee Recipient"
KeystorePasswordError = "keystore password must have more than 8 characters"
PortOccupationError = "port occupation check failed. Error: %v"
DefaultPortInvalidError = "default %s can not be zero"
PrintFileError = "error printing file content: %v"
CleaningEnvFileError = "error cleaning env file: %v"
CleaningDCFileError = "error cleaning docker compose file: %v"
PassphraseReadFileError = "error reading passphrase file: %v"
MnemonicReadFileError = "error reading passphrase file: %v"
MnemonicGenerationError = "error creating mnemonic: %v"
KeyEntryGenerationError = "error generating keystore: could not read sufficient secure random bytes"
AESParamsCreationError = "failed to create AES128CTR params: %w"
SecretEncryptionError = "failed to encrypt secret: %w"
KeystoreOutputExistingError = "output folder for keystores already exists"
KeystoreGenerationError = "error generating keystores: %v"
KeystoreDerivationError = "keystore %s cannot be derived, continuing to next keystore"
KeystoreExistingInWalletError = "keystore with name \"%s\" already exists"
KeystoreImportingError = "failed to import keystore with pubkey %s into output wallet: %v"
InvalidMnemonicError = "mnemonic is not valid"
BadMnemonicError = "bad mnemonic: %v"
ForkVersionDecodeError = "cannot decode fork version: %v"
DepositFileWriteError = "cannot write deposit file: %v"
KeystoreSecretKeyCreationError = "failed to create validator private key for path %q: %v"
WithdrawalSecretKeyCreationError = "failed to create withdrawal private key for path %q: %v"
KeystoreSecretKeyConvertionError = "cannot convert validator priv key: %v"
DepositDataEncodingError = "could not encode deposit data to json: %v"
InvalidLoggingFlag = "bad logging flag: %v"
CannotGenerateSecret = "cannot generate 32 bytes long secret"
ShowMnemonicError = "error displaying mnemonic: %v"
InvalidFilePathOrUrl = "invalid filepath or url: %s"
CannotGetUrlContent = "cannot get url %s content: %v"
CannotReadFileContent = "cannot read file %s content: %v"
ErrorCheckingFile = "error checking file %s: %v"
DestFileAlreadyExist = "destiny file %s already exist"
ErrorCreatingFile = "error creating file %s: %v"
ErrorDownloadingFile = "error downloading file from %s: %v"
ErrorCopyingFile = "error copying file from %s: %v"
ErrorWritingDeployBlockFile = "error writing custom deploy block file %s: %v"
InvalidUrlFlagError = "invalid %s url %s. URL must be in the format http(s)://<host>:<port>/<api>/<endpoint>/... or http://<host>/<api>/<endpoint>/"
InvalidEnodeError = "invalid enode %s. Bootnode must be in the format enode://<node id>@<host>:<port>"
InvalidEnrError = "invalid enr %s. ENR must be in the format enr:<base64 encoded string>"
InvalidService = "provided service %s is invalid"
SetupContainersErr = "error setting up service containers: %w"
StartingContainersErr = "error starting service containers: %w"
ReadingYmlErr = "error reading yml file: %w"
ParsingYmlErr = "error parsing yml file, it seems is not a valid docker-compose script: %w"
ServicesNotFoundErr = "services not found in the docker-compose script"
InvalidComposeErr = "provided docker-compose script is invalid: %w"
ErrDuplicatedBootNode = "duplicated boot node"
ErrGraffitiLength = "graffiti must have 16 characters at most. Provided graffiti %s has %d characters"
ErrCMDArgsNotSupported = "command %s does not support arguments. Please use flags instead"
ReadingInstructionError = "failed to read instructions from file %s"
IncorrectClientError = "incorrect %s client name \"%s\". Please provide correct client name. Use 'clients' command to see the list of supported clients"
ClosingFileError = "failed to close file %s"
ScriptIsNotRunningError = "services of docker-compose script provided are not running. Error: %v"
GettingLogsError = "failed to get logs for services %s. Error: %v"
DockerComposePsReturnedEmptyError = "'docker compose ps --services' returned empty string"
InvalidVolumePathError = "invalid path provided: %s. If you intended to pass a host directory, use absolute path"
ZipError = "all lists must have the same size"
CommandError = "command '%s' throws error: %v"
DistroInfoError = "failed to get linux distribution info. Error: %v"
EmptyClientMapError = "is not possible to select a random element from an empty collection"
NoSupportedClientsError = "collection of clients given for random choice doesn't have any supported client. Check the target network (flag --network). Use 'clients' command to see the list of supported clients for every supported network"
NetworkValidationFailedError = "'network' flag validation failed. Error: %v"
UnknownNetworkError = "unknown network \"%s\". Please provide correct network name. Use 'networks' command to see the list of supported networks"
GenerateJWTSecretError = "JWT secret generation failed. Error: %v"
GetPWDError = "something failed trying to get current working directory. Error: %v"
EmptyFeeRecipientError = "you should provide an Ethereum address for the Fee Recipient"
KeystorePasswordError = "keystore password must have more than 8 characters"
PortOccupationError = "port occupation check failed. Error: %v"
DefaultPortInvalidError = "default %s can not be zero"
PrintFileError = "error printing file content: %v"
CleaningEnvFileError = "error cleaning env file: %v"
CleaningDCFileError = "error cleaning docker compose file: %v"
PassphraseReadFileError = "error reading passphrase file: %v"
MnemonicReadFileError = "error reading passphrase file: %v"
MnemonicGenerationError = "error creating mnemonic: %v"
KeyEntryGenerationError = "error generating keystore: could not read sufficient secure random bytes"
AESParamsCreationError = "failed to create AES128CTR params: %w"
SecretEncryptionError = "failed to encrypt secret: %w"
KeystoreOutputExistingError = "output folder for keystores already exists"
KeystoreGenerationError = "error generating keystores: %v"
KeystoreDerivationError = "keystore %s cannot be derived, continuing to next keystore"
KeystoreExistingInWalletError = "keystore with name \"%s\" already exists"
KeystoreImportingError = "failed to import keystore with pubkey %s into output wallet: %v"
InvalidMnemonicError = "mnemonic is not valid"
BadMnemonicError = "bad mnemonic: %v"
ForkVersionDecodeError = "cannot decode fork version: %v"
DepositFileWriteError = "cannot write deposit file: %v"
KeystoreSecretKeyCreationError = "failed to create validator private key for path %q: %v"
WithdrawalSecretKeyCreationError = "failed to create withdrawal private key for path %q: %v"
KeystoreSecretKeyConvertionError = "cannot convert validator priv key: %v"
DepositDataEncodingError = "could not encode deposit data to json: %v"
InvalidLoggingFlag = "bad logging flag: %v"
CannotGenerateSecret = "cannot generate 32 bytes long secret"
ShowMnemonicError = "error displaying mnemonic: %v"
InvalidFilePathOrUrl = "invalid filepath or url: %s"
CannotGetUrlContent = "cannot get url %s content: %v"
CannotReadFileContent = "cannot read file %s content: %v"
ErrorCheckingFile = "error checking file %s: %v"
DestFileAlreadyExist = "destiny file %s already exist"
ErrorCreatingFile = "error creating file %s: %v"
ErrorDownloadingFile = "error downloading file from %s: %v"
ErrorCopyingFile = "error copying file from %s: %v"
ErrorWritingDeployBlockFile = "error writing custom deploy block file %s: %v"
InvalidUrlFlagError = "invalid %s url %s. URL must be in the format http(s)://<host>:<port>/<api>/<endpoint>/... or http://<host>/<api>/<endpoint>/"
InvalidEnodeError = "invalid enode %s. Bootnode must be in the format enode://<node id>@<host>:<port>"
InvalidEnrError = "invalid enr %s. ENR must be in the format enr:<base64 encoded string>"
InvalidService = "provided service %s is invalid"
SetupContainersErr = "error setting up service containers: %w"
StartingContainersErr = "error starting service containers: %w"
ReadingYmlErr = "error reading yml file: %w"
ParsingYmlErr = "error parsing yml file, it seems is not a valid docker-compose script: %w"
ServicesNotFoundErr = "services not found in the docker-compose script"
InvalidComposeErr = "provided docker-compose script is invalid: %w"
ErrDuplicatedBootNode = "duplicated boot node"
ErrGraffitiLength = "graffiti must have 16 characters at most. Provided graffiti %s has %d characters"
ErrCMDArgsNotSupported = "command %s does not support arguments. Please use flags instead"
ErrWithdrawalEth1SecretKeyCreation = "failed to create withdrawal private key for address 0x%s: %v"
ErrWithdrawalBLSSecretKeyCreation = "failed to create withdrawal private key for path %q: %v"
ErrInvalidWithdrawalAddr = "provided withdrawal address is not a valid Ethereum address"
)
8 changes: 7 additions & 1 deletion configs/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,14 @@ var networksConfigs map[string]NetworkConfig = map[string]NetworkConfig{
Name: NetworkHolesky,
NetworkService: "merge",
GenesisForkVersion: "0x00017000",
SupportsMEVBoost: false,
SupportsMEVBoost: true,
CheckpointSyncURL: "https://checkpoint-sync.holesky.ethpandaops.io/",
RelayURLs: []string{
"https://0xafa4c6985aa049fb79dd37010438cfebeb0f2bd42b115b89dd678dab0670c1de38da0c4e9138c9290a398ecd9a0b3110@boost-relay-holesky.flashbots.net",
"https://0x8db06236d88cf080e541f894507f6c933d40333405c36c8ea00158c165628ea57ad59b024467fe7d4d31113fadc0e187@holesky.agnostic-relay.net",
"https://0xab78bf8c781c58078c3beb5710c57940874dd96aef2835e7742c866b4c7c0406754376c2c8285a36c630346aa5c5f833@holesky.aestus.live",
"https://0xaa58208899c6105603b74396734a6263cc7d947f444f396a90f7b7d3e65d102aec7e5e5291b27e08d02c50a050825c2f@holesky.titanrelay.xyz",
},
},
NetworkCustom: {
Name: NetworkCustom,
Expand Down
Loading

0 comments on commit df81a46

Please sign in to comment.