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 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