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 901

bbn1pkxuhgsxdz2mvuxc3vxh8unl7tgcs3lclpx57h

Wallet 902

bbn1r60ewefncg88xtv7vnw5l4tk4a2hyv74tr3lkh

Wallet 903

bbn1nu30l6zxe8zmzrs3cp9kmnqajca6nlym7sfwa5

Wallet 904

bbn1mszyafkle9ekseun357f52czshcklfp099lqn9

Wallet 905

bbn160yfcnjc3ggy2jgrxdrfl87atzz77h97dcwvm9

Wallet 906

bbn1zmrxrrwkqs33lsq8ec8t8djq8w8lqwuuaxpwxj

Wallet 907

bbn1spdl4n59pgmkxlrp6w3xm55xsadyzlgv0yump5

Wallet 908

bbn16fgqu3h05lwumhep63gr9lz4hqgum2xml07guj

Wallet 909

bbn1c7zacxyggfkpw0jywrpme8uwfllgv3vcvxd4z0

Wallet 910

bbn1nw43yuz38e4dc8q2n62plnpxmnfzlugpvmhfh0

Wallet 911

bbn1dk5zgngqudvrfgrswswfsfftfspzdkrm9uypj5

Wallet 912

bbn1c5h56fqq4ht8x922gwuuxv5pjfajzp4ugukm8c

Wallet 913

bbn1jl2843s5uat5zmm270wkzexlkvzzwms0c0rs95

Wallet 914

bbn10prx3q0xtlagxgx6ztf0vdsg23n3czasexykys

Wallet 915

bbn1pkhqdvdm6ydf80p24vwv8mm2g7wk5uq9w0t2az

Wallet 916

bbn134tq7rc3e279m7ny3l2tmw7aa2hnyr3uxrmnl3

Wallet 917

bbn15a26lza2l88yzer6hald98flpcg870hvecpk3v

Wallet 918

bbn15ywemn9lr7gu7mpta59z3lnkejcjtz4aj88qrm

Wallet 919

bbn1c9w76va4fdnn5jp87l87gsyguzwummwcnp7r3s

Wallet 920

bbn1svrxldd2pyhsdc8jnxkghmyc7umvm24032wlad

Wallet 921

bbn1t79l9nnwspu64pav9s7rvwdd6y5skguuna8v4t

Wallet 922

bbn1fz2hy2th0pumfmufswlt2nl2zg390c6ux2pcf2

Wallet 923

bbn16z89q6re5u0t2dv6aqqpuu5ypd8uta6zmccjaq

Wallet 924

bbn12c54wl35pyrrrzumekrtm9qwrfdkapl9vyn60s

Wallet 925

bbn1expmg8p0h40nwzy2pwwrjgxysv0n9f7dtju6sh

Wallet 926

bbn1pva6d5s8lp5vpr7kw92067ul5jm688wkkr02ag

Wallet 927

bbn1th5r9ln0w7mcfcf4dst20qq3spyqqame5adf9l

Wallet 928

bbn1jfjxnja94hg5j02jjaxwrak5ap50t20lym4c0y

Wallet 929

bbn1q8q4k4y7n5mmah3ymze4jcgv52uk2lhxtldn00

Wallet 930

bbn1ewym7rl86fsjch2ggkvkya92mrwct63fqggpuc

Wallet 931

bbn1dj3mn8dvrzza5gnscdt80nqfhzsf9gpqzp30mn

Wallet 932

bbn19ds34sj8w2k9e3f8qaazmp0nl07972lpeltraf

Wallet 933

bbn1epuw7kpqzlpp5ps8zaaf30ljj5j82kjcc92y00

Wallet 934

bbn1nmlunpp7cps42kn6gfnz4gh0v3sj90w9437mn7

Wallet 935

bbn1spjh3cgnr9v3uukpqqx7spsw8smgh63j68sknp

Wallet 936

bbn18gmd57qr5yzjrj984mtcv25t852h42jz7kw3q2

Wallet 937

bbn1zmhhxfrhp4f62arp85n7v4x5g4xl8xsljdu3fw

Wallet 938

bbn1q3ts5qhrh3m6t970egemuuwywhlhpnmm54c86h

Wallet 939

bbn1s6x0vfk8kk26fzhlg6vranurnm402337hz3p6p

Wallet 940

bbn179x9gqd47g7j5750qmcwp6xj5pyk6vn7s64kvj

Wallet 941

bbn1pm0eajmrzckyn5fjtsck9x0vnpsxh8hx2am65g

Wallet 942

bbn1u40kfxn7g4utge4fwyqyhx7wuv9qndsq9xu2sc

Wallet 943

bbn1zelxsqz6gknelf5rxr0fwr8wsdnlukth47vxwd

Wallet 944

bbn144dvkfv4c9kjjucqttwq59ruzf4s4fpd8clhwf

Wallet 945

bbn1hnvtetslaykn2zc5yhs3pt7wzzt60em8vl2fs6

Wallet 946

bbn1006rlnsuqwpc94dzdnw6wxw5gcgcrpuye24ekg

Wallet 947

bbn16lk4ksyjtxznvje4k6cyv4reqsytpjwk96escj

Wallet 948

bbn1xwzwpse4mqenxtxexwhqpjdg598x33h0fxs9g9

Wallet 949

bbn188prj9f6vuuz6xx8dw2fhr35lzsh4exfqahg3e

Wallet 950

bbn1f0zfr5u3eapvrecrxryncec957zwj4lsmdx3eh

Wallet 951

bbn1jtlga7438cnw63hww9rx33euu522rj3rxnlyf2

Wallet 952

bbn1fsmyemyh8adcw8wnctksqjldq3pc2557syf4u0

Wallet 953

bbn1f98my05l2yzyj5hjvvkjqrdv64wfdzzgh936ae

Wallet 954

bbn1v0n0vkx28yqx8ntflx2kwc94ul6cck7a4ne6kt

Wallet 955

bbn10srw59hax4dxdkrq2h3hnyg23kp0ygh9h5fxfl

Wallet 956

bbn1pywwcuutxedsmtxthcg0vqa79jvu8ex44548nq

Wallet 957

bbn1fte9nqmzzyfjhrd9revemy650uxslg2mkux4uk

Wallet 958

bbn13lhuld4kag7f3qcfumevuxm6w486a9vd22x5fz

Wallet 959

bbn12vafsxgwe8l5waz3g7vgpphjuzecelmvemcqn2

Wallet 960

bbn12zz7zdpkp8rsv5tv8rs2nx4kltattryz09tmc8

Wallet 961

bbn1s4sxp8lzpa5gh87su20ffsy7dhen3dcuu8x6m4

Wallet 962

bbn1gnq9r7jdq7fpdj8nsgx6utq07lqh6tvevtwapw

Wallet 963

bbn1d30wj2qn56wnmhfaunu586qpergh7d32z4muah

Wallet 964

bbn1ygdn4zyg9vxdg4c6j4xkrpjp7xq5d47dyeu5v8

Wallet 965

bbn1j3usscuamx2clqcdagdccxrrvk3gqyljnch27v

Wallet 966

bbn10p02d78247t3x6fxusrz0lgw459ghcqf72eqla

Wallet 967

bbn1rg4m7lnsqdv5fhkpqhyszxyxqvrmf857eq0kpj

Wallet 968

bbn1hvlnzs3zqy6s65st089uamgqed5evvaap9pvxs

Wallet 969

bbn1uv66rurr8ny8hjznkay50kxcj83fnedxawmzu5

Wallet 970

bbn1mafeeemfgrdhl6plsafdu7vvdkzgnngf8ty5c8

Wallet 971

bbn1kufhqv8yda93ksx9zrhmeq7pyyekr2qn346x6l

Wallet 972

bbn1wkzmtrwc8w4w0vwk74qvkl5nvgfg0gc6ryfs8k

Wallet 973

bbn12nhn0hp7966tt6s6a66nr6ss4m83ytdc22kc8r

Wallet 974

bbn1fh629gkc7qq094jjwa8kd7tt27svllmv6zu3nh

Wallet 975

bbn16xhnjjjgjreut9g0tke6nth6cwm749cs8cng0h

Wallet 976

bbn1fdssakacpgxnl3f6r3d3d0z88mrwceedzlhdg9

Wallet 977

bbn107aj5308rtp9eqvfqup2y586acgggwhtcj6fac

Wallet 978

bbn1ghkj63dxzk0h3w907neelajqg0n4c8svyww8lu

Wallet 979

bbn1uqgp6amz7yp4lfgnsmcsdc5l9jnjt4jwjg684p

Wallet 980

bbn1zsplxyyyquvvval3xsrvl2qx4cxuq2klslpqal

Wallet 981

bbn1msukz86gq5lm082lv7vhv3jeq2zsp9dg0ywv95

Wallet 982

bbn1f4mqs2qaem05etujjfzjm6w20ysgdgmpv0qhku

Wallet 983

bbn16kcqu6xquyzu8rvxpuv6dyj50e9wcw6gvh4xfy

Wallet 984

bbn1f5md67us6gydxezwc497rdauegynfqhgk3dzc7

Wallet 985

bbn16p2um65jmll0z7y724jhqwrr3p690lafsaktp8

Wallet 986

bbn12hja0q63ne6aadk32qxtar03z5jleevsedmz48

Wallet 987

bbn1h3ce5w94hfzthq4fy9wfdzh7ww5vq6tlyx7qek

Wallet 988

bbn1gc25466tu32kq6lgh9qdkcv0zffwes6nexsjlw

Wallet 989

bbn1rpcw66kncgx3rg0y5zd70yyrt9j97eqsc86de6

Wallet 990

bbn1v2vptyppt7cms4wgcggvrag23e9qfmpwkxmrev

Wallet 991

bbn1wgz0f8qkz6tf2f0l693c7v42dxxyquf6ljpkxc

Wallet 992

bbn1tqklrhmt4s8q477cjmnnfuerdkdm56wzvgs90g

Wallet 993

bbn1ckxkd0awj005mu3x8wv5u08ehsh5cycxaq809k

Wallet 994

bbn1pjs90ngcgfcha58nrvydgdjmw8q0s3eht0c82t

Wallet 995

bbn13u4thxrnku2z9cu7pvqc3dtdz0nyzqy32qnrx2

Wallet 996

bbn19jm4rgxfjkq032fznap3j7lh9ewpzgrzpzs84s

Wallet 997

bbn1uucp0cpnnw42pwngyu4wru9p38kc9tjh3ngnhm

Wallet 998

bbn1e8krh72furzxsq6uxq4ur8pdz0ecetr3za9wwu

Wallet 999

bbn1a8me2xyy5rfxe837csan5gndk30ul4gxmh98xz

Wallet 1000

bbn1fm2ga6gady36waglerryv5qfl0vdgpvre853e3