Link a Finality Provider EOTS PK to your BABY Address

Before proceeding with this guide, please make sure you sign the terms first.

Proof-of-Possession (PoP) establishes ownership of both your finality provider’s EOTS key and your BABY address. For finality providers, the EOTS key is essentially a Schnorr key, which should have received delegations from the phase-1 network.

This guide demonstrates how to generate PoP, validate it, submit it to the API, and remove it if you need to bond your EOTS key to a different BABY address.

This guide assumes that you have created a Babylon address to receive the airdrop using the Babylon Address CLI Creation guide. Please ensure that you have access to your keyring before proceeding.

PoP format for finality providers

The Airdrop API requires the following JSON message format of a PoP for finality providers

{
  "eotsPublicKey": "3d0bebcbe800236ce8603c5bb1ab6c2af0932e947db4956a338f119797c37f1e",
  "babyPublicKey": "A0V6yw74EdvoAWVauFqkH/GVM9YIpZitZf6bVEzG69tT",
  "babySignEotsPk": "AOoIG2cwC2IMiJL3OL0zLEIUY201X1qKumDr/1qDJ4oQvAp78W1nb5EnVasRPQ/XrKXqudUDnZFprLd0jaRJtQ==",
  "eotsSignBaby": "pR6vxgU0gXq+VqO+y7dHpZgHTz3zr5hdqXXh0WcWNkqUnRjHrizhYAHDMV8gh4vks4PqzKAIgZ779Wqwf5UrXQ==",
  "babyAddress": "bbn17ew0he6svxrqj2c7mef7qsyg0assc2upa5gy7w"
}

Detailed specification of each field:

  • eotsPublicKey: The EOTS public key of the finality provider in hex format.
  • babyPublicKey: The Babylon secp256k1 public key in base64 format.
  • babyAddress: The BABY account address (bbn1..). The address is derived from the babyPublicKey and used as the primary identifier on the Babylon network.
  • eotsSignBaby: A Schnorr signature in base64 format, created by signing the sha256(babyAddress) with the EOTS private key.
  • babySignEotsPk: A signature of the eotsPublicKey, created by the Babylon private key. This signature follows the Cosmos ADR-036 specification and is encoded in base64. The signing doc spec can be found here.

One can develop tools by themselves following the above spec, or they can use our reference implementation and follow the guidance below.

1. Create PoP

1.1. Setup the EOTS Daemon

The EOTS daemon is utilized to create and manage the EOTS key of the finality provider. If you participated as a finality provider during the first phase of the Babylon mainnet, you should have already created your EOTS keys and stored them safely following this guide.

Note that for the purposes of this guide, you will need to upgrade your eotsd version to version v0.4.3 (previously v0.4.0 was used). To do this, please follow the instructions below.

First, download the finality provider toolset repository with git clone

git clone https://github.com/babylonlabs-io/finality-provider.git

Cloning into 'finality-provider'...

Then, checkout to the v0.4.3 release tag:

cd finality-provider # cd into the project directory
git checkout v0.4.3

Note: switching to 'v0.4.3'.

At the root of the finality provider repository install the finality provider binaries using make install.

make install
CGO_CFLAGS="-O -D__BLST_PORTABLE__" go install -mod=readonly --tags "" --ldflags ''  ./...

eotsd is part of the finality provider service suite, so running make install also generates fpd which is not used in this guide.

You can check if the installation succeeded by running eotsd --help.

eotsd --help
NAME:
   eotsd - Extractable One Time Signature Daemon (eotsd).

USAGE:
   eotsd [global options] command [command options] [arguments...]

COMMANDS:
   start               Start the Extractable One Time Signature Daemon.
   init                Initialize the eotsd home directory.
   sign-schnorr        Signs a Schnorr signature over arbitrary data with the EOTS private key.
   verify-schnorr-sig  Verify a Schnorr signature over arbitrary data with the given public key.
   pop                 Proof of Possession commands
   help, h             Shows a list of commands or help for one command

   Key management:
     keys  Command sets of managing keys for interacting with BTC eots keys.

GLOBAL OPTIONS:
   --help, -h  show help

1.2. Create the Proof of Possession (PoP)

The PoP can be created and exported using the eotsd pop export command. After which, you will need to enter passphrases for eots key and baby key consecutively.

eotsd pop export --home /path/to/eotsd/home/ --key-name <my-key-name> --keyring-backend file \
  --baby-home /path/to/babylon/home/ --baby-key-name <my-baby-key-name> --baby-keyring-backend file \
  --output-file /path/to/pop_fp.json
Enter keyring passphrase (attempt 1/3): # for your eots keyring
Enter keyring passphrase (attempt 1/3): # for your baby keyring
{
  "eotsPublicKey": "3d0bebcbe800236ce8603c5bb1ab6c2af0932e947db4956a338f119797c37f1e",
  "babyPublicKey": "A0V6yw74EdvoAWVauFqkH/GVM9YIpZitZf6bVEzG69tT",
  "babySignEotsPk": "AOoIG2cwC2IMiJL3OL0zLEIUY201X1qKumDr/1qDJ4oQvAp78W1nb5EnVasRPQ/XrKXqudUDnZFprLd0jaRJtQ==",
  "eotsSignBaby": "pR6vxgU0gXq+VqO+y7dHpZgHTz3zr5hdqXXh0WcWNkqUnRjHrizhYAHDMV8gh4vks4PqzKAIgZ779Wqwf5UrXQ==",
  "babyAddress": "bbn17ew0he6svxrqj2c7mef7qsyg0assc2upa5gy7w"
}

This command has several flag options:

  • --home specifies the home directory of the EOTS daemon in which the EOTS key created for phase-1 has been stored.
  • --key-name specified the name assigned to the EOTS key (is the value of the flag -key-name specified when running eotsd keys add --key-name ... ).
  • --passphrase specifies the password used to decrypt the key. The passphrase is required if it was specified when creating the EOTS key eotsd keys add --passphrase ....
  • --eots-pk is the EOTS public key which is specified as eots_pk in the GitHub registry for each finality provider (the -eots-pk flag takes priority over the -key-name flag, which requires eots.db in the -home directory).
  • --keyring-backend specifies the keyring backend. Any of [file, os, kwallet, test, pass, memory] are available. You can find more details about the available keyring backends here. By default, the test keyring backend is used, although it is recommended that you use an encrypted keyring.
  • --baby-home specifies the location where the BABY key is stored.
  • --baby-key-name specifies the key name of the BABY key.
  • --baby-keyring-backend specifies the keyring backend of the BABY key.
  • --output-file specifies the file path of the raw JSON result. Note that if the flag is not specified, the JSON file won't be generated.

Please refer to the Phase-1 registration guide if you want a reminder on where you stored your EOTS home directory.

If you accidentally lost the keyring file, you can recover the keyring with the mnemonic phrases by running the eotsd keys add --recover flag option to prompt input the mnemonic phrases and recover the key:

eotsd keys add --home /path/to/eotsd/home/ --key-name <key-name-recover> --keyring-backend file --recover

1.3. Validate the Proof of Possession (PoP)

To validate the JSON file that contains the PoP, run eotsd pop validate command:

eotsd pop validate /path/to/pop_fp.json
 Proof of Possession is valid!

If Proof of Possession is valid! is shown, the pop is successfully validated.

1.4. Troubleshooting

Common problems and possible errors that might appear.

DB timeout

If you can’t connect to the database and get the following error:

[eotsd] failed to create db backend: timeout

You should stop the process that is keeping the .db file locked

Config error

If there is something wrong with your current config and the following error pops up:

[eotsd] failed to load config at...

This is probably due to a new parameter appeared in the config and you could create a new default config with eotsd init ..., just remember to update the values to your key name and directory path

2. Submit PoP via API

To register your finality provider for the airdrop (if eligible), you need to submit the previously created PoP payload to the airdrop API endpoint:

curl -X POST 'https://airdrop-api.babylon.foundation/pop/baby-eots' \
-H 'Content-Type: application/json' \
-d '{
  "eotsPublicKey": "3d0bebcbe800236ce8603c5bb1ab6c2af0932e947db4956a338f119797c37f1e",
  "babyPublicKey": "A0V6yw74EdvoAWVauFqkH/GVM9YIpZitZf6bVEzG69tT",
  "babySignEotsPk": "AOoIG2cwC2IMiJL3OL0zLEIUY201X1qKumDr/1qDJ4oQvAp78W1nb5EnVasRPQ/XrKXqudUDnZFprLd0jaRJtQ==",
  "eotsSignBaby": "pR6vxgU0gXq+VqO+y7dHpZgHTz3zr5hdqXXh0WcWNkqUnRjHrizhYAHDMV8gh4vks4PqzKAIgZ779Wqwf5UrXQ==",
  "babyAddress": "bbn17ew0he6svxrqj2c7mef7qsyg0assc2upa5gy7w"
}'

In case of success, the API will return a 200 status code and the following response:

{"message": "ok"}

In the case that your EOTS key does not receive any stake/points or is otherwise not eligible, the API will return a 400 status code and the following response:

{"message":"Sorry, you are not in the FP list","code":400}

To make sure your finality provider was successfully registered, you can query it by the associated baby address and check whether your EOTS public key matches

curl -X 'GET' 'https://airdrop-api.babylon.foundation/pop/baby-eots?babyAddress=your-baby-address' -H 'accept: application/json'

The API will return the following response (formatted by jq):

[
  {
    "eotsPublicKey": "289719ef19e455816e474588007f1824df7f6b1bace7decf8bb1c435e4cb849e",
    "babyPublicKey": "Ax4u7IEfmG6q5Ai//uD9m9vKRdU/uhWd4GSVwxwHIYQm",
    "babyAddress": "bbn1v2auyq4pwgtp3yas9fdlkzehnhefzxg7vfpfdz"
  }
]

This response returns all the ETOS public keys associated with this BABY address. If there is no PoP associated with this BABY address it will return an empty slice.

3. Delete submitted PoP

If you wish to remove the BABY address associated with your finality provider, you can delete the submitted PoP and re-submit a new PoP that bonds the EOTS key to a different BABY address. Please note that this is a necessary first step if you want to change your Babylon address to a new one — i.e., you must first delete the existing association and then create a new one.

3.1. Retrieve the Deletion Message

The first step to deleting your PoP is to retrieve a message containing a custom nonce from the Babylon API. You can obtain this by calling the following endpoint (replace your-baby-address with the BABY address used in the submitted PoP):

curl -X GET 'https://airdrop-api.babylon.foundation/pop/baby-sign-message?address=your-baby-address'

Example response in JSON format:

{"message":"Welcome to Babylon Airdrop!\\r\\nAddress: bbn1v2a65yjl5cathzl8hdysqr9xz7w503xvvu85fx\\r\\nNonce: 0f7c99f145"}

3.2. Sign the response message

To prove that you are the owner of the finality provider key that intends to delete the existing proof of possession, you need to cryptographically sign the string literal that is stored inside the message attribute of the prior JSON response.

You can accomplish this by running eotsd pop delete command:

eotsd pop delete --home /path/to/eotsd/home/ --key-name <my-key-name> \
   --keyring-backend file --baby-home /path/to/babylon/home/ \
   --baby-key-name <my-baby-key-name> --baby-keyring-backend file \
   --message 'Welcome to Babylon Airdrop!\\r\\nAddress: bbn1v2a65yjl5cathzl8hdysqr9xz7w503xvvu85fx\\r\\nNonce: 0f7c99f145'
{
  "eotsPublicKey": "3d0bebcbe800236ce8603c5bb1ab6c2af0932e947db4956a338f119797c37f1e",
  "babyPublicKey": "A0V6yw74EdvoAWVauFqkH/GVM9YIpZitZf6bVEzG69tT",
  "babySignature": "FKc2rpM30yfc6ivx40H/UXF9YM+yv6Bu0UrdpS+CZx1XGCdCAxkMewr3D786hx/YhBm3UBV8qhdPp86OTVrShw==",
  "babyAddress": "bbn17ew0he6svxrqj2c7mef7qsyg0assc2upa5gy7w"
}

One additional flag to the previous eotsd pop export is -message, which specifies the message to be signed. In this example it would be 'Welcome to Babylon Airdrop!\\r\\nAddress: bbn1v2a65yjl5cathzl8hdysqr9xz7w503xvvu85fx\\r\\nNonce: 0f7c99f145'.

3.3. Submit the PoP Deletion Request

The output of the eotsd pop delete command is the payload you need to submit to the API to finalize the deletion request:

curl -X DELETE 'https://airdrop-api.babylon.foundation/pop/baby-eots' \
-H 'Content-Type: application/json' \
-d '{
  "eotsPublicKey": "3d0bebcbe800236ce8603c5bb1ab6c2af0932e947db4956a338f119797c37f1e",
  "babyPublicKey": "A0V6yw74EdvoAWVauFqkH/GVM9YIpZitZf6bVEzG69tT",
  "babySignature": "FKc2rpM30yfc6ivx40H/UXF9YM+yv6Bu0UrdpS+CZx1XGCdCAxkMewr3D786hx/YhBm3UBV8qhdPp86OTVrShw==",
  "babyAddress": "bbn17ew0he6svxrqj2c7mef7qsyg0assc2upa5gy7w"
}'

In case of success, the API will return a 200 status code and the following response:

{"message":"ok"}

To ensure deletion, getting PoP by your BABY wallet address will return an empty array:

curl -X GET 'https://airdrop-api.babylon.foundation/pop/baby-eots?babyAddress=bbn17ew0he6svxrqj2c7mef7qsyg0assc2upa5gy7w'
[]

Now, you can submit a new PoP with a new BABY key.

Search Your Wallet Address Here

Wallet 1101

bbn1hkfgvje5amf3wy55g5ny65xe9ngugl4pr3j6ut

Wallet 1102

bbn1p8pm4gdd4nt9rd048nrxhlkvw6y07psv0dgrtq

Wallet 1103

bbn1v5ppjzpf8sz3u5mxk890pwv08wjv2auq0mf9wh

Wallet 1104

bbn1f2mm28uvwz7l4ngyq55mmahrd9yvzy5ux59v8e

Wallet 1105

bbn1yr993mdgf7g9ynk3xg4yv6sydhr4cqypzj56nl

Wallet 1106

bbn1a4y8c6wll223nxfhhy6aytge9zq6rwvhdfnx6f

Wallet 1107

bbn1tmpf9xu9zsuf8qhu6k7gs0tmpg37ukrvmn37du

Wallet 1108

bbn14u27yrk7gu36ygtgzu2u68lna78l4spxdv8las

Wallet 1109

bbn1t8tqj3n0yzn9c2septvlk7h0js6glgjpk6rwsd

Wallet 1110

bbn10yhvk6jh37zwzqggaqghdwjtl9zafqmgp5zntp

Wallet 1111

bbn10jj3cs5fz0vxxw05pwc2smf6wk5jkt2w0swjad

Wallet 1112

bbn1fzg6q8mymplywcd9jtc775yyu607spj0tydm4y

Wallet 1113

bbn1y3vcgpeptzjf6xnfye04d0l9r3qx52st84q2fj

Wallet 1114

bbn1n9g4dwxrq8z4nd46l33zf5jwcllgrt9wfg8nvm

Wallet 1115

bbn1wkse89zqdrgkctyqufrq89dn376cxt2489lwun

Wallet 1116

bbn1zq9pt3p6wzarytksw07k6xeww6rudgudqv7duf

Wallet 1117

bbn1ydvseq9axn6nyswftvrv740g2su37zujjj668n

Wallet 1118

bbn19w2twlajr5x7l30qswvj3flmk9e2jevlxjk0fh

Wallet 1119

bbn14gwr58f6y5em9hkug7vhx0c3pgjk8a9sj4t0nj

Wallet 1120

bbn1q3v4442uqfkczqunk8vtfg39tlwxhc836mrfp3

Wallet 1121

bbn1h7zkdt82va69vn4zg0xgar42fkyujj6kugmshs

Wallet 1122

bbn1qny9qvv402z32w3epxe0fgyug6cd4qe855f5rr

Wallet 1123

bbn1trl8ttv0jz2z37978r26sthrqhm6rv69fhgs87

Wallet 1124

bbn1wfaracvnc9fqdsw2ypgxc9uss9smwdcpaq6l0l

Wallet 1125

bbn1adcgpheezjzgjh56cde7tn47w8709xznj3g79y

Wallet 1126

bbn1wlq0a0e2pxm6yuzpqg9p2w69hnr6mefr5l204z

Wallet 1127

bbn176tvvhxmy7amsn7tcym4v56q6tfcmp2c8dzsrg

Wallet 1128

bbn1hv7pedc6nw9r53mvd2kdax9q456wrw2l25n2n2

Wallet 1129

bbn16nfpuhtva2u3y2c4qxt7x8xnmtzuz3gsngy9eq

Wallet 1130

bbn19zz2j55dyxu60cmxqzkww66d8xw26k84dy2x8n

Wallet 1131

bbn1zvfwff72rwfzp3ucng04r0zwwhnvuugljkr7zh

Wallet 1132

bbn1ezhtxvaskvqsx8drcd626l95dj8sl4tyt4vrcd

Wallet 1133

bbn189qw7mk96samgtc49uclzq04042su5hkmqtu79

Wallet 1134

bbn1aw07dtk02luxj30kpjmf4hah9caqug38yy87d3

Wallet 1135

bbn16qucwg63mtt8t88qezzyj8smnt2086zzkxwgvj

Wallet 1136

bbn1zvjcec5h5tnmwnqy66n95uvwkfud8vh2y5dzxf

Wallet 1137

bbn1g3e7ejsw2mqt677exjgvja26tpnshlqllfuk8z

Wallet 1138

bbn16cu5ptq9a0f462jj237vqwsw8vf9l4mqzcnkkz

Wallet 1139

bbn132chtxezuyatfmku9qjj0e93yspfvk962dzlp7

Wallet 1140

bbn1nrc67y745v700jn5j6yymhes8jjamugzsyqz4x

Wallet 1141

bbn17q5e366whe5xln36q9tpvyvfncdzmfnp7ss2y0

Wallet 1142

bbn1sssfshffkr2hjnauhpmlukxrmkgyvy0wjstx50

Wallet 1143

bbn1504vem6f84vghcfv4r2xq4kx247t32pmhy0r26

Wallet 1144

bbn14pdc2lq9kdmsg65gwzpcxyh25ykfsjed555zqv

Wallet 1145

bbn1vxwvafwt82zwshfmsj0wwp7eevxk95rqaytuad

Wallet 1146

bbn1n5pmq8xcmldz8sph8e3kgskneucg7xyf0fnlpq

Wallet 1147

bbn1v34jatysj4wyhgg26al5xcvkjkuycmvltffk5t

Wallet 1148

bbn1jrklrr5j7hru55w0jqh7zy5d6y7yd437z7n87g

Wallet 1149

bbn1t39fl4qnd9pjhu94xf4hjg5nnm7nfe7xm307gw

Wallet 1150

bbn1k2zlwakwcctrr96sah9h2pqc4sx5xnlp8uf8a6

Wallet 1151

bbn1mh5vhl52e48c7v5zxz57m8e0u0k55s0ecmc72e

Wallet 1152

bbn1ekdzt5kgjcmru2kg0jnpvc5jll8as8tukmwysm

Wallet 1153

bbn133nlz6vvhzl7n7383hxkypkv8wkufqhsxvd0su

Wallet 1154

bbn15m6ltf9wrujnash76vhckrvdr4h2d0cs29nre9

Wallet 1155

bbn1gk5d9xrndew4wxcdq24272j0jpgqynjjeq3qqa

Wallet 1156

bbn1sjpz2kc4yh5m6rvfy3ct4plfqdcz3pf0r65ryr

Wallet 1157

bbn18wlkdc04ul0f9sryqqzg53y5x8tnjxv8jz8k9q

Wallet 1158

bbn1rvy6dtyg5vu9nek3uymshzww2crugr88r3qtc6