mirror of
https://github.com/stake-house/wagyu-key-gen.git
synced 2026-01-08 20:27:57 -05:00
Migration to ethstaker-deposit-cli
This commit is contained in:
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -17,7 +17,7 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-20.04, macos-13, macos-latest, windows-latest]
|
||||
python-version: ["3.11"]
|
||||
python-version: ["3.12"]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Python
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,4 +1,5 @@
|
||||
.vscode/
|
||||
.venv/
|
||||
node_modules/
|
||||
dist/
|
||||
.pnp.*
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Wagyu Key Gen
|
||||
[](https://www.gitpoap.io/gh/stake-house/wagyu-key-gen)
|
||||
|
||||
Wagyu Key Gen is a GUI application providing functionality to the [staking-deposit-cli](https://github.com/ethereum/staking-deposit-cli). It is a React app running in Electron. See `src/electron/` for the simple electron app and `src/react/` for where the magic happens.
|
||||
Wagyu Key Gen is a GUI application providing functionality to the [ethstaker-deposit-cli](https://github.com/eth-educators/ethstaker-deposit-cli). It is a React app running in Electron. See `src/electron/` for the simple electron app and `src/react/` for where the magic happens.
|
||||
|
||||
### Download wagyu at [https://wagyu.gg](https://wagyu.gg)
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ import { doesFileExist } from './BashUtils';
|
||||
*/
|
||||
const execFileProm = promisify(execFile);
|
||||
|
||||
const ETH2_DEPOSIT_DIR_NAME = "staking-deposit-cli-2.7.0";
|
||||
const ETH2_DEPOSIT_DIR_NAME = "ethstaker-deposit-cli-0.5.0";
|
||||
|
||||
/**
|
||||
* Paths needed to call the stakingdeposit_proxy application using the Python 3 version installed on
|
||||
@@ -42,7 +42,7 @@ const ETH2_DEPOSIT_DIR_NAME = "staking-deposit-cli-2.7.0";
|
||||
const ETH2_DEPOSIT_CLI_PATH = path.join("src", "vendors", ETH2_DEPOSIT_DIR_NAME);
|
||||
const SCRIPTS_PATH = path.join("src", "scripts");
|
||||
const REQUIREMENTS_PATH = path.join(ETH2_DEPOSIT_CLI_PATH, "requirements.txt");
|
||||
const WORD_LIST_PATH = path.join(ETH2_DEPOSIT_CLI_PATH, "staking_deposit", "key_handling",
|
||||
const WORD_LIST_PATH = path.join(ETH2_DEPOSIT_CLI_PATH, "ethstaker_deposit", "key_handling",
|
||||
"key_derivation", "word_lists");
|
||||
const REQUIREMENT_PACKAGES_PATH = path.join("dist", "packages");
|
||||
const STAKINGDEPOSIT_PROXY_PATH = path.join(SCRIPTS_PATH, "stakingdeposit_proxy.py");
|
||||
@@ -222,7 +222,7 @@ const generateKeys = async (
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a mnemonic using the staking-deposit-cli logic by calling the validate_mnemonic function
|
||||
* Validate a mnemonic using the ethstaker-deposit-cli logic by calling the validate_mnemonic function
|
||||
* from the stakingdeposit_proxy application.
|
||||
*
|
||||
* @param mnemonic The mnemonic to be validated.
|
||||
|
||||
@@ -10,7 +10,7 @@ fi
|
||||
|
||||
SCRIPTPATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"
|
||||
|
||||
EDCDIR=staking-deposit-cli-2.7.0
|
||||
EDCDIR=ethstaker-deposit-cli-0.5.0
|
||||
|
||||
TARGETPACKAGESPATH=$SCRIPTPATH/../../dist/packages
|
||||
ETH2DEPOSITCLIPATH=$SCRIPTPATH/../vendors/$EDCDIR
|
||||
@@ -19,8 +19,8 @@ ETH2REQUIREMENTSPATH=$ETH2DEPOSITCLIPATH/requirements.txt
|
||||
PYTHONPATH=$TARGETPACKAGESPATH:$ETH2DEPOSITCLIPATH:$(python3 -c "import sys;print(':'.join(sys.path))")
|
||||
DISTBINPATH=$SCRIPTPATH/../../build/bin
|
||||
DISTWORDSPATH=$SCRIPTPATH/../../build/word_lists
|
||||
SRCWORDSPATH=$SCRIPTPATH/../vendors/$EDCDIR/staking_deposit/key_handling/key_derivation/word_lists
|
||||
SRCINTLPATH=$SCRIPTPATH/../vendors/$EDCDIR/staking_deposit/intl
|
||||
SRCWORDSPATH=$SCRIPTPATH/../vendors/$EDCDIR/ethstaker_deposit/key_handling/key_derivation/word_lists
|
||||
SRCINTLPATH=$SCRIPTPATH/../vendors/$EDCDIR/ethstaker_deposit/intl
|
||||
|
||||
mkdir -p $DISTBINPATH
|
||||
mkdir -p $DISTWORDSPATH
|
||||
@@ -29,11 +29,17 @@ mkdir -p $TARGETPACKAGESPATH
|
||||
# Getting all the requirements
|
||||
python3 -m pip install -r $ETH2REQUIREMENTSPATH --target $TARGETPACKAGESPATH
|
||||
|
||||
# Getting packages metadata
|
||||
PYECCDATA=$(python3 -c "from PyInstaller.utils.hooks import copy_metadata;print(':'.join(copy_metadata('py_ecc')[0]))")
|
||||
SSZDATA=$(python3 -c "from PyInstaller.utils.hooks import copy_metadata;print(':'.join(copy_metadata('ssz')[0]))")
|
||||
|
||||
# Bundling Python stakingdeposit_proxy
|
||||
PYTHONPATH=$PYTHONPATH pyinstaller \
|
||||
--onefile \
|
||||
--distpath $DISTBINPATH \
|
||||
--add-data "$SRCINTLPATH:staking_deposit/intl" \
|
||||
--add-data "$SRCINTLPATH:ethstaker_deposit/intl" \
|
||||
--add-data "$PYECCDATA" \
|
||||
--add-data "$SSZDATA" \
|
||||
-p $PYTHONPATH \
|
||||
$SCRIPTPATH/stakingdeposit_proxy.py
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ rem Windows.
|
||||
|
||||
SET BATDIR=%~dp0
|
||||
|
||||
SET EDCDIR=staking-deposit-cli-2.7.0
|
||||
SET EDCDIR=ethstaker-deposit-cli-0.5.0
|
||||
|
||||
SET TARGETPACKAGESPATH=%BATDIR%..\..\dist\packages
|
||||
|
||||
@@ -17,8 +17,8 @@ FOR /F "tokens=* USEBACKQ delims=;" %%F IN (`python -c "import sys;print(';'.joi
|
||||
|
||||
SET DISTBINPATH=%BATDIR%..\..\build\bin
|
||||
SET DISTWORDSPATH=%BATDIR%..\..\build\word_lists
|
||||
SET SRCWORDSPATH=%BATDIR%..\vendors\%EDCDIR%\staking_deposit\key_handling\key_derivation\word_lists
|
||||
SET SRCINTLPATH=%BATDIR%..\vendors\%EDCDIR%\staking_deposit\intl
|
||||
SET SRCWORDSPATH=%BATDIR%..\vendors\%EDCDIR%\ethstaker_deposit\key_handling\key_derivation\word_lists
|
||||
SET SRCINTLPATH=%BATDIR%..\vendors\%EDCDIR%\ethstaker_deposit\intl
|
||||
|
||||
mkdir %DISTBINPATH% > nul 2> nul
|
||||
mkdir %DISTWORDSPATH% > nul 2> nul
|
||||
@@ -28,7 +28,7 @@ rem Getting all the requirements
|
||||
python -m pip install -r %ETH2REQUIREMENTSPATH% --target %TARGETPACKAGESPATH%
|
||||
|
||||
rem Bundling Python stakingdeposit_proxy
|
||||
pyinstaller --onefile --distpath %DISTBINPATH% --add-data "%SRCINTLPATH%;staking_deposit\intl" -p %PYTHONPATH% %BATDIR%stakingdeposit_proxy.py
|
||||
pyinstaller --onefile --distpath %DISTBINPATH% --add-data "%SRCINTLPATH%;ethstaker_deposit\intl" -p %PYTHONPATH% %BATDIR%stakingdeposit_proxy.py
|
||||
|
||||
rem Adding word list
|
||||
copy /Y %SRCWORDSPATH%\* %DISTWORDSPATH%
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""The stakingdeposit_proxy application.
|
||||
|
||||
This application is used as a proxy between our electron application and the staking-deposit-cli
|
||||
internals. It exposes some staking-deposit-cli functions as easy to use commands that can be called
|
||||
This application is used as a proxy between our electron application and the ethstaker-deposit-cli
|
||||
internals. It exposes some ethstaker-deposit-cli functions as easy to use commands that can be called
|
||||
on the CLI.
|
||||
"""
|
||||
|
||||
@@ -16,32 +16,32 @@ from typing import (
|
||||
|
||||
from eth_typing import HexAddress
|
||||
|
||||
from staking_deposit.key_handling.key_derivation.mnemonic import (
|
||||
from ethstaker_deposit.key_handling.key_derivation.mnemonic import (
|
||||
get_mnemonic,
|
||||
reconstruct_mnemonic
|
||||
)
|
||||
|
||||
from eth_utils import is_hex_address, to_normalized_address
|
||||
|
||||
from staking_deposit.credentials import (
|
||||
from ethstaker_deposit.credentials import (
|
||||
CredentialList,
|
||||
Credential
|
||||
)
|
||||
|
||||
from staking_deposit.exceptions import ValidationError
|
||||
from staking_deposit.utils.validation import (
|
||||
from ethstaker_deposit.exceptions import ValidationError
|
||||
from ethstaker_deposit.utils.validation import (
|
||||
validate_deposit,
|
||||
validate_bls_to_execution_change
|
||||
)
|
||||
from staking_deposit.utils.constants import (
|
||||
from ethstaker_deposit.utils.constants import (
|
||||
MAX_DEPOSIT_AMOUNT,
|
||||
)
|
||||
|
||||
from staking_deposit.settings import (
|
||||
from ethstaker_deposit.settings import (
|
||||
get_chain_setting,
|
||||
)
|
||||
|
||||
from staking_deposit.utils.crypto import SHA256
|
||||
from ethstaker_deposit.utils.crypto import SHA256
|
||||
|
||||
def generate_bls_to_execution_change(
|
||||
folder: str,
|
||||
@@ -116,7 +116,7 @@ def generate_bls_to_execution_change(
|
||||
with open(filefolder, 'w') as f:
|
||||
json.dump(bls_to_execution_changes, f)
|
||||
if os.name == 'posix':
|
||||
os.chmod(filefolder, int('440', 8)) # Read for owner & group
|
||||
os.chmod(filefolder, int('400', 8)) # Read for owner & group
|
||||
btec_file = filefolder
|
||||
|
||||
with open(btec_file, 'r') as f:
|
||||
@@ -173,7 +173,7 @@ def validate_bls_credentials(
|
||||
|
||||
|
||||
def validate_mnemonic(mnemonic: str, word_lists_path: str) -> str:
|
||||
"""Validate a mnemonic using the staking-deposit-cli logic and returns the mnemonic.
|
||||
"""Validate a mnemonic using the ethstaker-deposit-cli logic and returns the mnemonic.
|
||||
|
||||
Keyword arguments:
|
||||
mnemonic -- the mnemonic to validate
|
||||
@@ -253,7 +253,7 @@ def generate_keys(args):
|
||||
with open(filefolder, 'w') as f:
|
||||
json.dump(deposit_data, f, default=lambda x: x.hex())
|
||||
if os.name == 'posix':
|
||||
os.chmod(filefolder, int('440', 8)) # Read for owner & group
|
||||
os.chmod(filefolder, int('400', 8)) # Read for owner & group
|
||||
deposits_file = filefolder
|
||||
|
||||
items = zip(credentials.credentials, keystore_filefolders)
|
||||
|
||||
4
src/vendors/ethstaker-deposit-cli-0.5.0/.coveragerc
vendored
Normal file
4
src/vendors/ethstaker-deposit-cli-0.5.0/.coveragerc
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
[run]
|
||||
relative_files = True
|
||||
omit =
|
||||
tests/**
|
||||
1
src/vendors/ethstaker-deposit-cli-0.5.0/.github/CODEOWNERS
vendored
Normal file
1
src/vendors/ethstaker-deposit-cli-0.5.0/.github/CODEOWNERS
vendored
Normal file
@@ -0,0 +1 @@
|
||||
* @valefar-on-discord @remyroy
|
||||
23
src/vendors/ethstaker-deposit-cli-0.5.0/.github/dependabot.yml
vendored
Normal file
23
src/vendors/ethstaker-deposit-cli-0.5.0/.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
# To get started with Dependabot version updates, you'll need to specify which
|
||||
# package ecosystems to update and where the package manifests are located.
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "pip"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
6
src/vendors/ethstaker-deposit-cli-0.5.0/.github/pull_request_template.md
vendored
Normal file
6
src/vendors/ethstaker-deposit-cli-0.5.0/.github/pull_request_template.md
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
**What I did**
|
||||
|
||||
**Related issue**
|
||||
<!-- If this is a bug fix, make sure your description includes "fixes #xxxx", or "closes #xxxx" -->
|
||||
|
||||
**(not mandatory) A picture of a cute animal, if possible in relation to what you did**
|
||||
43
src/vendors/ethstaker-deposit-cli-0.5.0/.github/release_template.md
vendored
Normal file
43
src/vendors/ethstaker-deposit-cli-0.5.0/.github/release_template.md
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
[comment]: <> (This is a comment, it will not be included in the final release notes.)
|
||||
[comment]: <> (This template will be used to automatically generate release notes with the ci-build workflow.)
|
||||
[comment]: <> (The following values will be automatically replaced with generated content from the workflow.)
|
||||
[comment]: <> (`[GENERATED-RELEASE-NOTES]`: Replaced with the GitHub generated release notes.)
|
||||
[comment]: <> (`[WORKFLOW-URL]`: Replaced with the link to the workflow that generated the build.)
|
||||
[comment]: <> (`[BINARIES-TABLE]`: Replaced with the a markdown formatted table with a link to each binary download.)
|
||||
[comment]: <> (`[DOCKER-TABLE]`: Replaced with the a markdown formatted table with a link to the docker image.)
|
||||
|
||||
# Summary
|
||||
|
||||
`[Add a small summary here]`
|
||||
|
||||
# Known Issues
|
||||
|
||||
`[Remove this section if there is no known issue]`
|
||||
|
||||
# All changes
|
||||
|
||||
`[GENERATED-RELEASE-NOTES]`
|
||||
|
||||
# Building process
|
||||
|
||||
Release assets were built using Github Actions and [this workflow run](`[WORKFLOW-RUN-URL]`). You can establish the provenance of this build using [our artifact attestations](https://github.com/eth-educators/ethstaker-deposit-cli/attestations).
|
||||
|
||||
With [the GitHub CLI](https://cli.github.com/) installed, a simple way to verify these assets is to run this command while replacing `[filename]` with the path to the downloaded asset:
|
||||
|
||||
```console
|
||||
gh attestation verify [filename] --repo eth-educators/ethstaker-deposit-cli
|
||||
```
|
||||
|
||||
This step requires you to be online. If you want to perform this offline, follow [these instructions from GitHub](https://docs.github.com/en/actions/security-for-github-actions/using-artifact-attestations/verifying-attestations-offline).
|
||||
|
||||
# Binaries
|
||||
|
||||
`[BINARIES-TABLE]`
|
||||
|
||||
# Docker image
|
||||
|
||||
`[DOCKER-TABLE]`
|
||||
|
||||
## License
|
||||
|
||||
By downloading and using this software, you agree to the [license](LICENSE).
|
||||
372
src/vendors/ethstaker-deposit-cli-0.5.0/.github/workflows/build.yml
vendored
Normal file
372
src/vendors/ethstaker-deposit-cli-0.5.0/.github/workflows/build.yml
vendored
Normal file
@@ -0,0 +1,372 @@
|
||||
name: ci-build
|
||||
run-name: ${{ github.actor }} is building binaries, building the docker image and drafting a release
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
tags:
|
||||
- v*
|
||||
|
||||
# Defines two custom environment variables for the workflow. These are used for the Container registry domain, and a name for the Docker image that this workflow builds.
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
IMAGE_NAME: ${{ github.repository }}
|
||||
|
||||
jobs:
|
||||
build-binaries:
|
||||
runs-on: ${{ matrix.os }}
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
attestations: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-20.04, ubuntu-22.04-arm64, macos-13, macos-latest, windows-latest]
|
||||
python-version: ["3.12"]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
cache: 'pip'
|
||||
- name: Setup variables (Linux & macOS)
|
||||
if: ${{ startsWith(matrix.os, 'ubuntu-') || startsWith(matrix.os, 'macos-') }}
|
||||
env:
|
||||
MATRIX_OS: '${{ matrix.os }}'
|
||||
run: |
|
||||
echo "PYTHONHASHSEED=42" >> "$GITHUB_ENV"
|
||||
SHORT_SHA=$(echo ${{ github.sha }} | cut -c -7)
|
||||
echo "SHORT_SHA=${SHORT_SHA}" >> "$GITHUB_ENV"
|
||||
if [[ $MATRIX_OS == ubuntu-* ]] ;
|
||||
then
|
||||
BUILD_SYSTEM=linux
|
||||
BUILD_CONFIGS_PATH=./build_configs/linux
|
||||
fi
|
||||
if [[ $MATRIX_OS == macos-* ]] ;
|
||||
then
|
||||
BUILD_SYSTEM=darwin
|
||||
BUILD_CONFIGS_PATH=./build_configs/macos
|
||||
brew install coreutils
|
||||
fi
|
||||
BUILD_ARCHITECTURE=amd64
|
||||
if [[ $MATRIX_OS == *arm* ]] || [[ $MATRIX_OS == macos-latest ]] ;
|
||||
then
|
||||
BUILD_ARCHITECTURE=arm64
|
||||
fi
|
||||
BUILD_FILE_NAME=ethstaker_deposit-cli-${SHORT_SHA}-${BUILD_SYSTEM}-${BUILD_ARCHITECTURE}
|
||||
mkdir "${BUILD_FILE_NAME}"
|
||||
echo "BUILD_FILE_NAME=${BUILD_FILE_NAME}" >> "$GITHUB_ENV"
|
||||
echo "BUILD_CONFIGS_PATH=${BUILD_CONFIGS_PATH}" >> "$GITHUB_ENV"
|
||||
- name: Setup variables (Windows)
|
||||
if: ${{ startsWith(matrix.os, 'windows-') }}
|
||||
env:
|
||||
MATRIX_OS: '${{ matrix.os }}'
|
||||
run: |
|
||||
echo "PYTHONHASHSEED=42" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||
$env:SHORT_SHA = "${{ github.sha }}".Substring(0, 7)
|
||||
echo ("SHORT_SHA=" + $env:SHORT_SHA) | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||
if ($env:MATRIX_OS.Contains("arm")) {
|
||||
$env:BUILD_ARCHITECTURE = "arm64"
|
||||
}
|
||||
else {
|
||||
$env:BUILD_ARCHITECTURE = "amd64"
|
||||
}
|
||||
$env:BUILD_FILE_NAME = ("ethstaker_deposit-cli-" + $env:SHORT_SHA + "-windows-" + $env:BUILD_ARCHITECTURE)
|
||||
echo ("BUILD_FILE_NAME=" + $env:BUILD_FILE_NAME) | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||
mkdir $env:BUILD_FILE_NAME
|
||||
$env:BUILD_FILE_NAME_PATH = (".\" + $env:BUILD_FILE_NAME)
|
||||
echo ("BUILD_FILE_NAME_PATH=" + $env:BUILD_FILE_NAME_PATH) | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||
- name: Build on Linux & macOS
|
||||
if: ${{ startsWith(matrix.os, 'ubuntu-') || startsWith(matrix.os, 'macos-') }}
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -r "${BUILD_CONFIGS_PATH}"/requirements.txt
|
||||
pyinstaller --distpath ./"${BUILD_FILE_NAME}" "${BUILD_CONFIGS_PATH}"/build.spec
|
||||
export ARCHIVE_FILE_NAME="${BUILD_FILE_NAME}".tar.gz
|
||||
echo "ARCHIVE_FILE_NAME=${ARCHIVE_FILE_NAME}" >> "$GITHUB_ENV"
|
||||
tar -zcvf "${ARCHIVE_FILE_NAME}" ./"${BUILD_FILE_NAME}"
|
||||
mkdir -p output/artifacts
|
||||
cp "${ARCHIVE_FILE_NAME}" output/artifacts
|
||||
sha256sum "${ARCHIVE_FILE_NAME}" | head -c 64 > output/artifacts/"${ARCHIVE_FILE_NAME}".sha256
|
||||
- name: Build on Windows
|
||||
if: ${{ startsWith(matrix.os, 'windows-') }}
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -r build_configs/windows/requirements.txt
|
||||
pyinstaller --distpath $env:BUILD_FILE_NAME .\build_configs\windows\build.spec
|
||||
$env:ZIP_FILE_NAME = ($env:BUILD_FILE_NAME + ".zip")
|
||||
echo ("ZIP_FILE_NAME=" + $env:ZIP_FILE_NAME) | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
|
||||
Compress-Archive -Path $env:BUILD_FILE_NAME_PATH -DestinationPath $env:ZIP_FILE_NAME
|
||||
mkdir output\artifacts
|
||||
copy $env:ZIP_FILE_NAME output\artifacts
|
||||
$env:CHECKSUM_FILE_NAME_PATH = ("output\artifacts\" + $env:ZIP_FILE_NAME + ".sha256")
|
||||
certUtil -hashfile $env:ZIP_FILE_NAME SHA256 | findstr /i /v "SHA256" | findstr /i /v "CertUtil" > $env:CHECKSUM_FILE_NAME_PATH
|
||||
- name: Generate artifacts attestation
|
||||
uses: actions/attest-build-provenance@v1
|
||||
with:
|
||||
subject-path: output/artifacts/*
|
||||
- name: Archive production artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: binary-${{ matrix.os }}-${{ github.sha }}-${{ github.run_id }}
|
||||
path: output/artifacts
|
||||
build-and-push-docker:
|
||||
runs-on: ubuntu-latest
|
||||
# Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job.
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
attestations: write
|
||||
id-token: write
|
||||
outputs:
|
||||
metadata: ${{ steps.push.outputs.metadata }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
# Uses the `docker/login-action` action to log in to the Container registry registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here.
|
||||
- name: Log in to the Container registry
|
||||
# This pinned action came from docker/login-action@v3, releases can be found on https://github.com/docker/login-action/releases
|
||||
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
# This step uses [docker/metadata-action](https://github.com/docker/metadata-action#about) to extract tags and labels that will be applied to the specified image. The `id` "meta" allows the output of this step to be referenced in a subsequent step. The `images` value provides the base name for the tags and labels.
|
||||
- name: Extract metadata (tags, labels) for Docker
|
||||
id: meta
|
||||
# This pinned action came from docker/metadata-action@v5, releases can be found on https://github.com/docker/metadata-action/releases
|
||||
uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
# This step uses the `docker/build-push-action` action to build the image, based on your repository's `Dockerfile`. If the build succeeds, it pushes the image to GitHub Packages.
|
||||
# It uses the `context` parameter to define the build's context as the set of files located in the specified path. For more information, see "[Usage](https://github.com/docker/build-push-action#usage)" in the README of the `docker/build-push-action` repository.
|
||||
# It uses the `tags` and `labels` parameters to tag and label the image with the output from the "meta" step.
|
||||
- name: Build and push Docker image
|
||||
id: push
|
||||
# This pinned action came from docker/build-push-action@v6, releases can be found on https://github.com/docker/build-push-action/releases
|
||||
uses: docker/build-push-action@4f58ea79222b3b9dc2c8bbdd6debcef730109a75
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
|
||||
# This step generates an artifact attestation for the image, which is an unforgeable statement about where and how it was built. It increases supply chain security for people who consume the image. For more information, see "[AUTOTITLE](/actions/security-guides/using-artifact-attestations-to-establish-provenance-for-builds)."
|
||||
- name: Generate artifact attestation
|
||||
uses: actions/attest-build-provenance@v1
|
||||
with:
|
||||
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME}}
|
||||
subject-digest: ${{ steps.push.outputs.digest }}
|
||||
push-to-registry: true
|
||||
create-release:
|
||||
needs: [build-binaries, build-and-push-docker]
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Download build binaries
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: assets/
|
||||
pattern: binary-*
|
||||
- name: Create draft release
|
||||
uses: actions/github-script@v7
|
||||
env:
|
||||
DOCKER_IMAGE_METADATA: '${{ needs.build-and-push-docker.outputs.metadata }}'
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
|
||||
const { DOCKER_IMAGE_METADATA, REGISTRY, IMAGE_NAME } = process.env;
|
||||
|
||||
const dockerMetadata = JSON.parse(DOCKER_IMAGE_METADATA);
|
||||
|
||||
var tagName = '';
|
||||
var dockerVersion = '';
|
||||
if (context.eventName == 'push') {
|
||||
const tagRegex = /(?:refs\/tags\/)?(v\d+\.\d+\.\d+)$/;
|
||||
|
||||
const match = context.ref.match(tagRegex);
|
||||
if (match) {
|
||||
tagName = match[1];
|
||||
dockerVersion = tagName;
|
||||
} else {
|
||||
core.setFailed(`Cannot extract the tag version from ref value '${context.ref}'.`);
|
||||
}
|
||||
|
||||
} else if (context.eventName == 'workflow_dispatch') {
|
||||
tagName = `dev-${context.actor}-${context.sha.substring(0, 7)}-${context.runId}`;
|
||||
dockerVersion = dockerMetadata['containerimage.digest'].replace(':', '-');
|
||||
} else {
|
||||
core.setFailed(`Unhandled triggering event.`);
|
||||
}
|
||||
|
||||
console.log(`Creating draft release for tag ${tagName}...`)
|
||||
|
||||
console.log(`tagName: ${tagName}`);
|
||||
console.log(`context.sha: ${context.sha}`);
|
||||
|
||||
const { data: release } = await github.rest.repos.createRelease({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
tag_name: tagName,
|
||||
target_commitish: context.sha,
|
||||
draft: true,
|
||||
generate_release_notes: true,
|
||||
});
|
||||
|
||||
console.log(`Release ${release.id} created.`);
|
||||
|
||||
let binariesMap = new Map();
|
||||
const emptyBinaryObject = {
|
||||
system: null,
|
||||
architecture: null,
|
||||
binary_archive: null,
|
||||
binary_archive_download_url: null,
|
||||
binary_checksum: null,
|
||||
binary_checksum_download_url: null,
|
||||
attestation: null,
|
||||
};
|
||||
|
||||
const windowsSystem = 'Windows';
|
||||
const macOSSystem = 'macOS';
|
||||
const linuxSystem = 'Linux';
|
||||
|
||||
const amd64Architecture = 'x86_64';
|
||||
const arm64Architecture = 'aarch64';
|
||||
|
||||
binariesMap.set('windows-amd64', Object.assign({}, emptyBinaryObject, {
|
||||
system: windowsSystem,
|
||||
architecture: amd64Architecture,
|
||||
}));
|
||||
binariesMap.set('windows-arm64', Object.assign({}, emptyBinaryObject, {
|
||||
system: windowsSystem,
|
||||
architecture: arm64Architecture,
|
||||
}));
|
||||
binariesMap.set('darwin-amd64', Object.assign({}, emptyBinaryObject, {
|
||||
system: macOSSystem,
|
||||
architecture: amd64Architecture,
|
||||
}));
|
||||
binariesMap.set('darwin-arm64', Object.assign({}, emptyBinaryObject, {
|
||||
system: macOSSystem,
|
||||
architecture: arm64Architecture,
|
||||
}));
|
||||
binariesMap.set('linux-amd64', Object.assign({}, emptyBinaryObject, {
|
||||
system: linuxSystem,
|
||||
architecture: amd64Architecture,
|
||||
}));
|
||||
binariesMap.set('linux-arm64', Object.assign({}, emptyBinaryObject, {
|
||||
system: linuxSystem,
|
||||
architecture: arm64Architecture,
|
||||
}));
|
||||
|
||||
console.log('Uploading release assets...');
|
||||
|
||||
const binaryPlatformRegex = /(\w+)-(\w+)(?=\.(?:zip|tar\.gz)(.sha256)?$)/;
|
||||
|
||||
const archivesGlobber = await glob.create('assets/*/*')
|
||||
for await (const file of archivesGlobber.globGenerator()) {
|
||||
console.log(`Uploading ${path.basename(file)} to the release ${release.id}`);
|
||||
|
||||
const fileName = path.basename(file);
|
||||
const fileContent = fs.readFileSync(file);
|
||||
|
||||
const { data: asset } = await github.rest.repos.uploadReleaseAsset({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
release_id: release.id,
|
||||
name: fileName,
|
||||
data: fileContent,
|
||||
});
|
||||
|
||||
const match = fileName.match(binaryPlatformRegex);
|
||||
if (match) {
|
||||
const platform = `${match[1]}-${match[2]}`;
|
||||
|
||||
const binaryDetails = binariesMap.get(platform);
|
||||
|
||||
if (fileName.endsWith('.sha256')) {
|
||||
binariesMap.set(platform, Object.assign({}, binaryDetails, {
|
||||
binary_checksum: fileName,
|
||||
binary_checksum_download_url: asset.browser_download_url,
|
||||
}));
|
||||
} else {
|
||||
binariesMap.set(platform, Object.assign({}, binaryDetails, {
|
||||
binary_archive: fileName,
|
||||
binary_archive_download_url: asset.browser_download_url,
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const binariesTable = [
|
||||
'| System | Architecture | Binary | Checksum |',
|
||||
'|---------|--------------|--------------------|------------------------|'
|
||||
];
|
||||
|
||||
binariesMap.forEach((details, platform) => {
|
||||
if (
|
||||
details.binary_archive !== null &&
|
||||
details.binary_archive_download_url !== null &&
|
||||
details.binary_checksum !== null &&
|
||||
details.binary_checksum_download_url !== null
|
||||
) {
|
||||
const system = details.system;
|
||||
const architecture = details.architecture;
|
||||
const binaryName = details.binary_archive;
|
||||
const binaryUrl = details.binary_archive_download_url;
|
||||
const checksumName = details.binary_checksum;
|
||||
const checksumUrl = details.binary_checksum_download_url;
|
||||
|
||||
const binaryAssetUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/releases/download/${tagName}/${binaryName}`;
|
||||
const checksumAssetUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/releases/download/${tagName}/${checksumName}`;
|
||||
|
||||
binariesTable.push(`| ${system} | ${architecture} | [${binaryName}](${binaryAssetUrl}) | [sha256](${checksumAssetUrl}) |`);
|
||||
}
|
||||
});
|
||||
|
||||
const binariesTableContent = binariesTable.join('\n');
|
||||
|
||||
const dockerTable = [
|
||||
'| Version | Name | Package |',
|
||||
'|---------|------|---------|'
|
||||
];
|
||||
|
||||
dockerTable.push(`| ${dockerVersion} | \`${REGISTRY}/${IMAGE_NAME}:${dockerVersion}\` | [Github Package](https://github.com/${context.repo.owner}/${context.repo.repo}/pkgs/container/ethstaker-deposit-cli) |`);
|
||||
|
||||
const dockerTableContent = dockerTable.join('\n');
|
||||
|
||||
const { data: workflowRun } = await github.rest.actions.getWorkflowRun({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
run_id: context.runId,
|
||||
});
|
||||
|
||||
let releaseBodyTemplate = fs.readFileSync('.github/release_template.md', { encoding: 'utf8'});
|
||||
|
||||
console.log('Removing comments in release template...');
|
||||
|
||||
releaseBodyTemplate = releaseBodyTemplate.replaceAll(/^\[comment\]:\s*<>\s*\((.*?)\)\s*$/gm, '');
|
||||
releaseBodyTemplate = releaseBodyTemplate.trim();
|
||||
|
||||
let releaseBody = releaseBodyTemplate.replaceAll('`[GENERATED-RELEASE-NOTES]`', release.body);
|
||||
releaseBody = releaseBody.replaceAll('`[BINARIES-TABLE]`', binariesTableContent);
|
||||
releaseBody = releaseBody.replaceAll('`[WORKFLOW-RUN-URL]`', workflowRun.html_url);
|
||||
releaseBody = releaseBody.replaceAll('`[DOCKER-TABLE]`', dockerTableContent);
|
||||
|
||||
console.log('Updating release body with generated content and template...');
|
||||
|
||||
const { data: updatedRelease } = await github.rest.repos.updateRelease({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
release_id: release.id,
|
||||
tag_name: tagName,
|
||||
target_commitish: context.sha,
|
||||
body: releaseBody,
|
||||
});
|
||||
|
||||
console.log(`Release ${updatedRelease.id} updated. Explore it on ${updatedRelease.html_url}`);
|
||||
82
src/vendors/ethstaker-deposit-cli-0.5.0/.github/workflows/comment.yml
vendored
Normal file
82
src/vendors/ethstaker-deposit-cli-0.5.0/.github/workflows/comment.yml
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
# Safely comment on the PR - https://securitylab.github.com/resources/github-actions-preventing-pwn-requests/
|
||||
name: ci-comment
|
||||
run-name: ${{ github.actor }} is adding coverage report comment on PR
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: [ "ci-runner" ]
|
||||
types:
|
||||
- completed
|
||||
|
||||
jobs:
|
||||
completed-coverage:
|
||||
runs-on: ubuntu-latest
|
||||
if: >
|
||||
github.event.workflow_run.event == 'pull_request' &&
|
||||
github.event.workflow_run.conclusion == 'success'
|
||||
outputs:
|
||||
coverage: ${{ steps.output.outputs.coverage }}
|
||||
steps:
|
||||
- name: Get coverage job success
|
||||
uses: actions/github-script@v7
|
||||
env:
|
||||
WORKFLOW_RUN_ID: '${{ github.event.workflow_run.id }}'
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
const { WORKFLOW_RUN_ID } = process.env;
|
||||
|
||||
core.exportVariable('COVERAGE', 'unknown');
|
||||
|
||||
const { data: allJobs } = await github.rest.actions.listJobsForWorkflowRun({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
run_id: WORKFLOW_RUN_ID,
|
||||
});
|
||||
|
||||
allJobs.jobs.forEach((job) => {
|
||||
if (
|
||||
job.name === 'coverage-combine' &&
|
||||
job.status == 'completed' &&
|
||||
job.conclusion == 'success'
|
||||
) {
|
||||
core.exportVariable('COVERAGE', 'completed');
|
||||
}
|
||||
});
|
||||
- name: Output coverage status
|
||||
id: output
|
||||
run: echo "coverage=${COVERAGE}" >> "$GITHUB_OUTPUT"
|
||||
comment:
|
||||
needs: completed-coverage
|
||||
# Runs only if we have a completed coverage job from the ci-runner workflow
|
||||
if: ${{ needs.completed-coverage.outputs.coverage == 'completed' }}
|
||||
permissions:
|
||||
issues: write
|
||||
contents: write
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: results
|
||||
run-id: ${{ github.event.workflow_run.id }}
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Comment on PR
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
var fs = require('fs');
|
||||
const issueNumberPath = './issue_number'
|
||||
if (!fs.existsSync(issueNumberPath)) {
|
||||
console.log("Coverage artifacts were not downloaded, succeeding early");
|
||||
return;
|
||||
}
|
||||
var issueNumber = Number(fs.readFileSync(issueNumberPath));
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issueNumber,
|
||||
body: fs.readFileSync('./coverage-text-report').toString()
|
||||
});
|
||||
28
src/vendors/ethstaker-deposit-cli-0.5.0/.github/workflows/docs.yml
vendored
Normal file
28
src/vendors/ethstaker-deposit-cli-0.5.0/.github/workflows/docs.yml
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
name: docs
|
||||
run-name: ${{ github.actor }} is running docs
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup mdBook
|
||||
# This pinned action came from peaceiris/actions-mdbook@v2, releases can be found on https://github.com/peaceiris/actions-mdbook/releases
|
||||
uses: peaceiris/actions-mdbook@ee69d230fe19748b7abf22df32acaa93833fad08
|
||||
with:
|
||||
mdbook-version: '0.4.40'
|
||||
|
||||
- run: mdbook build ./docs
|
||||
|
||||
- name: Deploy
|
||||
# This pinned action came from peaceiris/actions-gh-pages@v4, releases can be found on https://github.com/peaceiris/actions-gh-pages/releases
|
||||
uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_dir: ./docs/book
|
||||
110
src/vendors/ethstaker-deposit-cli-0.5.0/.github/workflows/runner.yml
vendored
Normal file
110
src/vendors/ethstaker-deposit-cli-0.5.0/.github/workflows/runner.yml
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
name: ci-runner
|
||||
run-name: ${{ github.actor }} is testing and measuring code quality
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
types: [opened, synchronize, labeled, unlabeled]
|
||||
branches: [main]
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.12
|
||||
cache: 'pip'
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -r requirements.txt -r requirements_test.txt
|
||||
- name: Run type checker
|
||||
run: python -m mypy --config-file mypy.ini -p ethstaker_deposit
|
||||
- name: Run linter
|
||||
run: flake8 --config=flake8.ini ./ethstaker_deposit ./tests
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 'latest'
|
||||
- name: Install jsonlint
|
||||
run: npm install -g @prantlf/jsonlint@16.0.0
|
||||
- name: Validate JSON files
|
||||
run: |
|
||||
find ./ethstaker_deposit/intl -name "*.json" -exec jsonlint --no-duplicate-keys --quiet --compact {} \;
|
||||
ci-runner:
|
||||
needs: lint
|
||||
if: |
|
||||
contains(github.event.pull_request.labels.*.name, 'run-tests') ||
|
||||
github.event_name == 'push'
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, ubuntu-24.04-arm64, macos-13, macos-latest, windows-latest]
|
||||
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
cache: 'pip'
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -r requirements.txt -r requirements_test.txt
|
||||
- name: Run tests
|
||||
run: |
|
||||
coverage run --data-file=.coverage.${{ matrix.os }}.${{ matrix.python-version }} -m pytest tests
|
||||
- name: Upload coverage data
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: coverage-${{ matrix.os }}-${{ matrix.python-version }}
|
||||
path: .coverage.${{ matrix.os }}.${{ matrix.python-version }}
|
||||
retention-days: 1
|
||||
if-no-files-found: error
|
||||
include-hidden-files: true
|
||||
coverage-combine:
|
||||
needs: ci-runner
|
||||
if: github.event_name == 'pull_request'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.12
|
||||
cache: 'pip'
|
||||
- name: Download coverage data
|
||||
uses: actions/download-artifact@v4
|
||||
- name: Merge coverage data
|
||||
id: merge
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -r requirements.txt -r requirements_test.txt
|
||||
coverage combine coverage*
|
||||
coverage html
|
||||
- name: Upload final coverage html report
|
||||
uses: actions/upload-artifact@v4
|
||||
id: upload-html
|
||||
with:
|
||||
name: coverage-html-report
|
||||
path: htmlcov
|
||||
- name: Generate text report
|
||||
run: |
|
||||
mkdir results
|
||||
{
|
||||
echo "Test Coverage: [Download HTML Report](${{ steps.upload-html.outputs.artifact-url }})" ;
|
||||
echo ;
|
||||
echo \`\`\` ;
|
||||
coverage report ;
|
||||
echo \`\`\` ;
|
||||
} >> results/coverage-text-report
|
||||
echo ${{ github.event.number }} > results/issue_number
|
||||
- name: Upload final coverage text report
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: results
|
||||
path: results/
|
||||
@@ -1,10 +1,15 @@
|
||||
validator_keys
|
||||
bls_to_execution_changes
|
||||
bls_to_execution_changes_keystore
|
||||
exit_transactions
|
||||
partial_deposits
|
||||
validator_keys
|
||||
|
||||
# Python testing & linting:
|
||||
build/
|
||||
docs/book
|
||||
dist/
|
||||
venv/
|
||||
.venv/
|
||||
*.pytest_cache
|
||||
*.hypothesis
|
||||
*.mypy_cache
|
||||
@@ -12,3 +17,4 @@ venv/
|
||||
*.egg
|
||||
__pycache__
|
||||
.DS_Store
|
||||
.coverage
|
||||
25
src/vendors/ethstaker-deposit-cli-0.5.0/.pre-commit-config.yaml
vendored
Normal file
25
src/vendors/ethstaker-deposit-cli-0.5.0/.pre-commit-config.yaml
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
repos:
|
||||
- repo: https://github.com/pycqa/flake8
|
||||
rev: '7.1.1'
|
||||
hooks:
|
||||
- id: flake8
|
||||
files: ^(ethstaker_deposit|tests)/
|
||||
args: [--config, flake8.ini]
|
||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||
rev: 'v1.11.2'
|
||||
hooks:
|
||||
- id: mypy
|
||||
additional_dependencies:
|
||||
- click==8.1.7
|
||||
- eth-typing==5.0.0
|
||||
- eth-utils==5.0.0
|
||||
- pycryptodome==3.20.0
|
||||
- py-ecc==7.0.1
|
||||
- ssz==0.5.0
|
||||
files: ^ethstaker_deposit/
|
||||
args: [--config-file, mypy.ini]
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: 'v4.6.0'
|
||||
hooks:
|
||||
- id: check-json
|
||||
files: ^ethstaker_deposit/intl
|
||||
12
src/vendors/ethstaker-deposit-cli-0.5.0/Dockerfile
vendored
Normal file
12
src/vendors/ethstaker-deposit-cli-0.5.0/Dockerfile
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
# This image is from python:3.12.7-slim-bookworm (https://hub.docker.com/_/python)
|
||||
FROM python@sha256:032c52613401895aa3d418a4c563d2d05f993bc3ecc065c8f4e2280978acd249
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY requirements.txt ./
|
||||
|
||||
COPY ethstaker_deposit ./ethstaker_deposit
|
||||
|
||||
RUN pip3 install -r requirements.txt
|
||||
|
||||
ENTRYPOINT [ "python3", "-m", "ethstaker_deposit" ]
|
||||
@@ -1,7 +1,7 @@
|
||||
VENV_NAME?=venv
|
||||
VENV_ACTIVATE=. $(VENV_NAME)/bin/activate
|
||||
PYTHON=${VENV_NAME}/bin/python3.8
|
||||
DOCKER_IMAGE="ethereum/staking-deposit-cli:latest"
|
||||
PYTHON=${VENV_NAME}/bin/python3.12
|
||||
DOCKER_IMAGE="eth-educators/ethstaker-deposit-cli:latest"
|
||||
|
||||
help:
|
||||
@echo "clean - remove build and Python file artifacts"
|
||||
@@ -24,24 +24,22 @@ clean:
|
||||
|
||||
$(VENV_NAME)/bin/activate: requirements.txt
|
||||
@test -d $(VENV_NAME) || python3 -m venv --clear $(VENV_NAME)
|
||||
${VENV_NAME}/bin/python setup.py install
|
||||
${VENV_NAME}/bin/python -m pip install -r requirements.txt
|
||||
${VENV_NAME}/bin/python -m pip install -r requirements_test.txt
|
||||
${VENV_NAME}/bin/python -m pip install -r requirements.txt -r requirements_test.txt
|
||||
@touch $(VENV_NAME)/bin/activate
|
||||
|
||||
venv_build: $(VENV_NAME)/bin/activate
|
||||
|
||||
venv_build_test: venv_build
|
||||
${VENV_NAME}/bin/python -m pip install -r requirements_test.txt
|
||||
${VENV_NAME}/bin/python -m pip install -r requirements.txt -r requirements_test.txt
|
||||
|
||||
venv_test: venv_build_test
|
||||
$(VENV_ACTIVATE) && python -m pytest ./tests
|
||||
|
||||
venv_lint: venv_build_test
|
||||
$(VENV_ACTIVATE) && flake8 --config=flake8.ini ./staking_deposit ./tests && mypy --config-file mypy.ini -p staking_deposit
|
||||
$(VENV_ACTIVATE) && flake8 --config=flake8.ini ./ethstaker_deposit ./tests && mypy --config-file mypy.ini -p ethstaker_deposit
|
||||
|
||||
venv_deposit: venv_build
|
||||
$(VENV_ACTIVATE) && python ./staking_deposit/deposit.py $(filter-out $@,$(MAKECMDGOALS))
|
||||
$(VENV_ACTIVATE) && python -m ethstaker_deposit $(filter-out $@,$(MAKECMDGOALS))
|
||||
|
||||
build_macos: venv_build
|
||||
${VENV_NAME}/bin/python -m pip install -r ./build_configs/macos/requirements.txt
|
||||
34
src/vendors/ethstaker-deposit-cli-0.5.0/README.md
vendored
Normal file
34
src/vendors/ethstaker-deposit-cli-0.5.0/README.md
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
# ethstaker-deposit-cli docs
|
||||
|
||||
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
||||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
||||
## Documentation
|
||||
- [Introduction](https://deposit-cli.ethstaker.cc/landing.html)
|
||||
- [Quick Setup](https://deposit-cli.ethstaker.cc/quick_setup.html)
|
||||
|
||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||
|
||||
## Introduction
|
||||
|
||||
`ethstaker-deposit-cli` is a tool for creating [EIP-2335 format](https://eips.ethereum.org/EIPS/eip-2335) BLS12-381 keystores and a corresponding `deposit_data*.json` file for [Ethereum Staking Launchpad](https://github.com/ethereum/staking-launchpad). One can also provide a keystore file to generate a `signed_exit_transaction*.json` file to be broadcast at a later date to exit a validator.
|
||||
|
||||
- **Warning: Please generate your keystores on your own safe, completely offline device.**
|
||||
- **Warning: Please backup your mnemonic, keystores, and password securely.**
|
||||
|
||||
Please read [Launchpad Validator FAQs](https://launchpad.ethereum.org/faq#keys) before generating the keys.
|
||||
|
||||
You can find the audit report by Trail of Bits of the original staking-deposit-cli [here](https://github.com/trailofbits/publications/blob/master/reviews/ETH2DepositCLI.pdf). The audit of the updated ethstaker-deposit-cli is forthcoming.
|
||||
|
||||
## Canonical Deposit Contract and Launchpad
|
||||
|
||||
Ethstaker confirms the canonical Ethereum staking deposit contract addresses and launchpad URLs.
|
||||
Please be sure that your ETH is deposited only to this deposit contract address, depending on chain.
|
||||
|
||||
Depositing to the wrong address **will** lose you your ETH.
|
||||
|
||||
- Ethereum mainnet
|
||||
- Deposit address: [0x00000000219ab540356cBB839Cbe05303d7705Fa](https://etherscan.io/address/0x00000000219ab540356cBB839Cbe05303d7705Fa)
|
||||
- [Launchpad](https://launchpad.ethereum.org/)
|
||||
- Ethereum Holešky (Holešovice) testnet
|
||||
- Deposit address: [0x4242424242424242424242424242424242424242](https://holesky.etherscan.io/address/0x4242424242424242424242424242424242424242)
|
||||
- [Launchpad](https://holesky.launchpad.ethereum.org/)
|
||||
13
src/vendors/ethstaker-deposit-cli-0.5.0/SECURITY.md
vendored
Normal file
13
src/vendors/ethstaker-deposit-cli-0.5.0/SECURITY.md
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
We are still in active development. We will support the latest release with security updates as we find them.
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| 0.x.x | :white_check_mark: |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Private vulnerability reporting is enabled on this repository. Feel free to report any security vulnerability through [the GitHub *Report a vulnerability* feature](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities/privately-reporting-a-security-vulnerability#privately-reporting-a-security-vulnerability).
|
||||
6
src/vendors/ethstaker-deposit-cli-0.5.0/build_configs/common/requirements.in
vendored
Normal file
6
src/vendors/ethstaker-deposit-cli-0.5.0/build_configs/common/requirements.in
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
# common requirements.in
|
||||
cffi
|
||||
importlib-metadata
|
||||
macholib
|
||||
pyinstaller
|
||||
setuptools
|
||||
116
src/vendors/ethstaker-deposit-cli-0.5.0/build_configs/common/requirements.txt
vendored
Normal file
116
src/vendors/ethstaker-deposit-cli-0.5.0/build_configs/common/requirements.txt
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
# Install the requirements for the program
|
||||
-r ../../requirements.txt
|
||||
|
||||
#
|
||||
# This file is autogenerated by pip-compile with Python 3.12
|
||||
# by the following command:
|
||||
#
|
||||
# pip-compile --allow-unsafe --generate-hashes --no-annotate --output-file=build_configs/common/requirements.txt build_configs/common/requirements.in
|
||||
#
|
||||
altgraph==0.17.4 \
|
||||
--hash=sha256:1b5afbb98f6c4dcadb2e2ae6ab9fa994bbb8c1d75f4fa96d340f9437ae454406 \
|
||||
--hash=sha256:642743b4750de17e655e6711601b077bc6598dbfa3ba5fa2b2a35ce12b508dff
|
||||
cffi==1.17.0 \
|
||||
--hash=sha256:011aff3524d578a9412c8b3cfaa50f2c0bd78e03eb7af7aa5e0df59b158efb2f \
|
||||
--hash=sha256:0a048d4f6630113e54bb4b77e315e1ba32a5a31512c31a273807d0027a7e69ab \
|
||||
--hash=sha256:0bb15e7acf8ab35ca8b24b90af52c8b391690ef5c4aec3d31f38f0d37d2cc499 \
|
||||
--hash=sha256:0d46ee4764b88b91f16661a8befc6bfb24806d885e27436fdc292ed7e6f6d058 \
|
||||
--hash=sha256:0e60821d312f99d3e1569202518dddf10ae547e799d75aef3bca3a2d9e8ee693 \
|
||||
--hash=sha256:0fdacad9e0d9fc23e519efd5ea24a70348305e8d7d85ecbb1a5fa66dc834e7fb \
|
||||
--hash=sha256:14b9cbc8f7ac98a739558eb86fabc283d4d564dafed50216e7f7ee62d0d25377 \
|
||||
--hash=sha256:17c6d6d3260c7f2d94f657e6872591fe8733872a86ed1345bda872cfc8c74885 \
|
||||
--hash=sha256:1a2ddbac59dc3716bc79f27906c010406155031a1c801410f1bafff17ea304d2 \
|
||||
--hash=sha256:2404f3de742f47cb62d023f0ba7c5a916c9c653d5b368cc966382ae4e57da401 \
|
||||
--hash=sha256:24658baf6224d8f280e827f0a50c46ad819ec8ba380a42448e24459daf809cf4 \
|
||||
--hash=sha256:24aa705a5f5bd3a8bcfa4d123f03413de5d86e497435693b638cbffb7d5d8a1b \
|
||||
--hash=sha256:2770bb0d5e3cc0e31e7318db06efcbcdb7b31bcb1a70086d3177692a02256f59 \
|
||||
--hash=sha256:331ad15c39c9fe9186ceaf87203a9ecf5ae0ba2538c9e898e3a6967e8ad3db6f \
|
||||
--hash=sha256:3aa9d43b02a0c681f0bfbc12d476d47b2b2b6a3f9287f11ee42989a268a1833c \
|
||||
--hash=sha256:41f4915e09218744d8bae14759f983e466ab69b178de38066f7579892ff2a555 \
|
||||
--hash=sha256:4304d4416ff032ed50ad6bb87416d802e67139e31c0bde4628f36a47a3164bfa \
|
||||
--hash=sha256:435a22d00ec7d7ea533db494da8581b05977f9c37338c80bc86314bec2619424 \
|
||||
--hash=sha256:45f7cd36186db767d803b1473b3c659d57a23b5fa491ad83c6d40f2af58e4dbb \
|
||||
--hash=sha256:48b389b1fd5144603d61d752afd7167dfd205973a43151ae5045b35793232aa2 \
|
||||
--hash=sha256:4e67d26532bfd8b7f7c05d5a766d6f437b362c1bf203a3a5ce3593a645e870b8 \
|
||||
--hash=sha256:516a405f174fd3b88829eabfe4bb296ac602d6a0f68e0d64d5ac9456194a5b7e \
|
||||
--hash=sha256:5ba5c243f4004c750836f81606a9fcb7841f8874ad8f3bf204ff5e56332b72b9 \
|
||||
--hash=sha256:5bdc0f1f610d067c70aa3737ed06e2726fd9d6f7bfee4a351f4c40b6831f4e82 \
|
||||
--hash=sha256:6107e445faf057c118d5050560695e46d272e5301feffda3c41849641222a828 \
|
||||
--hash=sha256:6327b572f5770293fc062a7ec04160e89741e8552bf1c358d1a23eba68166759 \
|
||||
--hash=sha256:669b29a9eca6146465cc574659058ed949748f0809a2582d1f1a324eb91054dc \
|
||||
--hash=sha256:6ce01337d23884b21c03869d2f68c5523d43174d4fc405490eb0091057943118 \
|
||||
--hash=sha256:6d872186c1617d143969defeadac5a904e6e374183e07977eedef9c07c8953bf \
|
||||
--hash=sha256:6f76a90c345796c01d85e6332e81cab6d70de83b829cf1d9762d0a3da59c7932 \
|
||||
--hash=sha256:70d2aa9fb00cf52034feac4b913181a6e10356019b18ef89bc7c12a283bf5f5a \
|
||||
--hash=sha256:7cbc78dc018596315d4e7841c8c3a7ae31cc4d638c9b627f87d52e8abaaf2d29 \
|
||||
--hash=sha256:856bf0924d24e7f93b8aee12a3a1095c34085600aa805693fb7f5d1962393206 \
|
||||
--hash=sha256:8a98748ed1a1df4ee1d6f927e151ed6c1a09d5ec21684de879c7ea6aa96f58f2 \
|
||||
--hash=sha256:93a7350f6706b31f457c1457d3a3259ff9071a66f312ae64dc024f049055f72c \
|
||||
--hash=sha256:964823b2fc77b55355999ade496c54dde161c621cb1f6eac61dc30ed1b63cd4c \
|
||||
--hash=sha256:a003ac9edc22d99ae1286b0875c460351f4e101f8c9d9d2576e78d7e048f64e0 \
|
||||
--hash=sha256:a0ce71725cacc9ebf839630772b07eeec220cbb5f03be1399e0457a1464f8e1a \
|
||||
--hash=sha256:a47eef975d2b8b721775a0fa286f50eab535b9d56c70a6e62842134cf7841195 \
|
||||
--hash=sha256:a8b5b9712783415695663bd463990e2f00c6750562e6ad1d28e072a611c5f2a6 \
|
||||
--hash=sha256:a9015f5b8af1bb6837a3fcb0cdf3b874fe3385ff6274e8b7925d81ccaec3c5c9 \
|
||||
--hash=sha256:aec510255ce690d240f7cb23d7114f6b351c733a74c279a84def763660a2c3bc \
|
||||
--hash=sha256:b00e7bcd71caa0282cbe3c90966f738e2db91e64092a877c3ff7f19a1628fdcb \
|
||||
--hash=sha256:b50aaac7d05c2c26dfd50c3321199f019ba76bb650e346a6ef3616306eed67b0 \
|
||||
--hash=sha256:b7b6ea9e36d32582cda3465f54c4b454f62f23cb083ebc7a94e2ca6ef011c3a7 \
|
||||
--hash=sha256:bb9333f58fc3a2296fb1d54576138d4cf5d496a2cc118422bd77835e6ae0b9cb \
|
||||
--hash=sha256:c1c13185b90bbd3f8b5963cd8ce7ad4ff441924c31e23c975cb150e27c2bf67a \
|
||||
--hash=sha256:c3b8bd3133cd50f6b637bb4322822c94c5ce4bf0d724ed5ae70afce62187c492 \
|
||||
--hash=sha256:c5d97162c196ce54af6700949ddf9409e9833ef1003b4741c2b39ef46f1d9720 \
|
||||
--hash=sha256:c815270206f983309915a6844fe994b2fa47e5d05c4c4cef267c3b30e34dbe42 \
|
||||
--hash=sha256:cab2eba3830bf4f6d91e2d6718e0e1c14a2f5ad1af68a89d24ace0c6b17cced7 \
|
||||
--hash=sha256:d1df34588123fcc88c872f5acb6f74ae59e9d182a2707097f9e28275ec26a12d \
|
||||
--hash=sha256:d6bdcd415ba87846fd317bee0774e412e8792832e7805938987e4ede1d13046d \
|
||||
--hash=sha256:db9a30ec064129d605d0f1aedc93e00894b9334ec74ba9c6bdd08147434b33eb \
|
||||
--hash=sha256:dbc183e7bef690c9abe5ea67b7b60fdbca81aa8da43468287dae7b5c046107d4 \
|
||||
--hash=sha256:dca802c8db0720ce1c49cce1149ff7b06e91ba15fa84b1d59144fef1a1bc7ac2 \
|
||||
--hash=sha256:dec6b307ce928e8e112a6bb9921a1cb00a0e14979bf28b98e084a4b8a742bd9b \
|
||||
--hash=sha256:df8bb0010fdd0a743b7542589223a2816bdde4d94bb5ad67884348fa2c1c67e8 \
|
||||
--hash=sha256:e4094c7b464cf0a858e75cd14b03509e84789abf7b79f8537e6a72152109c76e \
|
||||
--hash=sha256:e4760a68cab57bfaa628938e9c2971137e05ce48e762a9cb53b76c9b569f1204 \
|
||||
--hash=sha256:eb09b82377233b902d4c3fbeeb7ad731cdab579c6c6fda1f763cd779139e47c3 \
|
||||
--hash=sha256:eb862356ee9391dc5a0b3cbc00f416b48c1b9a52d252d898e5b7696a5f9fe150 \
|
||||
--hash=sha256:ef9528915df81b8f4c7612b19b8628214c65c9b7f74db2e34a646a0a2a0da2d4 \
|
||||
--hash=sha256:f3157624b7558b914cb039fd1af735e5e8049a87c817cc215109ad1c8779df76 \
|
||||
--hash=sha256:f3e0992f23bbb0be00a921eae5363329253c3b86287db27092461c887b791e5e \
|
||||
--hash=sha256:f9338cc05451f1942d0d8203ec2c346c830f8e86469903d5126c1f0a13a2bcbb \
|
||||
--hash=sha256:ffef8fd58a36fb5f1196919638f73dd3ae0db1a878982b27a9a5a176ede4ba91
|
||||
importlib-metadata==8.4.0 \
|
||||
--hash=sha256:66f342cc6ac9818fc6ff340576acd24d65ba0b3efabb2b4ac08b598965a4a2f1 \
|
||||
--hash=sha256:9a547d3bc3608b025f93d403fdd1aae741c24fbb8314df4b155675742ce303c5
|
||||
macholib==1.16.3 \
|
||||
--hash=sha256:07ae9e15e8e4cd9a788013d81f5908b3609aa76f9b1421bae9c4d7606ec86a30 \
|
||||
--hash=sha256:0e315d7583d38b8c77e815b1ecbdbf504a8258d8b3e17b61165c6feb60d18f2c
|
||||
packaging==24.1 \
|
||||
--hash=sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002 \
|
||||
--hash=sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124
|
||||
pycparser==2.22 \
|
||||
--hash=sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6 \
|
||||
--hash=sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc
|
||||
pyinstaller==6.10.0 \
|
||||
--hash=sha256:143840f8056ff7b910bf8f16f6cd92cc10a6c2680bb76d0a25d558d543d21270 \
|
||||
--hash=sha256:28eca3817f176fdc19747e1afcf434f13bb9f17a644f611be2c5a61b1f498ed7 \
|
||||
--hash=sha256:308e0a8670c9c9ac0cebbf1bbb492e71b6675606f2ec78bc4adfc830d209e087 \
|
||||
--hash=sha256:3398a98fa17d47ccb31f8779ecbdacec025f7adb2f22757a54b706ac8b4fe906 \
|
||||
--hash=sha256:46d75359668993ddd98630a3669dc5249f3c446e35239b43bc7f4155bc574748 \
|
||||
--hash=sha256:6cf876d7d93b8b4f28d1ad57fa24645cf43119c79e985dd5e5f7a801245e6f53 \
|
||||
--hash=sha256:703e041718987e46ba0568a2c71ecf2459fddef57cf9edf3efeed4a53e3dae3f \
|
||||
--hash=sha256:95b55966e563e8b8f31a43882aea10169e9a11fdf38e626d86a2907b640c0701 \
|
||||
--hash=sha256:b7c90c91921b3749083115b28f30f40abf2bb481ceff196d2b2ce0eaa2b3d429 \
|
||||
--hash=sha256:d60fb22859e11483af735aec115fdde09467cdbb29edd9844839f2c920b748c0 \
|
||||
--hash=sha256:db05e3f2f10f9f78c56f1fb163d9cb453433429fe4281218ebaf1ebfd39ba942 \
|
||||
--hash=sha256:e9989f354ae4ed8a3bec7bdb37ae0d170751d6520e500f049c7cd0632d31d5c3
|
||||
pyinstaller-hooks-contrib==2024.8 \
|
||||
--hash=sha256:0057fe9a5c398d3f580e73e58793a1d4a8315ca91c3df01efea1c14ed557825a \
|
||||
--hash=sha256:29b68d878ab739e967055b56a93eb9b58e529d5b054fbab7a2f2bacf80cef3e2
|
||||
zipp==3.20.1 \
|
||||
--hash=sha256:9960cd8967c8f85a56f920d5d507274e74f9ff813a0ab8889a5b5be2daf44064 \
|
||||
--hash=sha256:c22b14cc4763c5a5b04134207736c107db42e9d3ef2d9779d465f5f1bcba572b
|
||||
|
||||
# The following packages are considered to be unsafe in a requirements file:
|
||||
setuptools==74.0.0 \
|
||||
--hash=sha256:0274581a0037b638b9fc1c6883cc71c0210865aaa76073f7882376b641b84e8f \
|
||||
--hash=sha256:a85e96b8be2b906f3e3e789adec6a9323abf79758ecfa3065bd740d81158b11e
|
||||
@@ -1,14 +1,19 @@
|
||||
# -*- mode: python ; coding: utf-8 -*-
|
||||
from PyInstaller.utils.hooks import copy_metadata
|
||||
|
||||
datas = [
|
||||
('../../ethstaker_deposit/key_handling/key_derivation/word_lists/*.txt', './ethstaker_deposit/key_handling/key_derivation/word_lists/'),
|
||||
('../../ethstaker_deposit/intl', './ethstaker_deposit/intl'),
|
||||
]
|
||||
datas += copy_metadata('py_ecc')
|
||||
datas += copy_metadata('ssz')
|
||||
|
||||
block_cipher = None
|
||||
|
||||
|
||||
a = Analysis(['../../staking_deposit/deposit.py'],
|
||||
a = Analysis(['../../ethstaker_deposit/deposit.py'],
|
||||
binaries=[],
|
||||
datas=[
|
||||
('../../staking_deposit/key_handling/key_derivation/word_lists/*.txt', './staking_deposit/key_handling/key_derivation/word_lists/'),
|
||||
('../../staking_deposit/intl', './staking_deposit/intl'),
|
||||
],
|
||||
datas=datas,
|
||||
hiddenimports=[],
|
||||
hookspath=[],
|
||||
runtime_hooks=[],
|
||||
1
src/vendors/ethstaker-deposit-cli-0.5.0/build_configs/linux/requirements.txt
vendored
Normal file
1
src/vendors/ethstaker-deposit-cli-0.5.0/build_configs/linux/requirements.txt
vendored
Normal file
@@ -0,0 +1 @@
|
||||
-r ../common/requirements.txt
|
||||
@@ -1,35 +1,40 @@
|
||||
# -*- mode: python ; coding: utf-8 -*-
|
||||
|
||||
block_cipher = None
|
||||
|
||||
|
||||
a = Analysis(['..\\..\\staking_deposit\\deposit.py'],
|
||||
binaries=[],
|
||||
datas=[
|
||||
('..\\..\\staking_deposit\\key_handling\\key_derivation\\word_lists\\*.txt', '.\\staking_deposit\\key_handling\\key_derivation\\word_lists'),
|
||||
('..\\..\\staking_deposit\\intl', '.\\staking_deposit\\intl'),
|
||||
],
|
||||
hiddenimports=[],
|
||||
hookspath=[],
|
||||
runtime_hooks=[],
|
||||
excludes=['FixTk', 'tcl', 'tk', '_tkinter', 'tkinter', 'Tkinter'],
|
||||
win_no_prefer_redirects=False,
|
||||
win_private_assemblies=False,
|
||||
cipher=block_cipher,
|
||||
noarchive=False)
|
||||
pyz = PYZ(a.pure, a.zipped_data,
|
||||
cipher=block_cipher)
|
||||
exe = EXE(pyz,
|
||||
a.scripts,
|
||||
a.binaries,
|
||||
a.zipfiles,
|
||||
a.datas,
|
||||
[],
|
||||
name='deposit',
|
||||
debug=False,
|
||||
bootloader_ignore_signals=False,
|
||||
strip=False,
|
||||
upx=True,
|
||||
upx_exclude=[],
|
||||
runtime_tmpdir=None,
|
||||
console=True )
|
||||
# -*- mode: python ; coding: utf-8 -*-
|
||||
from PyInstaller.utils.hooks import copy_metadata
|
||||
|
||||
datas = [
|
||||
('../../ethstaker_deposit/key_handling/key_derivation/word_lists/*.txt', './ethstaker_deposit/key_handling/key_derivation/word_lists/'),
|
||||
('../../ethstaker_deposit/intl', './ethstaker_deposit/intl'),
|
||||
]
|
||||
datas += copy_metadata('py_ecc')
|
||||
datas += copy_metadata('ssz')
|
||||
|
||||
block_cipher = None
|
||||
|
||||
|
||||
a = Analysis(['../../ethstaker_deposit/deposit.py'],
|
||||
binaries=[],
|
||||
datas=datas,
|
||||
hiddenimports=[],
|
||||
hookspath=[],
|
||||
runtime_hooks=[],
|
||||
excludes=['FixTk', 'tcl', 'tk', '_tkinter', 'tkinter', 'Tkinter'],
|
||||
win_no_prefer_redirects=False,
|
||||
win_private_assemblies=False,
|
||||
cipher=block_cipher,
|
||||
noarchive=False)
|
||||
pyz = PYZ(a.pure, a.zipped_data,
|
||||
cipher=block_cipher)
|
||||
exe = EXE(pyz,
|
||||
a.scripts,
|
||||
a.binaries,
|
||||
a.zipfiles,
|
||||
a.datas,
|
||||
[],
|
||||
name='deposit',
|
||||
debug=False,
|
||||
bootloader_ignore_signals=False,
|
||||
strip=False,
|
||||
upx=True,
|
||||
upx_exclude=[],
|
||||
runtime_tmpdir=None,
|
||||
console=True )
|
||||
1
src/vendors/ethstaker-deposit-cli-0.5.0/build_configs/macos/requirements.txt
vendored
Normal file
1
src/vendors/ethstaker-deposit-cli-0.5.0/build_configs/macos/requirements.txt
vendored
Normal file
@@ -0,0 +1 @@
|
||||
-r ../common/requirements.txt
|
||||
@@ -1,35 +1,40 @@
|
||||
# -*- mode: python ; coding: utf-8 -*-
|
||||
|
||||
block_cipher = None
|
||||
|
||||
|
||||
a = Analysis(['../../staking_deposit/deposit.py'],
|
||||
binaries=None,
|
||||
datas=[
|
||||
('../../staking_deposit/key_handling/key_derivation/word_lists/*.txt', './staking_deposit/key_handling/key_derivation/word_lists/'),
|
||||
('../../staking_deposit/intl', './staking_deposit/intl'),
|
||||
],
|
||||
hiddenimports=[],
|
||||
hookspath=[],
|
||||
runtime_hooks=[],
|
||||
excludes=['FixTk', 'tcl', 'tk', '_tkinter', 'tkinter', 'Tkinter'],
|
||||
win_no_prefer_redirects=False,
|
||||
win_private_assemblies=False,
|
||||
cipher=block_cipher,
|
||||
noarchive=False)
|
||||
pyz = PYZ(a.pure, a.zipped_data,
|
||||
cipher=block_cipher)
|
||||
exe = EXE(pyz,
|
||||
a.scripts,
|
||||
a.binaries,
|
||||
a.zipfiles,
|
||||
a.datas,
|
||||
[],
|
||||
name='deposit',
|
||||
debug=False,
|
||||
bootloader_ignore_signals=False,
|
||||
strip=False,
|
||||
upx=True,
|
||||
upx_exclude=[],
|
||||
runtime_tmpdir=None,
|
||||
console=True )
|
||||
# -*- mode: python ; coding: utf-8 -*-
|
||||
from PyInstaller.utils.hooks import copy_metadata
|
||||
|
||||
datas = [
|
||||
('..\\..\\ethstaker_deposit\\key_handling\\key_derivation\\word_lists\\*.txt', '.\\ethstaker_deposit\\key_handling\\key_derivation\\word_lists'),
|
||||
('..\\..\\ethstaker_deposit\\intl', '.\\ethstaker_deposit\\intl'),
|
||||
]
|
||||
datas += copy_metadata('py_ecc')
|
||||
datas += copy_metadata('ssz')
|
||||
|
||||
block_cipher = None
|
||||
|
||||
|
||||
a = Analysis(['..\\..\\ethstaker_deposit\\deposit.py'],
|
||||
binaries=[],
|
||||
datas=datas,
|
||||
hiddenimports=[],
|
||||
hookspath=[],
|
||||
runtime_hooks=[],
|
||||
excludes=['FixTk', 'tcl', 'tk', '_tkinter', 'tkinter', 'Tkinter'],
|
||||
win_no_prefer_redirects=False,
|
||||
win_private_assemblies=False,
|
||||
cipher=block_cipher,
|
||||
noarchive=False)
|
||||
pyz = PYZ(a.pure, a.zipped_data,
|
||||
cipher=block_cipher)
|
||||
exe = EXE(pyz,
|
||||
a.scripts,
|
||||
a.binaries,
|
||||
a.zipfiles,
|
||||
a.datas,
|
||||
[],
|
||||
name='deposit',
|
||||
debug=False,
|
||||
bootloader_ignore_signals=False,
|
||||
strip=False,
|
||||
upx=True,
|
||||
upx_exclude=[],
|
||||
runtime_tmpdir=None,
|
||||
console=True )
|
||||
7
src/vendors/ethstaker-deposit-cli-0.5.0/build_configs/windows/requirements.in
vendored
Normal file
7
src/vendors/ethstaker-deposit-cli-0.5.0/build_configs/windows/requirements.in
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
# Windows binary build requirements
|
||||
# Only use this to get new hashes, don't upgrade requirements.txt directly with pip-compile:
|
||||
# It can't find pywin32
|
||||
future
|
||||
pefile
|
||||
pywin32-ctypes
|
||||
#pywin32 is not found by pip-compile
|
||||
27
src/vendors/ethstaker-deposit-cli-0.5.0/build_configs/windows/requirements.txt
vendored
Normal file
27
src/vendors/ethstaker-deposit-cli-0.5.0/build_configs/windows/requirements.txt
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
-r ../common/requirements.txt
|
||||
|
||||
# Build tools for binary distribution
|
||||
future==1.0.0 \
|
||||
--hash=sha256:929292d34f5872e70396626ef385ec22355a1fae8ad29e1a734c3e43f9fbc216 \
|
||||
--hash=sha256:bd2968309307861edae1458a4f8a4f3598c03be43b97521076aebf5d94c07b05
|
||||
pefile==2024.8.26 \
|
||||
--hash=sha256:3ff6c5d8b43e8c37bb6e6dd5085658d658a7a0bdcd20b6a07b1fcfc1c4e9d632 \
|
||||
--hash=sha256:76f8b485dcd3b1bb8166f1128d395fa3d87af26360c2358fb75b80019b957c6f
|
||||
pywin32==306 \
|
||||
--hash=sha256:06d3420a5155ba65f0b72f2699b5bacf3109f36acbe8923765c22938a69dfc8d \
|
||||
--hash=sha256:1c73ea9a0d2283d889001998059f5eaaba3b6238f767c9cf2833b13e6a685f65 \
|
||||
--hash=sha256:37257794c1ad39ee9be652da0462dc2e394c8159dfd913a8a4e8eb6fd346da0e \
|
||||
--hash=sha256:383229d515657f4e3ed1343da8be101000562bf514591ff383ae940cad65458b \
|
||||
--hash=sha256:39b61c15272833b5c329a2989999dcae836b1eed650252ab1b7bfbe1d59f30f4 \
|
||||
--hash=sha256:5821ec52f6d321aa59e2db7e0a35b997de60c201943557d108af9d4ae1ec7040 \
|
||||
--hash=sha256:70dba0c913d19f942a2db25217d9a1b726c278f483a919f1abfed79c9cf64d3a \
|
||||
--hash=sha256:72c5f621542d7bdd4fdb716227be0dd3f8565c11b280be6315b06ace35487d36 \
|
||||
--hash=sha256:84f4471dbca1887ea3803d8848a1616429ac94a4a8d05f4bc9c5dcfd42ca99c8 \
|
||||
--hash=sha256:a7639f51c184c0272e93f244eb24dafca9b1855707d94c192d4a0b4c01e1100e \
|
||||
--hash=sha256:e25fd5b485b55ac9c057f67d94bc203f3f6595078d1fb3b458c9c28b7153a802 \
|
||||
--hash=sha256:e4c092e2589b5cf0d365849e73e02c391c1349958c5ac3e9d5ccb9a28e017b3a \
|
||||
--hash=sha256:e65028133d15b64d2ed8f06dd9fbc268352478d4f9289e69c190ecd6818b6407 \
|
||||
--hash=sha256:e8ac1ae3601bee6ca9f7cb4b5363bf1c0badb935ef243c4733ff9a393b1690c0
|
||||
pywin32-ctypes==0.2.3 \
|
||||
--hash=sha256:8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8 \
|
||||
--hash=sha256:d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755
|
||||
@@ -5,25 +5,23 @@ if [[ "$OSTYPE" == "linux"* ]] || [[ "$OSTYPE" == "linux-android"* ]] || [[ "$OS
|
||||
if [[ $1 == "install" ]]; then
|
||||
echo "Installing dependencies..."
|
||||
pip3 install -r requirements.txt
|
||||
python3 setup.py install
|
||||
exit 1
|
||||
fi
|
||||
echo "Running deposit-cli..."
|
||||
python3 ./staking_deposit/deposit.py "$@"
|
||||
python3 -m ethstaker_deposit "$@"
|
||||
|
||||
elif [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "cygwin" ]]; then
|
||||
echo $OSTYPE
|
||||
if [[ $1 == "install" ]]; then
|
||||
echo "Installing dependencies..."
|
||||
pip install -r requirements.txt
|
||||
python setup.py install
|
||||
exit 1
|
||||
fi
|
||||
echo "Running deposit-cli..."
|
||||
python ./staking_deposit/deposit.py "$@"
|
||||
python -m ethstaker_deposit "$@"
|
||||
|
||||
else
|
||||
echo "Sorry, to run deposit-cli on" $(uname -s)", please see the trouble-shooting on https://github.com/ethereum/staking-deposit-cli"
|
||||
echo "Sorry, to run deposit-cli on" $(uname -s)", please see the trouble-shooting on https://github.com/eth-educators/ethstaker-deposit-cli"
|
||||
exit 1
|
||||
|
||||
fi
|
||||
4
src/vendors/ethstaker-deposit-cli-0.5.0/docs/book.toml
vendored
Normal file
4
src/vendors/ethstaker-deposit-cli-0.5.0/docs/book.toml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
[book]
|
||||
language = "en"
|
||||
multilingual = false
|
||||
src = "src"
|
||||
1
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/CNAME
vendored
Normal file
1
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/CNAME
vendored
Normal file
@@ -0,0 +1 @@
|
||||
deposit-cli.ethstaker.cc
|
||||
30
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/SUMMARY.md
vendored
Normal file
30
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/SUMMARY.md
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
# Summary
|
||||
|
||||
- [Ethstaker Deposit CLI](landing.md)
|
||||
- [Quick Setup](quick_setup.md)
|
||||
- [Other Install Options](other_install_options.md)
|
||||
|
||||
# Commands
|
||||
|
||||
- [New Mnemonic](new_mnemonic.md)
|
||||
- [Existing Mnemonic](existing_mnemonic.md)
|
||||
- [Generate BLS to Execution Change](generate_bls_to_execution_change.md)
|
||||
- [Generate BLS to Execution Change Keystore](generate_bls_to_execution_change_keystore.md)
|
||||
- [Exit Transaction Keystore](exit_transaction_keystore.md)
|
||||
- [Exit Transaction Mnemonic](exit_transaction_mnemonic.md)
|
||||
- [Partial Deposit](partial_deposit.md)
|
||||
- [Test Keystore](test_keystore.md)
|
||||
|
||||
# File formats
|
||||
|
||||
- [Keystore](keystore_file.md)
|
||||
- [Deposit Data](deposit_data_file.md)
|
||||
- [BLS to Execution Change](bls_to_execution_change_file.md)
|
||||
- [BLS to Execution Change Keystore](bls_to_execution_change_keystore_file.md)
|
||||
- [Signed Exit Transaction](signed_exit_transaction_file.md)
|
||||
|
||||
# Development
|
||||
|
||||
- [Local Development](local_development.md)
|
||||
- [Release Process](release_process.md)
|
||||
- [Reporting a Vulnerability](reporting_vulnerability.md)
|
||||
28
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/bls_to_execution_change_file.md
vendored
Normal file
28
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/bls_to_execution_change_file.md
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
# BLS to Execution Change file
|
||||
|
||||
A BLS to execution change file is created when calling the **[generate-bls-to-execution-change](generate_bls_to_execution_change.md)** command.
|
||||
|
||||
The BLS to execution change file is a JSON file. It contains a list of messages to change the withdrawal credentials for one or many validators. The format of the BLS to execution change file is loosly based on the input for the POST `/eth/v1/beacon/pool/bls_to_execution_changes` [API endpoint](https://ethereum.github.io/beacon-APIs/#/Beacon/submitPoolBLSToExecutionChange) as defined by [the Ethereum Beacon APIs](https://github.com/ethereum/beacon-APIs). Part of this content is based on the [SignedBLSToExecutionChange](https://github.com/ethereum/consensus-specs/blob/dev/specs/capella/beacon-chain.md#signedblstoexecutionchange) container as defined in the [Ethereum Consensus Specifications](https://github.com/ethereum/consensus-specs/).
|
||||
|
||||
## Broadcasting
|
||||
|
||||
If you have access to a beacon node client running on your target network, you can publish these messages simply by calling the POST `/eth/v1/beacon/pool/bls_to_execution_changes` [API endpoint](https://ethereum.github.io/beacon-APIs/#/Beacon/submitPoolBLSToExecutionChange) and passing the content of the BLS to execution change file as the payload. You can also use [the Beaconcha.in Broadcast Signed Messages tool](https://beaconcha.in/tools/broadcast) which might be easier for most users.
|
||||
|
||||
## Example
|
||||
```JSON
|
||||
[
|
||||
{
|
||||
"message":{
|
||||
"validator_index":"1804776",
|
||||
"from_bls_pubkey":"0x970245df5f9cf7a082db195136a3066412b62e8bf04e21d7c3408d7fb36f34f20c4cb0883e798b82523b466f7a61c838",
|
||||
"to_execution_address":"0x4d496ccc28058b1d74b7a19541663e21154f9c84"
|
||||
},
|
||||
"signature":"0xa1e47e6b1fdf4dd5f1dd3ddb3d47d2dcf446d096d49d90afef06a38dc02fba6b4d16d1dc1184c791e54666dabb8bdedd0660bc9bb3bc5d0e592eaf5f0c978cca4fcafe4037672940d6f1a44d2a33503c30cb98ca695979b1de9e321a8a694bc2",
|
||||
"metadata":{
|
||||
"network_name":"holesky",
|
||||
"genesis_validators_root":"0x9143aa7c615a7f7115e2b6aac319c03529df8242ae705fba9df39b79c59fa8b1",
|
||||
"deposit_cli_version":"0.1.4-dev"
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
20
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/bls_to_execution_change_keystore_file.md
vendored
Normal file
20
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/bls_to_execution_change_keystore_file.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
# BLS to Execution Change Keystore file
|
||||
|
||||
A BLS to execution change keystore file is created when calling the **[generate-bls-to-execution-change-keystore](generate_bls_to_execution_change_keystore.md)** command.
|
||||
|
||||
The BLS to execution change keystore file is a JSON file. The format is very similar to the [BLS to execution change file](bls_to_execution_change_file.md) but with the `from_bls_pubkey` and `metadata` attributes removed.
|
||||
|
||||
## Utilizing
|
||||
|
||||
There is currently no integration with this file format with either the execution layer or beacon chain. The `signature` value must be provided as the `keystore_signature` for the [Signature file](https://github.com/eth-educators/update-credentials-without-mnemonic#signature-file-format).
|
||||
|
||||
## Example
|
||||
```JSON
|
||||
{
|
||||
"message":{
|
||||
"validator_index":"1804776",
|
||||
"to_execution_address":"0x4d496ccc28058b1d74b7a19541663e21154f9c84"
|
||||
},
|
||||
"signature":"0xa1e47e6b1fdf4dd5f1dd3ddb3d47d2dcf446d096d49d90afef06a38dc02fba6b4d16d1dc1184c791e54666dabb8bdedd0660bc9bb3bc5d0e592eaf5f0c978cca4fcafe4037672940d6f1a44d2a33503c30cb98ca695979b1de9e321a8a694bc2",
|
||||
}
|
||||
```
|
||||
59
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/deposit_data_file.md
vendored
Normal file
59
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/deposit_data_file.md
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
# Deposit Data file
|
||||
|
||||
A deposit data file is created when calling the **[new-mnemonic](new_mnemonic.md)**, the **[existing-mnemonic](existing_mnemonic.md)** or the **[partial-deposit](partial_deposit.md)** command.
|
||||
|
||||
The deposit data file is a JSON file that contains a list of deposits that is mostly used for the [Ethereum Staking Launchpad](https://github.com/ethereum/staking-launchpad). It is loosly based on [the DepositData structure](https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#depositdata) and the [deposit function](https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/deposit-contract.md#deposit-function) from the [deposit smart contract](https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/deposit-contract.md).
|
||||
|
||||
## Format
|
||||
Each deposit from the list will contain this structure:
|
||||
```JSON
|
||||
{
|
||||
"pubkey": "string",
|
||||
"withdrawal_credentials": "string",
|
||||
"amount": "number",
|
||||
"signature": "string",
|
||||
"deposit_message_root": "string",
|
||||
"deposit_data_root": "string",
|
||||
"fork_version": "string",
|
||||
"network_name": "string",
|
||||
"deposit_cli_version": "string"
|
||||
}
|
||||
```
|
||||
|
||||
- **pubkey**: The validator public key value to be passed to the deposit function call.
|
||||
- **withdrawal_credentials**: The withdrawal credentials value to be passed to the deposit function call.
|
||||
- **amount**: The deposit amount to be sent with the call to the deposit function call. This should always be 32 Ethers (in GWEI, `32000000000`) when performing a deposit for a validator to be activated. The unit for this value is GWEI. For partial deposits, this value can be an integer value higher or equal than 1 and generally lower than or equal to 2048 in Ethers.
|
||||
- **signature**: The signature value to be passed to the deposit function call.
|
||||
- **deposit_message_root**: A deposit message root value used for validation by the Ethereum Staking Launchpad.
|
||||
- **deposit_data_root**: The deposit data root value to be passed to the deposit function call.
|
||||
- **fork_version**: The fork version of the network that this deposit file was created for.
|
||||
- **network_name**: The network name of the network that this deposit file was created for.
|
||||
- **deposit_cli_version**: The tool version used to create this file. We are currently faking this value to work around [an issue](https://github.com/eth-educators/ethstaker-deposit-cli/issues/216) with the Launchpad.
|
||||
|
||||
## Example
|
||||
```JSON
|
||||
[
|
||||
{
|
||||
"pubkey":"962195958e742b8dc5b2a25adede82fc5cd661827cb1e1237025e3d7847801aa5584d5bfdc6893413264cccfbff54128",
|
||||
"withdrawal_credentials":"0007a213a9a50ddf7e00e53267af1c131ed82fec947f1c9656b54f9a20f7a87f",
|
||||
"amount":32000000000,
|
||||
"signature":"a2d56afe4540d5b506aea614848a0838b66c8707a91aa73cdb0e7b59d819f16be64881b5b621184b1668f4f1d024094a1861c5af783ded675b5763047c069c5eb805649f7c04656c96b31b0bccc34ed93c8fcd8f2e4a9e5c03453f305089d765",
|
||||
"deposit_message_root":"f9bdb1e800b8f9f0db98c77271745e3c6140f18bf420543bda84fa92c393ddc7",
|
||||
"deposit_data_root":"7cda08cd57c303f8af720b10a0852408bc31e015cb552f0029fc1024b8a1d615",
|
||||
"fork_version":"01017000",
|
||||
"network_name":"holesky",
|
||||
"deposit_cli_version":"2.7.0"
|
||||
},
|
||||
{
|
||||
"pubkey":"86ee0b826d7d5262324ace2fba4ed5f09a1cbef80552e3d945279f19bc4118a98e9a93257eb4c7731ccc10c19835d24f",
|
||||
"withdrawal_credentials":"00daf39b8996943de9e93d417a6c5a4b958e4ae7a4d6e27f72aa08d41faa012f",
|
||||
"amount":32000000000,
|
||||
"signature":"83b227d72d9f1362d8676a61b91bb3882059e89c7d862d8030b1d37e890143869c105a78efce2a734f202da95076782219010e896ec9f8328a9e553134773626810d6c455bc1250a20e52a01684c051dd3e46151587267214cbb396673a13e89",
|
||||
"deposit_message_root":"99dbb2392fef277c15e710ca0ead058c024adce15f9e8f369bbaea939c0009ed",
|
||||
"deposit_data_root":"0fcb16fdb536b00a037a3ccde67187d21abfb726d677e40709ae6910d44377a5",
|
||||
"fork_version":"01017000",
|
||||
"network_name":"holesky",
|
||||
"deposit_cli_version":"2.7.0"
|
||||
}
|
||||
]
|
||||
```
|
||||
47
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/existing_mnemonic.md
vendored
Normal file
47
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/existing_mnemonic.md
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
# existing-mnemonic
|
||||
|
||||
{{#include ./snippet/warning_message.md}}
|
||||
|
||||
## Description
|
||||
Uses an existing BIP-39 mnemonic phrase for key generation.
|
||||
|
||||
## Optional Arguments
|
||||
|
||||
- **`--chain`**: The chain to use for generating the deposit data. Options are: 'mainnet', 'sepolia', 'holesky', 'mekong', or 'ephemery'.
|
||||
|
||||
- **`--mnemonic`**: The mnemonic you used to create withdrawal credentials. <span class="warning"></span>
|
||||
|
||||
- **`--mnemonic_language`**: The language of your mnemonic. If this is not provided we will attempt to determine it based on the mnemonic.
|
||||
|
||||
- **`--mnemonic_password`**: The mnemonic password you used in your key generation. Note: It's not the keystore password. <span class="warning"></span>
|
||||
|
||||
- **`--validator_start_index`**: The index of the first validator's keys you wish to generate. If this is your first time generating keys with this mnemonic, use 0. If you have generated keys using this mnemonic before, use the next index from which you want to start generating keys from. As an example if you've generated 4 keys before (keys #0, #1, #2, #3), then enter 4 here.
|
||||
|
||||
- **`--num_validators`**: Number of validators to create.
|
||||
|
||||
- **`--keystore_password`**: The password that is used to encrypt the provided keystore. Note: It's not your mnemonic password. <span class="warning"></span>
|
||||
|
||||
- **`--withdrawal_address`**: The Ethereum address that will be used in withdrawal. It typically starts with '0x' followed by 40 hexadecimal characters. Please make sure you have full control over the address you choose here. Once you set a withdrawal address on chain, it cannot be changed.
|
||||
|
||||
- **`--compounding / --regular-withdrawal`**: Generates compounding validators with 0x02 withdrawal credentials for a 2048 ETH maximum effective balance or generate regular validators with 0x01 withdrawal credentials for a 32 ETH maximum effective balance. Use of this option requires a withdrawal address. This feature is only supported on networks that have undergone the Pectra fork. Defaults to regular withdrawal.
|
||||
|
||||
- **`--amount`**: The amount to deposit to these validators in ether denomination. Must be at least 1 ether and can not have greater precision than 1 gwei. Use of this option requires compounding validators. Defaults to 32 ether.
|
||||
|
||||
- **`--pbkdf2`**: Will use pbkdf2 key derivation instead of scrypt for generated keystore files as defined in [EIP-2335](https://eips.ethereum.org/EIPS/eip-2335#decryption-key). This can be a good alternative if you intend to work with a large number of keys, as it can improve performance however it is less secure. You should only use this option if you understand the associated risks and have familiarity with encryption.
|
||||
|
||||
- **`--folder`**: The folder where keystore and deposit data files will be saved.
|
||||
|
||||
- **`--devnet_chain_setting`**: The custom chain setting of a devnet or testnet. Note that it will override your `--chain` choice. This should be a JSON string containing an object with the following keys: network_name, genesis_fork_version, exit_fork_version and genesis_validator_root.
|
||||
|
||||
## Output files
|
||||
A successful call to this command will result in one or many [keystore files](keystore_file.md) created, one per validator created, and one [deposit data file](deposit_data_file.md) created. The amount for each deposit in the deposit data file should always be 32 Ethers (`32000000000` in GWEI) with this command.
|
||||
|
||||
## Example Usage
|
||||
|
||||
```sh
|
||||
./deposit existing-mnemonic
|
||||
```
|
||||
|
||||
## Note
|
||||
|
||||
To make a deposit for a different amount other than 32 ETH, you need to have an existing keystore file or create one by using either the above command or **[new-mnemonic](new_mnemonic.md)**. Then, use the **[partial-deposit](partial_deposit.md)** command to specify the desired amount for each validator.
|
||||
31
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/exit_transaction_keystore.md
vendored
Normal file
31
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/exit_transaction_keystore.md
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
# exit-transaction-keystore
|
||||
|
||||
{{#include ./snippet/warning_message.md}}
|
||||
|
||||
## Description
|
||||
Creates an exit transaction using a keystore file.
|
||||
|
||||
## Optional Arguments
|
||||
|
||||
- **`--chain`**: The chain to use for generating the deposit data. Options are: 'mainnet', 'sepolia', 'holesky', 'mekong', or 'ephemery'.
|
||||
|
||||
- **`--keystore`**: The keystore file associating with the validator you wish to exit.
|
||||
|
||||
- **`--keystore_password`**: The password that is used to encrypt the provided keystore. Note: It's not your mnemonic password. <span class="warning"></span>
|
||||
|
||||
- **`--validator_index`**: The validator index corresponding to the provided keystore.
|
||||
|
||||
- **`--epoch`**: The epoch of when the exit transaction will be valid. The transaction will always be valid by default.
|
||||
|
||||
- **`--output_folder`**: The folder path for the `signed_exit_transaction-*` JSON file.
|
||||
|
||||
- **`--devnet_chain_setting`**: The custom chain setting of a devnet or testnet. Note that it will override your `--chain` choice. This should be a JSON string containing an object with the following keys: network_name, genesis_fork_version, exit_fork_version and genesis_validator_root.
|
||||
|
||||
## Output files
|
||||
A successful call to this command will result in one [Signed Exit Transaction file](signed_exit_transaction_file.md) created.
|
||||
|
||||
## Example Usage
|
||||
|
||||
```sh
|
||||
./deposit exit-transaction-keystore --keystore /path/to/keystore.json
|
||||
```
|
||||
35
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/exit_transaction_mnemonic.md
vendored
Normal file
35
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/exit_transaction_mnemonic.md
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
# exit-transaction-mnemonic
|
||||
|
||||
{{#include ./snippet/warning_message.md}}
|
||||
|
||||
## Description
|
||||
Creates an exit transaction using a mnemonic phrase.
|
||||
|
||||
## Optional Arguments
|
||||
|
||||
- **`--chain`**: The chain to use for generating the deposit data. Options are: 'mainnet', 'sepolia', 'holesky', 'mekong', or 'ephemery'.
|
||||
|
||||
- **`--mnemonic`**: The mnemonic you used during key generation. <span class="warning"></span>
|
||||
|
||||
- **`--mnemonic_language`**: The language of your mnemonic. If this is not provided we will attempt to determine it based on the mnemonic.
|
||||
|
||||
- **`--mnemonic_password`**: The mnemonic password you used in your key generation. Note: It's not the keystore password. <span class="warning"></span>
|
||||
|
||||
- **`--validator_start_index`**: The index position for the keys to start generating keystores in [ERC-2334 format](https://eips.ethereum.org/EIPS/eip-2334#eth2-specific-parameters) format.
|
||||
|
||||
- **`--validator_indices`**: A list of the chosen validator index number(s) as identified on the beacon chain. Split multiple items with whitespaces or commas.
|
||||
|
||||
- **`--epoch`**: The epoch of when the exit transaction will be valid. The transaction will always be valid by default.
|
||||
|
||||
- **`--output_folder`**: The folder path for the `signed_exit_transaction-*` JSON file.
|
||||
|
||||
- **`--devnet_chain_setting`**: The custom chain setting of a devnet or testnet. Note that it will override your `--chain` choice. This should be a JSON string containing an object with the following keys: network_name, genesis_fork_version, exit_fork_version and genesis_validator_root.
|
||||
|
||||
## Output files
|
||||
A successful call to this command will result in one or more [Signed Exit Transaction files](signed_exit_transaction_file.md) created.
|
||||
|
||||
## Example Usage
|
||||
|
||||
```sh
|
||||
./deposit exit-transaction-mnemonic
|
||||
```
|
||||
37
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/generate_bls_to_execution_change.md
vendored
Normal file
37
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/generate_bls_to_execution_change.md
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
# generate-bls-to-execution-change
|
||||
|
||||
{{#include ./snippet/warning_message.md}}
|
||||
|
||||
## Description
|
||||
Generates a BLS to execution address change message. This is used to add a withdrawal address to a validator that does not currently have one.
|
||||
|
||||
## Optional Arguments
|
||||
|
||||
- **`--bls_to_execution_changes_folder`**: The path to store the change JSON file.
|
||||
|
||||
- **`--chain`**: The chain to use for generating the deposit data. Options are: 'mainnet', 'sepolia', 'holesky', 'mekong', or 'ephemery'.
|
||||
|
||||
- **`--mnemonic`**: The mnemonic you used to create withdrawal credentials. <span class="warning"></span>
|
||||
|
||||
- **`--mnemonic_language`**: The language of your mnemonic. If this is not provided we will attempt to determine it based on the mnemonic.
|
||||
|
||||
- **`--mnemonic_password`**: The mnemonic password you used in your key generation. Note: It's not the keystore password. <span class="warning"></span>
|
||||
|
||||
- **`--validator_start_index`**: The index position for the keys to start generating withdrawal credentials for.
|
||||
|
||||
- **`--validator_indices`**: A list of the chosen validator index number(s) as identified on the beacon chain. Split multiple items with whitespaces or commas.
|
||||
|
||||
- **`--bls_withdrawal_credentials_list`**: A list of the old BLS withdrawal credentials of the given validator(s). It is for confirming you are using the correct keys. Split multiple items with whitespaces or commas.
|
||||
|
||||
- **`--withdrawal_address`**: The Ethereum address that will be used in withdrawal. It typically starts with '0x' followed by 40 hexadecimal characters. Please make sure you have full control over the address you choose here. Once you set a withdrawal address on chain, it cannot be changed.
|
||||
|
||||
- **`--devnet_chain_setting`**: The custom chain setting of a devnet or testnet. Note that it will override your `--chain` choice. This should be a JSON string containing an object with the following keys: network_name, genesis_fork_version, exit_fork_version and genesis_validator_root.
|
||||
|
||||
## Output files
|
||||
A successful call to this command will result in one [BLS to Execution Change file](bls_to_execution_change_file.md) created.
|
||||
|
||||
## Example Usage
|
||||
|
||||
```sh
|
||||
./deposit generate-bls-to-execution-change
|
||||
```
|
||||
35
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/generate_bls_to_execution_change_keystore.md
vendored
Normal file
35
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/generate_bls_to_execution_change_keystore.md
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
# generate-bls-to-execution-change-keystore
|
||||
|
||||
<div class="warning">
|
||||
This command is associated with the a proposed solution to update withdrawal credentials for those who are missing their mnemonic. At this point this has not been approved or implemented and there is no guarantee credentials will be modified in the future.
|
||||
|
||||
The project is located [here](https://github.com/eth-educators/update-credentials-without-mnemonic) if you would like to learn more.
|
||||
</div>
|
||||
|
||||
## Description
|
||||
Signs a withdrawal credential update message using the provided keystore. This signature is one of the required proofs of ownership for validators who have lost or are missing their mnemonic and are unable to perform the BLS change needed to update their withdrawal credentials.
|
||||
|
||||
## Optional Arguments
|
||||
|
||||
- **`--chain`**: The chain to use for generating the deposit data. Options are: 'mainnet', 'sepolia', 'holesky', 'mekong', or 'ephemery'.
|
||||
|
||||
- **`--keystore`**: The keystore file associating with the validator you wish to sign with. This keystore file should match the provided validator index.
|
||||
|
||||
- **`--keystore_password`**: The password that is used to encrypt the provided keystore. Note: It's not your mnemonic password. <span class="warning"></span>
|
||||
|
||||
- **`--validator_index`**: The validator index corresponding to the provided keystore.
|
||||
|
||||
- **`--withdrawal_address`**: The Ethereum address that will be used in withdrawal. It typically starts with '0x' followed by 40 hexadecimal characters. Please make sure you have full control over the address you choose here. Once you set a withdrawal address on chain, it cannot be changed.
|
||||
|
||||
- **`--output_folder`**: The folder path for the `bls_to_execution_change_keystore_signature-*` JSON file.
|
||||
|
||||
- **`--devnet_chain_setting`**: The custom chain setting of a devnet or testnet. Note that it will override your `--chain` choice. This should be a JSON string containing an object with the following keys: network_name, genesis_fork_version, exit_fork_version and genesis_validator_root.
|
||||
|
||||
## Output files
|
||||
A successful call to this command will result in one [BLS to Execution Change Keystore file](bls_to_execution_change_keystore_file.md) created.
|
||||
|
||||
## Example Usage
|
||||
|
||||
```sh
|
||||
./deposit generate-bls-to-execution-change-keystore
|
||||
```
|
||||
7
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/keystore_file.md
vendored
Normal file
7
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/keystore_file.md
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
# Keystore file
|
||||
|
||||
A keystore file is created when calling the **[new-mnemonic](new_mnemonic.md)** or the **[existing-mnemonic](existing_mnemonic.md)** command.
|
||||
|
||||
The format of the keystore file is defined in the [ERC-2335: BLS12-381 Keystore](https://eips.ethereum.org/EIPS/eip-2335) document.
|
||||
|
||||
In the context of staking on the Ethereum blockchain, the keystore file is used to store the validator signing key and transport it across devices while being protected with a password. Once created by a tool such as ethstaker-deposit-cli, it will generally be copied on a device running a validator client to be imported by that validator client with the associated password. Once the validator signing key is available to the validator client, it generally provides all the secrets needed to perform the associated validator's duties.
|
||||
81
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/landing.md
vendored
Normal file
81
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/landing.md
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
# Welcome to the `ethstaker-deposit-cli`!
|
||||
|
||||
The [`ethstaker-deposit-cli`](https://github.com/eth-educators/ethstaker-deposit-cli) is a command-line tool forked from Ethereum's [`staking-deposit-cli`](https://github.com/ethereum/staking-deposit-cli) with more functionality and improved performance.
|
||||
|
||||
## Important Concerns
|
||||
|
||||
This tool generates and/or utilizes mnemonics and validator key material. Both are highly sensitive materials, and their exposure could lead to the loss or theft of funds, as well as the compromise of privacy. Users must take appropriate measures to secure this information.
|
||||
|
||||
Here are some core recommendations:
|
||||
|
||||
- **Use this tool offline**: We highly recommend using this tool in an offline environment, preferably air-gapped, using a live USB such as [Tails](https://tails.net/install/download/index.en.html).
|
||||
|
||||
- **Avoid using passwords or mnemonics as command line arguments**: When executing any command, you will be prompted for the necessary arguments. This prevents the arguments from being stored in your command history which could create an attack vector.
|
||||
|
||||
- **Do not expose or share any material**: This tool generates and uses critically secure material that should not be shared or exposed. There is an abundance of thieves that use malicious links and scam tactics to get you to expose sensitive material. Be sure to triple check any tools or websites you are using and remain vigilant.
|
||||
|
||||
- **Create backups of your mnemonic**: The mnemonic generated by this tool is essential for your operation and success as a validator. Losing this mnemonic can result in significant financial loss. Carefully follow the instructions when creating a mnemonic, ensure you make a backup copy, and store it in a secure location. For long-term protection, consider using products like CryptoSteel and ColdTi, which offer resistance to the elements.
|
||||
|
||||
## Getting Started
|
||||
|
||||
If you want to start creating validator keys, please follow the [Quick Setup Instructions](quick_setup.md) or if you would like to run locally, view the [Local Development Instructions](local_development.md).
|
||||
|
||||
The general usage of the CLI is:
|
||||
```sh
|
||||
./deposit [OPTIONS] COMMAND [ARGS]
|
||||
```
|
||||
|
||||
## Command Options
|
||||
|
||||
Each CLI command has a number of command options that can be provided:
|
||||
|
||||
- **`--language`**: The language you wish to use the CLI in. Options: العربية, ελληνικά, English, Français, Bahasa melayu, Italiano, 日本語, 한국어, Português do Brasil, român, 简体中文. Default to English.
|
||||
|
||||
- **`--non_interactive`**: Run CLI in non-interactive mode. This will skip all confirmation and internet connectivity checks.
|
||||
|
||||
- **`--ignore_connectivity`**: Skip internet connectivity check and warning.
|
||||
|
||||
|
||||
## Commands
|
||||
|
||||
**You are not required to specify each argument when executing the command. We will prompt you for each argument for security purposes.**
|
||||
|
||||
If there is a specific command you would like to understand more, please choose from the following list:
|
||||
|
||||
- **[new-mnemonic](new_mnemonic.md)**: Used to generate a new mnemonic, validator keys, and deposit file. It is not recommended to use this command if you have existing validators.
|
||||
|
||||
- **[existing-mnemonic](existing_mnemonic.md)**: Provide a mnemonic to regenerate validator keys or create new ones.
|
||||
|
||||
- **[generate-bls-to-execution-change](generate_bls_to_execution_change.md)**: Add a withdrawal address to a validator that does not currently have one. It is **required** to have the corresponding mnemonic.
|
||||
|
||||
- **[generate-bls-to-execution-change-keystore](generate_bls_to_execution_change_keystore.md)**: Sign an update withdrawal credentials message using your validator keystore.
|
||||
|
||||
- **[exit-transaction-keystore](exit_transaction_keystore.md)**: Generate an exit message using the keystore of your validators.
|
||||
|
||||
- **[exit-transaction-mnemonic](exit_transaction_mnemonic.md)**: Generate an exit message using the mnemonic of your validators.
|
||||
|
||||
- **[partial-deposit](partial_deposit.md)**: Generate a deposit file with an existing validator key. Can be used to initiate a validator or deposit to an existing validator.
|
||||
|
||||
- **[test-keystore](test_keystore.md)**: Verify access to the provided keystore file by attempting to decrypt with the provided keystore password.
|
||||
|
||||
## Canonical Deposit Contract and Launchpad
|
||||
|
||||
Ethstaker confirms the canonical Ethereum staking deposit contract addresses and launchpad URLs.
|
||||
Please be sure that your ETH is deposited only to this deposit contract address, depending on chain.
|
||||
|
||||
Depositing to the wrong address **will** lose you your ETH.
|
||||
|
||||
- Ethereum mainnet
|
||||
- Deposit address: [0x00000000219ab540356cBB839Cbe05303d7705Fa](https://etherscan.io/address/0x00000000219ab540356cBB839Cbe05303d7705Fa)
|
||||
- [Launchpad](https://launchpad.ethereum.org/)
|
||||
- Ethereum Holešky (Holešovice) testnet
|
||||
- Deposit address: [0x4242424242424242424242424242424242424242](https://holesky.etherscan.io/address/0x4242424242424242424242424242424242424242)
|
||||
- [Launchpad](https://holesky.launchpad.ethereum.org/)
|
||||
|
||||
## Contributing
|
||||
|
||||
This project is open-source and welcomes contributions from the community. If you would like to contribute to the `ethstaker-deposit-cli`, please read the [Local Development Instructions](local_development.md), fork the project, and create a pull request with a description of the changes you have made and why.
|
||||
|
||||
## Support
|
||||
|
||||
If you encounter any issues or have questions while using the `ethstaker-deposit-cli`, please contact us on the [Ethstaker discord](https://dsc.gg/ethstaker).
|
||||
79
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/local_development.md
vendored
Normal file
79
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/local_development.md
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
# Local Development Instructions
|
||||
|
||||
To install the `ethstaker-deposit-cli`, follow these steps:
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Ensure you have the following software installed on your system:
|
||||
|
||||
- **Git**: Version control system to clone the repository. [Download Git](https://git-scm.com/downloads)
|
||||
- **Python 3.9+**: The programming language required to run the tool. [Download Python](https://www.python.org/downloads/)
|
||||
- **pip**: Package installer for Python, which is included with Python 3.9+.
|
||||
|
||||
On Windows, you'll need:
|
||||
- **Git for Windows**: Version control system to clone the repository. Configure it to associate `.sh` files with `bash`. [Download GfW](https://git-scm.com/download/win)
|
||||
- **Windows Terminal**: Optional but recommended command line console. Configure GfW to install a Git Bash profile. [Download Windows Terminal](https://apps.microsoft.com/detail/9n0dx20hk701)
|
||||
- **Python 3.9+**: The programming language required to run the tool. [Download Python](https://apps.microsoft.com/detail/9ncvdn91xzqp)
|
||||
- **Visual Studio C++**: The compiler required to build some of the dependencies of the tool. [Download VS C++](https://visualstudio.microsoft.com/vs/features/cplusplus/)
|
||||
|
||||
## Local Development Steps
|
||||
|
||||
1. **Clone the Repository**
|
||||
|
||||
```sh
|
||||
git clone https://github.com/eth-educators/ethstaker-deposit-cli.git
|
||||
```
|
||||
|
||||
2. **Navigate to the Project Directory**
|
||||
|
||||
```sh
|
||||
cd ethstaker-deposit-cli
|
||||
```
|
||||
|
||||
3. **Setup virtualenv (optional)**
|
||||
|
||||
Install `venv` if not already installed, e.g. for Debian/Ubuntu:
|
||||
|
||||
```sh
|
||||
sudo apt update && sudo apt install python3-venv
|
||||
```
|
||||
|
||||
Create a new [virtual environment](https://docs.python.org/3/library/venv.html):
|
||||
|
||||
```sh
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
```
|
||||
|
||||
4. **Install Dependencies**
|
||||
|
||||
```sh
|
||||
pip3 install -r requirements.txt
|
||||
```
|
||||
|
||||
5. **Run the CLI**
|
||||
|
||||
You can now run the CLI tool using the following command:
|
||||
|
||||
```sh
|
||||
python3 -m ethstaker_deposit [OPTIONS] COMMAND [ARGS]
|
||||
```
|
||||
|
||||
6. **Use pre-commit for PRs**
|
||||
|
||||
Install `pre-commit` if not already installed, e.g. for Debian/Ubuntu:
|
||||
|
||||
```sh
|
||||
sudo apt update && sudo apt install pre-commit
|
||||
```
|
||||
|
||||
Enable it for your `git commit` workflow:
|
||||
```sh
|
||||
pre-commit install
|
||||
```
|
||||
|
||||
**To execute tests, you will need to install the test dependencies**:
|
||||
```sh
|
||||
python3 -m pip install -r requirements.txt -r requirements_test.txt
|
||||
python3 -m pytest tests
|
||||
```
|
||||
43
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/new_mnemonic.md
vendored
Normal file
43
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/new_mnemonic.md
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
# new-mnemonic
|
||||
|
||||
{{#include ./snippet/warning_message.md}}
|
||||
|
||||
## Description
|
||||
Generates a new BIP-39 mnemonic along with validator keystore and deposit files depending on how many validators you wish to create.
|
||||
|
||||
## Optional Arguments
|
||||
|
||||
- **`--mnemonic_language`**: The language of the BIP-39 mnemonic. Options are: 'chinese_simplified', 'chinese_traditional', 'czech', 'english', 'french', 'italian', 'japanese', 'korean', 'portuguese', 'spanish'.
|
||||
|
||||
- **`--chain`**: The chain to use for generating the deposit data. Options are: 'mainnet', 'sepolia', 'holesky', 'mekong', or 'ephemery'.
|
||||
|
||||
- **`--num_validators`**: Number of validators to create.
|
||||
|
||||
- **`--keystore_password`**: The password that is used to encrypt the provided keystore. Note: It's not your mnemonic password. <span class="warning"></span>
|
||||
|
||||
- **`--withdrawal_address`**: The Ethereum address that will be used in withdrawal. It typically starts with '0x' followed by 40 hexadecimal characters. Please make sure you have full control over the address you choose here. Once you set a withdrawal address on chain, it cannot be changed.
|
||||
|
||||
- **`--compounding / --regular-withdrawal`**: Generates compounding validators with 0x02 withdrawal credentials for a 2048 ETH maximum effective balance or generate regular validators with 0x01 withdrawal credentials for a 32 ETH maximum effective balance. Use of this option requires a withdrawal address. This feature is only supported on networks that have undergone the Pectra fork. Defaults to regular withdrawal.
|
||||
|
||||
- **`--amount`**: The amount to deposit to these validators in ether denomination. Must be at least 1 ether and can not have greater precision than 1 gwei. Use of this option requires compounding validators. Defaults to 32 ether.
|
||||
|
||||
- **`--pbkdf2`**: Will use pbkdf2 key encryption instead of scrypt for generated keystore files as defined in [EIP-2335](https://eips.ethereum.org/EIPS/eip-2335#decryption-key). This can be a good alternative if you intend to work with a large number of keys, as it can improve performance. pbkdf2 encryption is, however, less secure than scrypt. You should only use this option if you understand the associated risks and have familiarity with encryption.
|
||||
|
||||
- **`--folder`**: The folder where keystore and deposit data files will be saved.
|
||||
|
||||
- **`--devnet_chain_setting`**: The custom chain setting of a devnet or testnet. Note that it will override your `--chain` choice. This should be a JSON string containing an object with the following keys: network_name, genesis_fork_version, exit_fork_version and genesis_validator_root.
|
||||
|
||||
## Output files
|
||||
A successful call to this command will result in one or many [keystore files](keystore_file.md) created, one per validator created, and one [deposit data file](deposit_data_file.md) created. The amount for each deposit in the deposit data file should always be 32 Ethers (`32000000000` in GWEI) with this command.
|
||||
|
||||
## Example Usage
|
||||
|
||||
```sh
|
||||
./deposit new-mnemonic
|
||||
```
|
||||
|
||||
## Note
|
||||
|
||||
The newly generated mnemonic **must** be written down, on a piece of paper or transferred to steel. The clipboard is cleared when this command finishes. If the mnemonic is lost and the validator does not have a withdrawal address, funds **cannot** be recovered.
|
||||
|
||||
To make a deposit for a different amount other than 32 ETH, you need to have an existing keystore file or create one by using either the above command or **[existing-mnemonic](existing_mnemonic.md)**. Then, use the **[partial-deposit](partial_deposit.md)** command to specify the desired amount for each validator.
|
||||
268
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/other_install_options.md
vendored
Normal file
268
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/other_install_options.md
vendored
Normal file
@@ -0,0 +1,268 @@
|
||||
# Other Install Options
|
||||
|
||||
## Linux or MacOS users
|
||||
|
||||
### Option 1. Build `deposit-cli` with native Python
|
||||
|
||||
1. **Python version checking**
|
||||
|
||||
Ensure you are using Python version >= Python3.9:
|
||||
|
||||
```sh
|
||||
python3 -V
|
||||
```
|
||||
|
||||
2. **Installation**
|
||||
|
||||
Install the dependencies:
|
||||
|
||||
```sh
|
||||
pip3 install -r requirements.txt
|
||||
```
|
||||
|
||||
Or use the helper script:
|
||||
|
||||
```sh
|
||||
./deposit.sh install
|
||||
```
|
||||
|
||||
3. **Create keys and `deposit_data-*.json`**
|
||||
|
||||
Run one of the following command to enter the interactive CLI:
|
||||
|
||||
```sh
|
||||
./deposit.sh new-mnemonic
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```sh
|
||||
./deposit.sh existing-mnemonic
|
||||
```
|
||||
|
||||
You can also run the tool with optional arguments:
|
||||
|
||||
```sh
|
||||
./deposit.sh new-mnemonic --num_validators=<NUM_VALIDATORS> --mnemonic_language=english --chain=<CHAIN_NAME> --folder=<YOUR_FOLDER_PATH>
|
||||
```
|
||||
|
||||
```sh
|
||||
./deposit.sh existing-mnemonic --num_validators=<NUM_VALIDATORS> --validator_start_index=<START_INDEX> --chain=<CHAIN_NAME> --folder=<YOUR_FOLDER_PATH>
|
||||
```
|
||||
|
||||
### Option 2. Build `deposit-cli` with `virtualenv`
|
||||
|
||||
1. **Python version checking**
|
||||
|
||||
Ensure you are using Python version >= Python3.9:
|
||||
|
||||
```sh
|
||||
python3 -V
|
||||
```
|
||||
|
||||
2. **Installation**
|
||||
|
||||
Install `venv` if not already installed, e.g. for Debian/Ubuntu:
|
||||
|
||||
```sh
|
||||
sudo apt update && sudo apt install python3-venv
|
||||
```
|
||||
|
||||
Create a new [virtual environment](https://docs.python.org/3/library/venv.html):
|
||||
|
||||
```sh
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
```
|
||||
|
||||
and install the dependencies:
|
||||
|
||||
```sh
|
||||
pip3 install -r requirements.txt
|
||||
```
|
||||
|
||||
3. **Create keys and `deposit_data-*.json`**
|
||||
|
||||
Run one of the following command to enter the interactive CLI:
|
||||
|
||||
```sh
|
||||
python3 -m ethstaker_deposit new-mnemonic
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```sh
|
||||
python3 -m ethstaker_deposit existing-mnemonic
|
||||
```
|
||||
|
||||
You can also run the tool with optional arguments:
|
||||
|
||||
```sh
|
||||
python3 -m ethstaker_deposit new-mnemonic --num_validators=<NUM_VALIDATORS> --mnemonic_language=english --chain=<CHAIN_NAME> --folder=<YOUR_FOLDER_PATH>
|
||||
```
|
||||
|
||||
```sh
|
||||
python3 -m ethstaker_deposit existing-mnemonic --num_validators=<NUM_VALIDATORS> --validator_start_index=<START_INDEX> --chain=<CHAIN_NAME> --folder=<YOUR_FOLDER_PATH>
|
||||
```
|
||||
|
||||
### Option 3. Use published docker image
|
||||
|
||||
1. **Pull the official docker image**
|
||||
|
||||
Run the following command to pull the latest docker image published on the Github repository:
|
||||
|
||||
```sh
|
||||
docker pull ghcr.io/eth-educators/ethstaker-deposit-cli:latest
|
||||
```
|
||||
|
||||
2. **Create keys and `deposit_data-*.json`**
|
||||
|
||||
Run the following command to enter the interactive CLI:
|
||||
|
||||
```sh
|
||||
docker run -it --rm -v $(pwd)/validator_keys:/app/validator_keys ghcr.io/eth-educators/ethstaker-deposit-cli:latest
|
||||
```
|
||||
|
||||
You can also run the tool with optional arguments:
|
||||
|
||||
```sh
|
||||
docker run -it --rm -v $(pwd)/validator_keys:/app/validator_keys ghcr.io/eth-educators/ethstaker-deposit-cli:latest new-mnemonic --num_validators=<NUM_VALIDATORS> --mnemonic_language=english
|
||||
```
|
||||
|
||||
Example for 1 validator on the [Holesky testnet](https://holesky.launchpad.ethereum.org/) using english:
|
||||
|
||||
```sh
|
||||
docker run -it --rm -v $(pwd)/validator_keys:/app/validator_keys ghcr.io/eth-educators/ethstaker-deposit-cli:latest new-mnemonic --num_validators=1 --mnemonic_language=english --chain=holesky
|
||||
```
|
||||
|
||||
### Option 4. Use local docker image
|
||||
|
||||
1. **Build the docker image**
|
||||
|
||||
Run the following command to locally build the docker image:
|
||||
|
||||
```sh
|
||||
make build_docker
|
||||
```
|
||||
|
||||
2. **Create keys and `deposit_data-*.json`**
|
||||
|
||||
Run the following command to enter the interactive CLI:
|
||||
|
||||
```sh
|
||||
docker run -it --rm -v $(pwd)/validator_keys:/app/validator_keys eth-educators/ethstaker-deposit-cli
|
||||
```
|
||||
|
||||
You can also run the tool with optional arguments:
|
||||
|
||||
```sh
|
||||
docker run -it --rm -v $(pwd)/validator_keys:/app/validator_keys eth-educators/ethstaker-deposit-cli new-mnemonic --num_validators=<NUM_VALIDATORS> --mnemonic_language=english
|
||||
```
|
||||
|
||||
Example for 1 validator on the [Holesky testnet](https://holesky.launchpad.ethereum.org/) using english:
|
||||
|
||||
```sh
|
||||
docker run -it --rm -v $(pwd)/validator_keys:/app/validator_keys eth-educators/ethstaker-deposit-cli new-mnemonic --num_validators=1 --mnemonic_language=english --chain=holesky
|
||||
```
|
||||
|
||||
----
|
||||
|
||||
## For Windows users
|
||||
|
||||
|
||||
### Option 1. Build `deposit-cli` with native Python
|
||||
|
||||
1. **Python version checking**
|
||||
|
||||
Ensure you are using Python version >= Python12 (Assume that you've installed Python 3 as the main Python):
|
||||
|
||||
```sh
|
||||
python -V
|
||||
```
|
||||
|
||||
2. **Installation**
|
||||
|
||||
Install the dependencies:
|
||||
|
||||
```sh
|
||||
pip3 install -r requirements.txt
|
||||
```
|
||||
|
||||
Or use the helper script:
|
||||
|
||||
```sh
|
||||
sh deposit.sh install
|
||||
```
|
||||
|
||||
3. **Create keys and `deposit_data-*.json`**
|
||||
|
||||
Run one of the following command to enter the interactive CLI:
|
||||
|
||||
```sh
|
||||
./deposit.sh new-mnemonic
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```sh
|
||||
./deposit.sh existing-mnemonic
|
||||
```
|
||||
|
||||
You can also run the tool with optional arguments:
|
||||
|
||||
```sh
|
||||
./deposit.sh new-mnemonic --num_validators=<NUM_VALIDATORS> --mnemonic_language=english --chain=<CHAIN_NAME> --folder=<YOUR_FOLDER_PATH>
|
||||
```
|
||||
|
||||
```sh
|
||||
./deposit.sh existing-mnemonic --num_validators=<NUM_VALIDATORS> --validator_start_index=<START_INDEX> --chain=<CHAIN_NAME> --folder=<YOUR_FOLDER_PATH>
|
||||
```
|
||||
|
||||
### Option 2. Build `deposit-cli` with `virtualenv`
|
||||
|
||||
1. **Python version checking**
|
||||
|
||||
Ensure you are using Python version >= Python3.9 (Assume that you've installed Python 3 as the main Python):
|
||||
|
||||
```cmd
|
||||
python -V
|
||||
```
|
||||
|
||||
2. **Installation**
|
||||
|
||||
Create a new [virtual environment](https://docs.python.org/3/library/venv.html):
|
||||
|
||||
```sh
|
||||
python3 -m venv .venv
|
||||
.\.venv\Scripts\activate
|
||||
```
|
||||
|
||||
and install the dependencies:
|
||||
|
||||
```cmd
|
||||
pip3 install -r requirements.txt
|
||||
```
|
||||
|
||||
3. **Create keys and `deposit_data-*.json`**
|
||||
|
||||
Run one of the following command to enter the interactive CLI:
|
||||
|
||||
```cmd
|
||||
python -m ethstaker_deposit new-mnemonic
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```cmd
|
||||
python -m ethstaker_deposit existing-mnemonic
|
||||
```
|
||||
|
||||
You can also run the tool with optional arguments:
|
||||
|
||||
```cmd
|
||||
python -m ethstaker_deposit new-mnemonic --num_validators=<NUM_VALIDATORS> --mnemonic_language=english --chain=<CHAIN_NAME> --folder=<YOUR_FOLDER_PATH>
|
||||
```
|
||||
|
||||
```cmd
|
||||
python -m ethstaker_deposit existing-mnemonic --num_validators=<NUM_VALIDATORS> --validator_start_index=<START_INDEX> --chain=<CHAIN_NAME> --folder=<YOUR_FOLDER_PATH>
|
||||
```
|
||||
34
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/partial_deposit.md
vendored
Normal file
34
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/partial_deposit.md
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
# partial-deposit
|
||||
|
||||
{{#include ./snippet/warning_message.md}}
|
||||
|
||||
## Description
|
||||
Creates a deposit file with an existing validator key. A validator key can be created using the **[new-mnemonic](new_mnemonic.md)** or the **[existing-mnemonic](existing_mnemonic.md)** commands. Can be used to initiate a validator or deposit to an existing validator.
|
||||
If you wish to create a validator with 0x00 credentials, you must use the **[new-mnemonic](new_mnemonic.md)** or the **[existing-mnemonic](existing_mnemonic.md)** command.
|
||||
|
||||
## Optional Arguments
|
||||
|
||||
- **`--chain`**: The chain to use for generating the deposit data. Options are: 'mainnet', 'sepolia', 'holesky', 'mekong', or 'ephemery'.
|
||||
|
||||
- **`--keystore`**: The keystore file associating with the validator you wish to deposit to.
|
||||
|
||||
- **`--keystore_password`**: The password that is used to encrypt the provided keystore. Note: It's not your mnemonic password. <span class="warning"></span>
|
||||
|
||||
- **`--amount`**: The amount you wish to deposit in ether. Must be at least 1 and can not have precision beyond 1 gwei. Defaults to 32 ether.
|
||||
|
||||
- **`--withdrawal_address`**: The withdrawal address of the existing validator or the desired withdrawal address.
|
||||
|
||||
- **`--compounding / --regular-withdrawal`**: Generates compounding validators with 0x02 withdrawal credentials for a 2048 ETH maximum effective balance or generate regular validators with 0x01 withdrawal credentials for a 32 ETH maximum effective balance. Use of this option requires a withdrawal address. This feature is only supported on networks that have undergone the Pectra fork. Defaults to regular withdrawal.
|
||||
|
||||
- **`--output_folder`**: The folder path for the `deposit-*` JSON file.
|
||||
|
||||
- **`--devnet_chain_setting`**: The custom chain setting of a devnet or testnet. Note that it will override your `--chain` choice. This should be a JSON string containing an object with the following keys: network_name, genesis_fork_version, exit_fork_version and genesis_validator_root.
|
||||
|
||||
## Output file
|
||||
A successful call to this command will result in one [deposit data file](deposit_data_file.md) created.
|
||||
|
||||
## Example Usage
|
||||
|
||||
```sh
|
||||
./deposit partial-deposit --keystore /path/to/keystore.json
|
||||
```
|
||||
67
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/quick_setup.md
vendored
Normal file
67
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/quick_setup.md
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
# Quick Setup
|
||||
|
||||
This guide will walk you through the steps to download and set up the `ethstaker-deposit-cli` for your operating system.
|
||||
|
||||
**Build requirements**
|
||||
|
||||
- [Python **3.9+**](https://www.python.org/about/gettingstarted/)
|
||||
- [pip3](https://pip.pypa.io/en/stable/installing/)
|
||||
|
||||
## Step 1: Download the Latest Release
|
||||
|
||||
### Download binary executable file
|
||||
|
||||
1. Navigate to the [Releases page](https://github.com/eth-educators/ethstaker-deposit-cli/releases) of the `ethstaker-deposit-cli` repository.
|
||||
|
||||
2. Download the corresponding file for your operating system:
|
||||
- **Windows**: Look for a file with `windows` in the name.
|
||||
- **MacOS**: Look for a file with `darwin` in the name.
|
||||
- **Linux**: Look for a file with `linux` in the name.
|
||||
|
||||
3. Extract the contents of the zipped file
|
||||
|
||||
4. Open a terminal or command prompt and navigate to the extracted folder
|
||||
|
||||
For other installation options, including building with python or virtualenv and docker image instructions, go [here](other_install_options.md)
|
||||
|
||||
|
||||
## Step 2: Verify the Installation
|
||||
|
||||
1. Make sure you have [the GitHub CLI installed](https://cli.github.com/).
|
||||
|
||||
2. Verify the attestation against the corresponding file but be sure to replace the contents with the exact file name:
|
||||
```sh
|
||||
gh attestation verify ethstaker_deposit-cli-*******-***.*** --repo eth-educators/ethstaker-deposit-cli
|
||||
```
|
||||
|
||||
This step requires you to be online. If you want to perform this offline, follow [these instructions from GitHub](https://docs.github.com/en/actions/security-for-github-actions/using-artifact-attestations/verifying-attestations-offline).
|
||||
|
||||
3. You should see `✓ Verification succeeded!` in the output **otherwise do not continue**.
|
||||
|
||||
## Step 3: Usage
|
||||
|
||||
**Windows users:** You should replace `./deposit` with `deposit.exe` to run properly.
|
||||
|
||||
**MacOS users:** In order to run from the terminal, you must first open the file to bypass MacOS code signing issues. Do so by right clicking the `deposit` file and then selecting `Open`.
|
||||
|
||||
**Linux users:** On Unix-based systems, keystores and the deposit_data*.json have 440/-r--r----- file permissions (user & group read only). This improves security by limiting which users and processes that have access to these files. If you are getting permission denied errors when handling your keystores, consider changing which user/group owns the file (with chown) or, if need be, change the file permissions with chmod.
|
||||
|
||||
Determine which command best suites what you would like to accomplish:
|
||||
|
||||
- **[new-mnemonic](new_mnemonic.md)**: Used to generate a new mnemonic, validator keys, and deposit file. It is not recommended to use this command if you have existing validators.
|
||||
|
||||
- **[existing-mnemonic](existing_mnemonic.md)**: Provide a mnemonic to regenerate validator keys or create new ones.
|
||||
|
||||
- **[generate-bls-to-execution-change](generate_bls_to_execution_change.md)**: Update your withdrawal credentials of existing validators. It is **required** to have the corresponding mnemonic.
|
||||
|
||||
- **[generate-bls-to-execution-change-keystore](generate_bls_to_execution_change_keystore.md)**: Sign an update withdrawal credentials message using your validator keystore.
|
||||
|
||||
- **[exit-transaction-keystore](exit_transaction_keystore.md)**: Generate an exit message using the keystore of your validators.
|
||||
|
||||
- **[exit-transaction-mnemonic](exit_transaction_mnemonic.md)**: Generate an exit message using the mnemonic of your validators.
|
||||
|
||||
- **[partial-deposit](partial_deposit.md)**: Generate a partial deposit using a validator keystore.
|
||||
|
||||
---
|
||||
|
||||
If you encounter any issues, please check the [issues page](https://github.com/eth-educators/ethstaker-deposit-cli/issues) for help or to report a problem. You may also contact us on the [Ethstaker discord](https://dsc.gg/ethstaker).
|
||||
22
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/release_process.md
vendored
Normal file
22
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/release_process.md
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
# Release Process Instructions
|
||||
|
||||
This document is meant as a guide on how to perform and publish a new release version of [ethstaker-deposit-cli](https://github.com/eth-educators/ethstaker-deposit-cli). It includes step by step instructions to complete the release process.
|
||||
|
||||
1. Make sure all the tests from the latest [ci-runner workflow](https://github.com/eth-educators/ethstaker-deposit-cli/actions/workflows/runner.yml) on the latest commit of the main branch are completed. Make sure all tests are passing on all the supported platforms.
|
||||
2. Determine a new version number. Version numbers should adhere to [Semantic Versioning](https://semver.org/). For any official release, it should include a major, a minor and a patch identifier like `1.0.0`.
|
||||
3. Update `ethstaker_deposit/__init__.py`'s `__version__` variable with the new version number. Commit this change to the main branch of the main repository.
|
||||
4. Add a tag to the main repository for this changed version commit above. The name of this tag should be a string starting with `v` concatenated with the version number. With git, the main repository cloned and the commit above being the head, it can look like this:
|
||||
```console
|
||||
git tag -a -m 'Version 1.0.0' v1.0.0
|
||||
git push origin v1.0.0
|
||||
```
|
||||
5. Wait for all the build assets and the draft release to be created by [the ci-build workflow](https://github.com/eth-educators/ethstaker-deposit-cli/actions/workflows/build.yml).
|
||||
6. Open the draft release and fill in the different sections correctly.
|
||||
7. If this is not a production release, check the *Set as a pre-release* checkbox.
|
||||
8. Click the *Publish release* button.
|
||||
9. Determine a new dev version number. You can try to guess the next version number to the best of your ability. This will always be subject to change. Add a `dev` identifier to the version number to clearly indicate this is a dev version number.
|
||||
10. Update `ethstaker_deposit/__init__.py`'s `__version__` variable with a new dev version number. Commit this change to the main branch.
|
||||
|
||||
## Release Notes Template
|
||||
|
||||
You can find the latest release notes template on https://github.com/eth-educators/ethstaker-deposit-cli/blob/main/.github/release_template.md .
|
||||
3
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/reporting_vulnerability.md
vendored
Normal file
3
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/reporting_vulnerability.md
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# Reporting a Vulnerability
|
||||
|
||||
Private vulnerability reporting is enabled on [the ethstaker-deposit-cli repository](https://github.com/eth-educators/ethstaker-deposit-cli). Feel free to report any security vulnerability through [the GitHub *Report a vulnerability* feature](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities/privately-reporting-a-security-vulnerability#privately-reporting-a-security-vulnerability).
|
||||
20
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/signed_exit_transaction_file.md
vendored
Normal file
20
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/signed_exit_transaction_file.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
# Signed Exit Transaction file
|
||||
|
||||
A signed exit transaction file is created when calling the **[exit-transaction-keystore](exit_transaction_keystore.md)** or the **[exit-transaction-mnemonic](exit_transaction_mnemonic.md)** command.
|
||||
|
||||
The signed exit transaction file is a JSON file. It contains a single message to exit a validator. The format of the signed exit transaction file is loosly based on the input for the POST `/eth/v1/beacon/pool/voluntary_exits` [API endpoint](https://ethereum.github.io/beacon-APIs/#/Beacon/submitPoolVoluntaryExit) as defined by [the Ethereum Beacon APIs](https://github.com/ethereum/beacon-APIs). Part of this content is based on the [SignedVoluntaryExit](https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#signedvoluntaryexit) signed envelope as defined in the [Ethereum Consensus Specifications](https://github.com/ethereum/consensus-specs/).
|
||||
|
||||
## Broadcasting
|
||||
|
||||
If you have access to a beacon node client running on your target network, you can publish this message simply by calling the POST `/eth/v1/beacon/pool/voluntary_exits` [API endpoint](https://ethereum.github.io/beacon-APIs/#/Beacon/submitPoolVoluntaryExit) and passing the content of the signed exit transaction file as the payload. You can also use [the Beaconcha.in Broadcast Signed Messages tool](https://beaconcha.in/tools/broadcast) which might be easier for most users.
|
||||
|
||||
## Example
|
||||
```JSON
|
||||
{
|
||||
"message":{
|
||||
"epoch":"0",
|
||||
"validator_index":"1804776"
|
||||
},
|
||||
"signature":"0x97fa465cf1081755002e35fab245bd2872381b07cbfa4df245a13e3834aba83a347f5c2a36a34760e9fcc754dd862de700d103b1cb0d5d9ce293242ebf9ad44a6073e5c4794424428a8f983513d88e6ff6ddccbde7b3e0ea43554a0b856f3199"
|
||||
}
|
||||
```
|
||||
3
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/snippet/warning_message.md
vendored
Normal file
3
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/snippet/warning_message.md
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<div class="warning">
|
||||
Including sensitive arguments when executing CLI commands poses a security risk, as these values can be accessible through disk and shell history. This exposure can allow other users, including admins and malicious actors, to gain access to sensitive information, putting your funds at risk.
|
||||
</div>
|
||||
20
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/test_keystore.md
vendored
Normal file
20
src/vendors/ethstaker-deposit-cli-0.5.0/docs/src/test_keystore.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
# test-keystore
|
||||
|
||||
{{#include ./snippet/warning_message.md}}
|
||||
|
||||
## Description
|
||||
Will verify access to the provided keystore file by attempting to decrypt it with the provided keystore password.
|
||||
|
||||
|
||||
## Optional Arguments
|
||||
|
||||
- **`--keystore`**: The keystore file you wish to verify.
|
||||
|
||||
- **`--keystore_password`**: The password used to attempt decryption of the provided keystore file. Note: It is not your mnemonic password. <span class="warning"></span>
|
||||
|
||||
|
||||
## Example Usage
|
||||
|
||||
```sh
|
||||
./deposit test-keystore --keystore /path/to/keystore.json
|
||||
```
|
||||
1
src/vendors/ethstaker-deposit-cli-0.5.0/ethstaker_deposit/__init__.py
vendored
Normal file
1
src/vendors/ethstaker-deposit-cli-0.5.0/ethstaker_deposit/__init__.py
vendored
Normal file
@@ -0,0 +1 @@
|
||||
__version__ = '0.5.0'
|
||||
4
src/vendors/ethstaker-deposit-cli-0.5.0/ethstaker_deposit/__main__.py
vendored
Normal file
4
src/vendors/ethstaker-deposit-cli-0.5.0/ethstaker_deposit/__main__.py
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
from ethstaker_deposit import deposit
|
||||
|
||||
if __name__ == "__main__":
|
||||
deposit.run()
|
||||
72
src/vendors/ethstaker-deposit-cli-0.5.0/ethstaker_deposit/bls_to_execution_change_keystore.py
vendored
Normal file
72
src/vendors/ethstaker-deposit-cli-0.5.0/ethstaker_deposit/bls_to_execution_change_keystore.py
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
import json
|
||||
import os
|
||||
from typing import Any, Dict
|
||||
from eth_typing import HexAddress
|
||||
from eth_utils import to_canonical_address
|
||||
from py_ecc.bls import G2ProofOfPossession as bls
|
||||
|
||||
from ethstaker_deposit.exceptions import ValidationError
|
||||
from ethstaker_deposit.settings import BaseChainSetting
|
||||
from ethstaker_deposit.utils.ssz import (
|
||||
BLSToExecutionChangeKeystore,
|
||||
SignedBLSToExecutionChangeKeystore,
|
||||
compute_signing_root,
|
||||
compute_bls_to_execution_change_keystore_domain,
|
||||
)
|
||||
from ethstaker_deposit.utils.file_handling import (
|
||||
sensitive_opener,
|
||||
)
|
||||
|
||||
|
||||
def bls_to_execution_change_keystore_generation(
|
||||
chain_setting: BaseChainSetting,
|
||||
signing_key: int,
|
||||
withdrawal_address: HexAddress,
|
||||
validator_index: int) -> SignedBLSToExecutionChangeKeystore:
|
||||
if withdrawal_address is None:
|
||||
raise ValueError("The withdrawal address should NOT be empty.")
|
||||
if chain_setting.GENESIS_VALIDATORS_ROOT is None:
|
||||
raise ValidationError("The genesis validators root should NOT be empty "
|
||||
"for this chain to obtain the BLS to execution change.")
|
||||
|
||||
message = BLSToExecutionChangeKeystore( # type: ignore[no-untyped-call]
|
||||
validator_index=validator_index,
|
||||
to_execution_address=to_canonical_address(withdrawal_address),
|
||||
)
|
||||
domain = compute_bls_to_execution_change_keystore_domain(
|
||||
fork_version=chain_setting.GENESIS_FORK_VERSION,
|
||||
genesis_validators_root=chain_setting.GENESIS_VALIDATORS_ROOT,
|
||||
)
|
||||
signing_root = compute_signing_root(message, domain)
|
||||
signature = bls.Sign(signing_key, signing_root)
|
||||
|
||||
return SignedBLSToExecutionChangeKeystore( # type: ignore[no-untyped-call]
|
||||
message=message,
|
||||
signature=signature,
|
||||
)
|
||||
|
||||
|
||||
def export_bls_to_execution_change_keystore_json(folder: str,
|
||||
signed_execution_change: SignedBLSToExecutionChangeKeystore,
|
||||
timestamp: float) -> str:
|
||||
signed_bls_to_execution_change_keystore_json: Dict[str, Any] = {}
|
||||
|
||||
address = '0x' + signed_execution_change.message.to_execution_address.hex() # type: ignore[attr-defined]
|
||||
index = signed_execution_change.message.validator_index # type: ignore[attr-defined]
|
||||
signature = '0x' + signed_execution_change.signature.hex() # type: ignore[attr-defined]
|
||||
|
||||
message = {
|
||||
'to_execution_address': address,
|
||||
'validator_index': index,
|
||||
}
|
||||
signed_bls_to_execution_change_keystore_json.update({'message': message})
|
||||
signed_bls_to_execution_change_keystore_json.update({'signature': signature})
|
||||
|
||||
filefolder = os.path.join(
|
||||
folder,
|
||||
'bls_to_execution_change_keystore_signature-%s-%i.json' % (index, timestamp)
|
||||
)
|
||||
|
||||
with open(filefolder, 'w', encoding='utf-8', opener=sensitive_opener) as f:
|
||||
json.dump(signed_bls_to_execution_change_keystore_json, f)
|
||||
return filefolder
|
||||
128
src/vendors/ethstaker-deposit-cli-0.5.0/ethstaker_deposit/cli/existing_mnemonic.py
vendored
Normal file
128
src/vendors/ethstaker-deposit-cli-0.5.0/ethstaker_deposit/cli/existing_mnemonic.py
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
import click
|
||||
import pyperclip
|
||||
from typing import (
|
||||
Any,
|
||||
Callable,
|
||||
Optional,
|
||||
)
|
||||
|
||||
from ethstaker_deposit.exceptions import MultiLanguageError, ValidationError
|
||||
from ethstaker_deposit.key_handling.key_derivation.mnemonic import (
|
||||
reconstruct_mnemonic,
|
||||
)
|
||||
from ethstaker_deposit.utils import config
|
||||
from ethstaker_deposit.utils.constants import (
|
||||
MNEMONIC_LANG_OPTIONS,
|
||||
WORD_LISTS_PATH,
|
||||
)
|
||||
from ethstaker_deposit.utils.click import (
|
||||
captive_prompt_callback,
|
||||
choice_prompt_func,
|
||||
jit_option,
|
||||
prompt_if_none,
|
||||
)
|
||||
from ethstaker_deposit.utils.intl import fuzzy_reverse_dict_lookup, get_first_options, load_text
|
||||
from ethstaker_deposit.utils.validation import validate_int_range
|
||||
from .generate_keys import (
|
||||
generate_keys,
|
||||
generate_keys_arguments_decorator,
|
||||
)
|
||||
|
||||
|
||||
def load_mnemonic_arguments_decorator(function: Callable[..., Any]) -> Callable[..., Any]:
|
||||
'''
|
||||
This is a decorator that, when applied to a parent-command, implements the
|
||||
to obtain the necessary arguments for the generate_keys() subcommand.
|
||||
'''
|
||||
decorators = [
|
||||
jit_option(
|
||||
callback=lambda c, _, mnemonic:
|
||||
captive_prompt_callback(
|
||||
lambda mnemonic: validate_mnemonic(mnemonic=mnemonic, language=c.params.get('mnemonic_language')),
|
||||
prompt=lambda: load_text(['arg_mnemonic', 'prompt'], func='existing_mnemonic'),
|
||||
prompt_if=prompt_if_none,
|
||||
)(c, _, mnemonic),
|
||||
help=lambda: load_text(['arg_mnemonic', 'help'], func='existing_mnemonic'),
|
||||
param_decls='--mnemonic',
|
||||
prompt=False,
|
||||
type=str,
|
||||
),
|
||||
jit_option(
|
||||
callback=captive_prompt_callback(
|
||||
lambda x: x,
|
||||
lambda: load_text(['arg_mnemonic_password', 'prompt'], func='existing_mnemonic'),
|
||||
lambda: load_text(['arg_mnemonic_password', 'confirm'], func='existing_mnemonic'),
|
||||
lambda: load_text(['arg_mnemonic_password', 'mismatch'], func='existing_mnemonic'),
|
||||
hide_input=True,
|
||||
),
|
||||
default='',
|
||||
help=lambda: load_text(['arg_mnemonic_password', 'help'], func='existing_mnemonic'),
|
||||
hidden=True,
|
||||
param_decls='--mnemonic_password',
|
||||
prompt=False,
|
||||
),
|
||||
jit_option(
|
||||
callback=validate_mnemonic_language,
|
||||
default=None,
|
||||
help=lambda: load_text(['arg_mnemonic_language', 'help'], func='existing_mnemonic'),
|
||||
param_decls='--mnemonic_language',
|
||||
prompt=None,
|
||||
),
|
||||
]
|
||||
for decorator in reversed(decorators):
|
||||
function = decorator(function)
|
||||
return function
|
||||
|
||||
|
||||
def validate_mnemonic(mnemonic: str, language: Optional[str] = None) -> str:
|
||||
try:
|
||||
reconstructed_mnemonic = reconstruct_mnemonic(mnemonic, WORD_LISTS_PATH, language)
|
||||
except MultiLanguageError as e:
|
||||
# Get discovered languages from error and prompt user to select one of them
|
||||
available_languages = sorted(get_first_options({lang: MNEMONIC_LANG_OPTIONS[lang] for lang in e.languages}))
|
||||
prompt_message = choice_prompt_func(lambda: load_text(['arg_mnemonic_language'], func='validate_mnemonic'),
|
||||
available_languages,
|
||||
False)
|
||||
language = click.prompt(prompt_message())
|
||||
mnemonic_language = fuzzy_reverse_dict_lookup(language, MNEMONIC_LANG_OPTIONS)
|
||||
return validate_mnemonic(mnemonic=mnemonic, language=mnemonic_language)
|
||||
|
||||
if reconstructed_mnemonic is not None:
|
||||
return reconstructed_mnemonic
|
||||
else:
|
||||
raise ValidationError(load_text(['err_invalid_mnemonic']))
|
||||
|
||||
|
||||
def validate_mnemonic_language(ctx: click.Context, param: Any, language: str) -> Optional[str]:
|
||||
return fuzzy_reverse_dict_lookup(language, MNEMONIC_LANG_OPTIONS) if language else None
|
||||
|
||||
|
||||
@click.command(
|
||||
help=load_text(['arg_existing_mnemonic', 'help'], func='existing_mnemonic'),
|
||||
)
|
||||
@load_mnemonic_arguments_decorator
|
||||
@jit_option(
|
||||
callback=captive_prompt_callback(
|
||||
lambda num: validate_int_range(num, 0, 2**32),
|
||||
lambda: load_text(['arg_validator_start_index', 'prompt'], func='existing_mnemonic'),
|
||||
lambda: load_text(['arg_validator_start_index', 'confirm'], func='existing_mnemonic'),
|
||||
prompt_if=prompt_if_none,
|
||||
),
|
||||
default=0,
|
||||
help=lambda: load_text(['arg_validator_start_index', 'help'], func='existing_mnemonic'),
|
||||
param_decls="--validator_start_index",
|
||||
prompt=False, # the callback handles the prompt
|
||||
)
|
||||
@generate_keys_arguments_decorator
|
||||
@click.pass_context
|
||||
def existing_mnemonic(ctx: click.Context, mnemonic: str, mnemonic_password: str, **kwargs: Any) -> None:
|
||||
ctx.obj = {} if ctx.obj is None else ctx.obj # Create a new ctx.obj if it doesn't exist
|
||||
ctx.obj.update({'mnemonic': mnemonic, 'mnemonic_password': mnemonic_password})
|
||||
# Clear clipboard
|
||||
try: # Failing this on headless Linux is expected
|
||||
if not config.non_interactive:
|
||||
click.pause(load_text(['msg_confirm_clipboard_clearing']))
|
||||
pyperclip.copy(' ')
|
||||
except Exception:
|
||||
pass
|
||||
ctx.forward(generate_keys)
|
||||
150
src/vendors/ethstaker-deposit-cli-0.5.0/ethstaker_deposit/cli/exit_transaction_keystore.py
vendored
Normal file
150
src/vendors/ethstaker-deposit-cli-0.5.0/ethstaker_deposit/cli/exit_transaction_keystore.py
vendored
Normal file
@@ -0,0 +1,150 @@
|
||||
import click
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
from typing import Any, Optional
|
||||
|
||||
from ethstaker_deposit.exceptions import ValidationError
|
||||
from ethstaker_deposit.utils.exit_transaction import exit_transaction_generation, export_exit_transaction_json
|
||||
from ethstaker_deposit.key_handling.keystore import Keystore
|
||||
from ethstaker_deposit.settings import (
|
||||
MAINNET,
|
||||
ALL_CHAIN_KEYS,
|
||||
get_chain_setting,
|
||||
BaseChainSetting,
|
||||
)
|
||||
from ethstaker_deposit.utils import config
|
||||
from ethstaker_deposit.utils.click import (
|
||||
captive_prompt_callback,
|
||||
choice_prompt_func,
|
||||
jit_option,
|
||||
prompt_if_none,
|
||||
prompt_if_other_is_none,
|
||||
)
|
||||
from ethstaker_deposit.utils.constants import DEFAULT_EXIT_TRANSACTION_FOLDER_NAME
|
||||
from ethstaker_deposit.utils.intl import (
|
||||
closest_match,
|
||||
load_text,
|
||||
)
|
||||
from ethstaker_deposit.utils.validation import (
|
||||
validate_int_range,
|
||||
validate_keystore_file,
|
||||
verify_signed_exit_json,
|
||||
validate_devnet_chain_setting,
|
||||
)
|
||||
|
||||
|
||||
FUNC_NAME = 'exit_transaction_keystore'
|
||||
|
||||
|
||||
@click.command(
|
||||
help=load_text(['arg_exit_transaction_keystore', 'help'], func=FUNC_NAME),
|
||||
)
|
||||
@jit_option(
|
||||
callback=captive_prompt_callback(
|
||||
lambda x: closest_match(x, ALL_CHAIN_KEYS),
|
||||
choice_prompt_func(
|
||||
lambda: load_text(['arg_exit_transaction_keystore_chain', 'prompt'], func=FUNC_NAME),
|
||||
ALL_CHAIN_KEYS
|
||||
),
|
||||
prompt_if=prompt_if_other_is_none('devnet_chain_setting'),
|
||||
default=MAINNET,
|
||||
),
|
||||
default=MAINNET,
|
||||
help=lambda: load_text(['arg_exit_transaction_keystore_chain', 'help'], func=FUNC_NAME),
|
||||
param_decls='--chain',
|
||||
prompt=False, # the callback handles the prompt
|
||||
)
|
||||
@jit_option(
|
||||
callback=captive_prompt_callback(
|
||||
lambda file: validate_keystore_file(file),
|
||||
lambda: load_text(['arg_exit_transaction_keystore_keystore', 'prompt'], func=FUNC_NAME),
|
||||
prompt_if=prompt_if_none,
|
||||
),
|
||||
help=lambda: load_text(['arg_exit_transaction_keystore_keystore', 'help'], func=FUNC_NAME),
|
||||
param_decls='--keystore',
|
||||
prompt=False,
|
||||
)
|
||||
@jit_option(
|
||||
callback=captive_prompt_callback(
|
||||
lambda x: x,
|
||||
lambda: load_text(['arg_exit_transaction_keystore_keystore_password', 'prompt'], func=FUNC_NAME),
|
||||
None,
|
||||
lambda: load_text(['arg_exit_transaction_keystore_keystore_password', 'invalid'], func=FUNC_NAME),
|
||||
True,
|
||||
),
|
||||
help=lambda: load_text(['arg_exit_transaction_keystore_keystore_password', 'help'], func=FUNC_NAME),
|
||||
hide_input=True,
|
||||
param_decls='--keystore_password',
|
||||
prompt=lambda: load_text(['arg_exit_transaction_keystore_keystore_password', 'prompt'], func=FUNC_NAME),
|
||||
)
|
||||
@jit_option(
|
||||
callback=captive_prompt_callback(
|
||||
lambda num: validate_int_range(num, 0, 2**32),
|
||||
lambda: load_text(['arg_validator_index', 'prompt'], func=FUNC_NAME),
|
||||
),
|
||||
help=lambda: load_text(['arg_validator_index', 'help'], func=FUNC_NAME),
|
||||
param_decls='--validator_index',
|
||||
prompt=lambda: load_text(['arg_validator_index', 'prompt'], func=FUNC_NAME),
|
||||
)
|
||||
@jit_option(
|
||||
default=0,
|
||||
help=lambda: load_text(['arg_exit_transaction_keystore_epoch', 'help'], func=FUNC_NAME),
|
||||
param_decls='--epoch',
|
||||
)
|
||||
@jit_option(
|
||||
default=os.getcwd(),
|
||||
help=lambda: load_text(['arg_exit_transaction_keystore_output_folder', 'help'], func=FUNC_NAME),
|
||||
param_decls='--output_folder',
|
||||
type=click.Path(exists=True, file_okay=False, dir_okay=True),
|
||||
)
|
||||
@jit_option(
|
||||
callback=validate_devnet_chain_setting,
|
||||
default=None,
|
||||
help=lambda: load_text(['arg_devnet_chain_setting', 'help'], func=FUNC_NAME),
|
||||
param_decls='--devnet_chain_setting',
|
||||
is_eager=True,
|
||||
)
|
||||
@click.pass_context
|
||||
def exit_transaction_keystore(
|
||||
ctx: click.Context,
|
||||
chain: str,
|
||||
keystore: Keystore,
|
||||
keystore_password: str,
|
||||
validator_index: int,
|
||||
epoch: int,
|
||||
output_folder: str,
|
||||
devnet_chain_setting: Optional[BaseChainSetting],
|
||||
**kwargs: Any) -> None:
|
||||
try:
|
||||
secret_bytes = keystore.decrypt(keystore_password)
|
||||
except ValueError:
|
||||
click.echo(load_text(['arg_exit_transaction_keystore_keystore_password', 'mismatch']), err=True)
|
||||
sys.exit(1)
|
||||
|
||||
signing_key = int.from_bytes(secret_bytes, 'big')
|
||||
|
||||
# Get chain setting
|
||||
chain_setting = devnet_chain_setting if devnet_chain_setting is not None else get_chain_setting(chain)
|
||||
|
||||
signed_exit = exit_transaction_generation(
|
||||
chain_setting=chain_setting,
|
||||
signing_key=signing_key,
|
||||
validator_index=validator_index,
|
||||
epoch=epoch,
|
||||
)
|
||||
|
||||
folder = os.path.join(output_folder, DEFAULT_EXIT_TRANSACTION_FOLDER_NAME)
|
||||
if not os.path.exists(folder):
|
||||
os.mkdir(folder)
|
||||
|
||||
click.echo(load_text(['msg_exit_transaction_creation']))
|
||||
saved_folder = export_exit_transaction_json(folder=folder, signed_exit=signed_exit, timestamp=time.time())
|
||||
|
||||
click.echo(load_text(['msg_verify_exit_transaction']))
|
||||
if (not verify_signed_exit_json(saved_folder, keystore.pubkey, chain_setting)):
|
||||
raise ValidationError(load_text(['err_verify_exit_transaction']))
|
||||
|
||||
click.echo(load_text(['msg_creation_success']) + saved_folder)
|
||||
if not config.non_interactive:
|
||||
click.pause(load_text(['msg_pause']))
|
||||
190
src/vendors/ethstaker-deposit-cli-0.5.0/ethstaker_deposit/cli/exit_transaction_mnemonic.py
vendored
Normal file
190
src/vendors/ethstaker-deposit-cli-0.5.0/ethstaker_deposit/cli/exit_transaction_mnemonic.py
vendored
Normal file
@@ -0,0 +1,190 @@
|
||||
import click
|
||||
import concurrent.futures
|
||||
import os
|
||||
import time
|
||||
|
||||
from typing import Any, Sequence, Dict, Optional
|
||||
from ethstaker_deposit.cli.existing_mnemonic import load_mnemonic_arguments_decorator
|
||||
from ethstaker_deposit.credentials import Credential
|
||||
from ethstaker_deposit.exceptions import ValidationError
|
||||
from ethstaker_deposit.settings import (
|
||||
MAINNET,
|
||||
ALL_CHAIN_KEYS,
|
||||
get_chain_setting,
|
||||
BaseChainSetting,
|
||||
)
|
||||
from ethstaker_deposit.utils import config
|
||||
from ethstaker_deposit.utils.click import (
|
||||
captive_prompt_callback,
|
||||
choice_prompt_func,
|
||||
jit_option,
|
||||
prompt_if_other_is_none,
|
||||
)
|
||||
from ethstaker_deposit.utils.constants import DEFAULT_EXIT_TRANSACTION_FOLDER_NAME
|
||||
from ethstaker_deposit.utils.intl import (
|
||||
closest_match,
|
||||
load_text,
|
||||
)
|
||||
from ethstaker_deposit.utils.validation import (
|
||||
validate_int_range,
|
||||
validate_validator_indices,
|
||||
verify_signed_exit_json,
|
||||
validate_devnet_chain_setting,
|
||||
)
|
||||
|
||||
|
||||
def _credential_builder(kwargs: Dict[str, Any]) -> Credential:
|
||||
return Credential(**kwargs)
|
||||
|
||||
|
||||
def _exit_exporter(kwargs: Dict[str, Any]) -> str:
|
||||
credential: Credential = kwargs.pop('credential')
|
||||
return credential.save_exit_transaction(**kwargs)
|
||||
|
||||
|
||||
def _exit_verifier(kwargs: Dict[str, Any]) -> bool:
|
||||
credential: Credential = kwargs.pop('credential')
|
||||
kwargs['pubkey'] = credential.signing_pk.hex()
|
||||
kwargs['chain_setting'] = credential.chain_setting
|
||||
return verify_signed_exit_json(**kwargs)
|
||||
|
||||
|
||||
FUNC_NAME = 'exit_transaction_mnemonic'
|
||||
|
||||
|
||||
@click.command(
|
||||
help=load_text(['arg_exit_transaction_mnemonic', 'help'], func=FUNC_NAME),
|
||||
)
|
||||
@jit_option(
|
||||
callback=captive_prompt_callback(
|
||||
lambda x: closest_match(x, ALL_CHAIN_KEYS),
|
||||
choice_prompt_func(
|
||||
lambda: load_text(['arg_exit_transaction_mnemonic_chain', 'prompt'], func=FUNC_NAME),
|
||||
ALL_CHAIN_KEYS
|
||||
),
|
||||
prompt_if=prompt_if_other_is_none('devnet_chain_setting'),
|
||||
default=MAINNET,
|
||||
),
|
||||
default=MAINNET,
|
||||
help=lambda: load_text(['arg_exit_transaction_mnemonic_chain', 'help'], func=FUNC_NAME),
|
||||
param_decls='--chain',
|
||||
prompt=False, # the callback handles the prompt
|
||||
)
|
||||
@load_mnemonic_arguments_decorator
|
||||
@jit_option(
|
||||
callback=captive_prompt_callback(
|
||||
lambda num: validate_int_range(num, 0, 2**32),
|
||||
lambda: load_text(['arg_exit_transaction_mnemonic_start_index', 'prompt'], func=FUNC_NAME),
|
||||
),
|
||||
default=0,
|
||||
help=lambda: load_text(['arg_exit_transaction_mnemonic_start_index', 'help'], func=FUNC_NAME),
|
||||
param_decls="--validator_start_index",
|
||||
prompt=lambda: load_text(['arg_exit_transaction_mnemonic_start_index', 'prompt'], func=FUNC_NAME),
|
||||
)
|
||||
@jit_option(
|
||||
callback=captive_prompt_callback(
|
||||
lambda validator_indices: validate_validator_indices(validator_indices),
|
||||
lambda: load_text(['arg_exit_transaction_mnemonic_indices', 'prompt'], func=FUNC_NAME),
|
||||
),
|
||||
help=lambda: load_text(['arg_exit_transaction_mnemonic_indices', 'help'], func=FUNC_NAME),
|
||||
param_decls='--validator_indices',
|
||||
prompt=lambda: load_text(['arg_exit_transaction_mnemonic_indices', 'prompt'], func=FUNC_NAME),
|
||||
)
|
||||
@jit_option(
|
||||
default=0,
|
||||
help=lambda: load_text(['arg_exit_transaction_mnemonic_epoch', 'help'], func=FUNC_NAME),
|
||||
param_decls='--epoch',
|
||||
)
|
||||
@jit_option(
|
||||
default=os.getcwd(),
|
||||
help=lambda: load_text(['arg_exit_transaction_mnemonic_output_folder', 'help'], func=FUNC_NAME),
|
||||
param_decls='--output_folder',
|
||||
type=click.Path(exists=True, file_okay=False, dir_okay=True),
|
||||
)
|
||||
@jit_option(
|
||||
callback=validate_devnet_chain_setting,
|
||||
default=None,
|
||||
help=lambda: load_text(['arg_devnet_chain_setting', 'help'], func=FUNC_NAME),
|
||||
param_decls='--devnet_chain_setting',
|
||||
is_eager=True,
|
||||
)
|
||||
@click.pass_context
|
||||
def exit_transaction_mnemonic(
|
||||
ctx: click.Context,
|
||||
chain: str,
|
||||
mnemonic: str,
|
||||
mnemonic_password: str,
|
||||
validator_start_index: int,
|
||||
validator_indices: Sequence[int],
|
||||
epoch: int,
|
||||
output_folder: str,
|
||||
devnet_chain_setting: Optional[BaseChainSetting],
|
||||
**kwargs: Any) -> None:
|
||||
|
||||
folder = os.path.join(output_folder, DEFAULT_EXIT_TRANSACTION_FOLDER_NAME)
|
||||
|
||||
# Get chain setting
|
||||
chain_setting = devnet_chain_setting if devnet_chain_setting is not None else get_chain_setting(chain)
|
||||
|
||||
num_keys = len(validator_indices)
|
||||
key_indices = range(validator_start_index, validator_start_index + num_keys)
|
||||
|
||||
# We are not using CredentialList because from_mnemonic assumes key generation flow
|
||||
credentials = []
|
||||
with click.progressbar(length=num_keys, label=load_text(['msg_key_creation']), # type: ignore[var-annotated]
|
||||
show_percent=False, show_pos=True) as bar:
|
||||
|
||||
executor_kwargs = [{
|
||||
'mnemonic': mnemonic,
|
||||
'mnemonic_password': mnemonic_password,
|
||||
'index': index,
|
||||
'amount': 0,
|
||||
'chain_setting': chain_setting,
|
||||
'hex_withdrawal_address': None,
|
||||
'compounding': False,
|
||||
} for index in key_indices]
|
||||
|
||||
with concurrent.futures.ProcessPoolExecutor() as executor:
|
||||
for credential in executor.map(_credential_builder, executor_kwargs):
|
||||
credentials.append(credential)
|
||||
bar.update(1)
|
||||
|
||||
if not os.path.exists(folder):
|
||||
os.mkdir(folder)
|
||||
|
||||
transaction_filefolders = []
|
||||
with click.progressbar(length=num_keys, # type: ignore[var-annotated]
|
||||
label=load_text(['msg_exit_transaction_creation']),
|
||||
show_percent=False, show_pos=True) as bar:
|
||||
|
||||
executor_kwargs = [{
|
||||
'credential': credential,
|
||||
'validator_index': validator_index,
|
||||
'epoch': epoch,
|
||||
'folder': folder,
|
||||
'timestamp': time.time(),
|
||||
} for credential, validator_index in zip(credentials, validator_indices)]
|
||||
|
||||
with concurrent.futures.ProcessPoolExecutor() as executor:
|
||||
for filefolder in executor.map(_exit_exporter, executor_kwargs):
|
||||
transaction_filefolders.append(filefolder)
|
||||
bar.update(1)
|
||||
|
||||
with click.progressbar(length=num_keys, # type: ignore[var-annotated]
|
||||
label=load_text(['msg_verify_exit_transaction']),
|
||||
show_percent=False, show_pos=True) as bar:
|
||||
|
||||
executor_kwargs = [{
|
||||
'file_folder': file,
|
||||
'credential': credential,
|
||||
} for file, credential in zip(transaction_filefolders, credentials)]
|
||||
|
||||
with concurrent.futures.ProcessPoolExecutor() as executor:
|
||||
for valid_exit in executor.map(_exit_verifier, executor_kwargs):
|
||||
bar.update(1)
|
||||
if not valid_exit:
|
||||
raise ValidationError(load_text(['err_verify_exit_transactions']))
|
||||
|
||||
click.echo(load_text(['msg_creation_success']) + folder)
|
||||
if not config.non_interactive:
|
||||
click.pause(load_text(['msg_pause']))
|
||||
@@ -1,52 +1,67 @@
|
||||
import os
|
||||
import click
|
||||
import json
|
||||
import concurrent.futures
|
||||
from typing import (
|
||||
Any,
|
||||
Sequence,
|
||||
Dict,
|
||||
Optional
|
||||
)
|
||||
|
||||
from eth_typing import HexAddress
|
||||
|
||||
from staking_deposit.credentials import (
|
||||
from ethstaker_deposit.credentials import (
|
||||
CredentialList,
|
||||
Credential
|
||||
)
|
||||
from staking_deposit.utils.validation import (
|
||||
from ethstaker_deposit.utils.ascii_art import OWL_0
|
||||
from ethstaker_deposit.utils.validation import (
|
||||
validate_bls_withdrawal_credentials_list,
|
||||
validate_bls_withdrawal_credentials_matching,
|
||||
validate_eth1_withdrawal_address,
|
||||
validate_withdrawal_address,
|
||||
validate_int_range,
|
||||
verify_bls_to_execution_change_json,
|
||||
validate_validator_indices,
|
||||
validate_devnet_chain_setting,
|
||||
)
|
||||
from staking_deposit.utils.constants import (
|
||||
from ethstaker_deposit.utils.constants import (
|
||||
DEFAULT_BLS_TO_EXECUTION_CHANGES_FOLDER_NAME,
|
||||
MAX_DEPOSIT_AMOUNT,
|
||||
MIN_ACTIVATION_AMOUNT,
|
||||
)
|
||||
from staking_deposit.utils.click import (
|
||||
from ethstaker_deposit.utils.click import (
|
||||
captive_prompt_callback,
|
||||
choice_prompt_func,
|
||||
jit_option,
|
||||
prompt_if_none,
|
||||
prompt_if_other_is_none,
|
||||
)
|
||||
from staking_deposit.exceptions import ValidationError
|
||||
from staking_deposit.utils.intl import (
|
||||
from ethstaker_deposit.exceptions import ValidationError
|
||||
from ethstaker_deposit.utils.intl import (
|
||||
closest_match,
|
||||
load_text,
|
||||
)
|
||||
from staking_deposit.settings import (
|
||||
ALL_CHAINS,
|
||||
from ethstaker_deposit.utils import config
|
||||
from ethstaker_deposit.utils.terminal import clear_terminal
|
||||
from ethstaker_deposit.settings import (
|
||||
MAINNET,
|
||||
PRATER,
|
||||
ALL_CHAIN_KEYS,
|
||||
get_chain_setting,
|
||||
get_devnet_chain_setting,
|
||||
BaseChainSetting,
|
||||
)
|
||||
from .existing_mnemonic import (
|
||||
load_mnemonic_arguments_decorator,
|
||||
)
|
||||
|
||||
|
||||
def get_password(text: str) -> str:
|
||||
return click.prompt(text, hide_input=True, show_default=False, type=str)
|
||||
def _validate_credentials_match(kwargs: Dict[str, Any]) -> Optional[ValidationError]:
|
||||
credential: Credential = kwargs.pop('credential')
|
||||
bls_withdrawal_credentials: bytes = kwargs.pop('bls_withdrawal_credentials')
|
||||
|
||||
try:
|
||||
validate_bls_withdrawal_credentials_matching(bls_withdrawal_credentials, credential)
|
||||
except ValidationError as e:
|
||||
return e
|
||||
return None
|
||||
|
||||
|
||||
FUNC_NAME = 'generate_bls_to_execution_change'
|
||||
@@ -63,20 +78,18 @@ FUNC_NAME = 'generate_bls_to_execution_change'
|
||||
)
|
||||
@jit_option(
|
||||
callback=captive_prompt_callback(
|
||||
lambda x: closest_match(x, list(ALL_CHAINS.keys())),
|
||||
lambda x: closest_match(x, ALL_CHAIN_KEYS),
|
||||
choice_prompt_func(
|
||||
lambda: load_text(['arg_chain', 'prompt'], func=FUNC_NAME),
|
||||
list(ALL_CHAINS.keys())
|
||||
ALL_CHAIN_KEYS
|
||||
),
|
||||
prompt_if=prompt_if_other_is_none('devnet_chain_setting'),
|
||||
default=MAINNET,
|
||||
),
|
||||
default=MAINNET,
|
||||
help=lambda: load_text(['arg_chain', 'help'], func=FUNC_NAME),
|
||||
param_decls='--chain',
|
||||
prompt=choice_prompt_func(
|
||||
lambda: load_text(['arg_chain', 'prompt'], func=FUNC_NAME),
|
||||
# Since `prater` is alias of `goerli`, do not show `prater` in the prompt message.
|
||||
list(key for key in ALL_CHAINS.keys() if key != PRATER)
|
||||
),
|
||||
prompt=False, # the callback handles the prompt
|
||||
)
|
||||
@load_mnemonic_arguments_decorator
|
||||
@jit_option(
|
||||
@@ -103,27 +116,30 @@ FUNC_NAME = 'generate_bls_to_execution_change'
|
||||
lambda bls_withdrawal_credentials_list:
|
||||
validate_bls_withdrawal_credentials_list(bls_withdrawal_credentials_list),
|
||||
lambda: load_text(['arg_bls_withdrawal_credentials_list', 'prompt'], func=FUNC_NAME),
|
||||
prompt_if=prompt_if_none,
|
||||
),
|
||||
help=lambda: load_text(['arg_bls_withdrawal_credentials_list', 'help'], func=FUNC_NAME),
|
||||
param_decls='--bls_withdrawal_credentials_list',
|
||||
prompt=lambda: load_text(['arg_bls_withdrawal_credentials_list', 'prompt'], func=FUNC_NAME),
|
||||
prompt=False, # the callback handles the prompt, to avoid second callback with bytes
|
||||
)
|
||||
@jit_option(
|
||||
callback=captive_prompt_callback(
|
||||
lambda address: validate_eth1_withdrawal_address(None, None, address),
|
||||
lambda: load_text(['arg_execution_address', 'prompt'], func=FUNC_NAME),
|
||||
lambda: load_text(['arg_execution_address', 'confirm'], func=FUNC_NAME),
|
||||
lambda: load_text(['arg_execution_address', 'mismatch'], func=FUNC_NAME),
|
||||
lambda address: validate_withdrawal_address(None, None, address),
|
||||
lambda: load_text(['arg_withdrawal_address', 'prompt'], func=FUNC_NAME),
|
||||
lambda: load_text(['arg_withdrawal_address', 'confirm'], func=FUNC_NAME),
|
||||
lambda: load_text(['arg_withdrawal_address', 'mismatch'], func=FUNC_NAME),
|
||||
prompt_if=prompt_if_none,
|
||||
),
|
||||
help=lambda: load_text(['arg_execution_address', 'help'], func=FUNC_NAME),
|
||||
param_decls=['--execution_address', '--eth1_withdrawal_address'],
|
||||
prompt=lambda: load_text(['arg_execution_address', 'prompt'], func=FUNC_NAME),
|
||||
help=lambda: load_text(['arg_withdrawal_address', 'help'], func=FUNC_NAME),
|
||||
param_decls=['--withdrawal_address'],
|
||||
prompt=False, # the callback handles the prompt
|
||||
)
|
||||
@jit_option(
|
||||
# Only for devnet tests
|
||||
callback=validate_devnet_chain_setting,
|
||||
default=None,
|
||||
help="[DEVNET ONLY] Set specific GENESIS_FORK_VERSION value",
|
||||
help=lambda: load_text(['arg_devnet_chain_setting', 'help'], func=FUNC_NAME),
|
||||
param_decls='--devnet_chain_setting',
|
||||
is_eager=True,
|
||||
)
|
||||
@click.pass_context
|
||||
def generate_bls_to_execution_change(
|
||||
@@ -135,8 +151,8 @@ def generate_bls_to_execution_change(
|
||||
validator_start_index: int,
|
||||
validator_indices: Sequence[int],
|
||||
bls_withdrawal_credentials_list: Sequence[bytes],
|
||||
execution_address: HexAddress,
|
||||
devnet_chain_setting: str,
|
||||
withdrawal_address: HexAddress,
|
||||
devnet_chain_setting: Optional[BaseChainSetting],
|
||||
**kwargs: Any) -> None:
|
||||
# Generate folder
|
||||
bls_to_execution_changes_folder = os.path.join(
|
||||
@@ -147,16 +163,7 @@ def generate_bls_to_execution_change(
|
||||
os.mkdir(bls_to_execution_changes_folder)
|
||||
|
||||
# Get chain setting
|
||||
chain_setting = get_chain_setting(chain)
|
||||
|
||||
if devnet_chain_setting is not None:
|
||||
click.echo('\n%s\n' % '**[Warning] Using devnet chain setting to generate the SignedBLSToExecutionChange.**\t')
|
||||
devnet_chain_setting_dict = json.loads(devnet_chain_setting)
|
||||
chain_setting = get_devnet_chain_setting(
|
||||
network_name=devnet_chain_setting_dict['network_name'],
|
||||
genesis_fork_version=devnet_chain_setting_dict['genesis_fork_version'],
|
||||
genesis_validator_root=devnet_chain_setting_dict['genesis_validator_root'],
|
||||
)
|
||||
chain_setting = devnet_chain_setting if devnet_chain_setting is not None else get_chain_setting(chain)
|
||||
|
||||
if len(validator_indices) != len(bls_withdrawal_credentials_list):
|
||||
raise ValueError(
|
||||
@@ -165,7 +172,7 @@ def generate_bls_to_execution_change(
|
||||
)
|
||||
|
||||
num_validators = len(validator_indices)
|
||||
amounts = [MAX_DEPOSIT_AMOUNT] * num_validators
|
||||
amounts = [MIN_ACTIVATION_AMOUNT] * num_validators
|
||||
|
||||
credentials = CredentialList.from_mnemonic(
|
||||
mnemonic=mnemonic,
|
||||
@@ -174,16 +181,25 @@ def generate_bls_to_execution_change(
|
||||
amounts=amounts,
|
||||
chain_setting=chain_setting,
|
||||
start_index=validator_start_index,
|
||||
hex_eth1_withdrawal_address=execution_address,
|
||||
hex_withdrawal_address=withdrawal_address,
|
||||
compounding=False,
|
||||
)
|
||||
|
||||
# Check if the given old bls_withdrawal_credentials is as same as the mnemonic generated
|
||||
for i, credential in enumerate(credentials.credentials):
|
||||
try:
|
||||
validate_bls_withdrawal_credentials_matching(bls_withdrawal_credentials_list[i], credential)
|
||||
except ValidationError as e:
|
||||
click.echo('\n[Error] ' + str(e))
|
||||
return
|
||||
with click.progressbar(length=len(credentials.credentials), # type: ignore[var-annotated]
|
||||
label=load_text(['msg_credentials_verification']),
|
||||
show_percent=False, show_pos=True) as bar:
|
||||
executor_kwargs = [{
|
||||
'credential': credential,
|
||||
'bls_withdrawal_credentials': bls_withdrawal_credentials_list[i],
|
||||
} for i, credential in enumerate(credentials.credentials)]
|
||||
|
||||
with concurrent.futures.ProcessPoolExecutor() as executor:
|
||||
for e in executor.map(_validate_credentials_match, executor_kwargs):
|
||||
bar.update(1)
|
||||
if e is not None:
|
||||
click.echo('\n\n[Error] ' + str(e))
|
||||
return
|
||||
|
||||
btec_file = credentials.export_bls_to_execution_change_json(bls_to_execution_changes_folder, validator_indices)
|
||||
|
||||
@@ -191,12 +207,15 @@ def generate_bls_to_execution_change(
|
||||
btec_file,
|
||||
credentials.credentials,
|
||||
input_validator_indices=validator_indices,
|
||||
input_execution_address=execution_address,
|
||||
input_withdrawal_address=withdrawal_address,
|
||||
chain_setting=chain_setting,
|
||||
)
|
||||
if not json_file_validation_result:
|
||||
raise ValidationError(load_text(['err_verify_btec']))
|
||||
|
||||
clear_terminal()
|
||||
click.echo(OWL_0)
|
||||
click.echo(load_text(['msg_creation_success']) + str(bls_to_execution_changes_folder))
|
||||
|
||||
click.pause(load_text(['msg_pause']))
|
||||
if not config.non_interactive:
|
||||
click.pause(load_text(['msg_pause']))
|
||||
@@ -0,0 +1,167 @@
|
||||
import click
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
from typing import Any, Optional
|
||||
|
||||
from eth_typing import HexAddress
|
||||
|
||||
from ethstaker_deposit.bls_to_execution_change_keystore import (
|
||||
bls_to_execution_change_keystore_generation,
|
||||
export_bls_to_execution_change_keystore_json,
|
||||
)
|
||||
from ethstaker_deposit.exceptions import ValidationError
|
||||
from ethstaker_deposit.key_handling.keystore import Keystore
|
||||
from ethstaker_deposit.utils import config
|
||||
from ethstaker_deposit.utils.validation import (
|
||||
validate_withdrawal_address,
|
||||
validate_int_range,
|
||||
validate_keystore_file,
|
||||
verify_bls_to_execution_change_keystore_json,
|
||||
validate_devnet_chain_setting,
|
||||
)
|
||||
from ethstaker_deposit.utils.constants import (
|
||||
DEFAULT_BLS_TO_EXECUTION_CHANGES_KEYSTORE_FOLDER_NAME,
|
||||
)
|
||||
from ethstaker_deposit.utils.click import (
|
||||
captive_prompt_callback,
|
||||
choice_prompt_func,
|
||||
jit_option,
|
||||
prompt_if_none,
|
||||
prompt_if_other_is_none,
|
||||
)
|
||||
from ethstaker_deposit.utils.intl import (
|
||||
closest_match,
|
||||
load_text,
|
||||
)
|
||||
from ethstaker_deposit.settings import (
|
||||
MAINNET,
|
||||
ALL_CHAIN_KEYS,
|
||||
get_chain_setting,
|
||||
BaseChainSetting,
|
||||
)
|
||||
|
||||
|
||||
FUNC_NAME = 'generate_bls_to_execution_change_keystore'
|
||||
|
||||
|
||||
@click.command(
|
||||
help=load_text(['arg_generate_bls_to_execution_change', 'help'], func=FUNC_NAME),
|
||||
)
|
||||
@jit_option(
|
||||
callback=captive_prompt_callback(
|
||||
lambda x: closest_match(x, ALL_CHAIN_KEYS),
|
||||
choice_prompt_func(
|
||||
lambda: load_text(['arg_chain', 'prompt'], func=FUNC_NAME),
|
||||
ALL_CHAIN_KEYS
|
||||
),
|
||||
prompt_if=prompt_if_other_is_none('devnet_chain_setting'),
|
||||
default=MAINNET,
|
||||
),
|
||||
default=MAINNET,
|
||||
help=lambda: load_text(['arg_chain', 'help'], func=FUNC_NAME),
|
||||
param_decls='--chain',
|
||||
prompt=False, # the callback handles the prompt
|
||||
)
|
||||
@jit_option(
|
||||
callback=captive_prompt_callback(
|
||||
lambda file: validate_keystore_file(file),
|
||||
lambda: load_text(['arg_bls_to_execution_changes_keystore_keystore', 'prompt'], func=FUNC_NAME),
|
||||
prompt_if=prompt_if_none,
|
||||
),
|
||||
help=lambda: load_text(['arg_bls_to_execution_changes_keystore_keystore', 'help'], func=FUNC_NAME),
|
||||
param_decls='--keystore',
|
||||
prompt=False,
|
||||
)
|
||||
@jit_option(
|
||||
callback=captive_prompt_callback(
|
||||
lambda x: x,
|
||||
lambda: load_text(['arg_bls_to_execution_changes_keystore_keystore_password', 'prompt'], func=FUNC_NAME),
|
||||
None,
|
||||
lambda: load_text(['arg_bls_to_execution_changes_keystore_keystore_password', 'invalid'], func=FUNC_NAME),
|
||||
True,
|
||||
),
|
||||
help=lambda: load_text(['arg_bls_to_execution_changes_keystore_keystore_password', 'help'], func=FUNC_NAME),
|
||||
hide_input=True,
|
||||
param_decls='--keystore_password',
|
||||
prompt=lambda: load_text(['arg_bls_to_execution_changes_keystore_keystore_password', 'prompt'], func=FUNC_NAME),
|
||||
)
|
||||
@jit_option(
|
||||
callback=captive_prompt_callback(
|
||||
lambda num: validate_int_range(num, 0, 2**32),
|
||||
lambda: load_text(['arg_validator_index', 'prompt'], func=FUNC_NAME),
|
||||
),
|
||||
help=lambda: load_text(['arg_validator_index', 'help'], func=FUNC_NAME),
|
||||
param_decls='--validator_index',
|
||||
prompt=lambda: load_text(['arg_validator_index', 'prompt'], func=FUNC_NAME),
|
||||
)
|
||||
@jit_option(
|
||||
callback=captive_prompt_callback(
|
||||
lambda address: validate_withdrawal_address(None, None, address, True),
|
||||
lambda: load_text(['arg_withdrawal_address', 'prompt'], func=FUNC_NAME),
|
||||
lambda: load_text(['arg_withdrawal_address', 'confirm'], func=FUNC_NAME),
|
||||
lambda: load_text(['arg_withdrawal_address', 'mismatch'], func=FUNC_NAME),
|
||||
prompt_if=prompt_if_none,
|
||||
),
|
||||
help=lambda: load_text(['arg_withdrawal_address', 'help'], func=FUNC_NAME),
|
||||
param_decls=['--withdrawal_address'],
|
||||
prompt=False, # the callback handles the prompt
|
||||
)
|
||||
@jit_option(
|
||||
default=os.getcwd(),
|
||||
help=lambda: load_text(['arg_bls_to_execution_changes_keystore_output_folder', 'help'], func=FUNC_NAME),
|
||||
param_decls='--output_folder',
|
||||
type=click.Path(exists=True, file_okay=False, dir_okay=True),
|
||||
)
|
||||
@jit_option(
|
||||
callback=validate_devnet_chain_setting,
|
||||
default=None,
|
||||
help=lambda: load_text(['arg_devnet_chain_setting', 'help'], func=FUNC_NAME),
|
||||
param_decls='--devnet_chain_setting',
|
||||
is_eager=True,
|
||||
)
|
||||
@click.pass_context
|
||||
def generate_bls_to_execution_change_keystore(
|
||||
ctx: click.Context,
|
||||
chain: str,
|
||||
keystore: Keystore,
|
||||
keystore_password: str,
|
||||
validator_index: int,
|
||||
withdrawal_address: HexAddress,
|
||||
output_folder: str,
|
||||
devnet_chain_setting: Optional[BaseChainSetting],
|
||||
**kwargs: Any) -> None:
|
||||
try:
|
||||
secret_bytes = keystore.decrypt(keystore_password)
|
||||
except ValueError:
|
||||
click.echo(load_text(['arg_bls_to_execution_changes_keystore_keystore_password', 'mismatch']), err=True)
|
||||
sys.exit(1)
|
||||
|
||||
signing_key = int.from_bytes(secret_bytes, 'big')
|
||||
|
||||
# Get chain setting
|
||||
chain_setting = devnet_chain_setting if devnet_chain_setting is not None else get_chain_setting(chain)
|
||||
|
||||
signed_btec = bls_to_execution_change_keystore_generation(
|
||||
chain_setting=chain_setting,
|
||||
signing_key=signing_key,
|
||||
validator_index=validator_index,
|
||||
withdrawal_address=withdrawal_address,
|
||||
)
|
||||
|
||||
folder = os.path.join(output_folder, DEFAULT_BLS_TO_EXECUTION_CHANGES_KEYSTORE_FOLDER_NAME)
|
||||
if not os.path.exists(folder):
|
||||
os.mkdir(folder)
|
||||
|
||||
click.echo(load_text(['msg_key_creation']))
|
||||
saved_folder = export_bls_to_execution_change_keystore_json(folder=folder,
|
||||
signed_execution_change=signed_btec,
|
||||
timestamp=time.time())
|
||||
|
||||
click.echo(load_text(['msg_verify_btec']))
|
||||
if (not verify_bls_to_execution_change_keystore_json(saved_folder, keystore.pubkey, chain_setting)):
|
||||
raise ValidationError(load_text(['err_verify_btec']))
|
||||
|
||||
click.echo(load_text(['msg_creation_success']) + saved_folder)
|
||||
if not config.non_interactive:
|
||||
click.pause(load_text(['msg_pause']))
|
||||
209
src/vendors/ethstaker-deposit-cli-0.5.0/ethstaker_deposit/cli/generate_keys.py
vendored
Normal file
209
src/vendors/ethstaker-deposit-cli-0.5.0/ethstaker_deposit/cli/generate_keys.py
vendored
Normal file
@@ -0,0 +1,209 @@
|
||||
import click
|
||||
import os
|
||||
import time
|
||||
from typing import (
|
||||
Any,
|
||||
Callable,
|
||||
Optional,
|
||||
)
|
||||
|
||||
from eth_typing import HexAddress
|
||||
from ethstaker_deposit.credentials import (
|
||||
CredentialList,
|
||||
)
|
||||
from ethstaker_deposit.exceptions import ValidationError
|
||||
from ethstaker_deposit.utils import config
|
||||
from ethstaker_deposit.utils.validation import (
|
||||
verify_deposit_data_json,
|
||||
validate_int_range,
|
||||
validate_password_strength,
|
||||
validate_withdrawal_address,
|
||||
validate_yesno,
|
||||
validate_deposit_amount,
|
||||
validate_devnet_chain_setting,
|
||||
)
|
||||
from ethstaker_deposit.utils.constants import (
|
||||
DEFAULT_VALIDATOR_KEYS_FOLDER_NAME,
|
||||
MIN_ACTIVATION_AMOUNT,
|
||||
ETH2GWEI,
|
||||
)
|
||||
from ethstaker_deposit.utils.ascii_art import RHINO_0
|
||||
from ethstaker_deposit.utils.click import (
|
||||
captive_prompt_callback,
|
||||
choice_prompt_func,
|
||||
jit_option,
|
||||
prompt_if_none,
|
||||
prompt_if_other_is_none,
|
||||
prompt_if_other_exists,
|
||||
prompt_if_other_value,
|
||||
)
|
||||
from ethstaker_deposit.utils.intl import (
|
||||
closest_match,
|
||||
load_text,
|
||||
)
|
||||
from ethstaker_deposit.utils.terminal import clear_terminal
|
||||
from ethstaker_deposit.settings import (
|
||||
MAINNET,
|
||||
ALL_CHAIN_KEYS,
|
||||
get_chain_setting,
|
||||
BaseChainSetting,
|
||||
)
|
||||
|
||||
|
||||
min_activation_amount_eth = MIN_ACTIVATION_AMOUNT // ETH2GWEI
|
||||
|
||||
|
||||
def generate_keys_arguments_decorator(function: Callable[..., Any]) -> Callable[..., Any]:
|
||||
'''
|
||||
This is a decorator that, when applied to a parent-command, implements the
|
||||
to obtain the necessary arguments for the generate_keys() subcommand.
|
||||
'''
|
||||
decorators = [
|
||||
jit_option(
|
||||
callback=captive_prompt_callback(
|
||||
lambda num: validate_int_range(num, 1, 2**32),
|
||||
lambda: load_text(['num_validators', 'prompt'], func='generate_keys_arguments_decorator')
|
||||
),
|
||||
help=lambda: load_text(['num_validators', 'help'], func='generate_keys_arguments_decorator'),
|
||||
param_decls="--num_validators",
|
||||
prompt=lambda: load_text(['num_validators', 'prompt'], func='generate_keys_arguments_decorator'),
|
||||
),
|
||||
jit_option(
|
||||
default=os.getcwd(),
|
||||
help=lambda: load_text(['folder', 'help'], func='generate_keys_arguments_decorator'),
|
||||
param_decls='--folder',
|
||||
type=click.Path(exists=True, file_okay=False, dir_okay=True),
|
||||
),
|
||||
jit_option(
|
||||
callback=captive_prompt_callback(
|
||||
lambda x: closest_match(x, ALL_CHAIN_KEYS),
|
||||
choice_prompt_func(
|
||||
lambda: load_text(['chain', 'prompt'], func='generate_keys_arguments_decorator'),
|
||||
ALL_CHAIN_KEYS
|
||||
),
|
||||
prompt_if=prompt_if_other_is_none('devnet_chain_setting'),
|
||||
default=MAINNET,
|
||||
),
|
||||
default=MAINNET,
|
||||
help=lambda: load_text(['chain', 'help'], func='generate_keys_arguments_decorator'),
|
||||
param_decls='--chain',
|
||||
prompt=False, # the callback handles the prompt
|
||||
),
|
||||
jit_option(
|
||||
callback=captive_prompt_callback(
|
||||
validate_password_strength,
|
||||
lambda: load_text(['keystore_password', 'prompt'], func='generate_keys_arguments_decorator'),
|
||||
lambda: load_text(['keystore_password', 'confirm'], func='generate_keys_arguments_decorator'),
|
||||
lambda: load_text(['keystore_password', 'mismatch'], func='generate_keys_arguments_decorator'),
|
||||
True,
|
||||
prompt_if=prompt_if_none,
|
||||
),
|
||||
help=lambda: load_text(['keystore_password', 'help'], func='generate_keys_arguments_decorator'),
|
||||
hide_input=True,
|
||||
param_decls='--keystore_password',
|
||||
prompt=False, # the callback handles the prompt
|
||||
),
|
||||
jit_option(
|
||||
callback=captive_prompt_callback(
|
||||
lambda address: validate_withdrawal_address(None, None, address),
|
||||
lambda: load_text(['arg_withdrawal_address', 'prompt'], func='generate_keys_arguments_decorator'),
|
||||
lambda: load_text(['arg_withdrawal_address', 'confirm'], func='generate_keys_arguments_decorator'),
|
||||
lambda: load_text(['arg_withdrawal_address', 'mismatch'], func='generate_keys_arguments_decorator'),
|
||||
default="",
|
||||
prompt_if=prompt_if_none,
|
||||
),
|
||||
default="",
|
||||
help=lambda: load_text(['arg_withdrawal_address', 'help'], func='generate_keys_arguments_decorator'),
|
||||
param_decls=['--withdrawal_address', '--execution_address', '--eth1_withdrawal_address'],
|
||||
prompt=False, # the callback handles the prompt
|
||||
),
|
||||
jit_option(
|
||||
callback=captive_prompt_callback(
|
||||
lambda value: validate_yesno(None, None, value),
|
||||
lambda: load_text(['arg_compounding', 'prompt'], func='generate_keys_arguments_decorator'),
|
||||
default="False",
|
||||
prompt_if=prompt_if_other_exists('withdrawal_address'),
|
||||
),
|
||||
default=False,
|
||||
help=lambda: load_text(['arg_compounding', 'help'], func='generate_keys_arguments_decorator'),
|
||||
param_decls='--compounding/--regular-withdrawal',
|
||||
prompt=False, # the callback handles the prompt
|
||||
type=bool,
|
||||
show_default=True,
|
||||
),
|
||||
jit_option(
|
||||
callback=captive_prompt_callback(
|
||||
lambda amount: validate_deposit_amount(amount),
|
||||
lambda: load_text(['arg_amount', 'prompt'], func='generate_keys_arguments_decorator'),
|
||||
default=str(min_activation_amount_eth),
|
||||
prompt_if=prompt_if_other_value('compounding', True),
|
||||
),
|
||||
default=str(min_activation_amount_eth),
|
||||
help=lambda: load_text(['arg_amount', 'help'], func='generate_keys_arguments_decorator'),
|
||||
param_decls='--amount',
|
||||
prompt=False, # the callback handles the prompt
|
||||
show_default=True,
|
||||
),
|
||||
jit_option(
|
||||
default=False,
|
||||
is_flag=True,
|
||||
param_decls='--pbkdf2',
|
||||
help=lambda: load_text(['arg_pbkdf2', 'help'], func='generate_keys_arguments_decorator'),
|
||||
),
|
||||
jit_option(
|
||||
callback=validate_devnet_chain_setting,
|
||||
default=None,
|
||||
help=lambda: load_text(['arg_devnet_chain_setting', 'help'], func='generate_keys_arguments_decorator'),
|
||||
param_decls='--devnet_chain_setting',
|
||||
is_eager=True,
|
||||
),
|
||||
]
|
||||
for decorator in reversed(decorators):
|
||||
function = decorator(function)
|
||||
return function
|
||||
|
||||
|
||||
@click.command()
|
||||
@click.pass_context
|
||||
def generate_keys(ctx: click.Context, validator_start_index: int,
|
||||
num_validators: int, folder: str, chain: str, keystore_password: str,
|
||||
withdrawal_address: HexAddress, compounding: bool, amount: int, pbkdf2: bool,
|
||||
devnet_chain_setting: Optional[BaseChainSetting], **kwargs: Any) -> None:
|
||||
mnemonic = ctx.obj['mnemonic']
|
||||
mnemonic_password = ctx.obj['mnemonic_password']
|
||||
if withdrawal_address is None or not compounding:
|
||||
amount = MIN_ACTIVATION_AMOUNT
|
||||
amounts = [amount] * num_validators
|
||||
folder = os.path.join(folder, DEFAULT_VALIDATOR_KEYS_FOLDER_NAME)
|
||||
|
||||
# Get chain setting
|
||||
chain_setting = devnet_chain_setting if devnet_chain_setting is not None else get_chain_setting(chain)
|
||||
|
||||
if not os.path.exists(folder):
|
||||
os.mkdir(folder)
|
||||
clear_terminal()
|
||||
click.echo(RHINO_0)
|
||||
click.echo(load_text(['msg_key_creation']))
|
||||
credentials = CredentialList.from_mnemonic(
|
||||
mnemonic=mnemonic,
|
||||
mnemonic_password=mnemonic_password,
|
||||
num_keys=num_validators,
|
||||
amounts=amounts,
|
||||
chain_setting=chain_setting,
|
||||
start_index=validator_start_index,
|
||||
hex_withdrawal_address=withdrawal_address,
|
||||
compounding=compounding,
|
||||
use_pbkdf2=pbkdf2
|
||||
)
|
||||
|
||||
timestamp = time.time()
|
||||
|
||||
keystore_filefolders = credentials.export_keystores(password=keystore_password, folder=folder, timestamp=timestamp)
|
||||
deposits_file = credentials.export_deposit_data_json(folder=folder, timestamp=timestamp)
|
||||
if not credentials.verify_keystores(keystore_filefolders=keystore_filefolders, password=keystore_password):
|
||||
raise ValidationError(load_text(['err_verify_keystores']))
|
||||
if not verify_deposit_data_json(deposits_file, credentials.credentials):
|
||||
raise ValidationError(load_text(['err_verify_deposit']))
|
||||
click.echo(load_text(['msg_creation_success']) + folder)
|
||||
if not config.non_interactive:
|
||||
click.pause(load_text(['msg_pause']))
|
||||
@@ -1,26 +1,28 @@
|
||||
import click
|
||||
import pyperclip
|
||||
from typing import (
|
||||
Any,
|
||||
)
|
||||
|
||||
from staking_deposit.key_handling.key_derivation.mnemonic import (
|
||||
from ethstaker_deposit.key_handling.key_derivation.mnemonic import (
|
||||
get_mnemonic,
|
||||
reconstruct_mnemonic,
|
||||
)
|
||||
from staking_deposit.utils.click import (
|
||||
from ethstaker_deposit.utils.click import (
|
||||
captive_prompt_callback,
|
||||
choice_prompt_func,
|
||||
jit_option,
|
||||
)
|
||||
from staking_deposit.utils.constants import (
|
||||
from ethstaker_deposit.utils.constants import (
|
||||
MNEMONIC_LANG_OPTIONS,
|
||||
WORD_LISTS_PATH,
|
||||
)
|
||||
from staking_deposit.utils.intl import (
|
||||
from ethstaker_deposit.utils.intl import (
|
||||
fuzzy_reverse_dict_lookup,
|
||||
load_text,
|
||||
get_first_options,
|
||||
)
|
||||
from ethstaker_deposit.utils.terminal import clear_terminal
|
||||
|
||||
from .generate_keys import (
|
||||
generate_keys,
|
||||
@@ -38,6 +40,7 @@ languages = get_first_options(MNEMONIC_LANG_OPTIONS)
|
||||
callback=captive_prompt_callback(
|
||||
lambda mnemonic_language: fuzzy_reverse_dict_lookup(mnemonic_language, MNEMONIC_LANG_OPTIONS),
|
||||
choice_prompt_func(lambda: load_text(['arg_mnemonic_language', 'prompt'], func='new_mnemonic'), languages),
|
||||
default=lambda: load_text(['arg_mnemonic_language', 'default'], func='new_mnemonic'),
|
||||
),
|
||||
default=lambda: load_text(['arg_mnemonic_language', 'default'], func='new_mnemonic'),
|
||||
help=lambda: load_text(['arg_mnemonic_language', 'help'], func='new_mnemonic'),
|
||||
@@ -48,15 +51,31 @@ languages = get_first_options(MNEMONIC_LANG_OPTIONS)
|
||||
def new_mnemonic(ctx: click.Context, mnemonic_language: str, **kwargs: Any) -> None:
|
||||
mnemonic = get_mnemonic(language=mnemonic_language, words_path=WORD_LISTS_PATH)
|
||||
test_mnemonic = ''
|
||||
while mnemonic != reconstruct_mnemonic(test_mnemonic, WORD_LISTS_PATH):
|
||||
click.clear()
|
||||
click.echo(load_text(['msg_mnemonic_presentation']))
|
||||
while mnemonic != reconstruct_mnemonic(test_mnemonic, WORD_LISTS_PATH, mnemonic_language):
|
||||
clear_terminal()
|
||||
click.echo(
|
||||
load_text(['msg_mnemonic_presentation'])
|
||||
+ '\n\n********************\n'
|
||||
+ load_text(['msg_mnemonic_clipboard_warning'])
|
||||
+ '\n********************'
|
||||
)
|
||||
click.echo('\n\n%s\n\n' % mnemonic)
|
||||
click.pause(load_text(['msg_press_any_key']))
|
||||
|
||||
click.clear()
|
||||
test_mnemonic = click.prompt(load_text(['msg_mnemonic_retype_prompt']) + '\n\n')
|
||||
click.clear()
|
||||
clear_terminal()
|
||||
test_mnemonic = click.prompt(
|
||||
load_text(['msg_mnemonic_retype_prompt'])
|
||||
+ '\n\n********************\n'
|
||||
+ load_text(['msg_mnemonic_clipboard_warning'])
|
||||
+ '\n********************\n\n'
|
||||
)
|
||||
clear_terminal()
|
||||
# Clear clipboard
|
||||
try: # Failing this on headless Linux is expected
|
||||
click.pause(load_text(['msg_confirm_clipboard_clearing']))
|
||||
pyperclip.copy(' ')
|
||||
except Exception:
|
||||
pass
|
||||
# Do NOT use mnemonic_password.
|
||||
ctx.obj = {'mnemonic': mnemonic, 'mnemonic_password': ''}
|
||||
ctx.params['validator_start_index'] = 0
|
||||
221
src/vendors/ethstaker-deposit-cli-0.5.0/ethstaker_deposit/cli/partial_deposit.py
vendored
Normal file
221
src/vendors/ethstaker-deposit-cli-0.5.0/ethstaker_deposit/cli/partial_deposit.py
vendored
Normal file
@@ -0,0 +1,221 @@
|
||||
import json
|
||||
import click
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
from eth_typing import HexAddress
|
||||
from eth_utils import to_canonical_address
|
||||
from py_ecc.bls import G2ProofOfPossession as bls
|
||||
from typing import Any, Optional
|
||||
|
||||
from ethstaker_deposit.key_handling.keystore import Keystore
|
||||
from ethstaker_deposit.settings import (
|
||||
fake_cli_version,
|
||||
MAINNET,
|
||||
ALL_CHAIN_KEYS,
|
||||
get_chain_setting,
|
||||
BaseChainSetting,
|
||||
)
|
||||
from ethstaker_deposit.utils import config
|
||||
from ethstaker_deposit.utils.click import (
|
||||
captive_prompt_callback,
|
||||
choice_prompt_func,
|
||||
jit_option,
|
||||
prompt_if_none,
|
||||
prompt_if_other_is_none,
|
||||
prompt_if_other_exists,
|
||||
)
|
||||
from ethstaker_deposit.utils.constants import (
|
||||
DEFAULT_PARTIAL_DEPOSIT_FOLDER_NAME,
|
||||
EXECUTION_ADDRESS_WITHDRAWAL_PREFIX,
|
||||
COMPOUNDING_WITHDRAWAL_PREFIX,
|
||||
)
|
||||
from ethstaker_deposit.utils.deposit import export_deposit_data_json
|
||||
from ethstaker_deposit.utils.intl import (
|
||||
closest_match,
|
||||
load_text,
|
||||
)
|
||||
from ethstaker_deposit.utils.ssz import (
|
||||
DepositData,
|
||||
DepositMessage,
|
||||
compute_deposit_domain,
|
||||
compute_signing_root,
|
||||
)
|
||||
from ethstaker_deposit.utils.validation import (
|
||||
validate_deposit,
|
||||
validate_keystore_file,
|
||||
validate_deposit_amount,
|
||||
validate_withdrawal_address,
|
||||
validate_yesno,
|
||||
validate_devnet_chain_setting,
|
||||
)
|
||||
|
||||
|
||||
FUNC_NAME = 'partial_deposit'
|
||||
|
||||
|
||||
@click.command(
|
||||
help=load_text(['arg_partial_deposit', 'help'], func=FUNC_NAME),
|
||||
)
|
||||
@jit_option(
|
||||
callback=captive_prompt_callback(
|
||||
lambda x: closest_match(x, ALL_CHAIN_KEYS),
|
||||
choice_prompt_func(
|
||||
lambda: load_text(['arg_partial_deposit_chain', 'prompt'], func=FUNC_NAME),
|
||||
ALL_CHAIN_KEYS
|
||||
),
|
||||
prompt_if=prompt_if_other_is_none('devnet_chain_setting'),
|
||||
default=MAINNET,
|
||||
),
|
||||
default=MAINNET,
|
||||
help=lambda: load_text(['arg_partial_deposit_chain', 'help'], func=FUNC_NAME),
|
||||
param_decls='--chain',
|
||||
prompt=False, # the callback handles the prompt
|
||||
)
|
||||
@jit_option(
|
||||
callback=captive_prompt_callback(
|
||||
lambda file: validate_keystore_file(file),
|
||||
lambda: load_text(['arg_partial_deposit_keystore', 'prompt'], func=FUNC_NAME),
|
||||
prompt_if=prompt_if_none,
|
||||
),
|
||||
help=lambda: load_text(['arg_partial_deposit_keystore', 'help'], func=FUNC_NAME),
|
||||
param_decls='--keystore',
|
||||
prompt=False,
|
||||
)
|
||||
@jit_option(
|
||||
callback=captive_prompt_callback(
|
||||
lambda x: x,
|
||||
lambda: load_text(['arg_partial_deposit_keystore_password', 'prompt'], func=FUNC_NAME),
|
||||
None,
|
||||
lambda: load_text(['arg_partial_deposit_keystore_password', 'invalid'], func=FUNC_NAME),
|
||||
True,
|
||||
),
|
||||
help=lambda: load_text(['arg_partial_deposit_keystore_password', 'help'], func=FUNC_NAME),
|
||||
hide_input=True,
|
||||
param_decls='--keystore_password',
|
||||
prompt=lambda: load_text(['arg_partial_deposit_keystore_password', 'prompt'], func=FUNC_NAME),
|
||||
)
|
||||
@jit_option(
|
||||
callback=captive_prompt_callback(
|
||||
lambda amount: validate_deposit_amount(amount),
|
||||
lambda: load_text(['arg_partial_deposit_amount', 'prompt'], func=FUNC_NAME),
|
||||
default="32",
|
||||
prompt_if=prompt_if_none,
|
||||
),
|
||||
default="32",
|
||||
help=lambda: load_text(['arg_partial_deposit_amount', 'help'], func=FUNC_NAME),
|
||||
param_decls='--amount',
|
||||
prompt=False, # the callback handles the prompt, to avoid second callback with gwei
|
||||
)
|
||||
@jit_option(
|
||||
callback=captive_prompt_callback(
|
||||
lambda address: validate_withdrawal_address(None, None, address, True),
|
||||
lambda: load_text(['arg_withdrawal_address', 'prompt'], func=FUNC_NAME),
|
||||
lambda: load_text(['arg_withdrawal_address', 'confirm'], func=FUNC_NAME),
|
||||
lambda: load_text(['arg_withdrawal_address', 'mismatch'], func=FUNC_NAME),
|
||||
prompt_if=prompt_if_none,
|
||||
),
|
||||
help=lambda: load_text(['arg_withdrawal_address', 'help'], func=FUNC_NAME),
|
||||
param_decls=['--withdrawal_address', '--execution_address', '--eth1_withdrawal_credentials'],
|
||||
prompt=False, # the callback handles the prompt
|
||||
)
|
||||
@jit_option(
|
||||
callback=captive_prompt_callback(
|
||||
lambda value: validate_yesno(None, None, value),
|
||||
lambda: load_text(['arg_compounding', 'prompt'], func=FUNC_NAME),
|
||||
default="False",
|
||||
prompt_if=prompt_if_other_exists('withdrawal_address'),
|
||||
),
|
||||
default=False,
|
||||
help=lambda: load_text(['arg_compounding', 'help'], func=FUNC_NAME),
|
||||
param_decls='--compounding/--regular-withdrawal',
|
||||
prompt=False, # the callback handles the prompt
|
||||
type=bool,
|
||||
show_default=True,
|
||||
)
|
||||
@jit_option(
|
||||
default=os.getcwd(),
|
||||
help=lambda: load_text(['arg_partial_deposit_output_folder', 'help'], func=FUNC_NAME),
|
||||
param_decls='--output_folder',
|
||||
type=click.Path(exists=True, file_okay=False, dir_okay=True),
|
||||
)
|
||||
@jit_option(
|
||||
callback=validate_devnet_chain_setting,
|
||||
default=None,
|
||||
help=lambda: load_text(['arg_devnet_chain_setting', 'help'], func=FUNC_NAME),
|
||||
param_decls='--devnet_chain_setting',
|
||||
is_eager=True,
|
||||
)
|
||||
@click.pass_context
|
||||
def partial_deposit(
|
||||
ctx: click.Context,
|
||||
chain: str,
|
||||
keystore: Keystore,
|
||||
keystore_password: str,
|
||||
amount: int,
|
||||
withdrawal_address: HexAddress,
|
||||
compounding: bool,
|
||||
output_folder: str,
|
||||
devnet_chain_setting: Optional[BaseChainSetting],
|
||||
**kwargs: Any) -> None:
|
||||
try:
|
||||
secret_bytes = keystore.decrypt(keystore_password)
|
||||
except ValueError:
|
||||
click.echo(load_text(['arg_partial_deposit_keystore_password', 'mismatch']), err=True)
|
||||
sys.exit(1)
|
||||
|
||||
signing_key = int.from_bytes(secret_bytes, 'big')
|
||||
|
||||
# Get chain setting
|
||||
chain_setting = devnet_chain_setting if devnet_chain_setting is not None else get_chain_setting(chain)
|
||||
|
||||
if compounding:
|
||||
withdrawal_credentials = COMPOUNDING_WITHDRAWAL_PREFIX
|
||||
else:
|
||||
withdrawal_credentials = EXECUTION_ADDRESS_WITHDRAWAL_PREFIX
|
||||
|
||||
withdrawal_credentials += b'\x00' * 11
|
||||
withdrawal_credentials += to_canonical_address(withdrawal_address)
|
||||
|
||||
deposit_message = DepositMessage( # type: ignore[no-untyped-call]
|
||||
pubkey=bls.SkToPk(signing_key),
|
||||
withdrawal_credentials=withdrawal_credentials,
|
||||
amount=amount
|
||||
)
|
||||
|
||||
domain = compute_deposit_domain(fork_version=chain_setting.GENESIS_FORK_VERSION)
|
||||
|
||||
signing_root = compute_signing_root(deposit_message, domain)
|
||||
signature = bls.Sign(signing_key, signing_root)
|
||||
|
||||
signed_deposit = DepositData( # type: ignore[no-untyped-call]
|
||||
**deposit_message.as_dict(), # type: ignore[no-untyped-call]
|
||||
signature=signature
|
||||
)
|
||||
|
||||
folder = os.path.join(output_folder, DEFAULT_PARTIAL_DEPOSIT_FOLDER_NAME)
|
||||
if not os.path.exists(folder):
|
||||
os.mkdir(folder)
|
||||
|
||||
click.echo(load_text(['msg_partial_deposit_creation']))
|
||||
deposit_data = signed_deposit.as_dict() # type: ignore[no-untyped-call]
|
||||
deposit_data.update({'deposit_message_root': deposit_message.hash_tree_root})
|
||||
deposit_data.update({'deposit_data_root': signed_deposit.hash_tree_root})
|
||||
deposit_data.update({'fork_version': chain_setting.GENESIS_FORK_VERSION})
|
||||
deposit_data.update({'network_name': chain_setting.NETWORK_NAME})
|
||||
deposit_data.update({'deposit_cli_version': fake_cli_version})
|
||||
saved_folder = export_deposit_data_json(folder, time.time(), [deposit_data])
|
||||
|
||||
click.echo(load_text(['msg_verify_partial_deposit']))
|
||||
deposit_json = []
|
||||
with open(saved_folder, 'r', encoding='utf-8') as f:
|
||||
deposit_json = json.load(f)
|
||||
|
||||
if (not validate_deposit(deposit_json[0])):
|
||||
click.echo(load_text(['err_verify_partial_deposit']))
|
||||
return
|
||||
|
||||
click.echo(load_text(['msg_creation_success']) + saved_folder)
|
||||
if not config.non_interactive:
|
||||
click.pause(load_text(['msg_pause']))
|
||||
63
src/vendors/ethstaker-deposit-cli-0.5.0/ethstaker_deposit/cli/test_keystore.py
vendored
Normal file
63
src/vendors/ethstaker-deposit-cli-0.5.0/ethstaker_deposit/cli/test_keystore.py
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
import click
|
||||
import sys
|
||||
from typing import Any
|
||||
|
||||
from ethstaker_deposit.key_handling.keystore import Keystore
|
||||
from ethstaker_deposit.utils import config
|
||||
from ethstaker_deposit.utils.click import (
|
||||
captive_prompt_callback,
|
||||
jit_option,
|
||||
prompt_if_none,
|
||||
)
|
||||
from ethstaker_deposit.utils.intl import (
|
||||
load_text,
|
||||
)
|
||||
from ethstaker_deposit.utils.validation import validate_keystore_file
|
||||
|
||||
|
||||
FUNC_NAME = 'test_keystore'
|
||||
|
||||
|
||||
@click.command(
|
||||
help=load_text(['arg_test_keystore', 'help'], func=FUNC_NAME),
|
||||
)
|
||||
@jit_option(
|
||||
callback=captive_prompt_callback(
|
||||
lambda file: validate_keystore_file(file),
|
||||
lambda: load_text(['arg_test_keystore_keystore', 'prompt'], func=FUNC_NAME),
|
||||
prompt_if=prompt_if_none,
|
||||
),
|
||||
help=lambda: load_text(['arg_test_keystore_keystore', 'help'], func=FUNC_NAME),
|
||||
param_decls='--keystore',
|
||||
prompt=False,
|
||||
)
|
||||
@jit_option(
|
||||
callback=captive_prompt_callback(
|
||||
lambda x: x,
|
||||
lambda: load_text(['arg_test_keystore_keystore_password', 'prompt'], func=FUNC_NAME),
|
||||
None,
|
||||
lambda: load_text(['arg_test_keystore_keystore_password', 'invalid'], func=FUNC_NAME),
|
||||
True,
|
||||
),
|
||||
help=lambda: load_text(['arg_test_keystore_keystore_password', 'help'], func=FUNC_NAME),
|
||||
hide_input=True,
|
||||
param_decls='--keystore_password',
|
||||
prompt=lambda: load_text(['arg_test_keystore_keystore_password', 'prompt'], func=FUNC_NAME),
|
||||
)
|
||||
@click.pass_context
|
||||
def test_keystore(
|
||||
ctx: click.Context,
|
||||
keystore: Keystore,
|
||||
keystore_password: str,
|
||||
**kwargs: Any) -> None:
|
||||
click.echo(load_text(['msg_verify_keystore_file']))
|
||||
|
||||
try:
|
||||
keystore.decrypt(keystore_password)
|
||||
except ValueError:
|
||||
click.echo(load_text(['arg_test_keystore_keystore_password', 'mismatch']), err=True)
|
||||
sys.exit(1)
|
||||
|
||||
click.echo(load_text(['msg_verification_success']))
|
||||
if not config.non_interactive:
|
||||
click.pause(load_text(['msg_pause']))
|
||||
394
src/vendors/ethstaker-deposit-cli-0.5.0/ethstaker_deposit/credentials.py
vendored
Normal file
394
src/vendors/ethstaker-deposit-cli-0.5.0/ethstaker_deposit/credentials.py
vendored
Normal file
@@ -0,0 +1,394 @@
|
||||
import os
|
||||
import click
|
||||
from enum import Enum
|
||||
import time
|
||||
import json
|
||||
import concurrent.futures
|
||||
from typing import Dict, Optional, Any, Sequence
|
||||
|
||||
from eth_typing import Address, HexAddress
|
||||
from eth_utils import to_canonical_address
|
||||
from py_ecc.bls import G2ProofOfPossession as bls
|
||||
|
||||
from ethstaker_deposit.exceptions import ValidationError
|
||||
from ethstaker_deposit.utils.exit_transaction import exit_transaction_generation, export_exit_transaction_json
|
||||
from ethstaker_deposit.key_handling.key_derivation.path import mnemonic_and_path_to_key
|
||||
from ethstaker_deposit.key_handling.keystore import (
|
||||
Keystore,
|
||||
Pbkdf2Keystore,
|
||||
ScryptKeystore,
|
||||
)
|
||||
from ethstaker_deposit.settings import (
|
||||
fake_cli_version,
|
||||
DEPOSIT_CLI_VERSION,
|
||||
BaseChainSetting,
|
||||
)
|
||||
from ethstaker_deposit.utils.constants import (
|
||||
BLS_WITHDRAWAL_PREFIX,
|
||||
EXECUTION_ADDRESS_WITHDRAWAL_PREFIX,
|
||||
COMPOUNDING_WITHDRAWAL_PREFIX,
|
||||
ETH2GWEI,
|
||||
MAX_DEPOSIT_AMOUNT,
|
||||
MIN_DEPOSIT_AMOUNT,
|
||||
)
|
||||
from ethstaker_deposit.utils.crypto import SHA256
|
||||
from ethstaker_deposit.utils.deposit import export_deposit_data_json as export_deposit_data_json_util
|
||||
from ethstaker_deposit.utils.intl import load_text
|
||||
from ethstaker_deposit.utils.ssz import (
|
||||
compute_deposit_domain,
|
||||
compute_bls_to_execution_change_domain,
|
||||
compute_signing_root,
|
||||
BLSToExecutionChange,
|
||||
DepositData,
|
||||
DepositMessage,
|
||||
SignedBLSToExecutionChange,
|
||||
)
|
||||
from ethstaker_deposit.utils.file_handling import (
|
||||
sensitive_opener,
|
||||
)
|
||||
|
||||
|
||||
class WithdrawalType(Enum):
|
||||
BLS_WITHDRAWAL = 0
|
||||
EXECUTION_ADDRESS_WITHDRAWAL = 1
|
||||
COMPOUNDING_WITHDRAWAL = 2
|
||||
|
||||
|
||||
class Credential:
|
||||
"""
|
||||
A Credential object contains all of the information for a single validator and the corresponding functionality.
|
||||
Once created, it is the only object that should be required to perform any processing for a validator.
|
||||
"""
|
||||
def __init__(self, *, mnemonic: str, mnemonic_password: str,
|
||||
index: int, amount: int, chain_setting: BaseChainSetting,
|
||||
hex_withdrawal_address: Optional[HexAddress],
|
||||
compounding: Optional[bool] = False,
|
||||
use_pbkdf2: Optional[bool] = False):
|
||||
# Set path as EIP-2334 format
|
||||
# https://eips.ethereum.org/EIPS/eip-2334
|
||||
purpose = '12381'
|
||||
coin_type = '3600'
|
||||
account = str(index)
|
||||
withdrawal_key_path = f'm/{purpose}/{coin_type}/{account}/0'
|
||||
self.signing_key_path = f'{withdrawal_key_path}/0'
|
||||
|
||||
self.withdrawal_sk = mnemonic_and_path_to_key(
|
||||
mnemonic=mnemonic, path=withdrawal_key_path, password=mnemonic_password)
|
||||
self.signing_sk = mnemonic_and_path_to_key(
|
||||
mnemonic=mnemonic, path=self.signing_key_path, password=mnemonic_password)
|
||||
self.amount = amount
|
||||
self.chain_setting = chain_setting
|
||||
self.hex_withdrawal_address = hex_withdrawal_address
|
||||
self.compounding = compounding
|
||||
self.use_pbkdf2 = use_pbkdf2
|
||||
|
||||
@property
|
||||
def signing_pk(self) -> bytes:
|
||||
return bls.SkToPk(self.signing_sk)
|
||||
|
||||
@property
|
||||
def withdrawal_pk(self) -> bytes:
|
||||
return bls.SkToPk(self.withdrawal_sk)
|
||||
|
||||
@property
|
||||
def withdrawal_address(self) -> Optional[Address]:
|
||||
if self.hex_withdrawal_address is None:
|
||||
return None
|
||||
return to_canonical_address(self.hex_withdrawal_address)
|
||||
|
||||
@property
|
||||
def withdrawal_prefix(self) -> bytes:
|
||||
if self.withdrawal_address is not None:
|
||||
if self.compounding:
|
||||
return COMPOUNDING_WITHDRAWAL_PREFIX
|
||||
else:
|
||||
return EXECUTION_ADDRESS_WITHDRAWAL_PREFIX
|
||||
else:
|
||||
return BLS_WITHDRAWAL_PREFIX
|
||||
|
||||
@property
|
||||
def withdrawal_type(self) -> WithdrawalType:
|
||||
if self.withdrawal_prefix == BLS_WITHDRAWAL_PREFIX:
|
||||
return WithdrawalType.BLS_WITHDRAWAL
|
||||
elif self.withdrawal_prefix == EXECUTION_ADDRESS_WITHDRAWAL_PREFIX:
|
||||
return WithdrawalType.EXECUTION_ADDRESS_WITHDRAWAL
|
||||
elif self.withdrawal_prefix == COMPOUNDING_WITHDRAWAL_PREFIX:
|
||||
return WithdrawalType.COMPOUNDING_WITHDRAWAL
|
||||
else:
|
||||
raise ValueError(f"Invalid withdrawal_prefix {self.withdrawal_prefix.hex()}")
|
||||
|
||||
@property
|
||||
def withdrawal_credentials(self) -> bytes:
|
||||
if self.withdrawal_type == WithdrawalType.BLS_WITHDRAWAL:
|
||||
withdrawal_credentials = BLS_WITHDRAWAL_PREFIX
|
||||
withdrawal_credentials += SHA256(self.withdrawal_pk)[1:]
|
||||
elif (
|
||||
self.withdrawal_type == WithdrawalType.EXECUTION_ADDRESS_WITHDRAWAL
|
||||
and self.withdrawal_address is not None
|
||||
):
|
||||
withdrawal_credentials = EXECUTION_ADDRESS_WITHDRAWAL_PREFIX
|
||||
withdrawal_credentials += b'\x00' * 11
|
||||
withdrawal_credentials += self.withdrawal_address
|
||||
elif (
|
||||
self.withdrawal_type == WithdrawalType.COMPOUNDING_WITHDRAWAL
|
||||
and self.withdrawal_address is not None
|
||||
):
|
||||
withdrawal_credentials = COMPOUNDING_WITHDRAWAL_PREFIX
|
||||
withdrawal_credentials += b'\x00' * 11
|
||||
withdrawal_credentials += self.withdrawal_address
|
||||
else:
|
||||
raise ValueError(f"Invalid withdrawal_type {self.withdrawal_type}")
|
||||
return withdrawal_credentials
|
||||
|
||||
@property
|
||||
def deposit_message(self) -> DepositMessage:
|
||||
if not MIN_DEPOSIT_AMOUNT <= self.amount <= MAX_DEPOSIT_AMOUNT:
|
||||
raise ValidationError(f"{self.amount / ETH2GWEI} ETH deposits are not within the bounds of this cli.")
|
||||
return DepositMessage( # type: ignore[no-untyped-call]
|
||||
pubkey=self.signing_pk,
|
||||
withdrawal_credentials=self.withdrawal_credentials,
|
||||
amount=self.amount,
|
||||
)
|
||||
|
||||
@property
|
||||
def signed_deposit(self) -> DepositData:
|
||||
domain = compute_deposit_domain(fork_version=self.chain_setting.GENESIS_FORK_VERSION)
|
||||
signing_root = compute_signing_root(self.deposit_message, domain)
|
||||
signed_deposit = DepositData( # type: ignore[no-untyped-call]
|
||||
**self.deposit_message.as_dict(), # type: ignore[no-untyped-call]
|
||||
signature=bls.Sign(self.signing_sk, signing_root)
|
||||
)
|
||||
return signed_deposit
|
||||
|
||||
@property
|
||||
def deposit_datum_dict(self) -> Dict[str, bytes]:
|
||||
"""
|
||||
Return a single deposit datum for 1 validator including all
|
||||
the information needed to verify and process the deposit.
|
||||
"""
|
||||
signed_deposit_datum = self.signed_deposit
|
||||
datum_dict = signed_deposit_datum.as_dict() # type: ignore[no-untyped-call]
|
||||
datum_dict.update({'deposit_message_root': self.deposit_message.hash_tree_root})
|
||||
datum_dict.update({'deposit_data_root': signed_deposit_datum.hash_tree_root})
|
||||
datum_dict.update({'fork_version': self.chain_setting.GENESIS_FORK_VERSION})
|
||||
datum_dict.update({'network_name': self.chain_setting.NETWORK_NAME})
|
||||
datum_dict.update({'deposit_cli_version': fake_cli_version})
|
||||
return datum_dict
|
||||
|
||||
def signing_keystore(self, password: str) -> Keystore:
|
||||
secret = self.signing_sk.to_bytes(32, 'big')
|
||||
if self.use_pbkdf2:
|
||||
return Pbkdf2Keystore.encrypt(secret=secret, password=password, path=self.signing_key_path)
|
||||
else:
|
||||
return ScryptKeystore.encrypt(secret=secret, password=password, path=self.signing_key_path)
|
||||
|
||||
def save_signing_keystore(self, password: str, folder: str, timestamp: float) -> str:
|
||||
keystore = self.signing_keystore(password)
|
||||
filefolder = os.path.join(folder, 'keystore-%s-%i.json' % (keystore.path.replace('/', '_'), timestamp))
|
||||
keystore.save(filefolder)
|
||||
return filefolder
|
||||
|
||||
def verify_keystore(self, keystore_filefolder: str, password: str) -> bool:
|
||||
saved_keystore = Keystore.from_file(keystore_filefolder)
|
||||
secret_bytes = saved_keystore.decrypt(password)
|
||||
return self.signing_sk == int.from_bytes(secret_bytes, 'big')
|
||||
|
||||
def get_bls_to_execution_change(self, validator_index: int) -> SignedBLSToExecutionChange:
|
||||
if self.withdrawal_address is None:
|
||||
raise ValueError("The withdrawal address should NOT be empty.")
|
||||
if self.chain_setting.GENESIS_VALIDATORS_ROOT is None:
|
||||
raise ValidationError("The genesis validators root should NOT be empty "
|
||||
"for this chain to obtain the BLS to execution change.")
|
||||
|
||||
message = BLSToExecutionChange( # type: ignore[no-untyped-call]
|
||||
validator_index=validator_index,
|
||||
from_bls_pubkey=self.withdrawal_pk,
|
||||
to_execution_address=self.withdrawal_address,
|
||||
)
|
||||
domain = compute_bls_to_execution_change_domain(
|
||||
fork_version=self.chain_setting.GENESIS_FORK_VERSION,
|
||||
genesis_validators_root=self.chain_setting.GENESIS_VALIDATORS_ROOT,
|
||||
)
|
||||
signing_root = compute_signing_root(message, domain)
|
||||
signature = bls.Sign(self.withdrawal_sk, signing_root)
|
||||
|
||||
return SignedBLSToExecutionChange( # type: ignore[no-untyped-call]
|
||||
message=message,
|
||||
signature=signature,
|
||||
)
|
||||
|
||||
def get_bls_to_execution_change_dict(self, validator_index: int) -> Dict[str, bytes]:
|
||||
result_dict: Dict[str, Any] = {}
|
||||
signed_bls_to_execution_change = self.get_bls_to_execution_change(validator_index)
|
||||
message = {
|
||||
'validator_index':
|
||||
str(signed_bls_to_execution_change.message.validator_index), # type: ignore[attr-defined]
|
||||
'from_bls_pubkey': '0x'
|
||||
+ signed_bls_to_execution_change.message.from_bls_pubkey.hex(), # type: ignore[attr-defined]
|
||||
'to_execution_address': '0x'
|
||||
+ signed_bls_to_execution_change.message.to_execution_address.hex(), # type: ignore[attr-defined]
|
||||
}
|
||||
result_dict.update({'message': message})
|
||||
result_dict.update({'signature': '0x'
|
||||
+ signed_bls_to_execution_change.signature.hex()}) # type: ignore[attr-defined]
|
||||
|
||||
# metadata
|
||||
metadata: Dict[str, Any] = {
|
||||
'network_name': self.chain_setting.NETWORK_NAME,
|
||||
'genesis_validators_root': '0x' + self.chain_setting.GENESIS_VALIDATORS_ROOT.hex(),
|
||||
'deposit_cli_version': DEPOSIT_CLI_VERSION,
|
||||
}
|
||||
|
||||
result_dict.update({'metadata': metadata})
|
||||
return result_dict
|
||||
|
||||
def save_exit_transaction(self, validator_index: int, epoch: int, folder: str, timestamp: float) -> str:
|
||||
signing_key = self.signing_sk
|
||||
|
||||
signed_voluntary_exit = exit_transaction_generation(
|
||||
chain_setting=self.chain_setting,
|
||||
signing_key=signing_key,
|
||||
validator_index=validator_index,
|
||||
epoch=epoch
|
||||
)
|
||||
|
||||
return export_exit_transaction_json(folder=folder, signed_exit=signed_voluntary_exit, timestamp=timestamp)
|
||||
|
||||
|
||||
def _credential_builder(kwargs: Dict[str, Any]) -> Credential:
|
||||
return Credential(**kwargs)
|
||||
|
||||
|
||||
def _keystore_exporter(kwargs: Dict[str, Any]) -> str:
|
||||
credential: Credential = kwargs.pop('credential')
|
||||
return credential.save_signing_keystore(**kwargs)
|
||||
|
||||
|
||||
def _deposit_data_builder(credential: Credential) -> Dict[str, bytes]:
|
||||
return credential.deposit_datum_dict
|
||||
|
||||
|
||||
def _keystore_verifier(kwargs: Dict[str, Any]) -> bool:
|
||||
credential: Credential = kwargs.pop('credential')
|
||||
return credential.verify_keystore(**kwargs)
|
||||
|
||||
|
||||
def _bls_to_execution_change_builder(kwargs: Dict[str, Any]) -> Dict[str, bytes]:
|
||||
credential: Credential = kwargs.pop('credential')
|
||||
return credential.get_bls_to_execution_change_dict(**kwargs)
|
||||
|
||||
|
||||
class CredentialList:
|
||||
"""
|
||||
A collection of multiple Credentials, one for each validator.
|
||||
"""
|
||||
def __init__(self, credentials: list[Credential]):
|
||||
self.credentials = credentials
|
||||
|
||||
@classmethod
|
||||
def from_mnemonic(cls,
|
||||
*,
|
||||
mnemonic: str,
|
||||
mnemonic_password: str,
|
||||
num_keys: int,
|
||||
amounts: list[int],
|
||||
chain_setting: BaseChainSetting,
|
||||
start_index: int,
|
||||
hex_withdrawal_address: Optional[HexAddress],
|
||||
compounding: Optional[bool] = False,
|
||||
use_pbkdf2: Optional[bool] = False) -> 'CredentialList':
|
||||
if len(amounts) != num_keys:
|
||||
raise ValueError(
|
||||
f"The number of keys ({num_keys}) doesn't equal to the corresponding deposit amounts ({len(amounts)})."
|
||||
)
|
||||
key_indices = range(start_index, start_index + num_keys)
|
||||
|
||||
credentials: list[Credential] = []
|
||||
with click.progressbar(length=num_keys, label=load_text(['msg_key_creation']), # type: ignore[var-annotated]
|
||||
show_percent=False, show_pos=True) as bar:
|
||||
executor_kwargs = [{
|
||||
'mnemonic': mnemonic,
|
||||
'mnemonic_password': mnemonic_password,
|
||||
'index': index,
|
||||
'amount': amounts[index - start_index],
|
||||
'chain_setting': chain_setting,
|
||||
'hex_withdrawal_address': hex_withdrawal_address,
|
||||
'compounding': compounding,
|
||||
'use_pbkdf2': use_pbkdf2,
|
||||
} for index in key_indices]
|
||||
|
||||
with concurrent.futures.ProcessPoolExecutor() as executor:
|
||||
for credential in executor.map(_credential_builder, executor_kwargs):
|
||||
credentials.append(credential)
|
||||
bar.update(1)
|
||||
return cls(credentials)
|
||||
|
||||
def export_keystores(self, password: str, folder: str, timestamp: float) -> list[str]:
|
||||
filefolders: list[str] = []
|
||||
with click.progressbar(length=len(self.credentials), # type: ignore[var-annotated]
|
||||
label=load_text(['msg_keystore_creation']),
|
||||
show_percent=False, show_pos=True) as bar:
|
||||
executor_kwargs = [{
|
||||
'credential': credential,
|
||||
'password': password,
|
||||
'folder': folder,
|
||||
'timestamp': timestamp,
|
||||
} for credential in self.credentials]
|
||||
|
||||
with concurrent.futures.ProcessPoolExecutor() as executor:
|
||||
for filefolder in executor.map(_keystore_exporter, executor_kwargs):
|
||||
filefolders.append(filefolder)
|
||||
bar.update(1)
|
||||
return filefolders
|
||||
|
||||
def export_deposit_data_json(self, folder: str, timestamp: float) -> str:
|
||||
deposit_data = []
|
||||
with click.progressbar(length=len(self.credentials), # type: ignore[var-annotated]
|
||||
label=load_text(['msg_depositdata_creation']),
|
||||
show_percent=False, show_pos=True) as bar:
|
||||
|
||||
with concurrent.futures.ProcessPoolExecutor() as executor:
|
||||
for datum_dict in executor.map(_deposit_data_builder, self.credentials):
|
||||
deposit_data.append(datum_dict)
|
||||
bar.update(1)
|
||||
|
||||
return export_deposit_data_json_util(folder, timestamp, deposit_data)
|
||||
|
||||
def verify_keystores(self, keystore_filefolders: list[str], password: str) -> bool:
|
||||
all_valid_keystores = True
|
||||
with click.progressbar(length=len(self.credentials), # type: ignore[var-annotated]
|
||||
label=load_text(['msg_keystore_verification']),
|
||||
show_percent=False, show_pos=True) as bar:
|
||||
executor_kwargs = [{
|
||||
'credential': credential,
|
||||
'keystore_filefolder': fileholder,
|
||||
'password': password,
|
||||
} for credential, fileholder in zip(self.credentials, keystore_filefolders)]
|
||||
|
||||
with concurrent.futures.ProcessPoolExecutor() as executor:
|
||||
for valid_keystore in executor.map(_keystore_verifier, executor_kwargs):
|
||||
all_valid_keystores &= valid_keystore
|
||||
bar.update(1)
|
||||
|
||||
return all_valid_keystores
|
||||
|
||||
def export_bls_to_execution_change_json(self, folder: str, validator_indices: Sequence[int]) -> str:
|
||||
bls_to_execution_changes = []
|
||||
with click.progressbar(length=len(self.credentials), # type: ignore[var-annotated]
|
||||
label=load_text(['msg_bls_to_execution_change_creation']),
|
||||
show_percent=False, show_pos=True) as bar:
|
||||
|
||||
executor_kwargs = [{
|
||||
'credential': credential,
|
||||
'validator_index': validator_indices[i],
|
||||
} for i, credential in enumerate(self.credentials)]
|
||||
|
||||
with concurrent.futures.ProcessPoolExecutor() as executor:
|
||||
for bls_to_execution_change in executor.map(_bls_to_execution_change_builder, executor_kwargs):
|
||||
bls_to_execution_changes.append(bls_to_execution_change)
|
||||
bar.update(1)
|
||||
|
||||
filefolder = os.path.join(folder, 'bls_to_execution_change-%i.json' % time.time())
|
||||
with open(filefolder, 'w', encoding='utf-8', opener=sensitive_opener) as f:
|
||||
json.dump(bls_to_execution_changes, f)
|
||||
return filefolder
|
||||
134
src/vendors/ethstaker-deposit-cli-0.5.0/ethstaker_deposit/deposit.py
vendored
Normal file
134
src/vendors/ethstaker-deposit-cli-0.5.0/ethstaker_deposit/deposit.py
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
import click
|
||||
import socket
|
||||
import sys
|
||||
from multiprocessing import freeze_support
|
||||
|
||||
from ethstaker_deposit.cli.existing_mnemonic import existing_mnemonic
|
||||
from ethstaker_deposit.cli.exit_transaction_keystore import exit_transaction_keystore
|
||||
from ethstaker_deposit.cli.exit_transaction_mnemonic import exit_transaction_mnemonic
|
||||
from ethstaker_deposit.cli.generate_bls_to_execution_change import generate_bls_to_execution_change
|
||||
from ethstaker_deposit.cli.generate_bls_to_execution_change_keystore import generate_bls_to_execution_change_keystore
|
||||
from ethstaker_deposit.cli.new_mnemonic import new_mnemonic
|
||||
from ethstaker_deposit.cli.partial_deposit import partial_deposit
|
||||
from ethstaker_deposit.cli.test_keystore import test_keystore
|
||||
from ethstaker_deposit.exceptions import MultiLanguageError, ValidationError
|
||||
from ethstaker_deposit.utils.click import (
|
||||
captive_prompt_callback,
|
||||
choice_prompt_func,
|
||||
jit_option,
|
||||
deactivate_prompts_callback
|
||||
)
|
||||
from ethstaker_deposit.utils import config
|
||||
from ethstaker_deposit.utils.constants import INTL_LANG_OPTIONS
|
||||
from ethstaker_deposit.utils.intl import (
|
||||
get_first_options,
|
||||
fuzzy_reverse_dict_lookup,
|
||||
load_text,
|
||||
)
|
||||
from ethstaker_deposit.settings import (
|
||||
DEPOSIT_CLI_VERSION,
|
||||
)
|
||||
|
||||
|
||||
def check_python_version() -> None:
|
||||
'''
|
||||
Checks that the python version running is sufficient and exits if not.
|
||||
'''
|
||||
if sys.version_info < (3, 9):
|
||||
click.pause(load_text(['err_python_version']))
|
||||
sys.exit(78)
|
||||
|
||||
|
||||
def check_connectivity() -> None:
|
||||
'''
|
||||
Checks if there is an internet connection and warns the user if so.
|
||||
'''
|
||||
if '--help' in sys.argv:
|
||||
return None
|
||||
try:
|
||||
socket.setdefaulttimeout(2)
|
||||
socket.getaddrinfo('icann.org', 80)
|
||||
click.pause(load_text(['connectivity_warning']))
|
||||
except OSError:
|
||||
return None
|
||||
|
||||
|
||||
# Define commands available to the user and their order
|
||||
commands = [
|
||||
new_mnemonic,
|
||||
existing_mnemonic,
|
||||
generate_bls_to_execution_change,
|
||||
generate_bls_to_execution_change_keystore,
|
||||
exit_transaction_keystore,
|
||||
exit_transaction_mnemonic,
|
||||
partial_deposit,
|
||||
test_keystore,
|
||||
]
|
||||
|
||||
|
||||
class SortedGroup(click.Group):
|
||||
|
||||
def list_commands(self, ctx: click.Context) -> list[str]:
|
||||
return [x.name for x in commands]
|
||||
|
||||
|
||||
@click.group(cls=SortedGroup)
|
||||
@click.pass_context
|
||||
@jit_option(
|
||||
'--language',
|
||||
callback=captive_prompt_callback(
|
||||
lambda language: fuzzy_reverse_dict_lookup(language, INTL_LANG_OPTIONS),
|
||||
choice_prompt_func(lambda: 'Please choose your language', get_first_options(INTL_LANG_OPTIONS)),
|
||||
default='English',
|
||||
),
|
||||
default='English',
|
||||
help='The language you wish to use the CLI in.',
|
||||
prompt=choice_prompt_func(lambda: 'Please choose your language', get_first_options(INTL_LANG_OPTIONS))(),
|
||||
type=str,
|
||||
)
|
||||
@click.option(
|
||||
'--non_interactive',
|
||||
callback=deactivate_prompts_callback(["language"]),
|
||||
default=False,
|
||||
is_flag=True,
|
||||
help=(
|
||||
'Disables interactive prompts. Warning: With this flag, there will be no confirmation step(s) to verify the '
|
||||
'input value(s). This will also ignore the connectivity check. Please use it carefully.'
|
||||
),
|
||||
hidden=False,
|
||||
)
|
||||
@click.option(
|
||||
'--ignore_connectivity',
|
||||
default=False,
|
||||
is_flag=True,
|
||||
help=(
|
||||
'Disables internet connectivity check. Warning: It is strongly recommended not to use this tool with internet '
|
||||
'access. Ignoring this check can further the risk of theft and compromise of your generated key material.'
|
||||
),
|
||||
hidden=False,
|
||||
)
|
||||
@click.version_option(version=DEPOSIT_CLI_VERSION)
|
||||
def cli(ctx: click.Context, language: str, non_interactive: bool, ignore_connectivity: bool) -> None:
|
||||
if not ignore_connectivity and not non_interactive:
|
||||
check_connectivity()
|
||||
config.language = language
|
||||
config.non_interactive = non_interactive # Remove interactive commands
|
||||
|
||||
|
||||
for command in commands:
|
||||
cli.add_command(command)
|
||||
|
||||
|
||||
def run() -> None:
|
||||
freeze_support() # Needed when running under Windows in a frozen bundle
|
||||
check_python_version()
|
||||
|
||||
try:
|
||||
cli()
|
||||
except (MultiLanguageError, ValueError, ValidationError) as e:
|
||||
click.echo(f"\nError: {e}\n", err=True)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
run()
|
||||
9
src/vendors/ethstaker-deposit-cli-0.5.0/ethstaker_deposit/exceptions.py
vendored
Normal file
9
src/vendors/ethstaker-deposit-cli-0.5.0/ethstaker_deposit/exceptions.py
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
class ValidationError(Exception):
|
||||
...
|
||||
|
||||
|
||||
class MultiLanguageError(Exception):
|
||||
def __init__(self, languages: list[str]):
|
||||
self.languages = languages
|
||||
message = "Multiple valid languages found: %s" % ", ".join(languages)
|
||||
super().__init__(message)
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"check_python_version": {
|
||||
"err_python_version": "إصدار بايثون الخاص بك غير كافٍ، يرجى تثبيت الإصدار 3.8 أو الأحدث."
|
||||
"err_python_version": "إصدار بايثون الخاص بك غير كافٍ، يرجى تثبيت الإصدار 3.9 أو الأحدث."
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,6 @@
|
||||
"msg_deposit_verification": "التحقق من الإيداعات الخاصة بك:\t"
|
||||
},
|
||||
"validate_password_strength": {
|
||||
"msg_password_length": "يجب أن يكون طول كلمة المرور 8 على الأقل. الرجاء إعادة الكتابة"
|
||||
"msg_password_length": "يجب أن يكون طول كلمة المرور 12 على الأقل. الرجاء إعادة الكتابة"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"check_python_version": {
|
||||
"err_python_version": "Η έκδοση python σας δεν είναι επαρκής, εγκαταστήστε την έκδοση 3.8 ή μεγαλύτερη."
|
||||
"err_python_version": "Η έκδοση python σας δεν είναι επαρκής, εγκαταστήστε την έκδοση 3.9 ή μεγαλύτερη."
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,6 @@
|
||||
"msg_deposit_verification": "Επαλήθευση των καταθέσεών σας:\t"
|
||||
},
|
||||
"validate_password_strength": {
|
||||
"msg_password_length": "Το μήκος του κωδικού πρόσβασης πρέπει να είναι τουλάχιστον 8. Πληκτρολογήστε ξανά"
|
||||
"msg_password_length": "Το μήκος του κωδικού πρόσβασης πρέπει να είναι τουλάχιστον 12. Πληκτρολογήστε ξανά"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"validate_mnemonic": {
|
||||
"err_invalid_mnemonic": "That is not a valid mnemonic, please check for typos."
|
||||
"err_invalid_mnemonic": "That is not a valid mnemonic, please check for typos.",
|
||||
"arg_mnemonic_language": "We couldn't detect the language of your mnemonic phrase. Please select one of the available language options"
|
||||
},
|
||||
"existing_mnemonic": {
|
||||
"arg_existing_mnemonic": {
|
||||
@@ -10,6 +11,9 @@
|
||||
"help": "The mnemonic that you used to generate your keys. (It is recommended not to use this argument, and wait for the CLI to ask you for your mnemonic as otherwise it will appear in your shell history.)",
|
||||
"prompt": "Please enter your mnemonic separated by spaces (\" \"). Note: you only need to enter the first 4 letters of each word if you'd prefer."
|
||||
},
|
||||
"arg_mnemonic_language": {
|
||||
"help": "The language of your mnemonic. If this is not provided we will attempt to determine it based on the mnemonic provided."
|
||||
},
|
||||
"arg_mnemonic_password": {
|
||||
"help": "This is almost certainly not the argument you are looking for: it is for mnemonic passwords, not keystore passwords. Providing a password here when you didn't use one initially, can result in lost keys (and therefore funds)! Also note that if you used this tool to generate your mnemonic initially, then you did not use a mnemonic password. However, if you are certain you used a password to \"increase\" the security of your mnemonic, this is where you enter it.",
|
||||
"prompt": "Enter your mnemonic password (if you used one). Make sure you won't forget it, it can not be recovered.",
|
||||
@@ -19,7 +23,8 @@
|
||||
"arg_validator_start_index": {
|
||||
"help": "Enter the index (key number) you wish to start generating more keys from. For example, if you've generated 4 keys in the past, you'd enter 4 here.",
|
||||
"prompt": "Enter the index (key number) you wish to start generating more keys from. For example, if you've generated 4 keys in the past, you'd enter 4 here.",
|
||||
"confirm": "Please repeat the index to confirm"
|
||||
}
|
||||
"confirm": "Please repeat the validator start index to confirm"
|
||||
},
|
||||
"msg_confirm_clipboard_clearing": "WARNING: Your clipboard will be CLEARED. Press any key to clear the clipboard."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"exit_transaction_keystore": {
|
||||
"arg_exit_transaction_keystore" :{
|
||||
"help": "Generate an exit transaction that can be used to exit validators on Ethereum Beacon Chain."
|
||||
},
|
||||
"arg_exit_transaction_keystore_chain": {
|
||||
"help": "The name of the Ethereum PoS chain your validator is running on. \"mainnet\" is the default.",
|
||||
"prompt": "Please choose the (mainnet or testnet) network/chain name"
|
||||
},
|
||||
"arg_exit_transaction_keystore_epoch": {
|
||||
"help": "The epoch of when the exit transaction will be valid. The transaction will always be valid by default."
|
||||
},
|
||||
"arg_exit_transaction_keystore_keystore": {
|
||||
"help": "The keystore file associated with the validator you wish to exit.",
|
||||
"prompt": "Please enter the location of your keystore file."
|
||||
},
|
||||
"arg_exit_transaction_keystore_keystore_password": {
|
||||
"help": "The password that is used to encrypt the provided keystore. Note: It's not your mnemonic password. (It is recommended not to use this argument, and wait for the CLI to ask you for your password as otherwise it will appear in your shell history.)",
|
||||
"prompt": "Enter the password that is used to encrypt the provided keystore.",
|
||||
"mismatch": "Error: The provided keystore password was unable to decrypt this keystore file. Make sure you have the correct password and try again."
|
||||
},
|
||||
"arg_exit_transaction_keystore_output_folder": {
|
||||
"help": "The folder path where the exit transactions will be saved to. Pointing to `./exit_transactions` by default."
|
||||
},
|
||||
"arg_validator_index": {
|
||||
"help": "The validator index corresponding to the provided keystore.",
|
||||
"prompt": "Please enter the validator index of your validator that corresponds to the provided keystore as identified on the beacon chain."
|
||||
},
|
||||
"arg_devnet_chain_setting": {
|
||||
"help": "[DEVNET ONLY] Set a specific EXIT_FORK_VERSION and GENESIS_VALIDATORS_ROOT value. This should be a JSON string containing an object with the following keys: network_name, genesis_fork_version, exit_fork_version and genesis_validator_root. It should be similar to what you can find in settings.py. This will override any selected chain."
|
||||
},
|
||||
"msg_exit_transaction_creation": "\nCreating your exit transaction...",
|
||||
"msg_verify_exit_transaction": "\nVerifying your exit transaction...",
|
||||
"err_verify_exit_transaction": "\nThere was a problem verifying your exit transaction.\nPlease try again",
|
||||
"msg_creation_success": "\nSuccess!\nYour exit transaction file can be found at: ",
|
||||
"msg_pause": "\n\nPress any key."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"exit_transaction_mnemonic": {
|
||||
"arg_exit_transaction_mnemonic" :{
|
||||
"help": "Generate an exit transaction that can be used to exit validators on Ethereum Beacon Chain."
|
||||
},
|
||||
"arg_exit_transaction_mnemonic_chain": {
|
||||
"help": "The name of the Ethereum PoS chain your validator is running on. \"mainnet\" is the default.",
|
||||
"prompt": "Please choose the (mainnet or testnet) network/chain name"
|
||||
},
|
||||
"arg_exit_transaction_mnemonic_start_index": {
|
||||
"help": "Enter the index (key number) which you used when you created your keys. The default value is 0.",
|
||||
"prompt": "Enter the index (key number) which you used when you created your keys. The default value is 0."
|
||||
},
|
||||
"arg_exit_transaction_mnemonic_indices": {
|
||||
"help": "A list of the validator index number(s) of the certain validator(s)",
|
||||
"prompt": "Please enter a list of the validator index number(s) of your validator(s) as identified on the beacon chain. Split multiple items with whitespaces or commas."
|
||||
},
|
||||
"arg_exit_transaction_mnemonic_epoch": {
|
||||
"help": "The epoch of when the exit transaction will be valid. The transaction will always be valid by default."
|
||||
},
|
||||
"arg_exit_transaction_mnemonic_output_folder": {
|
||||
"help": "The folder path where the exit transactions will be saved to. Pointing to `./exit_transactions` by default."
|
||||
},
|
||||
"arg_devnet_chain_setting": {
|
||||
"help": "[DEVNET ONLY] Set a specific EXIT_FORK_VERSION and GENESIS_VALIDATORS_ROOT value. This should be a JSON string containing an object with the following keys: network_name, genesis_fork_version, exit_fork_version and genesis_validator_root. It should be similar to what you can find in settings.py. This will override any selected chain."
|
||||
},
|
||||
"msg_key_creation": "Creating your keys:\t",
|
||||
"msg_exit_transaction_creation": "Creating your exit transactions:\t",
|
||||
"msg_verify_exit_transaction": "Verifying your exit transactions:\t",
|
||||
"err_verify_exit_transactions": "\nThere was a problem verifying your exit transactions.\nPlease try again",
|
||||
"msg_creation_success": "\nSuccess!\nYour exit transaction files can be found at: ",
|
||||
"msg_pause": "\n\nPress any key."
|
||||
}
|
||||
}
|
||||
@@ -3,12 +3,15 @@
|
||||
"arg_generate_bls_to_execution_change" :{
|
||||
"help": "Generating the SignedBLSToExecutionChange data to enable withdrawals on Ethereum Beacon Chain."
|
||||
},
|
||||
"arg_execution_address": {
|
||||
"help": "The 20-byte (Eth1) execution address that will be used in withdrawal",
|
||||
"prompt": "Please enter the 20-byte execution address for the new withdrawal credentials. Note that you CANNOT change it once you have set it on chain.",
|
||||
"confirm": "Repeat your execution address for confirmation.",
|
||||
"arg_withdrawal_address": {
|
||||
"help": "The Ethereum address that will be used in withdrawal. It typically starts with '0x' followed by 40 hexadecimal characters. Please make sure you have full control over the address you choose here. Once you set a withdrawal address on chain, it cannot be changed.",
|
||||
"prompt": "Please enter the withdrawal address. Note that you CANNOT change it once you have set it on chain.",
|
||||
"confirm": "Repeat your withdrawal address for confirmation.",
|
||||
"mismatch": "Error: the two entered values do not match. Please type again."
|
||||
},
|
||||
"arg_devnet_chain_setting": {
|
||||
"help": "[DEVNET ONLY] Set a specific GENESIS_FORK_VERSION and GENESIS_VALIDATORS_ROOT value. This should be a JSON string containing an object with the following keys: network_name, genesis_fork_version, exit_fork_version and genesis_validator_root. It should be similar to what you can find in settings.py. This will override any selected chain."
|
||||
},
|
||||
"arg_validator_indices": {
|
||||
"help": "A list of the validator index number(s) of the certain validator(s)",
|
||||
"prompt": "Please enter a list of the validator index number(s) of your validator(s) as identified on the beacon chain. Split multiple items with whitespaces or commas."
|
||||
@@ -34,6 +37,7 @@
|
||||
"help": "The folder path for the keystore(s). Pointing to `./bls_to_execution_changes` by default."
|
||||
},
|
||||
"msg_key_creation": "Creating your SignedBLSToExecutionChange.",
|
||||
"msg_credentials_verification": "Verifying your withdrawal credentials.",
|
||||
"msg_creation_success": "\nSuccess!\nYour SignedBLSToExecutionChange JSON file can be found at: ",
|
||||
"msg_pause": "\n\nPress any key.",
|
||||
"err_verify_btec": "Failed to verify the bls_to_execution_change JSON files."
|
||||
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"generate_bls_to_execution_change_keystore": {
|
||||
"arg_generate_bls_to_execution_change" :{
|
||||
"help": "Generating the SignedBLSToExecutionChange data to enable withdrawals on Ethereum Beacon Chain."
|
||||
},
|
||||
"arg_withdrawal_address": {
|
||||
"help": "The Ethereum address that will be used in withdrawal. It typically starts with '0x' followed by 40 hexadecimal characters. Please make sure you have full control over the address you choose here. Once you set a withdrawal address on chain, it cannot be changed.",
|
||||
"prompt": "Please enter the withdrawal address. Note that you CANNOT change it once you have set it on chain.",
|
||||
"confirm": "Repeat your withdrawal address for confirmation.",
|
||||
"mismatch": "Error: the two entered values do not match. Please type again."
|
||||
},
|
||||
"arg_devnet_chain_setting": {
|
||||
"help": "[DEVNET ONLY] Set a specific GENESIS_FORK_VERSION and GENESIS_VALIDATORS_ROOT value. This should be a JSON string containing an object with the following keys: network_name, genesis_fork_version, exit_fork_version and genesis_validator_root. It should be similar to what you can find in settings.py. This will override any selected chain."
|
||||
},
|
||||
"arg_validator_index": {
|
||||
"help": "The validator index",
|
||||
"prompt": "Please enter the validator index number of your validator as identified on the beacon chain."
|
||||
},
|
||||
"arg_bls_withdrawal_credentials_list": {
|
||||
"help": "A list of 32-byte old BLS withdrawal credentials of the certain validator(s)",
|
||||
"prompt": "Please enter a list of the old BLS withdrawal credentials of your validator(s). Split multiple items with whitespaces or commas. The withdrawal credentials are in hexadecimal encoded form."
|
||||
},
|
||||
"arg_bls_to_execution_changes_keystore_keystore": {
|
||||
"help": "The keystore file associated with the validator you wish to exit.",
|
||||
"prompt": "Please enter the location of your keystore file."
|
||||
},
|
||||
"arg_bls_to_execution_changes_keystore_keystore_password": {
|
||||
"help": "The password that is used to encrypt the provided keystore. Note: It's not your mnemonic password. (It is recommended not to use this argument, and wait for the CLI to ask you for your password as otherwise it will appear in your shell history.)",
|
||||
"prompt": "Enter the password that is used to encrypt the provided keystore.",
|
||||
"mismatch": "Error: The provided keystore password was unable to decrypt this keystore file. Make sure you have the correct password and try again."
|
||||
},
|
||||
"arg_chain": {
|
||||
"help": "The name of Ethereum PoS chain you are targeting. Use \"mainnet\" if you are depositing ETH",
|
||||
"prompt": "Please choose the (mainnet or testnet) network/chain name"
|
||||
},
|
||||
"arg_fork": {
|
||||
"help": "The fork name of the fork you want to signing the message with.",
|
||||
"prompt": "Please choose the fork name of the fork you want to signing the message with."
|
||||
},
|
||||
"arg_bls_to_execution_changes_keystore_folder": {
|
||||
"help": "The folder path for the keystore(s). Pointing to `./bls_to_execution_changes` by default."
|
||||
},
|
||||
"arg_bls_to_execution_changes_keystore_output_folder": {
|
||||
"help": "Folder where you want to save the bls keystore change"
|
||||
},
|
||||
"msg_key_creation": "Creating your SignedBLSToExecutionChangeKeystore.",
|
||||
"msg_verify_btec": "Verifying the bls_to_execution_changes_keystore JSON file.",
|
||||
"msg_creation_success": "\nSuccess!\nYour SignedBLSToExecutionChangeKeystore JSON file can be found at: ",
|
||||
"msg_pause": "\n\nPress any key.",
|
||||
"err_verify_btec": "Failed to verify the bls_to_execution_change_keystore JSON file."
|
||||
}
|
||||
}
|
||||
48
src/vendors/ethstaker-deposit-cli-0.5.0/ethstaker_deposit/intl/en/cli/generate_keys.json
vendored
Normal file
48
src/vendors/ethstaker-deposit-cli-0.5.0/ethstaker_deposit/intl/en/cli/generate_keys.json
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"generate_keys_arguments_decorator": {
|
||||
"num_validators": {
|
||||
"help": "The number of new validator keys you want to generate (you can always generate more later)",
|
||||
"prompt": "Please choose how many new validators you wish to run"
|
||||
},
|
||||
"folder": {
|
||||
"help": "The folder path for the keystore(s) and deposit(s). Pointing to `./validator_keys` by default."
|
||||
},
|
||||
"chain": {
|
||||
"help": "The name of Ethereum PoS chain you are targeting. Use \"mainnet\" if you are depositing ETH",
|
||||
"prompt": "Please choose the (mainnet or testnet) network/chain name"
|
||||
},
|
||||
"keystore_password": {
|
||||
"help": "The password that will secure your keystores. You will need to re-enter this to decrypt them when you setup your Ethereum validators. (It is recommended not to use this argument, and wait for the CLI to ask you for your password, as otherwise it will appear in your shell history.)",
|
||||
"prompt": "Create a password that secures your validator keystore(s). You will need to re-enter this to decrypt them when you setup your Ethereum validators.",
|
||||
"confirm": "Repeat your keystore password for confirmation",
|
||||
"mismatch": "Error: the two entered values do not match. Please type again."
|
||||
},
|
||||
"arg_withdrawal_address": {
|
||||
"help": "The Ethereum address that will be used in withdrawal. It typically starts with '0x' followed by 40 hexadecimal characters. Please make sure you have full control over the address you choose here. Once you set a withdrawal address on chain, it cannot be changed.",
|
||||
"prompt": "Please enter the optional withdrawal address. Note that you CANNOT change it once you have set it on chain.",
|
||||
"confirm": "Repeat your withdrawal address for confirmation.",
|
||||
"mismatch": "Error: the two entered values do not match. Please type again."
|
||||
},
|
||||
"arg_compounding": {
|
||||
"help": "Generates compounding validators with 0x02 withdrawal credentials for a 2048 ETH maximum effective balance or generate regular validators with 0x01 withdrawal credentials for a 32 ETH maximum effective balance. Use of this option requires a withdrawal address. This feature is only supported on networks that have undergone the Pectra fork.",
|
||||
"prompt": "Please enter yes if you want to generate compounding validators with 0x02 withdrawal credentials for a 2048 ETH maximum effective balance. Compounding validators and 0x02 withdrawal credentials are only supported on networks that have undergone the Pectra fork. Please type no or nothing if you want regular validators with 0x01 withdrawal credentials for a 32 ETH maximum effective balance."
|
||||
},
|
||||
"arg_amount": {
|
||||
"help": "The amount to deposit to these validators in ether denomination. Must be at least 1 ether and can not have greater precision than 1 gwei. Use of this option requires compounding validators.",
|
||||
"prompt": "Please enter the amount you wish to deposit to these validators. Must be at least 1 ether and can not have greater precision than 1 gwei. 32 is required to activate a new validator"
|
||||
},
|
||||
"arg_pbkdf2": {
|
||||
"help": "Uses the pbkdf2 hashing function instead of scrypt for generated keystore files. "
|
||||
},
|
||||
"arg_devnet_chain_setting": {
|
||||
"help": "[DEVNET ONLY] Set specific GENESIS_FORK_VERSION value. This should be a JSON string containing an object with the following keys: network_name, genesis_fork_version, exit_fork_version and genesis_validator_root. It should be similar to what you can find in settings.py. This will override any selected chain."
|
||||
}
|
||||
},
|
||||
"generate_keys": {
|
||||
"msg_key_creation": "Creating your keys.",
|
||||
"msg_creation_success": "\nSuccess!\nYour keys can be found at: ",
|
||||
"msg_pause": "\n\nPress any key.",
|
||||
"err_verify_keystores": "Failed to verify the keystores.",
|
||||
"err_verify_deposit": "Failed to verify the deposit data JSON files."
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,8 @@
|
||||
},
|
||||
"msg_mnemonic_presentation": "This is your mnemonic (seed phrase). Write it down and store it safely. It is the ONLY way to retrieve your deposit.",
|
||||
"msg_press_any_key": "Press any key when you have written down your mnemonic.",
|
||||
"msg_mnemonic_retype_prompt": "Please type your mnemonic (separated by spaces) to confirm you have written it down. Note: you only need to enter the first 4 letters of each word if you'd prefer."
|
||||
"msg_mnemonic_retype_prompt": "Please type your mnemonic (separated by spaces) to confirm you have written it down. Note: you only need to enter the first 4 letters of each word if you'd prefer.",
|
||||
"msg_mnemonic_clipboard_warning": "WARNING: You MUST write the mnemonic down, as the clipboard will be cleared after this step.",
|
||||
"msg_confirm_clipboard_clearing": "WARNING: Your clipboard will be CLEARED. Press any key to clear the clipboard."
|
||||
}
|
||||
}
|
||||
44
src/vendors/ethstaker-deposit-cli-0.5.0/ethstaker_deposit/intl/en/cli/partial_deposit.json
vendored
Normal file
44
src/vendors/ethstaker-deposit-cli-0.5.0/ethstaker_deposit/intl/en/cli/partial_deposit.json
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"partial_deposit": {
|
||||
"arg_partial_deposit" :{
|
||||
"help": "Generate a partial deposit with any amount at least 1 ether which will be signed by the provided validator keystore. This will append to the balance of the provided validator or initiate the creation of one."
|
||||
},
|
||||
"arg_partial_deposit_chain": {
|
||||
"help": "The name of the Ethereum PoS chain your validator is running on. \"mainnet\" is the default.",
|
||||
"prompt": "Please choose the (mainnet or testnet) network/chain name"
|
||||
},
|
||||
"arg_partial_deposit_amount": {
|
||||
"help": "The amount to deposit to this validator in ether denomination. Must be at least 1 ether and can not have greater precision than 1 gwei. Default is 32 ether.",
|
||||
"prompt": "Please enter the amount you wish to deposit to this validator. Must be at least 1 ether and can not have greater precision than 1 gwei. 32 is required to activate a new validator"
|
||||
},
|
||||
"arg_partial_deposit_keystore": {
|
||||
"help": "The keystore file associated with the validator you wish to sign with and deposit to.",
|
||||
"prompt": "Please enter the location of your keystore file."
|
||||
},
|
||||
"arg_partial_deposit_keystore_password": {
|
||||
"help": "The password that is used to encrypt the provided keystore. Note: It's not your mnemonic password. (It is recommended not to use this argument, and wait for the CLI to ask you for your password as otherwise it will appear in your shell history.)",
|
||||
"prompt": "Enter the password that is used to encrypt the provided keystore.",
|
||||
"mismatch": "Error: The provided keystore password was unable to decrypt this keystore file. Make sure you have the correct password and try again."
|
||||
},
|
||||
"arg_partial_deposit_output_folder": {
|
||||
"help": "The folder path where the partial deposit will be saved to. Pointing to `./partial_deposits` by default."
|
||||
},
|
||||
"arg_withdrawal_address": {
|
||||
"help": "The withdrawal address of the validator. If you wish to create a validator with 0x00 credentials use the new-mnemonic or existing-mnemonic command.",
|
||||
"confirm": "Repeat the withdrawal address for confirmation.",
|
||||
"prompt": "Please enter the withdrawal address. If you wish to create a validator with 0x00 credentials use the new-mnemonic or existing-mnemonic command."
|
||||
},
|
||||
"arg_compounding": {
|
||||
"help": "Generates compounding validators with 0x02 withdrawal credentials for a 2048 ETH maximum effective balance or generate regular validators with 0x01 withdrawal credentials for a 32 ETH maximum effective balance. This feature is only supported on networks that have undergone the Pectra fork.",
|
||||
"prompt": "Please enter yes if you want to generate compounding validators with 0x02 withdrawal credentials for a 2048 ETH maximum effective balance. Compounding validators and 0x02 withdrawal credentials are only supported on networks that have undergone the Pectra fork. Please type no or nothing if you want regular validators with 0x01 withdrawal credentials for a 32 ETH maximum effective balance."
|
||||
},
|
||||
"arg_devnet_chain_setting": {
|
||||
"help": "[DEVNET ONLY] Set specific GENESIS_FORK_VERSION value. This should be a JSON string containing an object with the following keys: network_name, genesis_fork_version, exit_fork_version and genesis_validator_root. It should be similar to what you can find in settings.py. This will override any selected chain."
|
||||
},
|
||||
"msg_partial_deposit_creation": "\nCreating your partial deposit...",
|
||||
"msg_verify_partial_deposit": "\nVerifying your partial deposit...",
|
||||
"err_verify_partial_deposit": "\nThere was a problem verifying your partial deposit.\nPlease try again",
|
||||
"msg_creation_success": "\nSuccess!\nYour partial deposit file can be found at: ",
|
||||
"msg_pause": "\n\nPress any key."
|
||||
}
|
||||
}
|
||||
19
src/vendors/ethstaker-deposit-cli-0.5.0/ethstaker_deposit/intl/en/cli/test_keystore.json
vendored
Normal file
19
src/vendors/ethstaker-deposit-cli-0.5.0/ethstaker_deposit/intl/en/cli/test_keystore.json
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"test_keystore": {
|
||||
"arg_test_keystore" :{
|
||||
"help": "Verify your keystore file with a provided password"
|
||||
},
|
||||
"arg_test_keystore_keystore": {
|
||||
"help": "The keystore file you wish to verify.",
|
||||
"prompt": "Please enter the location of your keystore file."
|
||||
},
|
||||
"arg_test_keystore_keystore_password": {
|
||||
"help": "The password used to attempt decryption of the provided keystore file. Note: It is not your mnemonic password. (It is recommended not to use this argument, and wait for the CLI to ask you for your password as otherwise it will appear in your shell history.)",
|
||||
"prompt": "Enter the password that is used to encrypt the provided keystore.",
|
||||
"mismatch": "Error: The provided keystore password was unable to decrypt this keystore file. Make sure you have the correct password and try again."
|
||||
},
|
||||
"msg_verify_keystore_file": "\nVerifying your keystore file...",
|
||||
"msg_verification_success": "\nSuccess!\nYour keystore file was successfully decrypted with the provided password!",
|
||||
"msg_pause": "\n\nPress any key."
|
||||
}
|
||||
}
|
||||
@@ -3,15 +3,15 @@
|
||||
"msg_key_creation": "Creating your keys:\t\t"
|
||||
},
|
||||
"export_keystores": {
|
||||
"msg_keystore_creation": "Creating your keystores:\t"
|
||||
"msg_keystore_creation": "Creating your keystore-*.json file(s):\t"
|
||||
},
|
||||
"export_deposit_data_json": {
|
||||
"msg_depositdata_creation": "Creating your depositdata:\t"
|
||||
"msg_depositdata_creation": "Creating your deposit_data-*.json file(s):\t"
|
||||
},
|
||||
"export_bls_to_execution_change_json": {
|
||||
"msg_bls_to_execution_change_creation": "Creating your SignedBLSToExecutionChange:\t"
|
||||
},
|
||||
"verify_keystores": {
|
||||
"msg_keystore_verification": "Verifying your keystores:\t"
|
||||
"msg_keystore_verification": "Verifying your keystore-*.json file(s):\t"
|
||||
}
|
||||
}
|
||||
}
|
||||
8
src/vendors/ethstaker-deposit-cli-0.5.0/ethstaker_deposit/intl/en/deposit.json
vendored
Normal file
8
src/vendors/ethstaker-deposit-cli-0.5.0/ethstaker_deposit/intl/en/deposit.json
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"check_python_version": {
|
||||
"err_python_version": "Your python version is insufficient, please install version 3.9 or greater."
|
||||
},
|
||||
"check_connectivity": {
|
||||
"connectivity_warning": "\n*** Internet connectivity detected ***\n\nTo mitigate the risk of unauthorized access and safeguard generated key material, it is strongly advised to run this tool in an offline, airgapped environment. Operating online increases susceptibility to potential theft or compromise.\n\nBy continuing, you are accepting responsibility for the risk.\n\nPress any key to continue..."
|
||||
}
|
||||
}
|
||||
62
src/vendors/ethstaker-deposit-cli-0.5.0/ethstaker_deposit/intl/en/utils/validation.json
vendored
Normal file
62
src/vendors/ethstaker-deposit-cli-0.5.0/ethstaker_deposit/intl/en/utils/validation.json
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"verify_deposit_data_json": {
|
||||
"msg_deposit_verification": "Verifying your deposit_data-*.json file(s):\t"
|
||||
},
|
||||
"validate_password_strength": {
|
||||
"msg_password_length": "The password length should be at least 12. Please retype.",
|
||||
"msg_password_utf8_win32": "Your terminal is not UTF-8 encoded. To ensure the keystore file can be imported on Linux, the password should contain only English-language characters. Please retype.",
|
||||
"msg_password_utf8": "Your terminal is not UTF-8 encoded. To ensure the keystore file can be imported on Linux, the password should contain only English-language characters. Please retype.\nAlternatively, you can quit this program and relaunch it from a UTF-8 encoded terminal."
|
||||
},
|
||||
"validate_int_range": {
|
||||
"err_not_positive_integer": "That is not a positive integer. Please retype."
|
||||
},
|
||||
"validate_choice": {
|
||||
"err_invalid_choice": "That is not one of the valid choices. Please retype your choice."
|
||||
},
|
||||
"validate_withdrawal_address": {
|
||||
"err_invalid_ECDSA_hex_addr": "The given withdrawal address is not in hexadecimal encoded form.",
|
||||
"err_invalid_ECDSA_hex_addr_checksum": "The given withdrawal address is not in checksum form.",
|
||||
"err_missing_address": "An address must be provided",
|
||||
"msg_ECDSA_hex_addr_withdrawal": "**[Warning] you are setting a withdrawal address. Please ensure that you have full control over this address.**"
|
||||
},
|
||||
"validate_yesno": {
|
||||
"err_invalid_bool_value": "This is an invalid value for a yes/no question."
|
||||
},
|
||||
"validate_deposit_amount": {
|
||||
"err_invalid_amount": "Invalid amount provided. Please provide a value of at least 1 ether of how much you wish to deposit.",
|
||||
"err_not_gwei_denomination": "Invalid amount provided. Please provide a value can not have precision beyond 1 gwei.",
|
||||
"err_min_deposit": "Invalid amount provided. Please provide a value of at least 1 ether.",
|
||||
"err_max_deposit": "Invalid amount provided. The max deposit amount is 2048 ether. Please provide a lesser or equal amount."
|
||||
},
|
||||
"validate_bls_withdrawal_credentials": {
|
||||
"err_is_already_01_form": "The given withdrawal credentials is already in 0x01 form. Have you already set the withdrawal address?",
|
||||
"err_not_bls_form": "The given withdrawal credentials is not in BLS_WITHDRAWAL_PREFIX form."
|
||||
},
|
||||
"validate_bls_withdrawal_credentials_matching": {
|
||||
"err_not_matching": "The given withdrawal credentials does not match the old BLS withdrawal credentials that mnemonic generated."
|
||||
},
|
||||
"verify_bls_to_execution_change_json": {
|
||||
"msg_bls_to_execution_change_verification": "Verifying your BLSToExecutionChange file:\t"
|
||||
},
|
||||
"normalize_bls_withdrawal_credentials_to_bytes" :{
|
||||
"err_incorrect_hex_form": "The given input is not in hexadecimal encoded form."
|
||||
},
|
||||
"normalize_input_list": {
|
||||
"err_incorrect_list": "The given input should be a list of the old BLS withdrawal credentials of your validator(s). Split multiple items with whitespaces or commas."
|
||||
},
|
||||
"validate_keystore_file": {
|
||||
"err_file_not_found": "No file was found. Please verify the provided path and try again.",
|
||||
"err_invalid_keystore_file": "The discovered file is not the correct keystore file format. Please verify the provided path is to a keystore file and try again."
|
||||
},
|
||||
"validate_devnet_chain_setting": {
|
||||
"err_invalid_devnet_chain_setting": "Invalid JSON string for devnet_chain_setting. It should be a valide JSON object that contains at least the following keys: network_name, genesis_fork_version and exit_fork_version.",
|
||||
"arg_devnet_chain_setting_warning": "**[Warning] Using devnet chain setting with this command.**"
|
||||
},
|
||||
"validate_devnet_chain_setting_json": {
|
||||
"err_devnet_chain_setting_not_object": "Invalid JSON string for devnet_chain_setting. The JSON string does not contain an object at root.",
|
||||
"err_devnet_chain_setting_missing_keys": "Invalid JSON string for devnet_chain_setting. It is missing one or more of these key in the root object: network_name, genesis_fork_version or exit_fork_version.",
|
||||
"err_devnet_chain_setting_invalid_json": "Invalid JSON string for devnet_chain_setting. Decoding the JSON string was impossible. Make sure to pass a valid JSON string.",
|
||||
"err_devnet_chain_setting_key_length": "Invalid JSON string for devnet_chain_setting. The root object should only contain 3 or 4 keys.",
|
||||
"err_devnet_chain_setting_invalid_fourth_key": "Invalid JSON string for devnet_chain_setting. The root object is missing the genesis_validator_root key."
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user