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 501

bbn1y5ykrn2zude6cm30s9n8ruea99tjt3yrdzdzfw

Wallet 502

bbn1gy3ejmqhe09y3u584hrvg5glp00h8z6g9d49dj

Wallet 503

bbn18lyezqqcztexy426pwxuh879ktpsqyjncuxhf6

Wallet 504

bbn13j6m2twg43xupntlfdthxhpa35easac3y6tpuq

Wallet 505

bbn1p2sjr8508sem7t6lwx3ankq756rwl3puyvpd2p

Wallet 506

bbn1n56hhr5lu430skm7wt68sl8wv4t7pju3jz58ya

Wallet 507

bbn1mqrgu4agrlvm3zp6fhcgehuezvkve5xn4g4a75

Wallet 508

bbn1zywfk0439sjzlfqrdq8035qll4p6epkcaxxe7j

Wallet 509

bbn155gkcrq77w8l9ffts2ttlvwghc2w5xckh6xa32

Wallet 510

bbn1wczqhc0kgc0y3sxmhwm2eax4ns6y0x25sxpwvx

Wallet 511

bbn1g2umlpne47g0854qprr2j39sayk7tst5trknzl

Wallet 512

bbn1qpzdpjkwlyz6ym2w6rh0czgd9wlpw02jzq6kng

Wallet 513

bbn1e5gs2d2trnz8vwvr0hmx6md5fdml6spzrchzqq

Wallet 514

bbn133sns2zg6wz0xush7zxmqz7kutrsdgldfl0vqe

Wallet 515

bbn1x7egkz8sat0r937cmrqzzaehnmqtk9hlnz5ps0

Wallet 516

bbn1gpqpx73dgkd2wznecrn7hplz9psvtu7tf93nzq

Wallet 517

bbn15kjajnlaq9wjx2d25kvpfwypuk9fyv9508jqn0

Wallet 518

bbn1n2rrlpuxt0u82yurxns4fdr46mpplnwqdwr9ly

Wallet 519

bbn1zt46xzr7sfz8htphtc0k8l7qhy4wgej443k5jx

Wallet 520

bbn1qtm32uvtss0duw49u7nxewwz6wxqexfxxcelaj

Wallet 521

bbn1tvyk28dxmt00dpatng5n5nw63l44fh7v0nffuv

Wallet 522

bbn1g7ycwgq75g2f4cesdqlj3l04zv5e2kd4nx0h4s

Wallet 523

bbn1q3hxte3fmq75kz9uvqnl0ys4q527sln0czhu99

Wallet 524

bbn14wky40wg2h0hw3gsp4qxj0pjyqg65hg9ccqf26

Wallet 525

bbn18pspelm4m9xwlnjv6r9f3qmkn0nlrrjy27xn4z

Wallet 526

bbn10489qehvt89emlzw52etcuwghysceruj7r3guu

Wallet 527

bbn1a5xayzlfarjp7s5rdctzr0ke3zx7fkwyrfqt53

Wallet 528

bbn1z2qq3mf5e22whaxfm5pq8crafp2hsa76a4l5ka

Wallet 529

bbn1xqppeh9vh8mc3sspzzk0esv3x29dqcjfpk0p6g

Wallet 530

bbn1zgvalhxsrklxev6djhmct2mtpj6fvm6528q0w3

Wallet 531

bbn16a50rc0m8xc8k75kmwh55d3ucvmugxgzr24mz0

Wallet 532

bbn1vyenjy4terukvw59slu9emue4fklhsenhx8qwc

Wallet 533

bbn1j587p9v4u3hcwy4uqmsjg506ezad2qhtnfkdrw

Wallet 534

bbn1809ussrj53hefkq4nf4prvdexap632mxdmcgva

Wallet 535

bbn1c69tuyh08gmhx8rha8kar0fc2yfdz0ua2zjdk3

Wallet 536

bbn1gr6dku8q23gaut2sv42jcd2ptqtc26n3s0rrhp

Wallet 537

bbn1glkdqmtfs4jd7u37ujnu3f3dc0lylp5clk9gh8

Wallet 538

bbn12k7dad2g6q3eyq37mngzrsneydrgn7q86gjz0h

Wallet 539

bbn1c2dtn2vrzg49efs7ulhrffmwy7thymuvmhqs46

Wallet 540

bbn13zyv6un75a4n5n6mjuugphkt9lvurmruve5hv5

Wallet 541

bbn1csknk8yg6ffyt05h48wx7ulwfusm7asphj6xkp

Wallet 542

bbn1v7yk3y7e7hry9qdgxqkqfpa5cw4tzrllqwueye

Wallet 543

bbn16nlcmx0grcc2m0tgn0xv0mua8x07c0vqsnp3r0

Wallet 544

bbn1cu8vq2jl5e05l6ssduja8r2xevamms6hmjzrk4

Wallet 545

bbn1er7md5z4te0p6m5t4nvynpz56sq8e7xamz0mhr

Wallet 546

bbn13wpej8qsv2j4uw57yvwxrxfprh8pmhshff0hj6

Wallet 547

bbn16fucx34cpg8upa4xwksfyee6dt465sj75xxlxh

Wallet 548

bbn1mqvr8zdajqzcw4n4dtk0earveymwp0y2rsvzvu

Wallet 549

bbn1eqywrs2mld8kaxcvw2ezfq04s324sn545laeu9

Wallet 550

bbn1af8uff74w9hfwmnsv34gecm9n6cwgf2dy05ftp

Wallet 551

bbn14cer09fcj544cacs8q88a5u97w7jsrudfej2em

Wallet 552

bbn1xjll8g4suy5y98qewgf5r3x0ef63wp6gxha88e

Wallet 553

bbn10vkfn6jq09m22ncra76yqlque7udeyy2prphqx

Wallet 554

bbn1j8wpe4augpt3p8dtncu666zu3flpvpjgr5yff5

Wallet 555

bbn16t3g3efr70hmnd2rwhkpura0f5al8ymlwqhtgz

Wallet 556

bbn15qcfy0caa8np9fgygk2gvw7er4umra83je03fq

Wallet 557

bbn1cvtatrzllzcxs6paw57gwlu9ruzlmg85298u7a

Wallet 558

bbn1klcf48ur0yucyxkrzjl4uku6uwxeqejq4sagnn

Wallet 559

bbn13q2fasez9zjs5hac3yueu85pg252vtj5tplcq9

Wallet 560

bbn1m7xua28cv7f0fz8qsggq09lpe7zwy65ha4wdcv

Wallet 561

bbn14836e363fvc3ml0lmwf3gl0ve435n58xysqjr0

Wallet 562

bbn1e4el0lkq6dqw7mmhqjztnkz737n5qx6f40g0z7

Wallet 563

bbn13amnd5aqn7n3am9tw3mfxgw46pujcz88x0d696

Wallet 564

bbn196zyh4ekk834gdu34lsfrra4dax6zyepw6ewdy

Wallet 565

bbn1af9ahjq90pzcu6r9xqvp4lqleeyy2m5ru9v8f3

Wallet 566

bbn1hz04zjaha8gsh9eycjhfr4tnv6uu2ney9y9kvp

Wallet 567

bbn1uedndqltx3rnakutpmpdctvwet4q3z8m3rrgtw

Wallet 568

bbn1v6jhnrpa53t9rknjxkkg9fwj9y5scjle58egd9

Wallet 569

bbn1fyfnvvswqjmg2xlpx2grldmlnuzqj6zjh4j6mv

Wallet 570

bbn1zlx5ftrjn0tca7r9dsr0vzzljc6vdyj5jzynt9

Wallet 571

bbn1lx0fd70j44fwamsn6wud095hegatz23w3ke2pw

Wallet 572

bbn14yxz02wqgqn0jxyc2d6exr3zr4kdmt3m7gdm8y

Wallet 573

bbn1zgd7qc8md9rhuh8urvvzzg7x9cnp7uafttthj4

Wallet 574

bbn164cxq6rfz2u02fdaghfrmrf5quwv62y8f5lnfl

Wallet 575

bbn18ucxs3ej48rdwpehzg32rj5tww3jmtkr7qsdd3

Wallet 576

bbn176l7r2rp3v4ztjqcc9hqq3nvyf7sd62enns8us

Wallet 577

bbn18c3lzueztwm3973ysfez4khx2pcldff0j79lsx

Wallet 578

bbn1cv0hfuk0vhc5zgqrh0szcnet8ff04pte6eg7qn

Wallet 579

bbn1uulu2vm2sgk4nqmjph9fkr70va0hypmsl7wn4f

Wallet 580

bbn1a6uy04y63vt5w04ayxa3etrdedw9qn05mddqs7

Wallet 581

bbn1a0dg9zkqljjmfy40gusl9qr9vcxnfkc95vzmfr

Wallet 582

bbn16h5q8j9mv77r6r5haf3c9q579swl6vmcu2aqs8

Wallet 583

bbn1eyttpffw8qqmeha6es2cc90any8rqfdl8t5ccj

Wallet 584

bbn1dxl5mvr64dv7hneuvxnl3ktewu9wgxqdtskrv0

Wallet 585

bbn1tjg2qvsrcvc49sf0ksz4e4swn5zfsyvkymr0tk

Wallet 586

bbn14hx6vf0tkc0fm2wf8qhpagejyxc32cnlh5ccne

Wallet 587

bbn1603mnk65ny0a6m3fs59s0qmpupm9g93v04pvrv

Wallet 588

bbn13gmspxwn6y3ehmqjvmlyzh2gvm56j4e094r7kr

Wallet 589

bbn10sl2wtte5kjy3cs6wv8y5l2kgwmdpx8c8fnlfa

Wallet 590

bbn1eu9qcjqq80tldxpu8045jwsvtsjqwfglhmpvws

Wallet 591

bbn1r5tc5aqkrk68akdhl960jtjnjtwxpxa5xrvpya

Wallet 592

bbn1g0t437ennk9ts7vjtznz0lnmpna6t6gmugfplh

Wallet 593

bbn1v52tanddaaddsa0yzt9yhlau5cafmwrfpdl4n6

Wallet 594

bbn1e9pz5axlcravdakavlrpqqljswyhgzh2jlg6zp

Wallet 595

bbn1gkkxs72gjychar7xyf4fn6xwa6675ptpegzvmz

Wallet 596

bbn1cm985nzuv6lzduup9vlhlmwmqp40ls4ur4vrya

Wallet 597

bbn14wzk0ugft5gcvhehnwc3l3tdv828qzut336r5j

Wallet 598

bbn1k6vf4pt2mf8hr723a0y8j5dnd3mqwg8e763cme

Wallet 599

bbn1fesya574sflv9lwqr79tkxdyg5xxft89mhys58

Wallet 600

bbn1wky9rrgk2000vjmkxu8dcfdcn0ex9rry429pry