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 801

bbn15npz2ymzp8ac9jm2j53au4zgtn5mf0j0hdzngz

Wallet 802

bbn1839mdqfelegdulfx6lvpl0qncnpsvwn0ne8wey

Wallet 803

bbn1tfa0pa54ttea8zfxutcpz2m9zxc6km2r958500

Wallet 804

bbn1957ecg0ue2auj98c24nu6w70jyjpt78szy490j

Wallet 805

bbn14v7m7ef6dl0k4h2sj4l5rmjfsww94ece64uxfl

Wallet 806

bbn1xskz36zzze2f6vcqtz5qxtfwa75qjj4ls9wr52

Wallet 807

bbn14qr8enkh925f4n0aeyv2gr3g0pk4rhuqgy9ymg

Wallet 808

bbn1hgt649d0l5vnlg4nmgvkg0h0d0tttajqnrtkv0

Wallet 809

bbn1mscmy3zvsen5m69rp8g8rre26ay7zdlat9fcj6

Wallet 810

bbn1m7dj6dw80fmgu69nc79gmkcqxmgl4d9wycrqls

Wallet 811

bbn10mxgth0v4ewmncet3nmlksha2r82464y9ky53t

Wallet 812

bbn1003028k3afsp23w4t23wnzv3j2795skkwahgxu

Wallet 813

bbn1e5df3q4rf359vr696h407dagy4enhskqupuf5j

Wallet 814

bbn1eeyxjrq2rrldcl2kh2h0dxg9sv78ksfmjvf9gu

Wallet 815

bbn1u6gmuqc6se4x2k6dy23k3q36zn0s9h50eq8mfc

Wallet 816

bbn1wyl9evzcaqzmlz9c4tlx00cz75s9r3c6j7q6jy

Wallet 817

bbn193dtjl66x4de8v6hcxjl6sxkmzjrsah9hyrlvm

Wallet 818

bbn1stuhzahha4aeqdjckkhudfj9dng7tcljyrr85l

Wallet 819

bbn1fxehpvnk63sfmmuxk0vrkfuz6xc2r4jtvajf5d

Wallet 820

bbn1j6qfnkc6gjcxtyp2m3utaycejuglfsmj7kt5dl

Wallet 821

bbn1r9t05e647w6rvd9cktfnkz3d3wtukdj8sc7z74

Wallet 822

bbn1hsl70gvlljx63rezwl5ya43lh4hm4dgtrel0vm

Wallet 823

bbn1j87dk5yklrac29sq9alzchg5g3sg8y08cxel2n

Wallet 824

bbn1hlqhemqcfvde32u393v044t37mw7m6uujvry4n

Wallet 825

bbn1dlady20pn9sxukpqj88h20dqvj2y059uc6379r

Wallet 826

bbn1r4ydzqd0255zwetyyypzg9zyynudyeh7kjdhpn

Wallet 827

bbn1pjpz6czna250t3h8dhw43ul4pxug7vzu04nqdx

Wallet 828

bbn17xrzhvtr247zq5gtfhyk029ec8x437xvae8096

Wallet 829

bbn13nv5tmmw0prt46vjm4yuusdw7y3u57zursarur

Wallet 830

bbn1fguqnsnuqx63uk9xa5p9tyc3pzyqcqnzunkqan

Wallet 831

bbn1m4w9x02yyxjgypr7hwwmhfe9722hg5ffqndyt7

Wallet 832

bbn1gwvjydrwcd7n7mqdhjdhx8pntxxwrj03pldtee

Wallet 833

bbn1xxt7pa6xqkalflp6yq76c67xnd0da6kte85r3r

Wallet 834

bbn1uqcek6m8c859wsgzds05huueq5x7eqc830tf7w

Wallet 835

bbn12fsh6v3ej8w6h2js6m8u3wn88w6e4fnteu5mzm

Wallet 836

bbn1qthsnk69pglp0mknjzak9tdh2uzrj39lgpagk3

Wallet 837

bbn1wtv4dthpjgu9qf6v58yd27cwkwgq2v33c27s5j

Wallet 838

bbn1ual350u2xd4fg2ueqlp9qedyaajsfnvmfy9pqz

Wallet 839

bbn1xdxs4tysa27cj0fmzpgq22f9whx8l2s4xgxp2t

Wallet 840

bbn1sz500hfqhhq3kj39nj0hgdys4pnkr4jzhm4cdj

Wallet 841

bbn1l8mtqc2pqv2wadp9md7hxw8j7e7ha5w6srlt0k

Wallet 842

bbn1sn497dxf0u06fh9yplhktq9j8s87xqt2q4gdwv

Wallet 843

bbn1nhyc23usgy67r8ldh7j0dna4fcnj0k4r4kh7lq

Wallet 844

bbn14ut9gva3akmpew0rzrxde926j7kapjw4n63ycj

Wallet 845

bbn1wm0ygszvumpfarjrfynywl4sw3mratez8f7xll

Wallet 846

bbn1uwqvhv7msmm2csxv72vyszvz40xxhl73ul5k02

Wallet 847

bbn1cax3n9epn3ezx7ymfzgmvzhtdy47fq78n3hw48

Wallet 848

bbn1653rp8zuw7yucnxkjjscln3nm4444spn2m6k35

Wallet 849

bbn19xgt6u8puvg7lp6acsyudtadfj680xd8umfv40

Wallet 850

bbn18khnaz0kwtm0tsuh6kpwy5z2f5nzv3whcphmwq

Wallet 851

bbn19wlxdkujqgum0agfgksqxemkmle8ypv04n5vn0

Wallet 852

bbn1qcm9hh5ckqh7mqvun8z0auhc5suayymy3r9fsj

Wallet 853

bbn1gfzx4rfhyx76v753j82npusu7zskllecfqnzuk

Wallet 854

bbn1uaheqp67qjylrx6sdakdlxj6gt0kq99gu2m3dv

Wallet 855

bbn1v5j645natsmhzzhpwv4pw4sdpfd9jdtyy4tfwl

Wallet 856

bbn1r75p3ss6cdhvvna2j9g4qkk80tst2zj4r77mth

Wallet 857

bbn1y0f5s25g3k8awf3vp60r6fk69cuyeyz9er24nc

Wallet 858

bbn196gycaf0gzmp6hv7e64u7u5fn9tkfp7llsg7h9

Wallet 859

bbn1gzxmk4n8ugcjm3wlw3ltgpqkz2fgqrslyflksp

Wallet 860

bbn1xfssvsd6atn9jy74p9lr3vt9z8tx559nsfudxk

Wallet 861

bbn1lf27njgs89v8k2yjpcsfn5um7gu0gnaztsprfj

Wallet 862

bbn1ws0wxnclaf8y8cfm9q4dhdkl8af8ts8vwerwfy

Wallet 863

bbn1ngh5vhmx0juwt5xywqpcc6a6g4ht9dg4nan34h

Wallet 864

bbn1r55e7l89q6ylr3ny8v0g2alm5wkdr0q23d9zaw

Wallet 865

bbn1jxdw8wzlr8ud853xhy9dnuhn6frn03w24naqqz

Wallet 866

bbn1mwjupes5ufj8kfmnyqqxv9artqrlauqpuzz63t

Wallet 867

bbn1fkylm3p4tlc4rrycywkyzy6apcpe9lf4aczecy

Wallet 868

bbn1xe35vwyq8esph87dw06wlu2mzmvau0lucl57hy

Wallet 869

bbn1mzcyxfxh6lg3mcapkxcypn7x0g9r9e96xz4mfj

Wallet 870

bbn1ae4sq0d8cnqf0zretm2wsl2qe9g2y7mggyn474

Wallet 871

bbn1l7mvqufy4987ygk948vwe73rdptgammnstjc6a

Wallet 872

bbn1my5mkv7qhtlldszpg633l2ghk54vcgu8mcpfrs

Wallet 873

bbn1k0n3m9mfheq638jmgfzfj4at24ygnvvxgdasz5

Wallet 874

bbn13xxue2ma2lleqftlwhj0lxcvsw0822n6ghnnxq

Wallet 875

bbn102qvx6na040t6r638saq7wha77xj4qt5vwf8xn

Wallet 876

bbn1m20wmdlscsyplz44s96kcy28rx05ufmn2lhca4

Wallet 877

bbn12uktdruemcdx0hajmwxtnluhy6jypqx6qzg84g

Wallet 878

bbn167yurdr7a8h92hr40fx36sqnm9jyqwjlulj9mz

Wallet 879

bbn12dk630455etk3vxuqnrwc8y2gfypl2a93d8hkv

Wallet 880

bbn1eptp70f6ct0z50aqndj5hkx7phkk8jlmk57vj9

Wallet 881

bbn13p2jzfguluvwk0y2yx9gpw4a3wj9cmeewh3q4g

Wallet 882

bbn1gxgtsragywhx0yh9vvehnldqjm72hmcmqz9qzc

Wallet 883

bbn1vwnl08qv4aqlkzpvu2d0cmglh8nu9tgjq6elgx

Wallet 884

bbn16lq8ugwr2dujruaqal6cqe5vwtvtlx2sd0yzsm

Wallet 885

bbn1kckuyq9g056lp05z9hcnf03z2gzx2rwvgez26j

Wallet 886

bbn13v5vefw76p8hj7jd4lqx34nnyhq896p99kkhta

Wallet 887

bbn1wzydm65clmpflgtql7trap50zcccghd5n6stkp

Wallet 888

bbn10evqtcnfqta8h8slthctu987rzmntyn2hecdgx

Wallet 889

bbn1py2f57sx60vuczlsekuaq06vpntlqy884lzxtg

Wallet 890

bbn1f4n7mcy2lxa5l4hx6ryt2svejeyk00yw4s7999

Wallet 891

bbn1hdg7g38dah3drennlk9e9qvkq7szrn3qampr3w

Wallet 892

bbn1qhecjv3thzcvykhyrqrkshyh6nf4psrwur4c69

Wallet 893

bbn1gss5mq39jq2kr2c7h3e7pa4tuuxfaaqgmds8ah

Wallet 894

bbn15em98nex3z99d05lsg545dw8x3m8sp3s0xh9ca

Wallet 895

bbn13y7fkwr0ryyffh00qc9px2qwymzcvhakrqdm5j

Wallet 896

bbn1zq5zqz0fkswedxcqxs5ach5v24tdkpzdqcy2pu

Wallet 897

bbn1s7ew6dw2p658xmu7x6a992vl3llg6g3yng7h76

Wallet 898

bbn189043vhd9ztuf4reqh3yrgqtax2m5ddtnkephx

Wallet 899

bbn1e3fmkhhmktwmc5jcrty3pmg2whzyllr0gftvzp

Wallet 900

bbn1zk5459wk3vahle9tjzre7zaxu8awyemlnk4ck8