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 401

bbn1mrjex8rz5yjep9yhhs09p6ku0y22cppkkexyp5

Wallet 402

bbn1e63seq6juzs0tstx3t9h3h8w0zt7c0f4zsfcts

Wallet 403

bbn1nhal43y7mktve0hk4wrd27wuxgzxnam6lw3qee

Wallet 404

bbn14u7x6hwn82ffyl6zjs955kwp9k44sfsp9t7fyt

Wallet 405

bbn1s6tcr9fmh4gawwc275zwahntedzct9rg0rkt5e

Wallet 406

bbn1jm7c9ac6cl3pepvpgvuddzm5kl3n922jd398y3

Wallet 407

bbn1srcj0vsldkelxhvmju70td4ay9ly9lcu782pkn

Wallet 408

bbn18nh30uc4asmxlc86ceea5h0tz4c2usyfkenvvg

Wallet 409

bbn1m8hwcx24pkhd062at0j0xufr4ptfhrhkk85yy0

Wallet 410

bbn17498xz0kpppw64f8r6jjqvdnewgw4uulmle7ag

Wallet 411

bbn1qda9cuk9e5dn42uf6nxlvz9awpupk2fjsk4ej2

Wallet 412

bbn1jfgmkgsmrurvhqtjytxdkc9rxsd4pwz34avf98

Wallet 413

bbn1a53e0ms4asr90v2wnrr8le6dmmd6espqfwt3hs

Wallet 414

bbn1f0mkl7jyjwvuv36rtzr5cgmfhvcg4gsxvkmu5w

Wallet 415

bbn123ap0s5fymvrut24w5euxj0gl4r4hx7jsm76zc

Wallet 416

bbn1fg43v4fh76ud755u9tluh3x8jm2r6k5swdc7nx

Wallet 417

bbn1kcnxy9ma3zpkaj8tdudjhsdgszs8xmfdk69y6p

Wallet 418

bbn10wsym9n0z7vcfwtmrmq3dq98c6z7xh3ukpyqm8

Wallet 419

bbn15pcx6dtayt2m3fjlznzeyt8t293l9sjngumj84

Wallet 420

bbn1c4pfvct2keyjd2206tzh0uy2m0d09zevx58y46

Wallet 421

bbn1cu4uwxh2spev6uprc3lq9nfa4a4nv7uef93j7m

Wallet 422

bbn1mgr8xn6u7pc4zdj2ex5csnfqngs2k28xy08dlh

Wallet 423

bbn1w83wd9r9rpqzwefyk6vkuly3g3u3674zuhgvvq

Wallet 424

bbn1pgxtucg5jalfhqdecprq0upl0gttc3kd4kd5s7

Wallet 425

bbn145m2exrgdjtfclnrt2lf9gvx7cxgnj8eh2zqpf

Wallet 426

bbn1pvg58h8azy6pwfxgzka55qf3g28e6tk988lfs5

Wallet 427

bbn1cefqfgzsqjvpgz2avtkaue0zahmexlk09e2kgl

Wallet 428

bbn1adeeznnyt9mzt2t24z6n4gmqpvqg4aewpxuhjz

Wallet 429

bbn1tuqqkqmdw75ysqvqlqk3623n02qj57m38tk0fa

Wallet 430

bbn13nytqq0mc9nrlae5trfqxuf2m0wlk9wwc2ux4s

Wallet 431

bbn1xalcynsucq7ed42cp2cvemskt9vr3pl0pplv4v

Wallet 432

bbn1amfpmu7f60l9tqjcakp6mahdsmvy0zxaratxvq

Wallet 433

bbn105rfyahwj8wu2hwz84l7tlpz2ujxul33rhu48j

Wallet 434

bbn17xfcnaumkr3uhma7q73z8ezw2qhe0lhnx2f59q

Wallet 435

bbn1cedfdergrqt686qaw86tqkr9wjp9h2098pe3vs

Wallet 436

bbn1jzaqww0g3dkgvjkm0t9sljszauatus0f44wtyt

Wallet 437

bbn1qwvv9exfgd5887axtjlqgnp45raa7zv8gqh2wt

Wallet 438

bbn1uvt9sl675vvjsasucyrfzujjwrpasmsrg0gj0m

Wallet 439

bbn1f62xzzjhdezsv4kn8fpe9e0w5hlm22dccl99ju

Wallet 440

bbn1ssw7zrx8p5p5y8qfk4wfklf887xg73r6pgvfxu

Wallet 441

bbn1t8e0494wa3xase8z4qrh34rtfs6r70224cf9u2

Wallet 442

bbn1a39c7wmc88auq4gg25n35dgt508n5yvznm5fl6

Wallet 443

bbn199qxnwwe4q25aerj3tu9z97gc9ys6ntr0jdpg8

Wallet 444

bbn1ag92qjkg38nqvf42lkvn602u3naym639e4k4u0

Wallet 445

bbn17xtkg70x7uqcqczc4pflh4z68xz0mqhzsef3xk

Wallet 446

bbn1uu5kn8e5n4dcmwsuhz6n258jzxupq0va0lgcxs

Wallet 447

bbn1egmv9y8tkdm502ytsqcn872t492lanshc44v0g

Wallet 448

bbn143hw4zgd92a9xhsp8tvjxfyzdlz53v49yc8hnx

Wallet 449

bbn10kdyxtqt3whgck0kla6stm23cgknk8pz6m8hcd

Wallet 450

bbn1z6v9m9ruc7vuh0w2npl37y7ytepavlhuy7s45e

Wallet 451

bbn1c37hwvp6uvw4dcswdsrvxt5wcsc9qm2yjgy30a

Wallet 452

bbn1uxs7av60pakym4s7qr0u047q2lfjxxxm2zgs0y

Wallet 453

bbn172yn4dfdqfmx56jnharjtqemt0a8z08asers26

Wallet 454

bbn12dvvgcq3qe3fca0aak3fk4ngzshwvtujw6maqp

Wallet 455

bbn1zqw75k5waju8dv6jc3y5ptwpypp4de7t8gp5gk

Wallet 456

bbn1ueg8qd0dd462le0yv2zft56exmt7excpe8urk3

Wallet 457

bbn1ntr7uj4rrkyc77kj8u9g09ugy6mrkae5j8um6r

Wallet 458

bbn1nxlg8n63u4ap49hrpd5q0h3rde7srpn2tjfx7z

Wallet 459

bbn1s376wyvavg5dpeqe9djmej3u9jqnvap6w5kz4j

Wallet 460

bbn1ku8gr3xzmmg5xzyrqx9hsmw82uv5j7znumvx03

Wallet 461

bbn18umra3d4u9wc0nmf0zlu7vjw2p7y9s8lc4g6vp

Wallet 462

bbn1skuwr2d7h0yw0fcu3aptmex6eueunmeha0szya

Wallet 463

bbn1qvhj3qjea4mss7avqtuuevv4fnpfkkqmky6cfe

Wallet 464

bbn1g8xzs7gw2mlupu0puq3q7u6aekz7hz83m6tte8

Wallet 465

bbn1gcqx6864y2572ex7s895svrm42hfc8zxuf8yp8

Wallet 466

bbn1q70qys9pm284pvhrp6tr8k33mm3c3mf6snw2hq

Wallet 467

bbn1r08r8g0ul6ljrajrxycyw8v3jktf9ynqgvt7cd

Wallet 468

bbn1gk0q0vfxcz04sqchtjxyc038n8x06pd6wul089

Wallet 469

bbn1lclqx2djhjd57x7thz08mg0mnpfnhv6zkmrqcd

Wallet 470

bbn1jgdvwtakf07y6fqt9yx63zau9tn0d02pvejw6f

Wallet 471

bbn132r4fe5394c0ny4rhu8c0xh362ez9sfnjs5kkj

Wallet 472

bbn1lhlwtzqfhfgc0np5mr57970c5gas9c3n90pl8r

Wallet 473

bbn1gz5n37h38t7x7sdws2fsc7h8wt6g6vsk2a3krt

Wallet 474

bbn15hd8tra9t6yfdequp2gsvqva7axj59jm6ya6g7

Wallet 475

bbn1mg5jdcv0yhcj2qm04ffdwl7n54pc3dg6dn2g27

Wallet 476

bbn1hr2rxxmy5emsa9zecjsrvafxa3c2jkhgzeahzk

Wallet 477

bbn1l8y2qe8nu42qvx48v57tnsd7399wfa9qqcnrws

Wallet 478

bbn1yg8nak3jmy5mensc34talw5qvj9u2kj0dwh39f

Wallet 479

bbn1xpkwr2u9n6q79vfua0mfp80m8j07w5dssp0s9u

Wallet 480

bbn1ka7k94v6u7m7aun7wmnk059jjpe296xecwjyce

Wallet 481

bbn17l08sgczkpcq3xfdsw76v4r7mum8jd4masez7t

Wallet 482

bbn1r3l6ruf9ngn237fkumgnleztw4t8m4drsj497t

Wallet 483

bbn1s77x8wr2gzdhq8gt8c085vate0s23xu9te7l5l

Wallet 484

bbn1m9hl8ngeen3cxy5dgdgteem6vg82svtqjwfnsw

Wallet 485

bbn17n8u6wfnd5p7tp5kcznhuqa2ggkw9zasqv2gem

Wallet 486

bbn1yr0tyqu5pzudl0k7n8wklspc95gvly8sn0ps86

Wallet 487

bbn1hcsm3fqccphkdflldadssq502hr55qhjkgc7y6

Wallet 488

bbn15mc74pqmxq80aflzd8er8a7gs76czet4rwc89r

Wallet 489

bbn1fvmats2yddecucrjglmh5a98lak85f4hxyvsaa

Wallet 490

bbn1g97vtcwhr7hqf9cgjv6p7hgssr9qmdwys4227m

Wallet 491

bbn1n86g3ecld2l7jmj9vpyv706ayz7nrpe6y9pzv6

Wallet 492

bbn1ec5n0qquc2qcmpq2f3crnzp6h9vmtgpqsz0fyr

Wallet 493

bbn1vt60whuean4d96699k0qqvkm83aq2rrntcc608

Wallet 494

bbn10j4dhlpvuz7q225xnsh63a5th04el9dzrk709h

Wallet 495

bbn14dv3tag6w7vrj9a766nzern7e4nfkx6xrdqzmf

Wallet 496

bbn1zj8ul00qhryglwsrlwlx38szvj7t9e2f6rhxrz

Wallet 497

bbn1h3pgplcm9q59plhhjdf20e7mm3k2sc2725slvr

Wallet 498

bbn16unknyefzvma5xaazw3rpqe74tjzahjzah35du

Wallet 499

bbn1lfvpu6f83uuuugrlk4m68c2mgqacyhjx4uny50

Wallet 500

bbn1mtknga6ufuwk4kj7ue56g03uhkzvac6k3x9z8w