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 501

bbn1y5ykrn2zude6cm30s9n8ruea99tjt3yrdzdzfw

Wallet 502

bbn1gy3ejmqhe09y3u584hrvg5glp00h8z6g9d49dj

Wallet 503

bbn18lyezqqcztexy426pwxuh879ktpsqyjncuxhf6

Wallet 504

bbn13j6m2twg43xupntlfdthxhpa35easac3y6tpuq

Wallet 505

bbn1p2sjr8508sem7t6lwx3ankq756rwl3puyvpd2p

Wallet 506

bbn1n56hhr5lu430skm7wt68sl8wv4t7pju3jz58ya

Wallet 507

bbn1mqrgu4agrlvm3zp6fhcgehuezvkve5xn4g4a75

Wallet 508

bbn1zywfk0439sjzlfqrdq8035qll4p6epkcaxxe7j

Wallet 509

bbn155gkcrq77w8l9ffts2ttlvwghc2w5xckh6xa32

Wallet 510

bbn1wczqhc0kgc0y3sxmhwm2eax4ns6y0x25sxpwvx

Wallet 511

bbn1g2umlpne47g0854qprr2j39sayk7tst5trknzl

Wallet 512

bbn1qpzdpjkwlyz6ym2w6rh0czgd9wlpw02jzq6kng

Wallet 513

bbn1e5gs2d2trnz8vwvr0hmx6md5fdml6spzrchzqq

Wallet 514

bbn133sns2zg6wz0xush7zxmqz7kutrsdgldfl0vqe

Wallet 515

bbn1x7egkz8sat0r937cmrqzzaehnmqtk9hlnz5ps0

Wallet 516

bbn1gpqpx73dgkd2wznecrn7hplz9psvtu7tf93nzq

Wallet 517

bbn15kjajnlaq9wjx2d25kvpfwypuk9fyv9508jqn0

Wallet 518

bbn1n2rrlpuxt0u82yurxns4fdr46mpplnwqdwr9ly

Wallet 519

bbn1zt46xzr7sfz8htphtc0k8l7qhy4wgej443k5jx

Wallet 520

bbn1qtm32uvtss0duw49u7nxewwz6wxqexfxxcelaj

Wallet 521

bbn1tvyk28dxmt00dpatng5n5nw63l44fh7v0nffuv

Wallet 522

bbn1g7ycwgq75g2f4cesdqlj3l04zv5e2kd4nx0h4s

Wallet 523

bbn1q3hxte3fmq75kz9uvqnl0ys4q527sln0czhu99

Wallet 524

bbn14wky40wg2h0hw3gsp4qxj0pjyqg65hg9ccqf26

Wallet 525

bbn18pspelm4m9xwlnjv6r9f3qmkn0nlrrjy27xn4z

Wallet 526

bbn10489qehvt89emlzw52etcuwghysceruj7r3guu

Wallet 527

bbn1a5xayzlfarjp7s5rdctzr0ke3zx7fkwyrfqt53

Wallet 528

bbn1z2qq3mf5e22whaxfm5pq8crafp2hsa76a4l5ka

Wallet 529

bbn1xqppeh9vh8mc3sspzzk0esv3x29dqcjfpk0p6g

Wallet 530

bbn1zgvalhxsrklxev6djhmct2mtpj6fvm6528q0w3

Wallet 531

bbn16a50rc0m8xc8k75kmwh55d3ucvmugxgzr24mz0

Wallet 532

bbn1vyenjy4terukvw59slu9emue4fklhsenhx8qwc

Wallet 533

bbn1j587p9v4u3hcwy4uqmsjg506ezad2qhtnfkdrw

Wallet 534

bbn1809ussrj53hefkq4nf4prvdexap632mxdmcgva

Wallet 535

bbn1c69tuyh08gmhx8rha8kar0fc2yfdz0ua2zjdk3

Wallet 536

bbn1gr6dku8q23gaut2sv42jcd2ptqtc26n3s0rrhp

Wallet 537

bbn1glkdqmtfs4jd7u37ujnu3f3dc0lylp5clk9gh8

Wallet 538

bbn12k7dad2g6q3eyq37mngzrsneydrgn7q86gjz0h

Wallet 539

bbn1c2dtn2vrzg49efs7ulhrffmwy7thymuvmhqs46

Wallet 540

bbn13zyv6un75a4n5n6mjuugphkt9lvurmruve5hv5

Wallet 541

bbn1csknk8yg6ffyt05h48wx7ulwfusm7asphj6xkp

Wallet 542

bbn1v7yk3y7e7hry9qdgxqkqfpa5cw4tzrllqwueye

Wallet 543

bbn16nlcmx0grcc2m0tgn0xv0mua8x07c0vqsnp3r0

Wallet 544

bbn1cu8vq2jl5e05l6ssduja8r2xevamms6hmjzrk4

Wallet 545

bbn1er7md5z4te0p6m5t4nvynpz56sq8e7xamz0mhr

Wallet 546

bbn13wpej8qsv2j4uw57yvwxrxfprh8pmhshff0hj6

Wallet 547

bbn16fucx34cpg8upa4xwksfyee6dt465sj75xxlxh

Wallet 548

bbn1mqvr8zdajqzcw4n4dtk0earveymwp0y2rsvzvu

Wallet 549

bbn1eqywrs2mld8kaxcvw2ezfq04s324sn545laeu9

Wallet 550

bbn1af8uff74w9hfwmnsv34gecm9n6cwgf2dy05ftp

Wallet 551

bbn14cer09fcj544cacs8q88a5u97w7jsrudfej2em

Wallet 552

bbn1xjll8g4suy5y98qewgf5r3x0ef63wp6gxha88e

Wallet 553

bbn10vkfn6jq09m22ncra76yqlque7udeyy2prphqx

Wallet 554

bbn1j8wpe4augpt3p8dtncu666zu3flpvpjgr5yff5

Wallet 555

bbn16t3g3efr70hmnd2rwhkpura0f5al8ymlwqhtgz

Wallet 556

bbn15qcfy0caa8np9fgygk2gvw7er4umra83je03fq

Wallet 557

bbn1cvtatrzllzcxs6paw57gwlu9ruzlmg85298u7a

Wallet 558

bbn1klcf48ur0yucyxkrzjl4uku6uwxeqejq4sagnn

Wallet 559

bbn13q2fasez9zjs5hac3yueu85pg252vtj5tplcq9

Wallet 560

bbn1m7xua28cv7f0fz8qsggq09lpe7zwy65ha4wdcv

Wallet 561

bbn14836e363fvc3ml0lmwf3gl0ve435n58xysqjr0

Wallet 562

bbn1e4el0lkq6dqw7mmhqjztnkz737n5qx6f40g0z7

Wallet 563

bbn13amnd5aqn7n3am9tw3mfxgw46pujcz88x0d696

Wallet 564

bbn196zyh4ekk834gdu34lsfrra4dax6zyepw6ewdy

Wallet 565

bbn1af9ahjq90pzcu6r9xqvp4lqleeyy2m5ru9v8f3

Wallet 566

bbn1hz04zjaha8gsh9eycjhfr4tnv6uu2ney9y9kvp

Wallet 567

bbn1uedndqltx3rnakutpmpdctvwet4q3z8m3rrgtw

Wallet 568

bbn1v6jhnrpa53t9rknjxkkg9fwj9y5scjle58egd9

Wallet 569

bbn1fyfnvvswqjmg2xlpx2grldmlnuzqj6zjh4j6mv

Wallet 570

bbn1zlx5ftrjn0tca7r9dsr0vzzljc6vdyj5jzynt9

Wallet 571

bbn1lx0fd70j44fwamsn6wud095hegatz23w3ke2pw

Wallet 572

bbn14yxz02wqgqn0jxyc2d6exr3zr4kdmt3m7gdm8y

Wallet 573

bbn1zgd7qc8md9rhuh8urvvzzg7x9cnp7uafttthj4

Wallet 574

bbn164cxq6rfz2u02fdaghfrmrf5quwv62y8f5lnfl

Wallet 575

bbn18ucxs3ej48rdwpehzg32rj5tww3jmtkr7qsdd3

Wallet 576

bbn176l7r2rp3v4ztjqcc9hqq3nvyf7sd62enns8us

Wallet 577

bbn18c3lzueztwm3973ysfez4khx2pcldff0j79lsx

Wallet 578

bbn1cv0hfuk0vhc5zgqrh0szcnet8ff04pte6eg7qn

Wallet 579

bbn1uulu2vm2sgk4nqmjph9fkr70va0hypmsl7wn4f

Wallet 580

bbn1a6uy04y63vt5w04ayxa3etrdedw9qn05mddqs7

Wallet 581

bbn1a0dg9zkqljjmfy40gusl9qr9vcxnfkc95vzmfr

Wallet 582

bbn16h5q8j9mv77r6r5haf3c9q579swl6vmcu2aqs8

Wallet 583

bbn1eyttpffw8qqmeha6es2cc90any8rqfdl8t5ccj

Wallet 584

bbn1dxl5mvr64dv7hneuvxnl3ktewu9wgxqdtskrv0

Wallet 585

bbn1tjg2qvsrcvc49sf0ksz4e4swn5zfsyvkymr0tk

Wallet 586

bbn14hx6vf0tkc0fm2wf8qhpagejyxc32cnlh5ccne

Wallet 587

bbn1603mnk65ny0a6m3fs59s0qmpupm9g93v04pvrv

Wallet 588

bbn13gmspxwn6y3ehmqjvmlyzh2gvm56j4e094r7kr

Wallet 589

bbn10sl2wtte5kjy3cs6wv8y5l2kgwmdpx8c8fnlfa

Wallet 590

bbn1eu9qcjqq80tldxpu8045jwsvtsjqwfglhmpvws

Wallet 591

bbn1r5tc5aqkrk68akdhl960jtjnjtwxpxa5xrvpya

Wallet 592

bbn1g0t437ennk9ts7vjtznz0lnmpna6t6gmugfplh

Wallet 593

bbn1v52tanddaaddsa0yzt9yhlau5cafmwrfpdl4n6

Wallet 594

bbn1e9pz5axlcravdakavlrpqqljswyhgzh2jlg6zp

Wallet 595

bbn1gkkxs72gjychar7xyf4fn6xwa6675ptpegzvmz

Wallet 596

bbn1cm985nzuv6lzduup9vlhlmwmqp40ls4ur4vrya

Wallet 597

bbn14wzk0ugft5gcvhehnwc3l3tdv828qzut336r5j

Wallet 598

bbn1k6vf4pt2mf8hr723a0y8j5dnd3mqwg8e763cme

Wallet 599

bbn1fesya574sflv9lwqr79tkxdyg5xxft89mhys58

Wallet 600

bbn1wky9rrgk2000vjmkxu8dcfdcn0ex9rry429pry