The Two Ways to Exit a Validator

To exit an Ethereum validator one needs to submit s SignedVoluntaryExit (or exit message) to Ethereum's consensus layer, signed by the validator's private key (held by us). There are two ways to achieve this:

1. Exit Messages

Once a validator becomes active, Figment signs an exit message but doesn't broadcast it. You can store it encrypted until you're ready to exit your validator. Exit messages are good if you want to reduce dependency on their staking provider. They are generally used in preparation for disaster recovery in case we can't exit your validators for you, whatever the reason may be.

:point-right: [Guide] Working With Exit Messages

:point-right: [API Reference] Broadcast Exit Messages endpoint

2. On Demand Exits

Exit messages can however be cumbersome as an "everyday" method for exiting. So you can request to have us exit validators on your behalf. Just tell us which specific validators you want to exit (via their public keys) or how many validators attached to a specific withdrawal address you want to exit, and we will sign and broadcast exit messages.

:point-right: [API Reference] Exit Validators endpoint


The Exit Lifecycle of a Validator

In order to exit the active set, a validator must comply to these 3 rules:

  1. it must be active
  2. it has been active for at least 256 epochs (27.3 hours)
  3. it has not already initiated an exit
Lifecycle of an exiting ETH validator

Working With Exit Messages

Overview

Once a SignedVoluntaryExit is generated, anyone in possession can broadcast it on the consensus layer to exit the validator, which is why Figment requires your encryption key: so only you have access to them. Since pre-signed exit messages expire after two hard forks on the network, Figment automatically re-generates Exit Messages daily at 6:30am UTC for all validators that have already entered the activation queue. You should fetch and store up-to-date copies of encrypted Exit Messages for all of your validators at least as often as once per fork, such as monthly, to be safe.

🚧

Regeneration of exit messages

Daily regeneration of a new Exit Message does not invalidate previously generated Exit Messages as long as they are not older than two hard forks.

Creating a Keypair

Figment currently supports both GPG and RSA keys for encrypting Exit Messages on Ethereum. You must use a single encryption key for all of your validators per chain (i.e. one key for mainnet and one for testnet). Please get in touch with your Figment rep to provide or update your encryption key.

GPG

  • We recommend using the command gpg --full-generate-key
    • However you decide to generate the key, we require a GPG key size of at least 2048 bits
  • To export your public key (which you will provide to Figment): `gpg --output public_key.gpg --armor --export key_identifier (for example [email protected])

RSA

  • To generate your private key: openssl genrsa -out private_key.pem 4096
    • Note that we require an RSA key size of 4096 bits
  • To generate the public key (which you will provide to Figment): openssl rsa -in private_key.pem -outform PEM -pubout -out public_key.pem
    • Note: the public key should be in PKCS8 format, i.e. starting with:
      ----BEGIN PUBLIC KEY-----

Once you’ve provided your key to Figment…

  • You can expect your public key to be saved within 24 business hours of providing it to Figment
  • Once the public key has been saved, up-to-date versions of encrypted exit messages for all of your active validators will be generated daily at 6:30am UTC.

Retrieving Encrypted Exit Messages

  1. Once you have completed Figment’s Liability Disclaimer and provided your PGP public key with Figment, you will have easy access to pre-signed validator exit messages (technically named SignedVoluntaryExit) for all of your active validators. Note that a validator is not eligible for exit until 256 epochs (~27.3 hours) have passed since entering the active set.

  2. To retrieve your exit messages you can use Figment’s Validator API. Use Get Validators where you’ll be able to retrieve the encrypted exit message file from the presigned_exit_transaction field which resides in each validator’s attributes.

    1. The contents of the file are encrypted using the encryption key you provided to Figment.

      1. Below is the format of the file for GPG encrypted Exit Messages.

        -----BEGIN PGP MESSAGE-----
        Version: Date Created (Epoch Created)
        Comment: Validator Public Key
        
        wV4DhAgK6qzUbbYSAQdAcGntg7DvCl+4Sjz3sw8MGBfZo/Yv3ih/G3PNrzd2bUsw
        jwAX1EqYjC3PB35YCyPuVh0YC5Cp7x7QQvW5js0pSB+kiUTN6/jjmE0o5goreVj5
        0sB8AQTVG9R+g2Bs3eXaQSbVk/3ji6klJg9ReccQpkuTmAKI61YZmZ5YXhD20KDU
        7wj6PXxcI50ol2Y4OUYSdZr/W2NM42jhMWUEbBl1/T6DjWfRbwd+MDwUwtq790Zy
        d8lFBwy9zdYcGAU2EHEq4rvn08v/xdt5EHVUAsHOCTg9jbzw7QbEThL/BCpBt4t0
        +umtF3E9EYec3yR651brdTWo3rDLqsU0FW3o2VrrT9emQo7or6NDFSz0Hv70YX+U
        Qrq7dxDCUKdHmxQadje5PePaKbLiGaGnN8x81bDSsvKBXXLeTRNyZae5HPmFGNRP
        uSXM/Z54VsqBM0CZeoMjrcdHyr26G7Ar/geoKvIAyNwKTGmoVtZz5CfllpKgrPSH
        b9X5UsHtPrF4s5pfuK0dcHNQYnxazG4OlRaEhJ3j1g==
        =cLUy
        -----END PGP MESSAGE-----
        
      2. Below is the format of the file for RSA encrypted Exit Messages.

        aGV3bl7MuFX5q+gGBBDPkE1PHhZSPJP/ENRuFAptNYU43qQky9XRXbBJlwbL4bjxSfbX3FVlBJIE7eZZsi6iBGcucFBJGIMZ8B9/r9KnGrpGxhLDFZR5Atl4Nm81CgqZQ493CD4S4hAP+5eHxUUfnF/E1pEASk2BeBWslif2k1KY/B7EdQegXRghWwQVPQVkiOu7vhCJOGTj2VE0adybq3fiRvAO4EcZlYHYzeaAHPznq/oI7x3pzhK2dog5X8jtyfC8eloBQOKSn7mR76FJH+0yI2W3PURicqrzR61FRP1hzShxGByi1mf13NnrmdBubrnkJKnjScaIhTtnxky4dhstJz/jPlBf2iBJn+HFcL2H/C/RuI1iNs+G519Sovqv+gIjGEgtwv5FGuIfnHf3ZRCDGVnsvdR0DXVOsXNgtBpG6gjF+DS0Vyv6WXYP1CidNo4bZA3q35SoVznX8gfWQZG9tfvcLiKLCHA9bDFJmuTBUVxB60YuPMuNogO5+30/CBpRkTouXF8I3KJNuJN1ysPfKR9JCgmEJpxeCq4jqkesHGavayvPuMBwfmzboWrJzqq7m+hw7vtHHcb9EdxF8jbWW46k/oJn+ZiFlNO7zl7PETZi1T7SiZuem3o218pshi6ad+jdPj3elCuBN8+32qFFiQuU5KMeVSCIQ8NxtHo=
        
    2. Below we have provided boilerplate code for downloading your exit messages via API

      const fs = require('fs');
      const os = require("os");
      
      const queryParams = {
        presigned_exit_transaction: "true",
        status: "active_ongoing",
        withdrawal_address: "MY_WITHDRAWAL_ADDRESS"
      }
      
      const queryString = Object.keys(queryParams).map(key => key + '=' + queryParams[key]).join('&');
      const directoryName = `${os.homedir}/figment/ethereum/exit-transactions`;
      const apikey = "VALIDATOR_API_KEY";
      
      fetch(`https://hubble.figment.io/api/v1/prime/eth2_staking/validators?${queryString}`, {
        method: "GET",
        headers: {
            "Authorization" : `Bearer ${apikey}`,
            "Content-Type": "application/json" 
        }
      })
      .then((resp) => resp.json())
      .then((body) => {
        for(let i = 0; i < body.data.length; i++) {
          if (body.data[i].attributes.presigned_exit_transaction != undefined) {
            let presigned_exit_transaction = body.data[i].attributes.presigned_exit_transaction;
            let validator_pubkey = body.data[i].attributes.pubkey;
      
            fs.writeFile(`${directoryName}/${validator_pubkey}-exit-transaction.enc`, presigned_exit_transaction, (err) => {
              if(err)
                  console.log(err);
              else {
                console.log("The file was saved!");
                console.log("Content:");
                console.log(fs.readFileSync(`${directoryName}/${validator_pubkey}-exit-transaction.enc`, "utf8"));
              }
            });
          }
        }
      })
      .catch((err) => console.log("Error: " + err))
      

Decrypting Encrypted Exit Messages

  1. If you’re using GPG:

    gpg -d exit-transaction.enc | jq 
    

    See here for a Golang implementation.

  2. If you’re using RSA:

    base64 -d < exit-transaction.enc | openssl pkeyutl -decrypt -inkey private_key.pem -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256 | jq 
    
  3. Output:

    {
      "message": {
        "epoch": "156529", 
        "validator_index": "356323"
      },
      "signature": "0xa9bbed5545c6278a8f208c0ce60cf62d4a1b5110c9782b0ed1bdfc11547d036acebcbff23a6d6b312918e0f249474c180e62dfe09db1c7cc0136e6dd8c5fb7cbed73f88a592522cc716b71ac8f72da71d26d4f7825042939d24b35cf326c567c"
    }
    

Broadcasting

There are three ways you can broadcast your exit transactions once you are able to decrypt them.

  1. Using Figment’s Staking API - Figment’s Staking API will track the exit transaction for you and provide updates as the validator moves through the exit queue and the following withdrawal process.

    :point-right: [API] Broadcast Exit Messages

  1. Using your own Beacon Node - this solution is best for stakers who want to minimize any dependencies on third parties

    :point-right: Beacon API endpoint for submitting exit transaction

  2. Using beaconcha.in tool - beaconcha.in has recently released a public tool to simply broadcast pre-signed exit transactions

    :point-right: Webpage for submitting pre-signed exit transactions