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 201

bbn1l70w2gr62zjtr0eqz6npgqglea9s75l5qmszz4

Wallet 202

bbn1783cye0g6qnqjagck6vlk834fslt0z3x4483kq

Wallet 203

bbn1nj8dcw235klkl0nvdvfrp6dz8zy0vr89cgn7wf

Wallet 204

bbn18wvpqnz2qyahf9gzag9qcjrz38hg72as72zmuj

Wallet 205

bbn1skv2quty6zavcqfrnq746ll2pmyvj273j64yhc

Wallet 206

bbn13483d47gftuw45kygxp3vre6apv97xv45kpamz

Wallet 207

bbn13cwp22g37n478ywyemwjmvu7vv5utlnel3kvjm

Wallet 208

bbn14mngkgm3ey4aesjaf358pa5u9tz637y6vyvqp4

Wallet 209

bbn1xyplrytfl3sz7n0pe9w0gf9d45zn4pe0df5y0j

Wallet 210

bbn10y60u4gvf4kct0g8679tjx8ewkpyf0xjkw6dxu

Wallet 211

bbn1la63aajzdr6dlc9xm47a4u23maesdw47jsekkl

Wallet 212

bbn1sw7chn23upfxkc2xglefj233dnlxgwanjvq7kv

Wallet 213

bbn1myckz9qkak58vgylv92n9ypx8tvtx6pwkrgrgx

Wallet 214

bbn1ku4ljel90nfxe8pjx3ldtqw38l7xl6rh0f2f4m

Wallet 215

bbn1ed3jnj22uzdaz8n7xlezwwf5nvkducue378qhk

Wallet 216

bbn1xu5raqzk5fjlpznrdw5er3m5ynzm06808upc09

Wallet 217

bbn1v6vnzdrlp8pvat4vcma7re9g3r79paj5x2kxyx

Wallet 218

bbn1ew8s2sanvhwf2c2gxldf2sgppachs57enkgnmy

Wallet 219

bbn1swv07cxuaa8j7p6fdnfg8pegmf2apqn66tey9k

Wallet 220

bbn1nvmzj7qe9qvduv5vw9wqu4dj3nd7md3hwrexja

Wallet 221

bbn17qj5rphe62u9ru0he9l4rpptuyy9vmxstlch0g

Wallet 222

bbn177zmm0988jlf5l3syhv5vwcsas22cag0u5p5cz

Wallet 223

bbn15w6czjtdnznwksa4ng540tf4u29qq205yvxg94

Wallet 224

bbn1ny62u7zzjp2eh7rudtqehd442jzzvydjmaj9yg

Wallet 225

bbn1d2npc0363qpv5h7ejz7p3tnvp8dl93mdwsvn5z

Wallet 226

bbn1guvmdcch8hw3df5upxghtcdnyr3nv08crt8tfy

Wallet 227

bbn1z5xyrj2gl75c5m6827j0stkdcngrk0fv0znq9t

Wallet 228

bbn1texzx2j02mneweyhvc7yhvzakw0euhzgpdqzjg

Wallet 229

bbn1gu3d6424xmx9veyw76mse9hh6tmnc5mz08zhkh

Wallet 230

bbn1v9khqgk6xxguged5tf85ml2epngej5fl3vw2p0

Wallet 231

bbn1aefzj22kwzm52e5gaqlg8g496hxpsp84td9x8c

Wallet 232

bbn1hmzaw6tuxkxu65k04szkfqqsl80lpyjd4xtuhk

Wallet 233

bbn1rq2t57cwmpa7u0009625pvu96avsmad3wr57ry

Wallet 234

bbn104edwyj7h33jmjqxnhlv66cde77ur7s2el2g5z

Wallet 235

bbn1ezgle84u5ey9uq3nghn6v4fayp4zjwewspuj2z

Wallet 236

bbn14xxcewz96j8grevlspvpc2rf59ec7waf570qx7

Wallet 237

bbn14c0etg9wju5pmmp8ptfw20nu5rvd09hv35xevt

Wallet 238

bbn1m522zw63tp94g337jlgcf2aw8enf2fuz4w24as

Wallet 239

bbn1aaj22nk8f4d0fwd5dc5nj03ea6gfxy8x3t3mfa

Wallet 240

bbn1f3fh0028rggumeec8v584853x5kqf9pcslz6y5

Wallet 241

bbn1t67flegpxsjg4rzd7n7xveadzuzxwd7atrupr6

Wallet 242

bbn17wj7r3u2humj83c9ya5g86skl7l5nmsdfr4wph

Wallet 243

bbn16wvxj42q6u75nqfar753c6zf063y8gfvmvyje9

Wallet 244

bbn1h9fvyc09up4pu6md6we66jlnysjar522da039w

Wallet 245

bbn1tv3p2c2rr6h6dz54qhk59sxgq6ety5ces5z08j

Wallet 246

bbn1n42c7hkqj3z8ppv8cp438d9rfca8788xke7gef

Wallet 247

bbn1kaqxfwf26urx3yf2xwg3sz8mml2ykefkjkunk3

Wallet 248

bbn1hlkke3t6mpp5gvl3avna5tcxzl8t8se2ezvhw9

Wallet 249

bbn1sf4md0af6484cjgp6rhpy68urcf5crkc7yvh4c

Wallet 250

bbn1tq9gnxzgjhmf488mcc75ytnudnur4anj33fzmp

Wallet 251

bbn1wakrx4dc9fa663km2dpnfuknszfseskzvannln

Wallet 252

bbn15crwezt7g843sy3074f0y8rslsnfjhl0aqpm4w

Wallet 253

bbn1avg07pjfcpy52y906n8903w5hs3r5xs6qfpt4y

Wallet 254

bbn107034gh4wad33hpp86tng33dwttk69dwhpj857

Wallet 255

bbn18ya6l3fxy7kxwewkj546mtuz6n0p9ufzsd269y

Wallet 256

bbn1t20pzd3ghuzfgv979w8qtmzxa50wq0tvjl6kct

Wallet 257

bbn1heqtfs53k9m4nrksujrjckr3789u973fx5kpjv

Wallet 258

bbn1ajl8mhxvpvpul9sld257nchulntu9n5d4r24nu

Wallet 259

bbn1z8hjmgp00ugr5crpzqn9894e4vs6f6mdqe032f

Wallet 260

bbn18cgnvgeqzm0fnx5lvkwyg6hdsjasyez49ejneg

Wallet 261

bbn1a69j8tn95a076vd6jvhdc3kws5kqrx0sj2rhsw

Wallet 262

bbn1xv5yagfmwj3yrrnmg7wwt35k0tsg2cjapc4rxv

Wallet 263

bbn1v0p0a635qwut46sjetlus5lar95gfgvjpe6zm7

Wallet 264

bbn1g4hyd9fzx4kupcf85e3e9gcrrwvrc80y2tz7u4

Wallet 265

bbn1a6k848fyllqx5crz5764rdlpll6a28hksyzqtj

Wallet 266

bbn13ln0q8pqakfrmwvdczmz00jj9ym23pnp6rzt8e

Wallet 267

bbn1asfmcwu6v0p46uwnrjsenezavvqwwlpaxt3zwn

Wallet 268

bbn15mn9yg8hkzv3mdxl9eacum0ff4jhpmflwqych4

Wallet 269

bbn1yg2z5j2s3nemq5lqlef7wd4w4fkjw9cghq2aak

Wallet 270

bbn157f708uaxn5jvvnyheazy46vuvx2mxe9fa5jmu

Wallet 271

bbn1tzwwh2zfyydvqqvuzjs3ug0npxehg5pjk3vu5n

Wallet 272

bbn1zfm4lqj5a8x0d375p4dwzzz32sdq38x6tc54tn

Wallet 273

bbn18m8xv2u62xrw02l6s5u299wnqmps4ffm5wk585

Wallet 274

bbn1ul6wsqf6skw2r8lketw674w8rly5p0dgk93p30

Wallet 275

bbn16rnku48zgnc7lrg6pymf93783tn6j2zn7eekl8

Wallet 276

bbn1yyd05mpxyyh3tekv3zkuqwtsut55ujfrej0m0m

Wallet 277

bbn18te6h0c79a4h2yqk8wwkmhmlatzz88dwql7mzm

Wallet 278

bbn1zjfrjze65vc0eke9nuyuv3j3ds974lgpvl34r9

Wallet 279

bbn1fus5d7e75cmzspmdgqskse3j8fgdquprrl43kg

Wallet 280

bbn1l5p2dkkhz2wt35a9s9v4v47z3efaxea60lv05k

Wallet 281

bbn13uzgc4632x2qtsqqk89f66y4hhlwmf5qynqcn3

Wallet 282

bbn1anyc4gsnzc3umnur96rc72zpnknvvwwjdxdac2

Wallet 283

bbn12e6u9vt3e4dwx8evj6f47ut86pah8s2p5zrwdy

Wallet 284

bbn1khuee3342qcexfjzve0aqxqdhuw8u9py3qc3gs

Wallet 285

bbn109lt659xhl6x68ul88gskvmjzw9e2wcd3cjcz0

Wallet 286

bbn1q8qdyk5ngc9dpz9f5nlp9lz83zjy7jgdmvhlx9

Wallet 287

bbn1p4ytrusuxuq3u9rsy5f8l3fsr434u2fp0l9mvu

Wallet 288

bbn1g3x3dm6qmzs7tkjncjuz3yw652nmdap8jdmfey

Wallet 289

bbn1zu54nv48rtqm4u96uglravv0m7rppcwk3d6mnc

Wallet 290

bbn1j9lh26ywdc9vhtust9ct0q227tvmhl06hak5kp

Wallet 291

bbn1l2cuzdnadc4zwmch0pa7v0rr845vru7rar7hpx

Wallet 292

bbn1h48udje5n0mn5045gyqf5tz3n92hq7492k23p2

Wallet 293

bbn1q3cs0w74rn99vrtzfx5jfch4shnvv4rk59634f

Wallet 294

bbn1d2ytw3y7wh2gctfwqetfhftyygfwmm28y7zwwt

Wallet 295

bbn1jl4pfhgsfgj4xglfgy4yx0a8sxe6uvdgz8z4k7

Wallet 296

bbn1heypqzs8pw5dpg8upansrp8v2aljujvvzunjfd

Wallet 297

bbn14f9ljkr7z2cxvagylq30hmk0lr4w7jzgdrddf4

Wallet 298

bbn13hf38vscc6j8sw57ar2jj5f2nmwa3a4t2rkvxk

Wallet 299

bbn1tc3kpxftqm8tnpk8tctwdzs9k2qvakq0j08w6g

Wallet 300

bbn1yrp9hxkajf0232kcxsynh3fec45e9wh2jh84fh