{"id":18299964,"url":"https://github.com/chorusone/eth-staking-smith","last_synced_at":"2025-04-05T13:35:28.243Z","repository":{"id":64991892,"uuid":"526225846","full_name":"ChorusOne/eth-staking-smith","owner":"ChorusOne","description":"Ethereum 2.0 deposit CLI / library","archived":false,"fork":false,"pushed_at":"2024-10-29T13:55:19.000Z","size":351,"stargazers_count":21,"open_issues_count":4,"forks_count":8,"subscribers_count":13,"default_branch":"main","last_synced_at":"2024-10-29T16:03:46.356Z","etag":null,"topics":["ethereum","evm-team","proof-of-stake","staking"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ChorusOne.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2022-08-18T13:35:06.000Z","updated_at":"2024-10-29T13:55:19.000Z","dependencies_parsed_at":"2023-02-10T02:30:50.892Z","dependency_job_id":"6e7c925b-69b4-4f35-981f-2ca6bd33b3ce","html_url":"https://github.com/ChorusOne/eth-staking-smith","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ChorusOne%2Feth-staking-smith","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ChorusOne%2Feth-staking-smith/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ChorusOne%2Feth-staking-smith/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ChorusOne%2Feth-staking-smith/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ChorusOne","download_url":"https://codeload.github.com/ChorusOne/eth-staking-smith/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247342658,"owners_count":20923637,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ethereum","evm-team","proof-of-stake","staking"],"created_at":"2024-11-05T15:11:00.732Z","updated_at":"2025-04-05T13:35:27.894Z","avatar_url":"https://github.com/ChorusOne.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"eth-staking-smith\n================\n\n# Introduction\n\nCommand-line tool to facilitate key and deposit data generation for ethereum proof-of-stake validators.\n\nWhy we need yet another keystore / deposit tool:\n\n1. eth-staking-smith is written in Rust\n2. ability to use as a library to automate key and deposit data generation\n3. opt-out of writing to filesystem for better security\n4. defer entropy collection to operating system by using `getrandom`\n5. ability to overwrite withdrawal credentials for new and existing mnemonic\n6. ability to generate a `SignedBLSToExecutionChange` message to convert your BLS withdrawal address `0x00` to an execution `0x01` address\n\n# Blog post\n\n[Performant Ethereum validator key management](https://medium.com/chorus-one/eth-staking-smith-1ca8374571b5?source=rss-------1)\n\n# Usage\n\n```\ncargo build\n```\n\n## New mnemonic \n\nGenerate key and deposit data with a new mnemonic:\n\n```\n./target/debug/eth-staking-smith new-mnemonic --help\n```\n\n### Example command:\n\n```\n./target/debug/eth-staking-smith new-mnemonic --chain mainnet --keystore_password testtest --num_validators 1\n```\n\n## Existing mnemonic \n\nRegenerate key and deposit data with existing mnemonic:\n\n```\n./target/debug/eth-staking-smith existing-mnemonic --help\n```\n\n### Example command:\n\n```\n./target/debug/eth-staking-smith existing-mnemonic --chain mainnet --keystore_password testtest --mnemonic \"entire habit bottom mention spoil clown finger wheat motion fox axis mechanic country make garment bar blind stadium sugar water scissors canyon often ketchup\" --num_validators 1 --withdrawal_credentials \"0x0100000000000000000000000000000000000000000000000000000000000001\"\n```\n\n\n## Passing mnemonic as environment variable\n\nIt is not always desirable to pass mnemonic as CLI argument, because\nit can be either mistakenly recorded in shell history or recorded by\nthe monitoring software that could be logging process arguments on host.\n\nThis is why all commands that accept `--mnemonic` argument also support\ntaking mnemonic as environment variable `MNEMONIC`\n\nFor example, `existing-mnemonic` command works like follows with mnemonic in plain text:\n```\n./target/debug/eth-staking-smith existing-mnemonic --chain mainnet --keystore_password testtest --mnemonic \"entire habit bottom mention spoil clown finger wheat motion fox axis mechanic country make garment bar blind stadium sugar water scissors canyon often ketchup\" --num_validators 1 --withdrawal_credentials \"0x0100000000000000000000000000000000000000000000000000000000000001\"\n```\n\nAnd, as follows with mnemonic as an environment variable `MNEMONIC`:\n\n```\nexport MNEMONIC=\"entire habit bottom mention spoil clown finger wheat motion fox axis mechanic country make garment bar blind stadium sugar water scissors canyon often ketchup\"\n./target/debug/eth-staking-smith existing-mnemonic --chain mainnet --keystore_password testtest --num_validators 1 --withdrawal_credentials \"0x0100000000000000000000000000000000000000000000000000000000000001\"\n```\n\nOr, it makes possible to have bash prompt for mnemonic with hidden input like follows\n\n```\necho \"Please enter your mnemonic\" ; read -s MNEMONIC ; export MNEMONIC\nPlease enter your mnemonic\n./target/debug/eth-staking-smith existing-mnemonic --chain mainnet --keystore_password testtest --num_validators 1 --withdrawal_credentials \"0x0100000000000000000000000000000000000000000000000000000000000001\"\n```\n\n## Using custom testnet config\n\nBoth `existing-mnemonic` and `new-mnemonic` commands support generating validators for custom testnets.\nTo reference custom testnet config yaml file, pass `--testnet_config` parameter\nwith that config as value, and omit `--chain` parameter:\n\n### Example command\n```\n./target/debug/eth-staking-smith new-mnemonic --testnet_config /etc/privatenet/config.yaml --keystore_password testtest --num_validators 1 --withdrawal_credentials \"0x0100000000000000000000000000000000000000000000000000000000000001\"\n```\n\n## Converting your BLS 0x00 withdrawal address \n\nEthereum will be implementing a push-based approach for withdrawals, see [EIP-4895 docs](https://eips.ethereum.org/EIPS/eip-4895).\n\nThose who have configured a BLS withdrawal address (0x00) in the validators deposit contract, will have to undergo the following steps: \n1. generate a signed message to trigger BLS to execution address\n2. send the signed message to the beacon node\n\nYou can use `eth-staking-smith` as follows to convert your address:\n\n### Command to generate SignedBLSToExecutionChange\n\n```\n./target/debug/eth-staking-smith bls-to-execution-change --chain mainnet --mnemonic \"entire habit bottom mention spoil clown finger wheat motion fox axis mechanic country make garment bar blind stadium sugar water scissors canyon often ketchup\" --validator_start_index 0 --validator_index 100 --withdrawal_credentials \"0x0045b91b2f60b88e7392d49ae1364b55e713d06f30e563f9f99e10994b26221d\" \\\n--execution_address \"0x71C7656EC7ab88b098defB751B7401B5f6d8976F\"\n```\n\nNote that --validator-index and --validator-start-index are two distinct parameter, the former being index of validator on Beacon chain, and the latter is the index of validator private key derived from the seed\n\n\n### Command to send SignedBLSToExecutionChange request to Beacon node\n\n```\n./target/debug/eth-staking-smith bls-to-execution-change --chain mainnet --mnemonic \"entire habit bottom mention spoil clown finger wheat motion fox axis mechanic country make garment bar blind stadium sugar water scissors canyon often ketchup\" --validator_start_index 0 --validator_index 100 --withdrawal_credentials \"0x0045b91b2f60b88e7392d49ae1364b55e713d06f30e563f9f99e10994b26221d\" \\\n--execution_address \"0x71C7656EC7ab88b098defB751B7401B5f6d8976F\" \\\n--beacon-node-uri http://beacon-node.local:5052\n```\n\nNotice `--beacon-node-uri` parameter which makes payload to be sent to beacon node\n\n## Generating pre-signed exit message\n\nIt is possible to create pre-signed voluntary exit message for every validator that\nis generated from some known mnemonic, given the minimum epoch for exit to trigger.\n\nUse `eth-staking-smith` via command line like:\n\n### Command to generate presigned exit message\n\n```\n./target/debug/eth-staking-smith presigned-exit-message --chain mainnet --mnemonic \"entire habit bottom mention spoil clown finger wheat motion fox axis mechanic country make garment bar blind stadium sugar water scissors canyon often ketchup\" --validator_seed_index 0 --validator_beacon_index 100 --epoch 300000\n```\n\nNote that --validator-beacon-index and --validator-seed-index are two distinct parameter, the former being index of validator on Beacon chain, and the latter is the index of validator private key derived from the seed\n\nIt is also possible to directly pass private key with `--private-key` parameter instead,\nthen `--mnemonic` and `--validator-seed-index` may be omitted like follows\n\n```\n./target/debug/eth-staking-smith presigned-exit-message --chain mainnet --private-key \"0x3f3e0a69a6a66aeaec606a2ccb47c703afb2e8ae64f70a1650c03343b06e8f0c\" --validator_beacon_index 100 --epoch 300000\n```\n\n### Command to send VoluntaryExitMessage request to Beacon node\n\n```\n./target/debug/eth-staking-smith presigned-exit-message --chain mainnet --mnemonic \"entire habit bottom mention spoil clown finger wheat motion fox axis mechanic country make garment bar blind stadium sugar water scissors canyon often ketchup\" --validator_seed_index 0 --validator_beacon_index 100 --epoch 300000 \\\n--beacon-node-uri http://beacon-node.local:5052\n```\n\nNotice `--beacon-node-uri` parameter which makes payload to be sent to beacon node\n\n\n### Command to generate batch of presigned exit messages\n\nSometimes it may be desirable to generate batch of presigned exit messages for the\nvalidators created from the same mnemonic.\n\n```\n./target/debug/eth-staking-smith batch-presigned-exit-message --chain=mainnet --mnemonic='ski interest capable knee usual ugly duty exercise tattoo subway delay upper bid forget say' --epoch 305658  --seed-beacon-mapping='0:100,2:200'\n```\n\nInstead of accepting single `--validator-seed-index` and `--validator-beacon-index` pair of parameter,\nit takes comma-separated mapping of validator seed index to validator beacon index in `--seed-beacon-mapping`\nparameter. Keys and values in mapping should be separated by colon, so mapping of `0:100,2:200`\nwill read as follows\n\n- validator with seed index `0` with given mnemonic has index `100` on beacon chain\n- validator with seed index `1` has beacon index `200`\n\n## Exporting CLI standard output into common keystores folder format\n\nMost validator clients recognize the keystore folder format,\nproduced by upstream Python deposit CLI. While `eth-staking-smith` outputs\nall validator data into standard output, allowing for better security in\nenterprise setups, for small and individual stakers this is not convenient,\nas they need to be able to import validator keys directly into validator client.\n\nTo address such needs, `eth-staking-smith` provides convenience Python3 script\nto export JSON validator output into common keystore folder format. It should\nwork on any box with Python 3.10+ installed.\n\n```\nmkdir validator_keys/\n./target/debug/eth-staking-smith new-mnemonic --chain holesky --num_validators 2 \\\n  --keystore_password test \u003e validator_secrets.json\ncat validator_secrets.json | python3 scripts/generate_keys_folder.py\ncat validator_secrets.json | jq .mnemonic.seed \u003e mnemonic.txt\nrm validator_secrets.json\necho \"MAKE SURE TO BACK UP mnemonic.text IN THE SAFE PLACE\"\n\nls validator_keys/\ndeposit_data-1720014619.json  keystore-m_12381_3600_0_0_0-1720014619.json  keystore-m_12381_3600_1_0_0-1720014619.json\n```\n\nThe contents of `validator_keys/` folder might be imported into most\nvalidator clients, for example Lighthouse import command will look like that:\n\n```\necho \"test\" \u003e ./password.txt\nlighthouse account validator import \\\n  --network holesky --reuse-password\n  --directory validator_keys/ --password-file ./password.txt\n```\n\n\n# Implementation Details \nTo avoid heavy lifting, we're interfacing [Lighthouse account manager](https://github.com/sigp/lighthouse/blob/stable/account_manager), but optimizing it in a way so all operations are done in memory and key material is never written to filesystem during the generation to cater for our use case.\n\n## Entropy gathering\nWhen you run the command `new-mnemonic` a new mnemonic is generated from a seed. Entropy collection for the given seed is done by using the platform dependent `getrandom(2)` system call. On Linux, getrandom(2) pulls entropy from cryptographically secure RNG provided by Linux kernel, which implements ChaCha based PRNG algorithm that reseeds itself from multiple hardware TRNG sources with 300Hz frequency. If you're running on anything other than Linux, look up target platform implementation in https://github.com/rust-random/getrandom for details.\n\n## Ability to tweak performance parameters\nSpecifically, we have two arguments you may use for improving performance during key generation: \n1. You can opt-out of generating keystores by omitting the optional `--keystore_password` argument. Depending on how you manage your keys you would either store them as keystore files or simply store the private keys in vault. If you're doing the latter it would be more optimal for you to bypass the keystore generation and only retrieve the private keys such that you can store them in vault.\n2. To speed up the process of keystore generation, you may want to choose your key derivation function depending on your use case with `scrypt` with higher security parameters and slower performance vs `pbkdf2` achieving better performance with lower security parameters compared to `scrypt`.\n\n# Testing \n\n```\ncargo test\n```\n\n## E2E Tests\nTo test our code e2e, we've generated files using the [staking deposit cli v2.3.0](https://github.com/ethereum/staking-deposit-cli/releases/tag/v2.3.0) and are comparing the outputs during our tests. This is to guarantee that we're meeting the same criteria. Further error cases are checked in unit tests within the dedicated modules.\n\n# Glossary\n\n| Term      | Description |\n| ----------- | ----------- |\n| Wallet      | Interface to manage accounts       |\n| Account   | public/private keypair that points to your funds        |\n| keystore file   | encrypted version of your private key in JSON funds        |\n| key derviation function (kdf)   |  A Key Derivation Function lets you encrypt your keystore file with a password that you chose when running the cli. Eth staking smith supports `scrypt` or `pbkdf2` and will run the latter by default for improved performance.      |\n| decryption key   |    used to encrypt/decrypt keystore file    |\n| mnemonic phrase / seed phrase / seed words   | 12 or 24 word phrase to access infinite number of accounts, used to derive multiple private keys        |\n| seed   | secret value used to derive HD wallet addresses from a mnemonic phrase (BIP39 standard)       |\n| withdrawal credentials   |    Withdrawal Credentials is a 32-byte field in the deposit data, for verifying the destination of valid withdrawals. Currently, there are two types of withdrawals: BLS withdrawal (with a 00 prefix) and Ethereum withdrawals (with a 01 prefix). By default the former will be generated, however Ethereum is planning to fully move to 01 credentials once withdrawals become available |\n| withdrawal address   |  Address for which withdrawal credentials should be generated. Eth staking smith allows execution addresses with the format `^(0x[a-fA-F0-9]{40})$` |\n\n\n## Backwards compatibility\nThis project aims to present state-of-art Ethereum staking experience,\nand does not follow semver approach for new releases.\nInstead, backwards compatibility is provided on best-effort basis for both\nlibrary and command line interfaces, and every release that adds new\nfunctionality can be treated as major release.\n\nInterfaces may change as result of implementing new features, and/or\nbackwards incompatible changes in Ethereum protocol.\n\nIt is recommended to pin release version for users of command line interface,\nand pin specific git commit of `eth-staking-smith` for library interface users.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchorusone%2Feth-staking-smith","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchorusone%2Feth-staking-smith","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchorusone%2Feth-staking-smith/lists"}