Link a BTC PK to Your BABY Address

Before proceeding with this guide, please make sure you sign the terms first.

The Proof-of-Possession (PoP) establishes ownership of both your BTC key and BABY address. For BTC stakers, the BTC key refers to the Schnorr key that signs the staking transaction.

This guide demonstrates how to generate the PoP, validate it, submit it to the airdrop API, and remove it if you need to link your BTC 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 BTC stakers

The Airdrop API requires the following JSON message format of a PoP for btc stakers:

{
    "babyAddress": "bbn1xjz8fs9vkmefdqaxan5kv2d09vmwzru7jhy424",
    "btcAddress": "bc1qcpty6lpueassw9rhfrvkq6h0ufnhmc2nhgvpcr",
    "btcPublicKey": "79f71003589158b2579345540b08bbc74974c49dd5e0782e31d0de674540d513",
    "btcSignBaby": "AkcwRAIgcrI2IdD2JSFVIeQmtRA3wFjjiy+qEvqbX57rn6xvWWECIDis7vHSJeR8X91uMQReG0pPQFFLpeM0ga4BW+Tt2V54ASEDefcQA1iRWLJXk0VUCwi7x0l0xJ3V4HguMdDeZ0VA1RM=",
    "babySignBtc": "FnYTm9ZbhJZY202R9YBkjGEJqeJ/n5McZBpGH38P2pt0YRcjwOh8XgoeVQTU9So7/RHVHHdKNB09DVmtQJ7xtw==",
    "babyPublicKey": "Asezdqkvh+kLbuD75DirSwi/QFbJjFe2SquiivMaPS65"
}

Detailed specification of each field:

  • babyAddress: The Bech-32 encoded BABY address.
  • btcAddress: The Bech-32 encoded address of the staker BTC key used in phase-1 staking.
  • btcPublicKey: The hex encoded staker public key used.
  • btcSignBaby: The Base64 encoded BIP322 signature made using the key corresponding to the  btcAddress.
  • babySignBtc: The Base64 encoded ADR36 signature made using the key corresponding to the babyPublicKey. The signing doc spec can be found here.
  • babyPublicKey: The Base64 encoded Babylon public key corresponding to the babyAddress.

You have the option to either develop your own tooling following the above specification or use our reference implementation following the rest of the guide.

1. Generate PoP

1.1. Prepare the BTC wallet

We'll use the bitcoind wallet to demonstrate how to prepare your BTC wallet.

Launch your bitcoind instance and load the wallet you used for phase-1 staking (see instructions for bitcoind setup for phase-1):

bitcoin-cli -rpcuser=user -rpcpassword=pass loadwallet "walletName"

where:

  • rpcuser=user specifies the username for bitcoind RPC access.
  • rpcpassword=pass specifies the password for bitcoind RPC access.
  • loadwallet "walletName" specifies the name of wallet used in phase-1 staking.

1.2. Setup the stakercli

The stakercli program facilitates communication between your BABY keyring and bitcoind wallet to create a valid PoP payload.

First, clone the btc-staker repository:

git clone https://github.com/babylonlabs-io/btc-staker.git
Cloning into 'btc-staker'...

Next, checkout to the v0.15.2 release tag:

cd btc-staker
git checkout v0.15.2

In the root directory of btc-staker, install the binaries using make install:

make installCGO_CFLAGS="-O -D__BLST_PORTABLE__" go install -mod=readonly --tags "" --ldflags ''  ./...

Verify the installation by running stakercli --help.

make install
CGO_CFLAGS="-O -D__BLST_PORTABLE__" go install -mod=readonly --tags "" --ldflags ''  ./...

Verify the installation by running stakercli --help.

stakercli  --help
NAME:
   stakercli - Bitcoin staking controller
USAGE:
   stakercli [global options] command [command options] [arguments...]
COMMANDS:
   help, h  Shows a list of commands or help for one command
   Admin:
     admin, ad  Different utility and admin commands
   Daemon commands:
     daemon, dn  More advanced commands which require staker daemon to be running.
   PoP commands:
     pop  Commands realted to generation and verification of the Proof of Possession
   transaction commands:
     transaction, tr  Commands related to Babylon BTC transactions Staking/Unbonding/Slashing
GLOBAL OPTIONS:
   --btc-network value            Bitcoin network on which staking should take place (default: "testnet3")
   --btc-wallet-host value        Bitcoin wallet rpc host (default: "127.0.0.1:18554")
   --btc-wallet-rpc-user value    Bitcoin wallet rpc user (default: "user")
   --btc-wallet-rpc-pass value    Bitcoin wallet rpc password (default: "pass")
   --btc-wallet-passphrase value  Bitcoin wallet passphrase
   --help, -h                     show help

1.3. Create PoP

You can create and export the PoP using the stakercli pop gcp command:

stakercli pop gcp --btc-address bc1qcpty6lpueassw9rhfrvkq6h0ufnhmc2nhgvpcr \
   --baby-address bbn1xjz8fs9vkmefdqaxan5kv2d09vmwzru7jhy424 \
   --keyring-dir /path/to/babylon/keyring \
   --keyring-backend file --btc-wallet-host localhost:8332 \
   --output-file /path/to/pop.json
Enter keyring passphrase (attempt 1/3):
{
    "babyAddress": "bbn1xjz8fs9vkmefdqaxan5kv2d09vmwzru7jhy424",
    "btcAddress": "bc1qcpty6lpueassw9rhfrvkq6h0ufnhmc2nhgvpcr", 
    "btcPublicKey": "79f71003589158b2579345540b08bbc74974c49dd5e0782e31d0de674540d513",
    "btcSignBaby": "AkcwRAIgcrI2IdD2JSFVIeQmtRA3wFjjiy+qEvqbX57rn6xvWWECIDis7vHSJeR8X91uMQReG0pPQFFLpeM0ga4BW+Tt2V54ASEDefcQA1iRWLJXk0VUCwi7x0l0xJ3V4HguMdDeZ0VA1RM=",
    "babySignBtc": "FnYTm9ZbhJZY202R9YBkjGEJqeJ/n5McZBpGH38P2pt0YRcjwOh8XgoeVQTU9So7/RHVHHdKNB09DVmtQJ7xtw==",
    "babyPublicKey": "Asezdqkvh+kLbuD75DirSwi/QFbJjFe2SquiivMaPS65"
}

When --output-file is specified, this command generates a JSON file containing the PoP result at the specified path. Here are the available flag options:

  • --btc-address is the Bech-32 encoded address of the BTC key used in phase-1 staking.
  • --baby-address is the Bech-32 encoded BABY address.
  • --keyring-dir is the directory on which the BABY key that will receive the airdrop is stored. Note that this should not contain the direct parent directory of the key files (e.g., keyring-xxx). For example, if the keyring file is stored under ~/.babylond/keyring-file/, then ~/.babylond/ should be specified in the flag.
  • --keyring-backend is the backend of the BABY key. It should be the same as the one when the key was created.
  • --btc-wallet-host is the host of the BTC wallet. The default for BTC mainnet is localhost:8332.
  • --btc-wallet-rpc-user Bitcoin wallet rpc user (default: user). Specify if needed.
  • --btc-wallet-rpc-pass Bitcoin wallet rpc password (default: pass). Specify if needed.
  • --btc-wallet-passphrase Bitcoin wallet passphrase. Specify if needed.
  • --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.

1.4. Validate PoP

To validate the JSON file that contains the PoP, run stakercli pop validate command:

stakercli pop validate /path/to/pop.json
Proof of Possession is valid!

2. Submit PoP via API

To register your staker’s information 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-btc' \
-H 'Content-Type: application/json' \
-d '{
    "babyAddress": "bbn1xjz8fs9vkmefdqaxan5kv2d09vmwzru7jhy424",
    "btcAddress": "bc1qcpty6lpueassw9rhfrvkq6h0ufnhmc2nhgvpcr",
    "btcPublicKey": "79f71003589158b2579345540b08bbc74974c49dd5e0782e31d0de674540d513",
    "btcSignBaby": "AkcwRAIgcrI2IdD2JSFVIeQmtRA3wFjjiy+qEvqbX57rn6xvWWECIDis7vHSJeR8X91uMQReG0pPQFFLpeM0ga4BW+Tt2V54ASEDefcQA1iRWLJXk0VUCwi7x0l0xJ3V4HguMdDeZ0VA1RM=",
    "babySignBtc": "FnYTm9ZbhJZY202R9YBkjGEJqeJ/n5McZBpGH38P2pt0YRcjwOh8XgoeVQTU9So7/RHVHHdKNB09DVmtQJ7xtw==",
    "babyPublicKey": "Asezdqkvh+kLbuD75DirSwi/QFbJjFe2SquiivMaPS65"
}'

In case of success, the API will return a 200 status code and the following response:

{"message":"ok"}

In the case that your staker key does not have 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 staker list","code":400}

To make sure your staker key was successfully registered, you can query it by the associated baby address and check whether your staker public key matches

curl -X 'GET' 'https://airdrop-api.babylon.foundation/pop/baby-btc?babyAddress=your-baby-address' -H 'accept: application/json'

The API will return the following response (formatted by jq):

[
  {
    "babyAddress": "bbn1kg3hw2trn4lpv4kg92tafqpwq4lpea2ep5d9r4",
    "btcAddress": "bc1prfh4v3j0p9p66qzj79qe3p08q4gfntmsm7j4zehdq2ks0tn050yqczwlnt",
    "btcPublicKey": "7e0c0bee635c97dc877a2ec5f55f0c9f2d1620ee032c1823f204fe5c64b6613a",
    "babyPublicKey": {
      "type": "tendermint/PubKeySecp256k1",
      "value": "A7pgdC3q+IOeeavUqdhYpupU2U/qL+kEu0wDxXLhFs6m"
    }
  }
]

This response returns all the staker public keys associated with this BABY address. If there is no Proof of Possession 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 BTC key, you can delete the submitted PoP and re-submit a new PoP that bonds the BTC staker to a different BABY address. Please note that this is a necessary first step if you want to change your BABY 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 ownership of the staker key that intends to delete the existing PoP, you need to cryptographically sign the entire string literal found in the message attribute of the previous JSON response.

You can accomplish this by running stakercli pop gdp command:

stakercli pop gdp --btc-address bc1qrxxqcyf7deu669wku78np3nzyg5jdnegvpg9lt \
  --baby-address bbn1xjz8fs9vkmefdqaxan5kv2d09vmwzru7jhy424 \
  --keyring-dir /path/to/babylon/keyring \
  --keyring-backend file \
  --msg='Welcome to Babylon Airdrop!\\r\\nAddress: bbn1v2a65yjl5cathzl8hdysqr9xz7w503xvvu85fx\\r\\nNonce: 0f7c99f145'
Enter keyring passphrase (attempt 1/3):
{
    "babyAddress": "bbn1xjz8fs9vkmefdqaxan5kv2d09vmwzru7jhy424",
    "babySignature": "adEjxmRv+ujogTKt5Vnngo8BLatv+e0Xqs4KQzQm+gEUCTe8c4pXNAfYa5UMaEI0pbkqD5qKAo++LBbxVz/kkA==",
    "babyPublicKey": "Asezdqkvh+kLbuD75DirSwi/QFbJjFe2SquiivMaPS65",
    "btcAddress": "bc1qrxxqcyf7deu669wku78np3nzyg5jdnegvpg9lt"
}

where:

  • --msg is the message received from the API. It is important that string is closed in single quotes.
  • --keyring-dir is where the BABY key is stored.
  • --keyring-backend is the backend of the BABY key. It should be the same as the one when the key is created.
  • --btc-address is the address of the BTC key used in phase-1 staking. Bech-32 encoded.
  • --baby-address is the address derived from the BABY key used in a submitted PoP. Bech-32 encoded.

3.3. Submit the PoP Deletion Request

The output of the stakercli pop gdp command is the payload you need submit to the API in order to finalize the deletion request:

curl -X DELETE 'https://airdrop-api.babylon.foundation/pop/baby-btc' \
-H 'Content-Type: application/json' \
-d '{
    "babyAddress": "bbn1xjz8fs9vkmefdqaxan5kv2d09vmwzru7jhy424",
    "babySignature": "adEjxmRv+ujogTKt5Vnngo8BLatv+e0Xqs4KQzQm+gEUCTe8c4pXNAfYa5UMaEI0pbkqD5qKAo++LBbxVz/kkA==",
    "babyPublicKey": "Asezdqkvh+kLbuD75DirSwi/QFbJjFe2SquiivMaPS65",
    "btcAddress": "bc1qrxxqcyf7deu669wku78np3nzyg5jdnegvpg9lt"
}'

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-btc?babyAddress=your-baby-address'
[]

Now, you can submit a new PoP with a new BABY address.

Search Your Wallet Address Here

Wallet 201

bbn1l70w2gr62zjtr0eqz6npgqglea9s75l5qmszz4

Wallet 202

bbn1783cye0g6qnqjagck6vlk834fslt0z3x4483kq

Wallet 203

bbn1nj8dcw235klkl0nvdvfrp6dz8zy0vr89cgn7wf

Wallet 204

bbn18wvpqnz2qyahf9gzag9qcjrz38hg72as72zmuj

Wallet 205

bbn1skv2quty6zavcqfrnq746ll2pmyvj273j64yhc

Wallet 206

bbn13483d47gftuw45kygxp3vre6apv97xv45kpamz

Wallet 207

bbn13cwp22g37n478ywyemwjmvu7vv5utlnel3kvjm

Wallet 208

bbn14mngkgm3ey4aesjaf358pa5u9tz637y6vyvqp4

Wallet 209

bbn1xyplrytfl3sz7n0pe9w0gf9d45zn4pe0df5y0j

Wallet 210

bbn10y60u4gvf4kct0g8679tjx8ewkpyf0xjkw6dxu

Wallet 211

bbn1la63aajzdr6dlc9xm47a4u23maesdw47jsekkl

Wallet 212

bbn1sw7chn23upfxkc2xglefj233dnlxgwanjvq7kv

Wallet 213

bbn1myckz9qkak58vgylv92n9ypx8tvtx6pwkrgrgx

Wallet 214

bbn1ku4ljel90nfxe8pjx3ldtqw38l7xl6rh0f2f4m

Wallet 215

bbn1ed3jnj22uzdaz8n7xlezwwf5nvkducue378qhk

Wallet 216

bbn1xu5raqzk5fjlpznrdw5er3m5ynzm06808upc09

Wallet 217

bbn1v6vnzdrlp8pvat4vcma7re9g3r79paj5x2kxyx

Wallet 218

bbn1ew8s2sanvhwf2c2gxldf2sgppachs57enkgnmy

Wallet 219

bbn1swv07cxuaa8j7p6fdnfg8pegmf2apqn66tey9k

Wallet 220

bbn1nvmzj7qe9qvduv5vw9wqu4dj3nd7md3hwrexja

Wallet 221

bbn17qj5rphe62u9ru0he9l4rpptuyy9vmxstlch0g

Wallet 222

bbn177zmm0988jlf5l3syhv5vwcsas22cag0u5p5cz

Wallet 223

bbn15w6czjtdnznwksa4ng540tf4u29qq205yvxg94

Wallet 224

bbn1ny62u7zzjp2eh7rudtqehd442jzzvydjmaj9yg

Wallet 225

bbn1d2npc0363qpv5h7ejz7p3tnvp8dl93mdwsvn5z

Wallet 226

bbn1guvmdcch8hw3df5upxghtcdnyr3nv08crt8tfy

Wallet 227

bbn1z5xyrj2gl75c5m6827j0stkdcngrk0fv0znq9t

Wallet 228

bbn1texzx2j02mneweyhvc7yhvzakw0euhzgpdqzjg

Wallet 229

bbn1gu3d6424xmx9veyw76mse9hh6tmnc5mz08zhkh

Wallet 230

bbn1v9khqgk6xxguged5tf85ml2epngej5fl3vw2p0

Wallet 231

bbn1aefzj22kwzm52e5gaqlg8g496hxpsp84td9x8c

Wallet 232

bbn1hmzaw6tuxkxu65k04szkfqqsl80lpyjd4xtuhk

Wallet 233

bbn1rq2t57cwmpa7u0009625pvu96avsmad3wr57ry

Wallet 234

bbn104edwyj7h33jmjqxnhlv66cde77ur7s2el2g5z

Wallet 235

bbn1ezgle84u5ey9uq3nghn6v4fayp4zjwewspuj2z

Wallet 236

bbn14xxcewz96j8grevlspvpc2rf59ec7waf570qx7

Wallet 237

bbn14c0etg9wju5pmmp8ptfw20nu5rvd09hv35xevt

Wallet 238

bbn1m522zw63tp94g337jlgcf2aw8enf2fuz4w24as

Wallet 239

bbn1aaj22nk8f4d0fwd5dc5nj03ea6gfxy8x3t3mfa

Wallet 240

bbn1f3fh0028rggumeec8v584853x5kqf9pcslz6y5

Wallet 241

bbn1t67flegpxsjg4rzd7n7xveadzuzxwd7atrupr6

Wallet 242

bbn17wj7r3u2humj83c9ya5g86skl7l5nmsdfr4wph

Wallet 243

bbn16wvxj42q6u75nqfar753c6zf063y8gfvmvyje9

Wallet 244

bbn1h9fvyc09up4pu6md6we66jlnysjar522da039w

Wallet 245

bbn1tv3p2c2rr6h6dz54qhk59sxgq6ety5ces5z08j

Wallet 246

bbn1n42c7hkqj3z8ppv8cp438d9rfca8788xke7gef

Wallet 247

bbn1kaqxfwf26urx3yf2xwg3sz8mml2ykefkjkunk3

Wallet 248

bbn1hlkke3t6mpp5gvl3avna5tcxzl8t8se2ezvhw9

Wallet 249

bbn1sf4md0af6484cjgp6rhpy68urcf5crkc7yvh4c

Wallet 250

bbn1tq9gnxzgjhmf488mcc75ytnudnur4anj33fzmp

Wallet 251

bbn1wakrx4dc9fa663km2dpnfuknszfseskzvannln

Wallet 252

bbn15crwezt7g843sy3074f0y8rslsnfjhl0aqpm4w

Wallet 253

bbn1avg07pjfcpy52y906n8903w5hs3r5xs6qfpt4y

Wallet 254

bbn107034gh4wad33hpp86tng33dwttk69dwhpj857

Wallet 255

bbn18ya6l3fxy7kxwewkj546mtuz6n0p9ufzsd269y

Wallet 256

bbn1t20pzd3ghuzfgv979w8qtmzxa50wq0tvjl6kct

Wallet 257

bbn1heqtfs53k9m4nrksujrjckr3789u973fx5kpjv

Wallet 258

bbn1ajl8mhxvpvpul9sld257nchulntu9n5d4r24nu

Wallet 259

bbn1z8hjmgp00ugr5crpzqn9894e4vs6f6mdqe032f

Wallet 260

bbn18cgnvgeqzm0fnx5lvkwyg6hdsjasyez49ejneg

Wallet 261

bbn1a69j8tn95a076vd6jvhdc3kws5kqrx0sj2rhsw

Wallet 262

bbn1xv5yagfmwj3yrrnmg7wwt35k0tsg2cjapc4rxv

Wallet 263

bbn1v0p0a635qwut46sjetlus5lar95gfgvjpe6zm7

Wallet 264

bbn1g4hyd9fzx4kupcf85e3e9gcrrwvrc80y2tz7u4

Wallet 265

bbn1a6k848fyllqx5crz5764rdlpll6a28hksyzqtj

Wallet 266

bbn13ln0q8pqakfrmwvdczmz00jj9ym23pnp6rzt8e

Wallet 267

bbn1asfmcwu6v0p46uwnrjsenezavvqwwlpaxt3zwn

Wallet 268

bbn15mn9yg8hkzv3mdxl9eacum0ff4jhpmflwqych4

Wallet 269

bbn1yg2z5j2s3nemq5lqlef7wd4w4fkjw9cghq2aak

Wallet 270

bbn157f708uaxn5jvvnyheazy46vuvx2mxe9fa5jmu

Wallet 271

bbn1tzwwh2zfyydvqqvuzjs3ug0npxehg5pjk3vu5n

Wallet 272

bbn1zfm4lqj5a8x0d375p4dwzzz32sdq38x6tc54tn

Wallet 273

bbn18m8xv2u62xrw02l6s5u299wnqmps4ffm5wk585

Wallet 274

bbn1ul6wsqf6skw2r8lketw674w8rly5p0dgk93p30

Wallet 275

bbn16rnku48zgnc7lrg6pymf93783tn6j2zn7eekl8

Wallet 276

bbn1yyd05mpxyyh3tekv3zkuqwtsut55ujfrej0m0m

Wallet 277

bbn18te6h0c79a4h2yqk8wwkmhmlatzz88dwql7mzm

Wallet 278

bbn1zjfrjze65vc0eke9nuyuv3j3ds974lgpvl34r9

Wallet 279

bbn1fus5d7e75cmzspmdgqskse3j8fgdquprrl43kg

Wallet 280

bbn1l5p2dkkhz2wt35a9s9v4v47z3efaxea60lv05k

Wallet 281

bbn13uzgc4632x2qtsqqk89f66y4hhlwmf5qynqcn3

Wallet 282

bbn1anyc4gsnzc3umnur96rc72zpnknvvwwjdxdac2

Wallet 283

bbn12e6u9vt3e4dwx8evj6f47ut86pah8s2p5zrwdy

Wallet 284

bbn1khuee3342qcexfjzve0aqxqdhuw8u9py3qc3gs

Wallet 285

bbn109lt659xhl6x68ul88gskvmjzw9e2wcd3cjcz0

Wallet 286

bbn1q8qdyk5ngc9dpz9f5nlp9lz83zjy7jgdmvhlx9

Wallet 287

bbn1p4ytrusuxuq3u9rsy5f8l3fsr434u2fp0l9mvu

Wallet 288

bbn1g3x3dm6qmzs7tkjncjuz3yw652nmdap8jdmfey

Wallet 289

bbn1zu54nv48rtqm4u96uglravv0m7rppcwk3d6mnc

Wallet 290

bbn1j9lh26ywdc9vhtust9ct0q227tvmhl06hak5kp

Wallet 291

bbn1l2cuzdnadc4zwmch0pa7v0rr845vru7rar7hpx

Wallet 292

bbn1h48udje5n0mn5045gyqf5tz3n92hq7492k23p2

Wallet 293

bbn1q3cs0w74rn99vrtzfx5jfch4shnvv4rk59634f

Wallet 294

bbn1d2ytw3y7wh2gctfwqetfhftyygfwmm28y7zwwt

Wallet 295

bbn1jl4pfhgsfgj4xglfgy4yx0a8sxe6uvdgz8z4k7

Wallet 296

bbn1heypqzs8pw5dpg8upansrp8v2aljujvvzunjfd

Wallet 297

bbn14f9ljkr7z2cxvagylq30hmk0lr4w7jzgdrddf4

Wallet 298

bbn13hf38vscc6j8sw57ar2jj5f2nmwa3a4t2rkvxk

Wallet 299

bbn1tc3kpxftqm8tnpk8tctwdzs9k2qvakq0j08w6g

Wallet 300

bbn1yrp9hxkajf0232kcxsynh3fec45e9wh2jh84fh