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 301

bbn1gysxgy62w5q9k00tldwwm2hnfaqh64cs3gq045

Wallet 302

bbn1ql6g20jcvf5kqreq0z92czflfchggsay3gc8hk

Wallet 303

bbn1ljh43sag9s6pj6h0cucz59wv7utc699lfpg6j3

Wallet 304

bbn1p0xzy0r7j2yutxvhaa9ql4ldfqqjucugmz8wcr

Wallet 305

bbn17hwc27rpkdfr66laq95lxfar2nrr8me49upxhh

Wallet 306

bbn1gece6fs5phgqm00d5pq25q2jq0jphj5yhyzxxr

Wallet 307

bbn1uwu97fck9sajv3wlnu5ae9qw6ppland0qntjyk

Wallet 308

bbn1mdq787p2kls9uz38ap439t4dap34sqdjy0qyp4

Wallet 309

bbn1jl406km7eq08ha0tsr9yayprr373lw76tx0v0w

Wallet 310

bbn1mkzf6ztp9aq2g4haxaz0mfdjz34sn9x3xf208t

Wallet 311

bbn146glgq8cj0sfg8s4v43jtj94hdtdjhm0vtr2y7

Wallet 312

bbn1ep5x94uj8mnffzjk687hqc6as9xm3sjdfk7x9g

Wallet 313

bbn1yl2dej6dkywhsfmy4tcdtzjnsatgqflkgfjthp

Wallet 314

bbn146446ekdxqfxdwem2ryd8ptaglsrtkjn8qt3je

Wallet 315

bbn1ay52m8wm46rp25amzh600qwxaj0t9ufd2axh3r

Wallet 316

bbn10k342hgmfsm04jma9suc42y7sd40sr94dm2350

Wallet 317

bbn1ds88w0ln9ftgq8t6rh53fsryn3r8k8dx3ewche

Wallet 318

bbn1gldxlsq70x52tw4w9cdasu6wk9va5xx8gwvfqu

Wallet 319

bbn1j3ppq9um98e6rvzqw2rev0ss3qv5wmgdhkrgtq

Wallet 320

bbn1dc0a9k6tlxkm5a9g3qpu3gy63ndscang7t5sht

Wallet 321

bbn1yap6z9000luz3nmfkdn96mmkhc5uk3sem789gc

Wallet 322

bbn17t2mjea3ly3ce4mv6fsnacm5tm2ugd2dvqur6d

Wallet 323

bbn13mfgzuda9wxd3qx0mqnsu9xxxh065s5k6whnjz

Wallet 324

bbn1xsz7j3c0zmrg34su5nyql82nrt6zkvwcrslq6j

Wallet 325

bbn1ppgm3qeu2uejfrgxd60zeg62sv4t6nn60p4fyh

Wallet 326

bbn1u8husmljyk4rlmc35ncp22fj7kpfvd3zk8k3w2

Wallet 327

bbn1c9uhptn8hk6jleys0vn9necumm7u0hvgpyf5as

Wallet 328

bbn14h26e0rzge5yl0c9x5k9quqlgh6fkh4v23y2a0

Wallet 329

bbn1z98eg2ztdp2glyla62629nrlvczg8s7fc42qjl

Wallet 330

bbn1zrlsh07x3dt0qh6mu65504g86kqfj3l2aezl6m

Wallet 331

bbn1tpu75t0097tg46dmdjwj5veurt2zt2cn0f6ty0

Wallet 332

bbn172gqpfu583yseddq697wl8u5rxusyej820pap4

Wallet 333

bbn1p7gnav0cxytrjs24tsd7e6tzed58tfm07982v0

Wallet 334

bbn1weud9cvsd2hrc3zdmz0ug0fv5wlearypegrh6n

Wallet 335

bbn14g9dtt5gn8zvxx7dz5z06hspef6tm5rn2sw3rc

Wallet 336

bbn1vy9eg6d5gg2xvzhu7f6598cmdp2yxldvpvjgeq

Wallet 337

bbn125rh8d62hs4a7d7cgy7xa6hj362t8wvrfg5duk

Wallet 338

bbn1nlyu6qzeuaeeefhstcc2lvn0kv5ur20xxkrczn

Wallet 339

bbn1m0qjrg0hw37y8zuxhtmpw3qp60js6fp7zp67wg

Wallet 340

bbn147s48qhxcyw3ra20hqnnc8rwmstegycugvz0ja

Wallet 341

bbn1ptry5acdxjwj6xvsmk7942xp2gs6724ezl4295

Wallet 342

bbn12y2u5pvtl3wzlu0y008qvlpk4swvw39up9jph5

Wallet 343

bbn13szs2zp62p4x33qlc6ttqhkm0a6damw053fema

Wallet 344

bbn1w3e9xs7x7ja9gfyn6klpaye5dr8hc68g050ny3

Wallet 345

bbn1qnqvuswaw8s3efuz0xdrumqq6tuz8k7l7ndta9

Wallet 346

bbn1eukyk0uhwxlvvkgx30pdkvq7nycycze9x4d5rp

Wallet 347

bbn12h2awqfulxu7ruzv5g7wssmnllj5c0gg97p5gq

Wallet 348

bbn1mjw2y7k52wne63fd8se0waa53zyvsv9qndrdjm

Wallet 349

bbn1s9482c98zw392fe7p4awpuh4v39z5xg3ngnn7f

Wallet 350

bbn1pwj0tkr7r03pzguwd8p328rnymzkts4hztynqh

Wallet 351

bbn1e0zu9pee0x2ungkau828dhu95sjx605tqkxjhn

Wallet 352

bbn1cqvl29tywhgcxx4fp38nwvqyxschgplrr4vt4q

Wallet 353

bbn1fdvnxssw86gfye4dakv6w53yzvpr9cjrf32sum

Wallet 354

bbn1ec3gvg294rs4ggrpfj84yxfer3pfhlgtnhkcl3

Wallet 355

bbn1rwuc72jven7s90cqmmncu9dwhkfj62mua3ulep

Wallet 356

bbn1dfushcy82vx9225yxaza7aaafnn7r9uzsj6eft

Wallet 357

bbn1cc0ef5s5gr9puu25tk47l42cyhyfrskvm9ne8g

Wallet 358

bbn1d3d2rcg09ahvrz3ufyn77adx49gtw8284j7sdp

Wallet 359

bbn1ghrpfanlpyxexasld77ekny99cta6jcgezt3uk

Wallet 360

bbn1v6tevtflttxsx4qdlr9vzacfdtwjwu308dufaj

Wallet 361

bbn13q6klgfxfaf6fsd34xuxp5l7perjhnx7pv2gn5

Wallet 362

bbn1hu8vqhtk0lr76jd55e2muk8pmyavrpafqjcwe4

Wallet 363

bbn1y989v3qrxagaxpjd8tr0gjjtcnk3tq9xwmt7ha

Wallet 364

bbn1kjruag2yjn62pykfhgky5ammgcx7hame2w54pe

Wallet 365

bbn14rql0qyrq0vd9523luxga0zr449a0n973zmnsu

Wallet 366

bbn16urnjnmmzyjtnvu68xhf7ve4gunwp3zkmfts25

Wallet 367

bbn12mv5prq7jh2k47ntaevturfrmj6qyk7cfq4mdn

Wallet 368

bbn1qp2tfhsz2wv9wjfs530uf770cgawu2dwlc0kuy

Wallet 369

bbn19h884swtqsklsvx2mqs4kqcewxpk7qr0nd6xcn

Wallet 370

bbn10s7ca3lut2xtzj6fq0hnznyy8jx75lxss5k237

Wallet 371

bbn1hnjvzkp3x69can22y425sk45ds5czzpvwe7fkm

Wallet 372

bbn17x4syatad9jamwfeccrppz0mk83szd5nhvfsrg

Wallet 373

bbn1nrz6es3vm30c77wk92sd8e0sc3p2tezw39a68j

Wallet 374

bbn1mtrkgq5rhchwu6krcau34a8k7h8yj8prwtufu2

Wallet 375

bbn1rhy5t5xv2fjzmrvj72j26xul9sc4pywu68vhjr

Wallet 376

bbn1ux084vmv5qeerrqzfpcq7t29fr5mn0fa8ndr38

Wallet 377

bbn1ren67x9nxt3nlfxmxmrmllpv9yurl3wflm0cky

Wallet 378

bbn16f3kca34y7u5dv8ymv6lxnpytwefqh0hvc8g22

Wallet 379

bbn1zuyrdp0y9wsrgdts0g5cuqu03jwj6z20l48p7t

Wallet 380

bbn1t3v3hvhf5ph5cnj92wftjehl665gxurghn7hn8

Wallet 381

bbn15vcnj695jrkft9nx4dz9yl4zawjyrw936k0adc

Wallet 382

bbn1x8juehetewenhktm4d00w2nm7e509uqjuvyqv7

Wallet 383

bbn12yj4wa3vs442efrfvgvmvslq75x03t5d0hxrfj

Wallet 384

bbn1lemwff7v4m8lqg325gtwl24w2dwxyccg2fmu0y

Wallet 385

bbn148h6rndsz4g3crnmm4dc0rpr8t28rj2zjm2jhk

Wallet 386

bbn109z5tz09syajx3ef56pc7sy8t39tlrgg56enza

Wallet 387

bbn1yeyytu6jhjnxes4ufty8yaxkyawzz7462q6hd6

Wallet 388

bbn1zsgpymkv0tjumsa7wlt07pql0x3s9nqa4qlran

Wallet 389

bbn16g3gm6gvaq2uwhv0ty2z9200d8p3yn9jy633fr

Wallet 390

bbn1df2prh4s6a2djv0uyuy80erprqkw59lznvp4rd

Wallet 391

bbn1lztm7kycww74qck3087hvawfnea6ldtjqfa78f

Wallet 392

bbn1nxscktq3murju3tlv3f923rzyvu2hdmwwd799s

Wallet 393

bbn19gu0alc0g8k7v0rj60xkxv2ky23u65axsmk768

Wallet 394

bbn1pu6ahpa33yeaclv5dcfmwssp25nnxv6szslqrx

Wallet 395

bbn1f4jdq7d9pezrp6asnvxjgqwxcs4tmsr8svqatn

Wallet 396

bbn1qlhg8dtgkwvzzmdztwy9mv4aegj97lu9eu2ww7

Wallet 397

bbn10wswn8xu5mgcqaesnl3895ku0gknmzv8y9076s

Wallet 398

bbn1upkfhv5wacah74y2mwpfr54ersd0fha9j4y2a3

Wallet 399

bbn1nusnyl2nrzcyu37weanu0p8xrrgdp7tp595puq

Wallet 400

bbn1z8zhxujzhl3y3lmhjjsm8dv0q4jrpdhtlzrqt5