# Preparing Voluntary Exits in Advance

By [Ladislaus](https://paragraph.com/@ladislaus) · 2023-02-15

---

`→ updated on 02/27/2023: added a section for generating a voluntary exit message without a mnemonic / offline computer (with ethdo v1.28.4+)`

* * *

With the upcoming Shanghai/Capella network upgrade, the Ethereum validator lifecycle will be formally closed. Although the exit process itself had been specified all along, it is worth reviewing it once again, adding the final piece of the puzzle to it: [withdrawals](https://notes.ethereum.org/@launchpad/withdrawals-faq)🦉

Additionally, about 60% of all mainnet validators will have to rotate their [withdrawal credentials](https://notes.ethereum.org/@launchpad/withdrawals-faq#Q-What-are-0x00-and-0x01-withdrawal-credentials-prefixes) if they wish to receive their accrued rewards & their deposit, eventually.

> Stakers will need to touch their mnemonic in order to generate the necessary [BLS-to-Execution message](https://notes.ethereum.org/@launchpad/withdrawals-faq#Q-If-I-used---eth1_withdrawal_address-when-making-my-initial-deposit-which-type-of-withdrawal-credentials-do-I-have). _On this occasion_ they may as well consider preparing a voluntary exit message in advance.

A **voluntary exit message (VEM)** for a given validator requires a signature and thus accessibility to its [private validator key](https://www.attestant.io/posts/exploring-staking-keys/). Node operators usually follow the [official](https://docs.teku.consensys.net/HowTo/Voluntary-Exit/#:~:text=A%20voluntary%20exit%20is%20when,successfully%20exited%20to%20avoid%20penalties.) [exit](https://lighthouse-book.sigmaprime.io/voluntary-exit.html#:~:text=A%20validator%20can%20initiate%20a,since%20it%20has%20been%20activated.) [documentation](https://docs.prylabs.network/docs/wallet/exiting-a-validator) provided by their clients of choice - but what if the the node and the expected keystores are not at hand?

A VEM can be generated in advance as described in the following tutorial and, for example, be backed up as a .json file on an arbitrary hard drive.

* * *

Unlucky scenarios to prepare for
--------------------------------

First, let’s think of a few scenarios for (unslashed) validators which lack their private validator key, but instead are equipped with a voluntary exit message in advance:

### 1\. ) Node operator discontinuance

*   The validator operator is not able to access and maintain the node for the foreseeable future anymore (e.g. suddenly passed away)
    

It should be better practice to `provide their heirs` with a way to exit and withdraw the staked ETH without too much technical knowledge.

### 2\. ) Staking-as-a-service provider disappearance

Customers of (semi-)custodial staking providers (32ETH tranches) must trust their node operator to properly handle their private signing key(s). Even if the withdrawal credentials point at a customer controlled address, staking-as-a-service providers technically _can_ reduce the trust assumptions even further. Customers _should_ ask their providers for a prepared exit message for their validator(s).

The mechanism is comparable to an [escape hatch for Layer-2 protocols](https://l2beat.com/scaling/risk): if the staking provider were to disappear, a customer can independently initiate an exit.

### 3\. ) Node compromising

*   The node has been physically stolen, hacked, lost or is inaccessible for other reasons.
    

A race starts to not let the attacker slash the validator (although the attacker has little incentive to do so, there is an increased risk for a [signer slashing](https://eth2book.info/altair/part2/incentives/slashing#introduction))

Assuming an empty _exit queue_, it may take just 4 epochs (~26 minutes) between submitting a prepared exit message to the network and the validator being _exited_. (see schematic overview below)

Once _exited_, a validator is exempted from all consensus duties and the risk of committing a slashable offense is eliminated.

_\-- As an in-depth analysis of the exit process is out of scope for this post, feel free to refer to_ [_primary sources_](https://www.youtube.com/watch?v=G8UstwmGtyE) _on_ [_how withdrawals_](https://docs.google.com/presentation/d/1ojzvCMVKaXIedNdTk1zWnPC_HmGVCjwgr126m7PY3AQ/edit#slide=id.ga18ab66bc8_0_32) _/_ [_exits_](https://ethereum.org/en/staking/withdrawals/#exiting-staking-entirely) _work_ [_in detail_](https://medium.com/intotheblock/understanding-the-exit-queue-on-ethereums-shanghai-upgrade-cdb4dc029564) _--_

![simplified exit process representation - thanks to @benjaminion_xyz for review](https://storage.googleapis.com/papyrus_images/ed3ea0f596d35de0a23979adbc5ad65d08d4cf9f197c569c14dfbad553c799ef.png)

simplified exit process representation - thanks to @benjaminion\_xyz for review

* * *

> [👉 **note and very important caveat** 👈](https://ethstaker.gitbook.io/ethstaker-knowledge-base/faq#how-long-do-pre-signed-exit-messages-remain-valid)

A signed voluntary exit is valid only for the current protocol specification and one upgrade.
---------------------------------------------------------------------------------------------

That means, VEMs signed for the (previous) _Altair_ fork specifications are valid in both _Altair_ and _Bellatrix_ (the subsequent upgrade), but will become invalid in _Capella_ (the upcoming upgrade). As a result, stakers may wish to refresh their stored exit messages after every upgrade (or every other one at a minimum).

[![]({{DOMAIN}}/editor/youtube/play.png)](https://www.youtube.com/watch?v=uTWpSYn4MA8)

_thanks to @benjaminion\_xyz for this critical hint_

UPDATE

> Feel free to follow-up on [**discussions and change requests to remove the expiry date**](https://github.com/ethereum/consensus-specs/pull/3288) for voluntary exit messages as soon as the next network upgrade (Deneb).

* * *

How to get started?
-------------------

⚠️ As an imminent precaution, generating and submitting VEMs as well as BLS-to-Execution change messages should be **practiced on testnets**! ⚠️

*   Before Goerli, [Zhejiang testnet](https://blog.ethereum.org/2023/02/10/finalized-no-38) is a great place to start. Here, the Shanghai/Capella upgrade is already live (guides: [one](https://github.com/eth-educators/ethstaker-guides/blob/main/zhejiang.md), [two](https://github.com/eth-educators/ethstaker-guides/blob/main/zhejiang-alt.md), [three](https://mirror.xyz/ladislaus.eth/nYZCmrO7ZndrP92kGyJG0-wzbnIsd3HwxsII-gT1zu8))
    

Since the Ethereum Foundation maintained Staking-Deposit-CLI [currently lacks the VEM generation feature](https://github.com/ethereum/staking-deposit-cli/issues/316), we will use `ethdo` - an audited, [open source third party tool](https://github.com/wealdtech/ethdo) by well-renowned community members [attestant](https://attestant.io).

> Sidenote: keep your initial mnemonic secure even after the one-time withdrawal credential change - it remains a must-have for validator keystore re-creation and consequently for VEM generation as well!

Generate voluntary exit message(s)
----------------------------------

The VEM generation process itself is a combined online & offline process (for mnemonic security reasons). For a high-level, conceptual overview of a possible VEM generation setup, refer to the following diagram:

![conceptual overview of an online+offline VEM generation setup](https://storage.googleapis.com/papyrus_images/77ea1049661854fbc3c1ba4dde970c1e1b4d4cb7045845f2162a96fab32b5719.png)

conceptual overview of an online+offline VEM generation setup

### Prerequisites

*   Retrieve the [latest version of ethdo](https://github.com/wealdtech/ethdo/releases)
    
*   Prepare a Linux Live USB drive and copy _ethdo_ to it _(well-documented elsewhere)_
    
*   Get a hand on your (secret) mnemonic/seed phrase - **operate with extra caution(!)**
    
    > check-out a similar, more detailed [step-by-step guide](https://github.com/eth-educators/eth-docker/tree/main/.eth/ethdo#changing-withdrawal-credentials) for withdrawal credential changes by the fine folks from [eth-docker.net](http://eth-docker.net)
    

### 1.) Online preparation

On an (online) computer **with a beacon node attached/connected**, prompt the following command in the directory at which _ethdo_ is located:

    $ ./ethdo --connection http://localhost:5052 validator exit --prepare-offline --timeout 2m --allow-insecure-connections
    

This command creates an _offline-preparation.json_ file which contains information about all validators on the network. Copy it to the bootable USB drive as well (same folder as ethdo). It will be used during the offline step (2).

![excerpt from an offline-preparation.json for Zhejiang testnet](https://storage.googleapis.com/papyrus_images/2d3f4cbf82c7d93d280b32e871678ea2638ade9de4626badea3065ee288cfc77.png)

excerpt from an offline-preparation.json for Zhejiang testnet

_Alternatively_ using Docker:

    $ touch $(pwd)/offline-preparation.json && docker run --rm -it --network=host -v $(pwd)/offline-preparation.json:/app/offline-preparation.json wealdtech/ethdo --connection 127.0.0.1:5052 validator exit --prepare-offline --timeout 2m --allow-insecure-connections
    

* * *

### 2.) Offline operations

> _potentially combine this step with generating a_ [_BLS-to-Execution message_](https://github.com/wealdtech/ethdo/blob/master/docs/changingwithdrawalcredentials.md)

Boot into your offline computer and generate the VEM (exit-operation.json) for **_each_** validator (index) individually, making use of your mnemonic and information from the _offline-preparation.json_:

    $ ./ethdo validator exit --offline --mnemonic="vocal ethics ... tomato bargain" --validator=123456
    

`This command creates an exit-operation.json file which includes a signed VEM.`

![example output for a exit-operation.json](https://storage.googleapis.com/papyrus_images/49fb283796e856a25596f9b52b2759e584eba51b4e8ed16e97ac5bb8b656d637.png)

example output for a exit-operation.json

→ The file may then be stored safely as preparation for scenarios as described above.

* * *

### 3.) Online broadcasting of VEMs to the network

On an online computer: broadcast each validator exit message to the network

### Option #1 - without a local beacon node

👉 This would be the required `task for node operator heirs`👈

They need access to the VEM, (i.e exit-operation.json) file(s) and access to a command line:

    $ curl -d @exit-operation.json -H "Content-Type: application/json" -X POST https://beacon.zhejiang.ethpandaops.io/eth/v1/beacon/pool/voluntary_exits
    

_Adjust the public beacon public API accordingly (e.g. to mainnet endpoints)_

This message broadcast does **not** require gas (i.e. no transaction fee).

> note: [beaconcha.in](https://beaconcha.in/) offers a **drag & drop web interface** for broadcasting VEM messages, eliminating the need for command line knowledge

[https://zhejiang.beaconcha.in/tools/broadcast](https://zhejiang.beaconcha.in/tools/broadcast)

![beaconcha.in web interface (for VEMs & BLS-to-Execution change messages)](https://storage.googleapis.com/papyrus_images/9b75e4b74ad782d8ef2bbc5cc7421ed77e86630c901978a76de292c726bdf419.png)

beaconcha.in web interface (for VEMs & BLS-to-Execution change messages)

Alternatively, _attestant_ has announced they will provide a mainnet endpoint in order to submit exit messages as well.

* * *

### Option #2 - via ethdo and a local beacon node attached

    $ ./ethdo --connection http://localhost:5052 validator exit --signed-operation exit-operation.json
    

_Alternatively_ using Docker:

    $ docker run --rm -it --network=host -v $(pwd)/exit-operation.json:/app/exit-operation.json wealdtech/ethdo validator exit --signed-operation exit-operation.json
    

_Adjust the Docker volumes and exit-operation files for each validator accordingly_

* * *

Optional
--------

### 4\. ) Verify that the exit message has made it on-chain

As shown in the exit process chart at the top, the VEM will either still be processed or already be incorporated into a block.

### Option #1 without a local beacon node

    $ curl -X GET "https://beacon.zhejiang.ethpandaops.io/eth/v1/beacon/pool/voluntary_exits" -H "accept:application/json"
    

_Adjust the public beacon public API accordingly (e.g. to mainnet endpoints)_

* * *

### Option #2 - via ethdo and a local beacon node attached

    $ ./ethdo --connection http://localhost:5052 validator info --validator=123456
    

_Alternatively_ using Docker:

    $ docker run --rm -it --network=host wealdtech/ethdo --connection 127.0.0.1:5052 validator info --validator=123456
    

* * *

> Repeated call for mainnet caution:
> 
> *   _Be aware that generating voluntary exit messages involves dealing with your validator mnemonic. Thus,\*\*\*never\*_ **trust\*** instructions from a random stranger writing blogposts on mirror.xyz or elsewhere!\*
>     
>     _Make sure to follow official client teams instructions and guidelines whenever possible._
>     

* * *

`UPDATE`

Generating a VEM (online only)
------------------------------

![conceptual overview of an online VEM generation setup](https://storage.googleapis.com/papyrus_images/33222af88bf12e85f40c684b830ae8b57559c990f4878cb2bf2f03fe47c81186.png)

conceptual overview of an online VEM generation setup

### Prerequisites

*   validator signing key (and the corresponding passphrase)
    
*   _ethdo v.1.28.4+_ (and a local beacon node for _offline-preparation.json_ file)
    

Going this path does not require an offline computer. It allows forward-looking and anticipatory node operators to generate a VEM in advance **without touching their mnemonic/seed phrase**. Instead, generating a VEM _only_ requires a validator signing key (and the corresponding passphrase).

> Note: in case the staking machine and thus the validator signing key is inaccessible (think of scenario 3 mentioned earlier), follow the VEM generation process (online+offline) with an mnemonic as described above.

* * *

*   Follow the `1.) Online preparation` section as described above.
    
*   Afterwards, based of the _ethdo_ directory prompt the following command to generate a VEM (exit-operation.json) for **_each_** validator individually, making use of your _signing-key.json file_ and information from the _offline-preparation.json_:
    

    $ ./ethdo validator exit --validator=/validator_keys/keystore-m_12381_3600_1_0_0-1677445363.json --passphrase=password123 --offline
    

_Change the keystore-directory & -filename as well as the keystore password - i.e._ `passphrase` _\- accordingly. Note: the “passphrase” is NOT the mnemonic!_

_Alternatively_ using Docker:

    $ touch $(pwd)/exit-operation.json && docker run --rm -it -v $(pwd)/exit-operation.json:/app/exit-operation.json -v $(pwd)/offline-preparation.json:/app/offline-preparation.json -v $(pwd)/validator_keys/keystore-m_12381_3600_1_0_0-1677445363.json:/app/keystore-m_12381_3600_1_0_0-1677445363.json wealdtech/ethdo validator exit --validator=keystore-m_12381_3600_1_0_0-1677445363.json --passphrase=password123 --offline
    

*   Follow the `3.) Online broadcasting of VEMs to the network` section as described above.
    

> note: _attestant_ intends to provide a way to obtain the information for the offline-preparation.json without the need for accessing a local beacon node, i.e. step 1.) may be obsolete

* * *

\*\*\*\*

_Please keep in mind this is a testnet guide that may contain mistakes and that takes shortcuts which come with trade-offs. It could quickly become outdated as it’s subject to ever evolving network and software changes._

\*\*\*\*\*\*\*\*

_This post was supported by a grant from a CLR funding round held by EthStaker, mainly matched by the EF._

---

*Originally published on [Ladislaus](https://paragraph.com/@ladislaus/preparing-voluntary-exits-in-advance)*
