Welcome back, dear readers! If you’re here, it means you’ve survived the setup and you're ready to get your hands dirty with some actual Bitcoin internal magic.
In my previous log, we got our Signet nodes up, running, and stealthily "cloaked" for the BOSS (Bitcoin Open Source Software) Challenge. Now, it’s time for the first real trial: Challenge 1 - Recover Wallet State.
The quest? Compute your wallet balance by scanning the blockchain manually. The catch? The evaluation environment has the Bitcoin Core wallet disabled. No getbalance, no shortcuts. Just you, your code, and the raw blocks. Let’s go! ⚡️
đź› Step 0: The "Sanity Check" (CLI)
Before we start automating, we need a "North Star" to make sure we aren't chasing ghosts. We'll use the Bitcoin CLI to see what our balance should be. This is your benchmark!
1. Create your local wallet:
docker exec bitcoin_signet bitcoin-cli -signet -datadir=/home/bitcoin/.bitcoin createwallet "boss" false false "" false true true
2. Import that descriptor:
docker exec bitcoin_signet bitcoin-cli -signet -datadir=/home/bitcoin/.bitcoin -rpcwallet=boss importdescriptors '[{ "desc": "tr(tprv8ZgxMBicQKsPfCkDmSmHXuKAVA8zwwXLWTHEgyyisMioZ8gn3nTmmNwUzBMKWnNMkhRYN3E9qVCZrZ6MC645cqYdpy9jTYHhBwG1KhpNAMd/86h/1h/0h/0/*)#hjz07900", "timestamp": 0, "active": true }]'
3. Peek at the results:
docker exec bitcoin_signet bitcoin-cli -signet -datadir=/home/bitcoin/.bitcoin -rpcwallet=boss getwalletinfo
If you see a balance, BOOM! 💥 You know what number you’re aiming for. Now let’s write the code to find it manually.
🧬 The Deep Dive: P2TR Derivation
To find our coins, we need the Witness Program. In the land of Taproot (BIP 341), the address is derived from a "tweaked" public key. Even if we’re just using the Key Path (no complex scripts), we have to commit to a script path.
The "Golden" Benchmarking Script
We’re using bitcoinjs-lib and tiny-secp256k1 to handle the heavy elliptic curve math.
CRITICAL NOTE: You cannot use this JavaScript program for your final submission! The BOSS challenge strictly requires Python, C, C++, or Rust. Use this JS script as a benchmark to verify your logic. If your Python/Rust code generates the same strings as this script, you’re on the right track!
import { BIP32Factory } from "bip32";
import ECPairFactory from "ecpair";
import * as ecc from "tiny-secp256k1";
import * as bitcoin from "bitcoinjs-lib";
import fs from "fs";
// Initialize the ECC library—Taproot needs this!
bitcoin.initEccLib(ecc);
export const bip32 = BIP32Factory(ecc);
export const ECPair = ECPairFactory(ecc);
const net = bitcoin.networks.testnet;
const xpriv = bip32.fromBase58(
"tprv8ZgxMBicQKsPfF4wki3EzsSYvohmC5z2B92m74LscyiFAHwZUtn4Lhbfosc1zCQRzN4aXiPqiH64xbTbsnRCgTskJWspELwAYSdyZSekqyp",
net,
);
// Derive the path from the descriptor: m/86'/1'/0'/0
const derived = xpriv.derivePath("m/86'/1'/0'/0");
const addresses = [];
const internals = [];
const witnesses = [];
console.log("🚀 Starting derivation for 2000 keys...");
for (let i = 0; i < 2000; i++) {
const current = derived.derive(i);
// Extract the X-only internal pubkey (32 bytes)
const internalPubkey = current.publicKey.slice(1, 33);
// Generate the P2TR payment—bitcoinjs handles the TapTweak automatically!
const { address, pubkey } = bitcoin.payments.p2tr({
internalPubkey,
network: net,
});
addresses.push(address);
witnesses.push(pubkey?.toHex()); // This is your Witness Program!
internals.push(internalPubkey.toHex());
}
// Write to files so you can 'diff' against your main submission code
fs.writeFileSync("addresses.json", JSON.stringify(addresses, null, 2));
fs.writeFileSync("witnesses.json", JSON.stringify(witnesses, null, 2));
fs.writeFileSync("internals.json", JSON.stringify(internals, null, 2));
console.log("âś… Done! Check your JSON files and compare them with your challenge code.");
🎯 Why This is Your Secret Weapon
The BOSS Challenge requires you to:
- Derive 2000 keys.
- Compute the P2TR witness program for each.
- Scan the first 300 blocks of the signet chain.
The Witness Program (the pubkey in the code above) is the actual hex string you’ll be looking for inside the scriptPubKey of transaction outputs on-chain.
Doing this math manually in Python or Rust can be tricky—using this JS script ensures you aren't debugging your scanner when the problem is actually your derivation!
⏠What's Next?
Now that you have your list of 2000 witness programs in witnesses.json, it's time to go hunting! Grab your blocks, iterate through the transactions, and start tallying that balance.
Are you smashing the challenge in Rust or Python? Drop a comment below and let's talk TapTweak math! 🚀🔥
Top comments (0)