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 101

bbn1r7l2kewkha79wpdnkmeqp3dpcew8q8e7u53g8c

Wallet 102

bbn17sqv068s6225dhs5rfhelepvgwcntaulpj2mdy

Wallet 103

bbn172zggajugk9z5fyvjkcs8xmf7jkzghkwzg7n5n

Wallet 104

bbn1nwpt3ddkqalxyrdc3mvemgk6hdnhphkdl565jk

Wallet 105

bbn1p655nr52wepstj39jr3skwv6nkmdrfkajmrksn

Wallet 106

bbn1ls6pq4glasyg3tph0zfcn8ryv3zp59rrpa9d59

Wallet 107

bbn1zgnmnqexl7y2yzww4d7rh7n3nlcyzgcge2rpur

Wallet 108

bbn1nhe3jd4paax2dgqnaregszh7nv6ytqy6asyjjy

Wallet 109

bbn1awhjlvx4f0kt4c7v38ejcrzmx5k7u6f644nx37

Wallet 110

bbn1cg2r7cq4rg8p4jxvunvgpksu7atzql0c6lf0wz

Wallet 111

bbn1mvvggslu2hc786mj2fykxeyqndzd009m5jctqd

Wallet 112

bbn1smdrwz809z6e825edlehrftx5lv6zzwd8m2a4s

Wallet 113

bbn1pk2jfqstfyy4g2wt3wkmk98gghec6zak83z0ye

Wallet 114

bbn15ltyydqgnlvs0sw0tvq9prmt7x9ply2s4744fq

Wallet 115

bbn13g3xc04v5hptz4t6kxgujn4rsgqnmz6pzuv4zv

Wallet 116

bbn1unp0j2zxacf7jg9c0wl2secp4q2zn23efv5mg9

Wallet 117

bbn1nltym5xupjmlshsz5lqlgznle95j2ch3artlac

Wallet 118

bbn165drychg5qfhf0clv8q0zpl7xstvme7yd2lceg

Wallet 119

bbn1j5g0jrw4ks9vtjfgxyfmaw27vx7ryrn9m3hm9a

Wallet 120

bbn16lxuejpj7ksljnl6w0tqdv2sehr9y0e58fngjv

Wallet 121

bbn14r676ass5w73rlg9y587787mapqaawk8nj35k0

Wallet 122

bbn1y4g0qlaehe5pufxmf6kd46cm34g9k8dwyp6m84

Wallet 123

bbn1tm9tv65j2pavu2p0a0fvs59nu6p6q8p6lvrjap

Wallet 124

bbn18fm60ys0r2j0jgd4vlmr0ahznlcy897z357par

Wallet 125

bbn1maee2cq9azg9eeyxhg5un48mncewfel48xdzkz

Wallet 126

bbn1cf649s6m5l5lfl4pdxy4cj5fsy3dvu7t282wxf

Wallet 127

bbn1ywuen7fmd6jklzr624rfsevcdz5nwlr7lmv30z

Wallet 128

bbn1jyc7mdcm3rrnaaxdnjhlw27keufzj0kqz6myqk

Wallet 129

bbn1g2v0p4gujck74ytgfekcl982jyseww3a2ytc4v

Wallet 130

bbn12ep7g0cnj4ua00wxpkz7p4zn4c2u2g7wsf2gfs

Wallet 131

bbn1nzpsgsd2g0rw8z34srk9er5gvvenvd9f7qqq2w

Wallet 132

bbn12chr53ttcz99yckrfllwhpyxqmge8jwhyh6tww

Wallet 133

bbn135f6624ply0e6v8whuh97569xkm96f25lygngp

Wallet 134

bbn1lmmrv58fk8kcvcxjyv9zd7gn0p99kfhftqtgwz

Wallet 135

bbn17z58ts6hnxa4rncmcjqwdtavyzz6y8447s3dq0

Wallet 136

bbn10y9feyw6h0egzrjhrwc6l4fex67ufjl5mh980h

Wallet 137

bbn1htfjpgpw2803hvyujfpvgalj598afms2vwelx8

Wallet 138

bbn12flnuj6wxfxe3ctnuzg34yghxht70htgs5nec8

Wallet 139

bbn1ex43hrx8zg50uyydlxw6gg6l2n749sj0xwv3w6

Wallet 140

bbn1fpmn5jnsp5u7c4knseguzdllzvjgsgm9tewx5e

Wallet 141

bbn15cuafmf774cr4m0qvlgwtkupwxpq78u63y9pud

Wallet 142

bbn17vxkq82s2nu5yrcflfm2wfccxty7327s00avff

Wallet 143

bbn1zuun009525u7mpca4uyrk70kuynnmnrga8kvrj

Wallet 144

bbn17hchzyau4gaseph6sl2r3gfdgg3tp63nu2zjyj

Wallet 145

bbn1lekqr5a3rp3cwhmuw0n6m4lupvfqqud4venrr7

Wallet 146

bbn1ena36ngkkuzmnf605ftlsxfeaphh4hru6feq6w

Wallet 147

bbn1a5nju037du6sqlsldzlua8wazwet48vf4s0au7

Wallet 148

bbn13agy332d2lvvg4pv78um0xy03efv9dp3v4ul8t

Wallet 149

bbn1325mxa9mjaw22vhpwknjwfd0guwqcvk9e3v6ku

Wallet 150

bbn15d52p7d26r4j7vzwufdqgx2r724qqfshje5drt

Wallet 151

bbn1qhdlanf5vpj763ph9sh73j322z5tx3tan3ztwx

Wallet 152

bbn18kz7vypw63n2pntmhf7mkz8y2cjk3a2crj9q9z

Wallet 153

bbn18xynl3ttqus798h9swq4m0zh6ydtggu69hp77m

Wallet 154

bbn1p9w7qad20txvyq83tpp8tmn4ax9u9gv20vhccu

Wallet 155

bbn18uyf2qhz865a0snxaezsdtfyzjh5nwqwrx93ju

Wallet 156

bbn14u7szku8nrxatsvh0dw9a8dpzy0zr6qmz6e9nm

Wallet 157

bbn1mzhk807edkfpf79t4z840fy9dqsaf5yd0283jm

Wallet 158

bbn1qygx0jn0ryyazr636u6z784l9w6tmqlxz4efsk

Wallet 159

bbn16y8ptkcge4cz6vf4j598eqheqqwakqygt4s972

Wallet 160

bbn1n3kusf3gcwha5y8397v78qf9r45tv367r43vqm

Wallet 161

bbn152hnjv096uev4e3d87s0ew454hk3cq52ln443f

Wallet 162

bbn1s9cav0vw0p2wdkt0yccyt6dgmesc2z2k7l7sgq

Wallet 163

bbn1cus8mgujalrf7xrtwzzdqqk7y2ze46djx7quzm

Wallet 164

bbn1quvyyfvvjzqjylju8a0fdkwprmmrc65ftejh4k

Wallet 165

bbn1q53tj0u53awh8pctp8qjlgtlvk0ak5erdxxtav

Wallet 166

bbn1wqy6zgll7zwqd9m2zd5jc07trr7hnjjj0dfmqz

Wallet 167

bbn1vv5ctvq534eyyw5xj8ex8e9q7dy07hkaz7jw5z

Wallet 168

bbn1uzcykp2quth32jx69m6dw5p9ks58tc2guhm6gl

Wallet 169

bbn18t6rswhc43thqtzt6jhuj58rx3dlj94jksd2zx

Wallet 170

bbn1pw94pvtsr5t8r0cezm03d32psat44dsvmt53mf

Wallet 171

bbn1u4axuedm54qnjk549yjx3mhmya9td3t9ue6zp6

Wallet 172

bbn18n2aakgaher87l7cztv09ydj2l7aualnva2k7v

Wallet 173

bbn1fqwulncqntug6h9nzh5glq7tyahc4amxz0k9lw

Wallet 174

bbn10r39fueph9fq7a6lgswu4zdsg8t3gxlqmja4n2

Wallet 175

bbn1skj7gwu73s598h7ye6x735zxvuz987yl4sek43

Wallet 176

bbn1x4fwf3edr0lj3l6x90rcqmzshe0nhnxztcr94n

Wallet 177

bbn1lsw8ue7ggvcywxm9csfzzlqj3wstluwfc3ffjv

Wallet 178

bbn1hp8k4v0857fte89slx2slszgp8kte8tt39n444

Wallet 179

bbn1px4vhthdqnj7pz2wg2qzcvrm7ldpywcw5u6l4v

Wallet 180

bbn167g505wsxyzave7l76hlmns78804pag66yzt6l

Wallet 181

bbn1s75d2qxwhqy2sx7500m6ntuar97lrzd6qv0aa2

Wallet 182

bbn1r70xzwj6xr8vwye3m0tpcu2n09hgc529qwnp7d

Wallet 183

bbn158vrwhujuvvh7e6tlcj67qf3yn8kkh7cg4hnt8

Wallet 184

bbn13l4r8xszkv8q4hqh67jpd92ytmvwugyu506lah

Wallet 185

bbn1q4upmps9zlsaktrxspxhg76plc26hmrs7mz6dj

Wallet 186

bbn1whmj20d20egejugk9gxdz8t806pa2kllcrcqkq

Wallet 187

bbn1h50w38t8k46uwszf59ln2l4vpefezurugdcmjf

Wallet 188

bbn10mhezuz88x40lqsz80fmfcc6dm5dl4qkqrmmfx

Wallet 189

bbn1vgyrk53wsallxx4350pe7pwmz9kyueh80q99k4

Wallet 190

bbn15eppf5f203lt55wdm3athptjnla83wv5kckzu2

Wallet 191

bbn1k6h5suh7jdrda5accfpv9m47wt0pgtw0hgvlg6

Wallet 192

bbn19u337np3xlhjq744v59gu2t5c6mvslp7q7jv4e

Wallet 193

bbn10v7lu9eg22x5eakfdxf5u52gqefwfnn46at6ku

Wallet 194

bbn17vz9a2mpnt3avne2fcyetnyhn2gfyr20j35kcs

Wallet 195

bbn1e6g8kd4v5xqwcwz85vsdyymm85ctlm4pmqyvea

Wallet 196

bbn1nllrurc2fkf7jvqr460lemungcmc2gd7cu5h4m

Wallet 197

bbn13f63jlleklvkchg9fxyrtjxq3qknp06nasnf58

Wallet 198

bbn19k908e6y5d3hh32mw0qr8h4u52l5fg4p8l5079

Wallet 199

bbn12a2r9mwk8w5tkx5x9r4fpkchqll2msweastdm6

Wallet 200

bbn1wtk458zel4usjyujhsvd2ku0vzz9v5y46qzhwp