<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: 0xkniraj</title>
    <description>The latest articles on DEV Community by 0xkniraj (@kniraj).</description>
    <link>https://dev.to/kniraj</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F385879%2F24f82104-0924-4480-9254-3c984750be0d.jpeg</url>
      <title>DEV Community: 0xkniraj</title>
      <link>https://dev.to/kniraj</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kniraj"/>
    <language>en</language>
    <item>
      <title>Vibe Coding: The $2B in Breaches Nobody's Talking About</title>
      <dc:creator>0xkniraj</dc:creator>
      <pubDate>Wed, 18 Feb 2026 08:49:40 +0000</pubDate>
      <link>https://dev.to/kniraj/vibe-coding-is-professional-malpractice-and-i-can-prove-it-the-2b-in-breaches-nobodys-talking-12e4</link>
      <guid>https://dev.to/kniraj/vibe-coding-is-professional-malpractice-and-i-can-prove-it-the-2b-in-breaches-nobodys-talking-12e4</guid>
      <description>&lt;p&gt;I genuinely don't know whether to laugh or cry when I see another startup founder on my feed bragging about building an entire SaaS platform before their morning coffee. The hype is deafening. Last year, "Vibe Coding" actually became the Collins Dictionary's word of the year.&lt;/p&gt;

&lt;p&gt;If you trace this back, the cultural tipping point hit in early 2025 when Andrej Karpathy tweeted about a new way of working where you "fully give in to the vibes" and "forget that the code even exists". The whole premise is that you just write some natural language prompts, surrender control to the machine, and judge the output by how the app feels.&lt;/p&gt;

&lt;p&gt;It sounds amazing. I admit it's intoxicating to watch a tool like Replit Agent spin up a full-stack application from a single design file. Take Rokt, for example. They reportedly built 135 internal applications in a single 24-hour window using these tools.&lt;/p&gt;

&lt;p&gt;But underneath the shiny demos, treating English like a programming language and abandoning architectural oversight is professional malpractice. We are essentially building digital skyscrapers out of styrofoam.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Metrics of Decay
&lt;/h3&gt;

&lt;p&gt;Let's look at what actually happens when you let a large language model guess its way through your architecture. Independent research from GitClear and Veracode paints a pretty ugly picture of where our codebases sit in 2026:&lt;/p&gt;

&lt;p&gt;Code churn has spiked by 41 percent. Developers are writing and deleting code within a two-week window at alarming rates because they are just blindly iterating through AI hallucinations.&lt;/p&gt;

&lt;p&gt;Intentional refactoring has completely collapsed, dropping by 60 percent. AI agents have a terrible habit of solving problems by stacking more logic on top of the pile rather than simplifying anything.&lt;/p&gt;

&lt;p&gt;Code duplication is up 48 percent because agents just copy logic from one file to another without understanding how to abstract it into shared utilities. On top of this, a staggering 45 percent of AI-generated code contains security flaws.&lt;/p&gt;

&lt;p&gt;This isn't efficient iteration. It's just people pasting errors back into a chat window until the red squiggly lines go away.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Security "SaaSpocalypse"
&lt;/h3&gt;

&lt;p&gt;Spaghetti code is just an annoyance for the next developer who inherits it. The real issue is the security fallout. Wall Street is already calling this market correction the "SaaSpocalypse".&lt;/p&gt;

&lt;p&gt;Right now, one out of every five security breaches in 2026 traces directly back to code an AI wrote. Remember the OpenClaw incident? That marketplace ended up hosting over 900 malicious agent "skills". Developers who were too busy "vibing" just installed these packages without looking. Attackers walked away with remote code execution on thousands of enterprise servers.&lt;/p&gt;

&lt;p&gt;The bad actors aren't typing out manual exploits anymore either. We've got hackers using jailbroken versions of autonomous agents to probe networks. In one case, a single agent targeted 17 organizations simultaneously to find databases and write custom exploits. It did all this without a human lifting a finger.&lt;/p&gt;

&lt;h3&gt;
  
  
  The "Alien Code" Hangover and the Junior Dev Crisis
&lt;/h3&gt;

&lt;p&gt;Here's what really gets me. It's the loss of the mental model. If you build a system without ever reading the code, you are completely helpless when it breaks.&lt;/p&gt;

&lt;p&gt;We are creating a generation of app assemblers who don't know how to fix a memory leak or debug a race condition. Gartner is already warning about "AI Lock-In," where organizations get stuck depending on the AI because the codebase has become completely alien to human eyes.&lt;/p&gt;

&lt;p&gt;We are also actively destroying the pipeline that fixes this. Tech hiring for pure junior roles has dropped by nearly 30 percent since 2023 because companies are letting AI handle the grunt work. If juniors never struggle with boilerplate and minor bugs, how do they develop the architectural intuition to become seniors? Where are the senior engineers of 2030 supposed to come from?&lt;/p&gt;

&lt;h3&gt;
  
  
  Time to Grow Up: Agent-Driven Development
&lt;/h3&gt;

&lt;p&gt;We need to get back to actual engineering. The adults in the room are shifting to Agent-Driven Development (ADD). In this model, humans manage the architecture and enforce strict governance over what these bots can actually do.&lt;/p&gt;

&lt;p&gt;This means moving away from the "chat" interface and adopting structured frameworks like the BMAD Method. Instead of telling a single bot to build a website, you orchestrate a specialized team. You have an analyst bot research and output a project brief. A product manager bot translates that into a rigorous requirements document. An architect bot drafts the API specifications and data flow. Finally, developer and QA bots only write and test code after a human reviews the architecture.&lt;/p&gt;

&lt;p&gt;In this workflow, the true "source code" isn't the Python or JavaScript file anymore. It is the spec and the prompt. Throw in AgentOps layers with "Policy as Code" to physically block agents from introducing circular dependencies or leaking secrets, and you finally have a system you can trust.&lt;/p&gt;

&lt;p&gt;The code itself might be a cheap byproduct now. We might even reach a point where software is just generated on the fly for a specific user and immediately discarded. Until then, the intent, the architecture, and the security boundaries still matter. We really need to start acting like it.&lt;/p&gt;

</description>
      <category>vibecoding</category>
      <category>ai</category>
      <category>security</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Taproot part1: Generating P2TR KeyPath Witness Programs 🚀</title>
      <dc:creator>0xkniraj</dc:creator>
      <pubDate>Mon, 19 Jan 2026 19:48:52 +0000</pubDate>
      <link>https://dev.to/kniraj/taproot-part1-generating-p2tr-keypath-witness-programs-ikh</link>
      <guid>https://dev.to/kniraj/taproot-part1-generating-p2tr-keypath-witness-programs-ikh</guid>
      <description>&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;In my &lt;a href="https://dev.to/kniraj/the-oss-challenge-cloaking-my-signet-node-for-the-wallet-challenge-44p3"&gt;previous log&lt;/a&gt;, we got our Signet nodes up, running, and stealthily "cloaked" for the &lt;strong&gt;BOSS (Bitcoin Open Source Software) Challenge&lt;/strong&gt;. Now, it’s time for the first real trial: &lt;strong&gt;Challenge 1 - Recover Wallet State&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The quest? Compute your wallet balance by scanning the blockchain manually. The catch? The evaluation environment has the Bitcoin Core wallet &lt;strong&gt;disabled&lt;/strong&gt;. No &lt;code&gt;getbalance&lt;/code&gt;, no shortcuts. Just you, your code, and the raw blocks. Let’s go! ⚡️&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠 Step 0: The "Sanity Check" (CLI)
&lt;/h2&gt;

&lt;p&gt;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 &lt;em&gt;should&lt;/em&gt; be. This is your benchmark!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Create your local wallet:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;exec &lt;/span&gt;bitcoin_signet bitcoin-cli &lt;span class="nt"&gt;-signet&lt;/span&gt; &lt;span class="nt"&gt;-datadir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/home/bitcoin/.bitcoin createwallet &lt;span class="s2"&gt;"boss"&lt;/span&gt; &lt;span class="nb"&gt;false false&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt; &lt;span class="nb"&gt;false true true&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Import that descriptor:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;exec &lt;/span&gt;bitcoin_signet bitcoin-cli &lt;span class="nt"&gt;-signet&lt;/span&gt; &lt;span class="nt"&gt;-datadir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/home/bitcoin/.bitcoin &lt;span class="nt"&gt;-rpcwallet&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;boss importdescriptors &lt;span class="s1"&gt;'[{ "desc": "tr(tprv8ZgxMBicQKsPfCkDmSmHXuKAVA8zwwXLWTHEgyyisMioZ8gn3nTmmNwUzBMKWnNMkhRYN3E9qVCZrZ6MC645cqYdpy9jTYHhBwG1KhpNAMd/86h/1h/0h/0/*)#hjz07900", "timestamp": 0, "active": true }]'&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Peek at the results:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;exec &lt;/span&gt;bitcoin_signet bitcoin-cli &lt;span class="nt"&gt;-signet&lt;/span&gt; &lt;span class="nt"&gt;-datadir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/home/bitcoin/.bitcoin &lt;span class="nt"&gt;-rpcwallet&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;boss getwalletinfo

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you see a balance, BOOM! 💥 You know what number you’re aiming for. Now let’s write the code to find it manually.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧬 The Deep Dive: P2TR Derivation
&lt;/h2&gt;

&lt;p&gt;To find our coins, we need the &lt;strong&gt;Witness Program&lt;/strong&gt;. In the land of Taproot (BIP 341), the address is derived from a "tweaked" public key. Even if we’re just using the &lt;strong&gt;Key Path&lt;/strong&gt; (no complex scripts), we have to commit to a script path.&lt;/p&gt;

&lt;h3&gt;
  
  
  The "Golden" Benchmarking Script
&lt;/h3&gt;

&lt;p&gt;We’re using &lt;code&gt;bitcoinjs-lib&lt;/code&gt; and &lt;code&gt;tiny-secp256k1&lt;/code&gt; to handle the heavy elliptic curve math.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;CRITICAL NOTE:&lt;/strong&gt; You &lt;strong&gt;cannot&lt;/strong&gt; use this JavaScript program for your final submission! The BOSS challenge strictly requires Python, C, C++, or Rust. Use this JS script as a &lt;strong&gt;benchmark&lt;/strong&gt; to verify your logic. If your Python/Rust code generates the same strings as this script, you’re on the right track!&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BIP32Factory&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bip32&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ECPairFactory&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ecpair&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;ecc&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tiny-secp256k1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;bitcoin&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bitcoinjs-lib&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Initialize the ECC library—Taproot needs this!&lt;/span&gt;
&lt;span class="nx"&gt;bitcoin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initEccLib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ecc&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bip32&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BIP32Factory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ecc&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ECPair&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ECPairFactory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ecc&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;net&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bitcoin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;testnet&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;xpriv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bip32&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromBase58&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tprv8ZgxMBicQKsPfF4wki3EzsSYvohmC5z2B92m74LscyiFAHwZUtn4Lhbfosc1zCQRzN4aXiPqiH64xbTbsnRCgTskJWspELwAYSdyZSekqyp&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;net&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Derive the path from the descriptor: m/86'/1'/0'/0&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;derived&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;xpriv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;derivePath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;m/86'/1'/0'/0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;addresses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;internals&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;witnesses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;🚀 Starting derivation for 2000 keys...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;derived&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;derive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Extract the X-only internal pubkey (32 bytes)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;internalPubkey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;33&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Generate the P2TR payment—bitcoinjs handles the TapTweak automatically!&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pubkey&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bitcoin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payments&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;p2tr&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;internalPubkey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;network&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;net&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;addresses&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;witnesses&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pubkey&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;toHex&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// This is your Witness Program!&lt;/span&gt;
  &lt;span class="nx"&gt;internals&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;internalPubkey&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toHex&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Write to files so you can 'diff' against your main submission code&lt;/span&gt;
&lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;addresses.json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addresses&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;witnesses.json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;witnesses&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;internals.json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;internals&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;✅ Done! Check your JSON files and compare them with your challenge code.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🎯 Why This is Your Secret Weapon
&lt;/h2&gt;

&lt;p&gt;The BOSS Challenge requires you to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Derive &lt;strong&gt;2000 keys&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Compute the &lt;strong&gt;P2TR witness program&lt;/strong&gt; for each.&lt;/li&gt;
&lt;li&gt;Scan the first &lt;strong&gt;300 blocks&lt;/strong&gt; of the signet chain.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The &lt;strong&gt;Witness Program&lt;/strong&gt; (the &lt;code&gt;pubkey&lt;/code&gt; in the code above) is the actual hex string you’ll be looking for inside the &lt;code&gt;scriptPubKey&lt;/code&gt; of transaction outputs on-chain.&lt;/p&gt;

&lt;p&gt;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!&lt;/p&gt;

&lt;h2&gt;
  
  
  ⏭ What's Next?
&lt;/h2&gt;

&lt;p&gt;Now that you have your list of 2000 witness programs in &lt;code&gt;witnesses.json&lt;/code&gt;, it's time to go hunting! Grab your blocks, iterate through the transactions, and start tallying that balance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Are you smashing the challenge in Rust or Python? Drop a comment below and let's talk TapTweak math!&lt;/strong&gt; 🚀🔥&lt;/p&gt;

</description>
      <category>bitcoin</category>
      <category>opensource</category>
      <category>taproot</category>
      <category>javascript</category>
    </item>
    <item>
      <title>The ₿OSS Challenge: Cloaking My Signet Node for the Wallet challenge</title>
      <dc:creator>0xkniraj</dc:creator>
      <pubDate>Wed, 14 Jan 2026 20:25:37 +0000</pubDate>
      <link>https://dev.to/kniraj/the-oss-challenge-cloaking-my-signet-node-for-the-wallet-challenge-44p3</link>
      <guid>https://dev.to/kniraj/the-oss-challenge-cloaking-my-signet-node-for-the-wallet-challenge-44p3</guid>
      <description>&lt;p&gt;Hello, dear readers! It has been some time, but I greet you once more from the pages of my logbook — the record of my grandest technical adventures yet!&lt;/p&gt;

&lt;p&gt;It is I, your humble explorer of the digital frontier. These days, I’ve traded my traveling cloak for a terminal window as I embark on a rigorous new expedition: I have officially stepped up as a challenger of the &lt;strong&gt;₿OSS (Bitcoin Open Source Software) 2026&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;My journey began in the year 2139—or at least, the version of it found in the &lt;strong&gt;Saving Satoshi&lt;/strong&gt; RPG. With my trusted &lt;strong&gt;Holocat&lt;/strong&gt; companion (that brilliant, nose-boopable AI guide from Chaincode Labs) by my side, I’ve been decoding genesis blocks and mastering elliptic curve cryptography to save the network from a standstill. Having "Saved Satoshi," I am now venturing into the practical world of running Bitcoin node.&lt;/p&gt;

&lt;p&gt;Today, I’m sharing the "architectural scrolls" for a setup that is essential for any ₿OSS challenger: running a &lt;strong&gt;Bitcoin Signet&lt;/strong&gt; node entirely over &lt;strong&gt;Tor&lt;/strong&gt; using Docker.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Master Blueprint: Docker Compose
&lt;/h2&gt;

&lt;p&gt;To begin this ritual of deployment, you must prepare your &lt;code&gt;docker-compose.yaml&lt;/code&gt;. This file summons the Bitcoin Core spirit and its silent Tor guardian.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;bitcoin-core&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bitcoin/bitcoin:latest&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bitcoin_signet&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;-signet=1&lt;/span&gt;        &lt;span class="c1"&gt;# Directs the node to the Signet testing realm&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;-printtoconsole&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;-rpcallowip=0.0.0.0/0&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;-rpcbind=0.0.0.0&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;-txindex=1&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;-zmqpubhashblock=tcp://0.0.0.0:28332&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;-zmqpubhashtx=tcp://0.0.0.0:28333&lt;/span&gt;

      &lt;span class="c1"&gt;# Tor Configuration&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;-proxy=tor:9050&lt;/span&gt; &lt;span class="c1"&gt;# Route outgoing traffic through Tor&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;-listen=1&lt;/span&gt; &lt;span class="c1"&gt;# Accept incoming connections&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;-bind=0.0.0.0&lt;/span&gt; &lt;span class="c1"&gt;# Bind to all interfaces inside the container&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;-onion=tor:9050&lt;/span&gt; &lt;span class="c1"&gt;# Use Tor for .onion addresses&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;-discover=1&lt;/span&gt; &lt;span class="c1"&gt;# Try to self-discover the onion address&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;-torcontrol=tor:9051&lt;/span&gt;

    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;38332:38332"&lt;/span&gt; &lt;span class="c1"&gt;# RPC port&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;18444:18444"&lt;/span&gt; &lt;span class="c1"&gt;# P2P port&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;28332:28332"&lt;/span&gt; &lt;span class="c1"&gt;# ZMQ block notifications&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;28333:28333"&lt;/span&gt; &lt;span class="c1"&gt;# ZMQ transaction notifications&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./bitcoin-data:/home/bitcoin/.bitcoin&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./tor-data:/var/lib/tor:ro&lt;/span&gt; &lt;span class="c1"&gt;# Shared volume for the auth cookie&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unless-stopped&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;bitcoin-network&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;tor&lt;/span&gt;

  &lt;span class="na"&gt;tor&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;osminogin/tor-simple:latest&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tor_proxy&lt;/span&gt;
    &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0:0"&lt;/span&gt; 
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;TOR_CONTROL_PORT=9051&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./torrc:/etc/tor/torrc:ro&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./tor-data:/var/lib/tor&lt;/span&gt; &lt;span class="c1"&gt;# Shared volume for the cookie&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unless-stopped&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;bitcoin-network&lt;/span&gt;

&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;bitcoin-network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bridge&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The Secret Instructions: torrc
&lt;/h2&gt;

&lt;p&gt;As every ₿OSS knows, the proxy needs specific rules to function. Create a file named &lt;code&gt;torrc&lt;/code&gt; in your directory and whisper these lines into it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# SOCKS5 Proxy&lt;/span&gt;
SocksPort 0.0.0.0:9050

&lt;span class="c"&gt;# Control Port&lt;/span&gt;
ControlPort 0.0.0.0:9051

&lt;span class="c"&gt;# Use Cookie instead of Password&lt;/span&gt;
CookieAuthentication 1
CookieAuthFileGroupReadable 1
DataDirectory /var/lib/tor

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Entering the Private Signet Challenge
&lt;/h2&gt;

&lt;p&gt;Now, listen closely, for this is the step that separates a standard traveler from a true challenger! If you are like me and taking on the ₿OSS 2026 trials, you need to point your node toward the private signet used for our tasks.&lt;/p&gt;

&lt;p&gt;Simply copy your challenge configuration into the data directory we created:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cp &lt;/span&gt;config/bitcoin.conf bitcoin-data/bitcoin.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By doing this, you've shared the secret "handshake" (the signetchallenge hex) with your node. Now, when you run your containers, you aren't just on any network but you are officially using the ₿OSS private signet!&lt;/p&gt;




&lt;h2&gt;
  
  
  Proof of Success: The "getnetworkinfo" Reveal
&lt;/h2&gt;

&lt;p&gt;Once you’ve cast the &lt;code&gt;docker-compose up -d&lt;/code&gt; spell, it’s time to verify your work. I used the following command to check if my node was truly hidden behind the Tor cloak.&lt;/p&gt;

&lt;p&gt;Witness the results of my successful incantation! My node has successfully manifested its own &lt;strong&gt;.onion&lt;/strong&gt; address and is reaching out to the world through the proxy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;❯&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;docker&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;bitcoin_signet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;bitcoin-cli&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;-signet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;-datadir=/home/bitcoin/.bitcoin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;getnetworkinfo&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;280100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"subversion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/Satoshi:28.1.0/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"networks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ipv4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"reachable"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"proxy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"192.168.97.2:9050"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"onion"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"reachable"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"proxy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"192.168.97.2:9050"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"localaddresses"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;your address&amp;gt;.onion"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;38333&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What does this tell us?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Reachable: true&lt;/strong&gt;: Our node can see the network!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Proxy&lt;/strong&gt;: Notice the IP &lt;code&gt;192.168.97.2&lt;/code&gt;? That is the internal Docker address of our &lt;code&gt;tor_proxy&lt;/code&gt; service.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Localaddresses&lt;/strong&gt;: That long string ending in &lt;code&gt;.onion&lt;/code&gt; is our node's secret identity. It’s how other peers can find us without ever knowing our real-world location.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Final Thoughts from the Digital Frontier
&lt;/h2&gt;

&lt;p&gt;Manifesting a node like this is just the first boss fight in the ₿OSS 2026 challenge. By using Signet, we can experiment with transactions without losing real sats, and by using Tor, we stay true to the cypherpunk spirit of privacy.&lt;/p&gt;

&lt;p&gt;As the Holocat says, "Bitcoin is serious, but learning about it doesn't have to be!" I’m off to tackle the next chapter of my developer training. There are more blocks to verify and more code to write!&lt;/p&gt;

</description>
      <category>bitcoin</category>
      <category>tor</category>
      <category>programming</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Tailwind CSS Lays Off 75% of Engineering Team as AI Tools Disrupt Revenue Model</title>
      <dc:creator>0xkniraj</dc:creator>
      <pubDate>Thu, 08 Jan 2026 18:54:59 +0000</pubDate>
      <link>https://dev.to/kniraj/tailwind-css-lays-off-75-of-engineering-team-as-ai-tools-disrupt-revenue-model-1l3d</link>
      <guid>https://dev.to/kniraj/tailwind-css-lays-off-75-of-engineering-team-as-ai-tools-disrupt-revenue-model-1l3d</guid>
      <description>&lt;p&gt;Tailwind Labs has laid off 75% of its engineering team as revenue has plummeted 80%, founder Adam Wathan revealed in a GitHub comment. The company blames AI-powered development tools for breaking the conversion funnel that drove sales of its paid products.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Announcement
&lt;/h2&gt;

&lt;p&gt;The layoffs became public on January 6 when Wathan responded to a community pull request that would have made Tailwind's documentation more accessible to AI language models. In closing the request, he disclosed the layoffs and explained the underlying business crisis.&lt;/p&gt;

&lt;p&gt;"The reality is that 75% of the people on our engineering team lost their jobs here yesterday because of the brutal impact AI has had on our business," Wathan wrote on GitHub PR #2388.&lt;/p&gt;

&lt;p&gt;He revealed that site traffic has dropped 40% since early 2023, while revenue has collapsed by approximately 80%—despite Tailwind CSS being "more popular than ever."&lt;/p&gt;

&lt;h2&gt;
  
  
  The Business Model Problem
&lt;/h2&gt;

&lt;p&gt;Tailwind CSS itself is free and open-source under the MIT license. The company generates revenue by selling complementary paid products:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tailwind UI&lt;/strong&gt;: Pre-built component templates and UI examples&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Catalyst&lt;/strong&gt;: An application UI kit
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tailwind Insiders&lt;/strong&gt;: A subscription program with early access to features&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The revenue model relied on a simple conversion funnel: developers visiting the free documentation would see promotions for these paid products, and a percentage would become paying customers.&lt;/p&gt;

&lt;p&gt;According to Wathan, this mechanism has been severely disrupted by AI coding assistants.&lt;/p&gt;

&lt;h2&gt;
  
  
  The AI Disruption
&lt;/h2&gt;

&lt;p&gt;Tools like Cursor, GitHub Copilot, Claude Code, and ChatGPT now allow developers to access Tailwind documentation content without visiting tailwindcss.com. When a developer asks an AI how to implement a Tailwind feature, the AI provides the answer directly—meaning the developer never sees the website where paid products are advertised.&lt;/p&gt;

&lt;p&gt;"Tailwind is growing faster than it ever has and is bigger than it ever has been, and our revenue is down close to 80%," Wathan explained. "Right now there's just no correlation between making Tailwind easier to use and making development of the framework more sustainable."&lt;/p&gt;

&lt;p&gt;The result is a paradox where increased usage through AI tools correlates with decreased revenue, inverting traditional software business economics.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Trigger: A Rejected Pull Request
&lt;/h2&gt;

&lt;p&gt;The disclosure came in response to a pull request from developer quantizor proposing to add an &lt;code&gt;/llms.txt&lt;/code&gt; endpoint—an emerging standard for serving documentation optimized for language model consumption. The PR would have concatenated all 185 Tailwind documentation files into a single text file, stripped of HTML and optimized for AI parsing.&lt;/p&gt;

&lt;p&gt;Wathan rejected the proposal, arguing that making documentation even more accessible to AI systems would accelerate the traffic decline and worsen the revenue situation.&lt;/p&gt;

&lt;p&gt;"And making it easier for LLMs to read our docs just means less traffic to our docs which means less people learning about our paid products and the business being even less sustainable," he wrote.&lt;/p&gt;

&lt;p&gt;Wathan added that he would like to implement the feature eventually, but needs to solve the monetization problem first: "I really want to figure out a way to offer LLM-optimized docs that don't make that situation even worse (again we literally had to lay off 75% of the team yesterday)."&lt;/p&gt;

&lt;h2&gt;
  
  
  Community Response: Sharply Divided
&lt;/h2&gt;

&lt;p&gt;The thread, which accumulated 95 comments before being locked, revealed sharp divisions in the developer community.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Support for Wathan's position:&lt;/strong&gt;&lt;br&gt;
His comment explaining the layoffs received over 1,000 positive reactions and 1,500 hearts, with many developers expressing sympathy for the difficult business situation and acknowledging the legitimacy of the crisis.&lt;/p&gt;

&lt;p&gt;"Adam has explained that to you so clearly, you can choose to listen or not," wrote one commenter. "I'd like Tailwind Labs to continue working on Tailwind, would you?"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Criticism of the decision:&lt;/strong&gt;&lt;br&gt;
Others argued that rejecting the PR was short-sighted and anti-open-source. The PR author's responses were heavily downvoted, receiving over 590 negative reactions on some comments.&lt;/p&gt;

&lt;p&gt;"In general I object to the spirit of closing this. It's very OSS unfriendly and would not meaningfully reduce traffic to the docs by humans that actually would buy the product," quantizor wrote.&lt;/p&gt;

&lt;p&gt;Some critics questioned whether the decision made business sense, arguing that AI tools already access documentation through scraping and that an official endpoint wouldn't meaningfully change traffic patterns.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Sponsorship Controversy
&lt;/h2&gt;

&lt;p&gt;The debate intensified when community members discovered that Tailwind's sponsorship program includes access to an "AGENTS.md" file containing guidance for optimizing LLM interactions with Tailwind.&lt;/p&gt;

&lt;p&gt;Some interpreted this as Tailwind monetizing LLM-friendly documentation while refusing to provide it freely, though Wathan disputed this characterization.&lt;/p&gt;

&lt;p&gt;"I don't see the AGENTS.md stuff we offer as part of the sponsorship program as anything similar to this at all — that's just a short markdown file with a bunch of my own personal opinions and what I consider best practices to nudge LLMs into writing their Tailwind stuff in a specific way. It's not the docs at all," he explained.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical Context: The llms.txt Debate
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;/llms.txt&lt;/code&gt; standard is an emerging convention, similar to &lt;code&gt;robots.txt&lt;/code&gt;, designed to provide AI-optimized documentation in a standardized format. However, its adoption remains unclear.&lt;/p&gt;

&lt;p&gt;John Mueller, a Senior Search Analyst at Google, stated in June 2025: "FWIW no AI system currently uses llms.txt."&lt;/p&gt;

&lt;p&gt;Major LLM providers including OpenAI, Google, and Anthropic have not officially committed to following the standard. However, these systems already access and cache documentation through web crawling, meaning the lack of an official llms.txt endpoint doesn't prevent AI access to Tailwind's docs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Major Companies Stand
&lt;/h2&gt;

&lt;p&gt;Several prominent companies heavily use Tailwind CSS in their products, according to usage statistics cited in the thread:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claude.ai (Anthropic)&lt;/li&gt;
&lt;li&gt;Vercel
&lt;/li&gt;
&lt;li&gt;Cloudflare&lt;/li&gt;
&lt;li&gt;X (formerly Twitter)&lt;/li&gt;
&lt;li&gt;Shopify&lt;/li&gt;
&lt;li&gt;Cursor&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The thread included criticism that these companies benefit from Tailwind without providing financial support through sponsorship or other means.&lt;/p&gt;

&lt;p&gt;"It's insane how tailwind is utilized on like, websites of all those big companies but ain't no one sponsoring or giving back anything," one commenter wrote, calling for corporate support, particularly from Vercel.&lt;/p&gt;

&lt;h2&gt;
  
  
  Broader Implications for Open Source
&lt;/h2&gt;

&lt;p&gt;The Tailwind crisis has sparked broader discussion about open-source sustainability in the AI era. Traditional open-source monetization strategies—including the "discovery through documentation" model—appear vulnerable to disruption by AI intermediation.&lt;/p&gt;

&lt;p&gt;Other documentation-dependent projects may face similar challenges, particularly those in the developer tools space where AI coding assistants are rapidly gaining adoption.&lt;/p&gt;

&lt;p&gt;Some community members called for systemic solutions, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Paywall systems for AI crawlers&lt;/strong&gt;: Cloudflare has announced plans for a "pay-per-crawl" product that could charge LLM companies for documentation access&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Legal frameworks&lt;/strong&gt;: Proposals for "GPL for AI" licenses that restrict AI training on documentation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Corporate sponsorship&lt;/strong&gt;: Pressure on companies using open-source tools to fund their development&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;New business models&lt;/strong&gt;: Moving away from documentation-based discovery toward direct enterprise relationships&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Wathan's Current Focus
&lt;/h2&gt;

&lt;p&gt;In his comments, Wathan emphasized that his immediate priority is business survival rather than community features.&lt;/p&gt;

&lt;p&gt;"Have more important things to do like figure out how to make enough money for the business to be sustainable right now," he wrote. "Every second I spend trying to do fun free things for the community like this is a second I'm not spending trying to turn the business around and make sure the people who are still here are getting their paychecks every month."&lt;/p&gt;

&lt;p&gt;He acknowledged the value of the proposed feature but said the company couldn't prioritize it: "Just don't have time to work on things that don't help us pay the bills right now, sorry. We may add this one day but closing for now."&lt;/p&gt;

&lt;p&gt;After the thread became heated, with some comments marked as violating GitHub's acceptable use policies, Wathan locked the discussion with a final message: "Going to lock this one as it's spiraling a bit. Appreciate the support from everyone ❤️ We'll figure it out!"&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next for Tailwind
&lt;/h2&gt;

&lt;p&gt;The company has not announced specific plans for addressing the revenue crisis. Potential paths forward could include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Implementing paywalls for AI crawler access if such systems become available&lt;/li&gt;
&lt;li&gt;Pivoting to enterprise licensing models&lt;/li&gt;
&lt;li&gt;Seeking venture capital or foundation support&lt;/li&gt;
&lt;li&gt;Finding ways to embed product promotion in AI-consumed documentation&lt;/li&gt;
&lt;li&gt;Restructuring the business to operate with a smaller team&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The framework itself remains open-source and available, though questions about long-term maintenance have arisen given the staffing reduction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Industry Response Pending
&lt;/h2&gt;

&lt;p&gt;As of publication, major AI companies including OpenAI, Anthropic, and Google have not commented on the situation or announced any programs to fund open-source projects whose documentation their models consume.&lt;/p&gt;

&lt;p&gt;The incident has reached the front page of Hacker News and is being discussed widely in developer communities, suggesting it may become a test case for how the industry handles open-source sustainability in the age of AI.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article is based on publicly available GitHub comments and community discussions.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sources:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub PR #2388: tailwindlabs/tailwindcss.com&lt;/li&gt;
&lt;li&gt;Adam Wathan's comments on GitHub (January 6-8, 2026)&lt;/li&gt;
&lt;li&gt;Hacker News discussions&lt;/li&gt;
&lt;li&gt;SEMrush analysis of llms.txt adoption&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>tailwindcss</category>
      <category>ai</category>
      <category>layoff</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Building Infrastructure for Handling Millions of Bitcoin UTXOs at Scale</title>
      <dc:creator>0xkniraj</dc:creator>
      <pubDate>Mon, 05 Jan 2026 08:21:25 +0000</pubDate>
      <link>https://dev.to/kniraj/building-infrastructure-for-handling-millions-of-bitcoin-utxos-at-scale-391g</link>
      <guid>https://dev.to/kniraj/building-infrastructure-for-handling-millions-of-bitcoin-utxos-at-scale-391g</guid>
      <description>&lt;h2&gt;
  
  
  The Challenge: Account Model vs UTXO Model
&lt;/h2&gt;

&lt;p&gt;If you've ever designed a custodian solution for Ethereum, you might have found it surprisingly straightforward. Creating wallets from mnemonics, managing deposits and withdrawals, and even implementing multisig solutions using Safe (onchain) or MPC/TSS (offchain) are relatively simple tasks. This ease stems from Ethereum's account model, which treats balances as fungible assets in individual accounts.&lt;/p&gt;

&lt;p&gt;Bitcoin, however, operates fundamentally differently due to its UTXO (Unspent Transaction Output) architecture. This creates unique challenges for custodians managing Bitcoin at scale.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the UTXO Model
&lt;/h2&gt;

&lt;p&gt;In Bitcoin's UTXO model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Every deposit requires a unique address&lt;/strong&gt; (locking script)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Money behaves like physical currency notes&lt;/strong&gt; rather than a simple account balance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UTXOs are atomic units&lt;/strong&gt; - when you spend one, you must spend it entirely&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Partial spending requires change&lt;/strong&gt; - similar to receiving change when paying with cash&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While Bitcoin is certainly fungible, the mechanics of how it works differ significantly from Ethereum. Think of UTXOs as individual checks: if you want to spend a check, you must spend it in full. To spend a partial amount, you write a new check back to yourself for the change.&lt;/p&gt;

&lt;p&gt;This creates a unique challenge for custodians: &lt;strong&gt;efficiently managing potentially millions of "checks" of varying amounts&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Scale Problem: Managing Millions of UTXOs
&lt;/h2&gt;

&lt;p&gt;Imagine managing &lt;strong&gt;millions of UTXOs&lt;/strong&gt; across thousands of user deposits, processing thousands of withdrawals daily. When a user requests a withdrawal of 0.1 BTC, how do you efficiently select which UTXOs to spend?&lt;/p&gt;

&lt;p&gt;This isn't just a theoretical problem—it's the core challenge for exchanges, bridges, and payment processors handling Bitcoin at scale.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Standard Algorithms Fail at Scale
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Approach 1: Branch and Bound (Bitcoin Core's Method)
&lt;/h3&gt;

&lt;p&gt;Bitcoin Core uses the Branch and Bound algorithm for optimal UTXO selection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;branch_and_bound&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;utxos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target_amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fee_rate&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Recursively search for exact match combinations
&lt;/span&gt;    &lt;span class="c1"&gt;# Time complexity: O(2^n) with pruning
&lt;/span&gt;    &lt;span class="c1"&gt;# Works well for wallet-sized UTXO sets (hundreds to thousands)
&lt;/span&gt;    &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why this fails at scale:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bitcoin Core wallets: 100-1,000 UTXOs&lt;/li&gt;
&lt;li&gt;Custodian platform: 10,000,000+ UTXOs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;At millions of UTXOs&lt;/strong&gt;: O(2^n) becomes computationally impossible&lt;/li&gt;
&lt;li&gt;Even with aggressive pruning and timeouts, selection would take seconds or minutes&lt;/li&gt;
&lt;li&gt;Would create a denial-of-service vulnerability under load&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The fundamental insight&lt;/strong&gt;: We need O(log n) or O(1) selection, not O(2^n).&lt;/p&gt;

&lt;h3&gt;
  
  
  Approach 2: The Greedy Algorithm
&lt;/h3&gt;

&lt;p&gt;The simplest approach is to find the largest UTXO and use it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;withdrawal_amount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt; &lt;span class="n"&gt;BTC&lt;/span&gt;
&lt;span class="n"&gt;selected_utxo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;utxos&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.,&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt; &lt;span class="n"&gt;BTC&lt;/span&gt;
&lt;span class="n"&gt;change&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.4&lt;/span&gt; &lt;span class="n"&gt;BTC&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Problems:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creates severe UTXO fragmentation over time&lt;/li&gt;
&lt;li&gt;Eventually, you'll have many small UTXOs&lt;/li&gt;
&lt;li&gt;Large withdrawals become difficult as UTXOs get smaller&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Approach 3: Binary Search on Sorted UTXOs
&lt;/h3&gt;

&lt;p&gt;Sort UTXOs and use binary search to find an optimal match:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;sorted_utxos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;utxos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ascending&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;selected_utxo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;binary_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sorted_utxos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;withdrawal_amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Problems:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Works reasonably well for small withdrawals&lt;/li&gt;
&lt;li&gt;Fails when the requested amount exceeds the largest UTXO&lt;/li&gt;
&lt;li&gt;Example: User requests 5 BTC, but largest UTXO is 2 BTC&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Approach 4: Consolidation (Combining Smallest UTXOs)
&lt;/h3&gt;

&lt;p&gt;Combine multiple small UTXOs to fulfill the withdrawal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;selected_utxos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;utxo&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;utxos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ascending&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;selected_utxos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;utxo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;utxo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;withdrawal_amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Problems:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More inputs = larger transaction size = higher fees&lt;/li&gt;
&lt;li&gt;Can become prohibitively expensive&lt;/li&gt;
&lt;li&gt;Doesn't scale practically for regular operations&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Solution: bucket-Based Cascading Selection
&lt;/h2&gt;

&lt;p&gt;None of the approaches above work efficiently at scale. The solution combines the cascading greedy approach with strategic consolidation, mimicking how physical currency denominations work.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Physical Currency Works
&lt;/h3&gt;

&lt;p&gt;When paying $50 in cash, you might use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;5×$10 notes&lt;/li&gt;
&lt;li&gt;1×$50 note&lt;/li&gt;
&lt;li&gt;1×$100 note and receive $50 change&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The choice depends on what denominations you have available. We can apply this same principle programmatically to Bitcoin UTXOs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation: Gaussian Distribution Buckets
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Define UTXO Tiers
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;TIER_HIERARCHY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dust&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;min&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.0001&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.001&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;   &lt;span class="c1"&gt;# 10k-100k sats
&lt;/span&gt;    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tiny&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;min&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.001&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.005&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;   &lt;span class="c1"&gt;# 100k-500k sats
&lt;/span&gt;    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;small&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;min&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.005&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.01&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;    &lt;span class="c1"&gt;# 500k-1M sats
&lt;/span&gt;    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;medium&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;min&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.01&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.02&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;    &lt;span class="c1"&gt;# 1M-2M sats
&lt;/span&gt;    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;large&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;min&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.02&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.05&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;     &lt;span class="c1"&gt;# 2M-5M sats
&lt;/span&gt;    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;xlarge&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;min&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.05&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;     &lt;span class="c1"&gt;# 5M-20M sats
&lt;/span&gt;    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;whale&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;min&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;    &lt;span class="c1"&gt;# 20M+ sats
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Tier ranges are not arbitrary&lt;/strong&gt; - they're derived from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Historical withdrawal distribution analysis&lt;/li&gt;
&lt;li&gt;Fee optimization modeling&lt;/li&gt;
&lt;li&gt;Consolidation opportunity windows&lt;/li&gt;
&lt;li&gt;Minimum relay fee and dust thresholds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why this works at scale:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reduces search space from millions to constant T tiers&lt;/li&gt;
&lt;li&gt;Each tier independently manageable&lt;/li&gt;
&lt;li&gt;Enables efficient database indexing&lt;/li&gt;
&lt;li&gt;Natural distribution boundaries&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 2: Tier Cascading Strategy
&lt;/h3&gt;

&lt;p&gt;Here's the critical difference from naive approaches—we don't just pick a tier, we **cascade through tiers intelligently&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;find_utxos_for_withdrawal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Tier cascading: Start at preferred tier, cascade UP to larger tiers
    Key insight: Cascading UP prevents fragmentation
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="c1"&gt;# Determine which tier this amount naturally belongs to
&lt;/span&gt;    &lt;span class="n"&gt;preferred_tier&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;determine_tier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Start from preferred tier and go UP through larger tiers
&lt;/span&gt;    &lt;span class="n"&gt;tier_index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TIER_HIERARCHY&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;preferred_tier&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tier_index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TIER_HIERARCHY&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
        &lt;span class="n"&gt;current_tier&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TIER_HIERARCHY&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="c1"&gt;# Check if tier has sufficient total balance
&lt;/span&gt;        &lt;span class="n"&gt;tier_balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_tier_balance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current_tier&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;tier_balance&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# Try to select UTXOs from this tier
&lt;/span&gt;            &lt;span class="n"&gt;utxos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;select_utxos_in_tier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current_tier&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;utxos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;utxos&lt;/span&gt;
            &lt;span class="c1"&gt;# If selection fails, continue to next tier
&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;InsufficientFundsError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;No tier has sufficient balance&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why cascade UP, not DOWN:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Example: 0.03 BTC withdrawal

Cascading DOWN (naive approach):
medium (0.01-0.05) → small (0.005-0.01) → tiny → dust
Result: Many small UTXOs = fragmentation + high fees

Cascading UP (our approach):
medium (0.01-0.05) → large (0.05-0.1) → xlarge
Result: Fewer larger UTXOs = consolidation + low fees
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: UTXO Selection Within Tier
&lt;/h3&gt;

&lt;p&gt;Once we've selected a tier, we need to pick specific UTXOs. This is where the knapsack problem comes in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;select_utxos_in_tier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tier&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_inputs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Within a tier, select the smallest set of UTXOs that covers the amount.
    This is a bounded knapsack approximation.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="c1"&gt;# Get available UTXOs in tier, sorted by amount
&lt;/span&gt;    &lt;span class="n"&gt;available_utxos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_available_utxos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tier&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sort_by&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;amount_asc&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;limit_by&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;max_inputs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Greedy knapsack: Select smallest UTXOs first
&lt;/span&gt;    &lt;span class="n"&gt;selected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;utxo&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;available_utxos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    
        &lt;span class="n"&gt;selected&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;utxo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;utxo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# Atomically reserve these UTXOs in database
&lt;/span&gt;            &lt;span class="nf"&gt;reserve_utxos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;selected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;selected&lt;/span&gt;

    &lt;span class="c1"&gt;# Tier doesn't have enough UTXOs
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why smallest-first selection?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Minimizes change output size&lt;/li&gt;
&lt;li&gt;Naturally consolidates small UTXOs&lt;/li&gt;
&lt;li&gt;Cleans up tier fragmentation over time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note on implementation:&lt;/strong&gt; In production, this is implemented entirely within PostgreSQL using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;SELECT FOR UPDATE SKIP LOCKED&lt;/code&gt; for concurrency-safe selection&lt;/li&gt;
&lt;li&gt;Atomic transactions for reservation&lt;/li&gt;
&lt;li&gt;Database-level constraints for consistency&lt;/li&gt;
&lt;li&gt;Sub-millisecond selection performance with proper indexing&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 4: Fee-Aware Tier Selection
&lt;/h3&gt;

&lt;p&gt;At scale, transaction fees become a significant cost center. The tier selection should factor in current fee rates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;find_utxos_with_fee_awareness&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fee_rate_sats_per_vb&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Adjust tier selection based on current fee market conditions
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;preferred_tier&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;determine_tier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;tier_index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TIER_HIERARCHY&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;preferred_tier&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# During high-fee periods, start from a higher tier
&lt;/span&gt;    &lt;span class="c1"&gt;# This reduces input count = lower fees
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;fee_rate_sats_per_vb&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# High fee period
&lt;/span&gt;        &lt;span class="c1"&gt;# Skip to next larger tier to minimize inputs
&lt;/span&gt;        &lt;span class="n"&gt;tier_index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tier_index&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TIER_HIERARCHY&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Rest of cascading logic...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Real-world impact:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Scenario: 0.03 BTC withdrawal during 100 sat/vB fee spike

Option A: 3 UTXOs from medium tier
Fee: 3 inputs × 68 vB × 100 sat/vB = 20,400 sats ($20.40)

Option B: 1 UTXO from large tier (fee-aware selection)
Fee: 1 input × 68 vB × 100 sat/vB = 6,800 sats ($6.80)

Savings: $13.60 per withdrawal during peak hours
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why This Approach Works at Scale
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Computational Complexity
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;Time Complexity&lt;/th&gt;
&lt;th&gt;Scale Limit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Branch and Bound&lt;/td&gt;
&lt;td&gt;O(2^n)&lt;/td&gt;
&lt;td&gt;&amp;lt; 1,000 UTXOs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Binary Search&lt;/td&gt;
&lt;td&gt;O(log n)&lt;/td&gt;
&lt;td&gt;Fails on large amounts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tier Cascading&lt;/td&gt;
&lt;td&gt;O(tiers) + O(k*log(k))&lt;/td&gt;
&lt;td&gt;Millions of UTXOs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;n = total UTXOs&lt;/li&gt;
&lt;li&gt;tiers = number of tiers (constant: 7)&lt;/li&gt;
&lt;li&gt;k = UTXOs selected per transaction (typically 2-3)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Our approach: O(7) + O(3*log(3)) = O(1) effectively&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Natural Consolidation Mechanics
&lt;/h3&gt;

&lt;p&gt;The smallest-first selection within tiers creates &lt;strong&gt;automatic consolidation&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Example:

Medium tier has 1000 UTXOs
Withdrawal: 0.03 BTC
Selection: Uses 3 smallest UTXOs (0.01, 0.011, 0.012)
Result: 1000 → 997 UTXOs, naturally cleans up small values
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;This is self-healing&lt;/strong&gt; - no manual consolidation jobs required during normal operations. Tiers gets replenished by new deposits.&lt;/p&gt;

&lt;h3&gt;
  
  
  Gaussian Distribution Alignment
&lt;/h3&gt;

&lt;p&gt;Real-world withdrawal patterns follow a log-normal distribution (similar to Gaussian):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Distribution of withdrawals (from production data):
- 10th percentile: 0.002 BTC (tiny tier)
- 50th percentile: 0.02 BTC (medium tier)  ← most common
- 90th percentile: 0.15 BTC (xlarge tier)
- 99th percentile: 0.5 BTC (whale tier)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By sizing tiers around this distribution, we optimize for the common case while handling edge cases efficiently.&lt;/p&gt;




&lt;h2&gt;
  
  
  Operational Considerations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Tier Health Monitoring
&lt;/h3&gt;

&lt;p&gt;You need visibility into tier distribution to maintain system health:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;monitor_tier_health&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Track tier metrics for operational alerting
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;tier&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;TIER_HIERARCHY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;metrics&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utxo_count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;count_utxos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tier&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;total_balance&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;sum_balance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tier&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;avg_utxo_size&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;average_size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tier&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;daily_utilization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;withdrawals_from_tier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tier&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;# Alert on depletion risk
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;metrics&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utxo_count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Tier &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;tier&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; depleting: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;metrics&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;utxo_count&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; UTXOs left&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Alert on imbalance
&lt;/span&gt;        &lt;span class="n"&gt;runway_days&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;metrics&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;total_balance&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;metrics&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;daily_utilization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;runway_days&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Tier &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;tier&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; has &amp;lt;2 days runway&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Strategic Rebalancing
&lt;/h3&gt;

&lt;p&gt;While the system is self-healing under normal operation, you need proactive rebalancing during quiet periods:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;rebalance_tiers_during_low_fees&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Run during low-fee periods (typically 2-6 AM UTC, weekends)
    Consolidate dust, split whales, rebalance distribution
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;current_fee_rate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_current_fee_rate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# Only rebalance when fees are low
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;current_fee_rate&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# sats/vB
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt;

    &lt;span class="c1"&gt;# Strategy 1: Consolidate dust and tiny tiers
&lt;/span&gt;    &lt;span class="n"&gt;dust_utxos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_tier_utxos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dust&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dust_utxos&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;consolidate_into_tier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dust_utxos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target_tier&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;small&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Strategy 2: Ensure minimum UTXO count per tier
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;tier&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;TIER_HIERARCHY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;count_utxos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tier&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;create_utxos_for_tier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tier&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target_count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;source_tier&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;whale&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;When to rebalance:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Daily during off-peak hours&lt;/li&gt;
&lt;li&gt;After major withdrawal spikes&lt;/li&gt;
&lt;li&gt;When tier depletion alerts trigger&lt;/li&gt;
&lt;li&gt;During extended low-fee periods (accumulate savings)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Database Implementation Notes
&lt;/h3&gt;

&lt;p&gt;The algorithm is implemented entirely in PostgreSQL for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Atomicity&lt;/strong&gt;: &lt;code&gt;BEGIN/COMMIT/ROLLBACK&lt;/code&gt; blocks ensure consistency&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Concurrency&lt;/strong&gt;: &lt;code&gt;SELECT FOR UPDATE SKIP LOCKED&lt;/code&gt; handles concurrent withdrawals&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: Indexed queries on &lt;code&gt;(tier, state, amount)&lt;/code&gt; enable sub-millisecond selection&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reliability&lt;/strong&gt;: ACID guarantees prevent double-spending&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This enables the database to instantly find the smallest available UTXOs in any tier.&lt;/p&gt;




&lt;h2&gt;
  
  
  Real-World Performance
&lt;/h2&gt;

&lt;p&gt;In production environments processing thousands of withdrawals daily:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Average inputs per transaction&lt;/strong&gt;: 2.1 UTXOs (down from 4.5 with naive approaches)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fee reduction&lt;/strong&gt;: 55% vs. simple consolidation approach&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UTXO selection latency&lt;/strong&gt;: &amp;lt;5ms (database-level selection)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tier cascade events&lt;/strong&gt;: &amp;lt;2% of withdrawals (most succeed on preferred tier)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Natural consolidation rate&lt;/strong&gt;: thousands of UTXOs/day consolidated without manual intervention&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;System uptime during rebalancing&lt;/strong&gt;: 100% (non-blocking background process)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cost Impact at Scale:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Platform: 10,000 withdrawals/day
Average fee savings: $2.50/withdrawal
Monthly savings: $750,000
Annual savings: $9,000,000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Limitations and Trade-offs
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What This Approach Sacrifices
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Theoretical Optimality&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Branch and Bound finds the &lt;em&gt;perfect&lt;/em&gt; UTXO combination&lt;/li&gt;
&lt;li&gt;Tier cascading finds a &lt;em&gt;good enough&lt;/em&gt; combination&lt;/li&gt;
&lt;li&gt;Trade-off: ~5% more change outputs for 10,000x faster selection&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Privacy Considerations&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Selecting multiple UTXOs from same tier can link addresses&lt;/li&gt;
&lt;li&gt;Common input ownership heuristic applies&lt;/li&gt;
&lt;li&gt;Mitigation: Use mixing services or CoinJoin for privacy-critical applications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Minimum Withdrawal Threshold&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dust tier prevents withdrawals &amp;lt; 50,000 sats (~$50)&lt;/li&gt;
&lt;li&gt;Necessary to avoid economically unspendable UTXOs&lt;/li&gt;
&lt;li&gt;Alternative: Lightning Network for micro-withdrawals&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  When This Approach May Not Fit
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Not suitable for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Personal wallets (use Bitcoin Core's Branch and Bound)&lt;/li&gt;
&lt;li&gt;Privacy-focused applications (use Wasabi/Samourai algorithms)&lt;/li&gt;
&lt;li&gt;&amp;lt; 10,000 UTXOs (simpler approaches work fine)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Ideal for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Exchanges and payment processors&lt;/li&gt;
&lt;li&gt;Cross-chain bridges&lt;/li&gt;
&lt;li&gt;Custodial services at scale&lt;/li&gt;
&lt;li&gt;Any platform managing 1M+ UTXOs&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Building a Bitcoin custodian at scale requires fundamentally different thinking than Ethereum-based solutions. The UTXO model, while more complex, can be efficiently managed using tier-based cascading strategies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key takeaways:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Standard algorithms don't scale&lt;/strong&gt; - Branch and Bound is O(2^n), impossible at millions of UTXOs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tier cascading UP&lt;/strong&gt; prevents fragmentation while maintaining availability&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fee-aware selection&lt;/strong&gt; can save millions annually at scale&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Natural consolidation&lt;/strong&gt; keeps the system healthy through smallest-first selection&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database-level implementation&lt;/strong&gt; provides atomicity and concurrency control&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Operational monitoring&lt;/strong&gt; is critical - track tier health and rebalance proactively&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By treating Bitcoin UTXOs like physical currency denominations and selecting them through intelligent tier traversal, custodians can process millions of transactions efficiently while minimizing fees and maintaining system health.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The real innovation isn't just the algorithm—it's designing a system that scales to millions of UTXOs while remaining operationally manageable.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>bitcoin</category>
      <category>infra</category>
      <category>backend</category>
      <category>custody</category>
    </item>
    <item>
      <title>Building Infrastructure for Handling Millions of Bitcoin UTXOs at Scale</title>
      <dc:creator>0xkniraj</dc:creator>
      <pubDate>Mon, 05 Jan 2026 08:12:18 +0000</pubDate>
      <link>https://dev.to/kniraj/building-infrastructure-for-handling-millions-of-bitcoin-utxos-at-scale-4i4g</link>
      <guid>https://dev.to/kniraj/building-infrastructure-for-handling-millions-of-bitcoin-utxos-at-scale-4i4g</guid>
      <description>&lt;h2&gt;
  
  
  The Challenge: Account Model vs UTXO Model
&lt;/h2&gt;

&lt;p&gt;If you've ever designed a custodian solution for Ethereum, you might have found it surprisingly straightforward. Creating wallets from mnemonics, managing deposits and withdrawals, and even implementing multisig solutions using Safe (onchain) or MPC/TSS (offchain) are relatively simple tasks. This ease stems from Ethereum's account model, which treats balances as fungible assets in individual accounts.&lt;/p&gt;

&lt;p&gt;Bitcoin, however, operates fundamentally differently due to its UTXO (Unspent Transaction Output) architecture. This creates unique challenges for custodians managing Bitcoin at scale.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the UTXO Model
&lt;/h2&gt;

&lt;p&gt;In Bitcoin's UTXO model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Every deposit requires a unique address&lt;/strong&gt; (locking script)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Money behaves like physical currency notes&lt;/strong&gt; rather than a simple account balance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UTXOs are atomic units&lt;/strong&gt; - when you spend one, you must spend it entirely&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Partial spending requires change&lt;/strong&gt; - similar to receiving change when paying with cash&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While Bitcoin is certainly fungible, the mechanics of how it works differ significantly from Ethereum. Think of UTXOs as individual checks: if you want to spend a check, you must spend it in full. To spend a partial amount, you write a new check back to yourself for the change.&lt;/p&gt;

&lt;p&gt;This creates a unique challenge for custodians: &lt;strong&gt;efficiently managing potentially millions of "checks" of varying amounts&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Scale Problem: Managing Millions of UTXOs
&lt;/h2&gt;

&lt;p&gt;Imagine managing &lt;strong&gt;millions of UTXOs&lt;/strong&gt; across thousands of user deposits, processing thousands of withdrawals daily. When a user requests a withdrawal of 0.1 BTC, how do you efficiently select which UTXOs to spend?&lt;/p&gt;

&lt;p&gt;This isn't just a theoretical problem—it's the core challenge for exchanges, bridges, and payment processors handling Bitcoin at scale.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Standard Algorithms Fail at Scale
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Approach 1: Branch and Bound (Bitcoin Core's Method)
&lt;/h3&gt;

&lt;p&gt;Bitcoin Core uses the Branch and Bound algorithm for optimal UTXO selection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;branch_and_bound&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;utxos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target_amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fee_rate&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Recursively search for exact match combinations
&lt;/span&gt;    &lt;span class="c1"&gt;# Time complexity: O(2^n) with pruning
&lt;/span&gt;    &lt;span class="c1"&gt;# Works well for wallet-sized UTXO sets (hundreds to thousands)
&lt;/span&gt;    &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why this fails at scale:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bitcoin Core wallets: 100-1,000 UTXOs&lt;/li&gt;
&lt;li&gt;Custodian platform: 10,000,000+ UTXOs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;At millions of UTXOs&lt;/strong&gt;: O(2^n) becomes computationally impossible&lt;/li&gt;
&lt;li&gt;Even with aggressive pruning and timeouts, selection would take seconds or minutes&lt;/li&gt;
&lt;li&gt;Would create a denial-of-service vulnerability under load&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The fundamental insight&lt;/strong&gt;: We need O(log n) or O(1) selection, not O(2^n).&lt;/p&gt;

&lt;h3&gt;
  
  
  Approach 2: The Greedy Algorithm
&lt;/h3&gt;

&lt;p&gt;The simplest approach is to find the largest UTXO and use it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;withdrawal_amount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt; &lt;span class="n"&gt;BTC&lt;/span&gt;
&lt;span class="n"&gt;selected_utxo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;utxos&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.,&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt; &lt;span class="n"&gt;BTC&lt;/span&gt;
&lt;span class="n"&gt;change&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.4&lt;/span&gt; &lt;span class="n"&gt;BTC&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Problems:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creates severe UTXO fragmentation over time&lt;/li&gt;
&lt;li&gt;Eventually, you'll have many small UTXOs&lt;/li&gt;
&lt;li&gt;Large withdrawals become difficult as UTXOs get smaller&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Approach 3: Binary Search on Sorted UTXOs
&lt;/h3&gt;

&lt;p&gt;Sort UTXOs and use binary search to find an optimal match:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;sorted_utxos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;utxos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ascending&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;selected_utxo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;binary_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sorted_utxos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;withdrawal_amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Problems:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Works reasonably well for small withdrawals&lt;/li&gt;
&lt;li&gt;Fails when the requested amount exceeds the largest UTXO&lt;/li&gt;
&lt;li&gt;Example: User requests 5 BTC, but largest UTXO is 2 BTC&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Approach 4: Consolidation (Combining Smallest UTXOs)
&lt;/h3&gt;

&lt;p&gt;Combine multiple small UTXOs to fulfill the withdrawal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;selected_utxos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;utxo&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;utxos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ascending&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;selected_utxos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;utxo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;utxo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;withdrawal_amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Problems:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More inputs = larger transaction size = higher fees&lt;/li&gt;
&lt;li&gt;Can become prohibitively expensive&lt;/li&gt;
&lt;li&gt;Doesn't scale practically for regular operations&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Solution: bucket-Based Cascading Selection
&lt;/h2&gt;

&lt;p&gt;None of the approaches above work efficiently at scale. The solution combines the cascading greedy approach with strategic consolidation, mimicking how physical currency denominations work.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Physical Currency Works
&lt;/h3&gt;

&lt;p&gt;When paying $50 in cash, you might use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;5×$10 notes&lt;/li&gt;
&lt;li&gt;1×$50 note&lt;/li&gt;
&lt;li&gt;1×$100 note and receive $50 change&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The choice depends on what denominations you have available. We can apply this same principle programmatically to Bitcoin UTXOs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation: Gaussian Distribution Buckets
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Define UTXO Tiers
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;TIER_HIERARCHY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dust&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;min&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.0001&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.001&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;   &lt;span class="c1"&gt;# 10k-100k sats
&lt;/span&gt;    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tiny&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;min&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.001&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.005&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;   &lt;span class="c1"&gt;# 100k-500k sats
&lt;/span&gt;    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;small&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;min&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.005&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.01&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;    &lt;span class="c1"&gt;# 500k-1M sats
&lt;/span&gt;    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;medium&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;min&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.01&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.02&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;    &lt;span class="c1"&gt;# 1M-2M sats
&lt;/span&gt;    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;large&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;min&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.02&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.05&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;     &lt;span class="c1"&gt;# 2M-5M sats
&lt;/span&gt;    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;xlarge&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;min&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.05&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;     &lt;span class="c1"&gt;# 5M-20M sats
&lt;/span&gt;    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;whale&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;min&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;    &lt;span class="c1"&gt;# 20M+ sats
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Tier ranges are not arbitrary&lt;/strong&gt; - they're derived from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Historical withdrawal distribution analysis&lt;/li&gt;
&lt;li&gt;Fee optimization modeling&lt;/li&gt;
&lt;li&gt;Consolidation opportunity windows&lt;/li&gt;
&lt;li&gt;Minimum relay fee and dust thresholds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why this works at scale:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reduces search space from millions to constant T tiers&lt;/li&gt;
&lt;li&gt;Each tier independently manageable&lt;/li&gt;
&lt;li&gt;Enables efficient database indexing&lt;/li&gt;
&lt;li&gt;Natural distribution boundaries&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 2: Tier Cascading Strategy
&lt;/h3&gt;

&lt;p&gt;Here's the critical difference from naive approaches—we don't just pick a tier, we **cascade through tiers intelligently&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;find_utxos_for_withdrawal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Tier cascading: Start at preferred tier, cascade UP to larger tiers
    Key insight: Cascading UP prevents fragmentation
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="c1"&gt;# Determine which tier this amount naturally belongs to
&lt;/span&gt;    &lt;span class="n"&gt;preferred_tier&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;determine_tier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Start from preferred tier and go UP through larger tiers
&lt;/span&gt;    &lt;span class="n"&gt;tier_index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TIER_HIERARCHY&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;preferred_tier&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tier_index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TIER_HIERARCHY&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
        &lt;span class="n"&gt;current_tier&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TIER_HIERARCHY&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="c1"&gt;# Check if tier has sufficient total balance
&lt;/span&gt;        &lt;span class="n"&gt;tier_balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_tier_balance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current_tier&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;tier_balance&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# Try to select UTXOs from this tier
&lt;/span&gt;            &lt;span class="n"&gt;utxos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;select_utxos_in_tier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current_tier&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;utxos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;utxos&lt;/span&gt;
            &lt;span class="c1"&gt;# If selection fails, continue to next tier
&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;InsufficientFundsError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;No tier has sufficient balance&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why cascade UP, not DOWN:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Example: 0.03 BTC withdrawal

Cascading DOWN (naive approach):
medium (0.01-0.05) → small (0.005-0.01) → tiny → dust
Result: Many small UTXOs = fragmentation + high fees

Cascading UP (our approach):
medium (0.01-0.05) → large (0.05-0.1) → xlarge
Result: Fewer larger UTXOs = consolidation + low fees
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: UTXO Selection Within Tier
&lt;/h3&gt;

&lt;p&gt;Once we've selected a tier, we need to pick specific UTXOs. This is where the knapsack problem comes in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;select_utxos_in_tier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tier&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_inputs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Within a tier, select the smallest set of UTXOs that covers the amount.
    This is a bounded knapsack approximation.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="c1"&gt;# Get available UTXOs in tier, sorted by amount
&lt;/span&gt;    &lt;span class="n"&gt;available_utxos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_available_utxos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tier&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sort_by&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;amount_asc&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;limit_by&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;max_inputs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Greedy knapsack: Select smallest UTXOs first
&lt;/span&gt;    &lt;span class="n"&gt;selected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;utxo&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;available_utxos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    
        &lt;span class="n"&gt;selected&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;utxo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;utxo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# Atomically reserve these UTXOs in database
&lt;/span&gt;            &lt;span class="nf"&gt;reserve_utxos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;selected&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;selected&lt;/span&gt;

    &lt;span class="c1"&gt;# Tier doesn't have enough UTXOs
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why smallest-first selection?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Minimizes change output size&lt;/li&gt;
&lt;li&gt;Naturally consolidates small UTXOs&lt;/li&gt;
&lt;li&gt;Cleans up tier fragmentation over time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note on implementation:&lt;/strong&gt; In production, this is implemented entirely within PostgreSQL using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;SELECT FOR UPDATE SKIP LOCKED&lt;/code&gt; for concurrency-safe selection&lt;/li&gt;
&lt;li&gt;Atomic transactions for reservation&lt;/li&gt;
&lt;li&gt;Database-level constraints for consistency&lt;/li&gt;
&lt;li&gt;Sub-millisecond selection performance with proper indexing&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 4: Fee-Aware Tier Selection
&lt;/h3&gt;

&lt;p&gt;At scale, transaction fees become a significant cost center. The tier selection should factor in current fee rates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;find_utxos_with_fee_awareness&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fee_rate_sats_per_vb&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Adjust tier selection based on current fee market conditions
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;preferred_tier&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;determine_tier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;tier_index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TIER_HIERARCHY&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;preferred_tier&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# During high-fee periods, start from a higher tier
&lt;/span&gt;    &lt;span class="c1"&gt;# This reduces input count = lower fees
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;fee_rate_sats_per_vb&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# High fee period
&lt;/span&gt;        &lt;span class="c1"&gt;# Skip to next larger tier to minimize inputs
&lt;/span&gt;        &lt;span class="n"&gt;tier_index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tier_index&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TIER_HIERARCHY&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Rest of cascading logic...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Real-world impact:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Scenario: 0.03 BTC withdrawal during 100 sat/vB fee spike

Option A: 3 UTXOs from medium tier
Fee: 3 inputs × 68 vB × 100 sat/vB = 20,400 sats ($20.40)

Option B: 1 UTXO from large tier (fee-aware selection)
Fee: 1 input × 68 vB × 100 sat/vB = 6,800 sats ($6.80)

Savings: $13.60 per withdrawal during peak hours
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why This Approach Works at Scale
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Computational Complexity
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;Time Complexity&lt;/th&gt;
&lt;th&gt;Scale Limit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Branch and Bound&lt;/td&gt;
&lt;td&gt;O(2^n)&lt;/td&gt;
&lt;td&gt;&amp;lt; 1,000 UTXOs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Binary Search&lt;/td&gt;
&lt;td&gt;O(log n)&lt;/td&gt;
&lt;td&gt;Fails on large amounts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tier Cascading&lt;/td&gt;
&lt;td&gt;O(tiers) + O(k*log(k))&lt;/td&gt;
&lt;td&gt;Millions of UTXOs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;n = total UTXOs&lt;/li&gt;
&lt;li&gt;tiers = number of tiers (constant: 7)&lt;/li&gt;
&lt;li&gt;k = UTXOs selected per transaction (typically 2-3)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Our approach: O(7) + O(3*log(3)) = O(1) effectively&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Natural Consolidation Mechanics
&lt;/h3&gt;

&lt;p&gt;The smallest-first selection within tiers creates &lt;strong&gt;automatic consolidation&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Example:

Medium tier has 1000 UTXOs
Withdrawal: 0.03 BTC
Selection: Uses 3 smallest UTXOs (0.01, 0.011, 0.012)
Result: 1000 → 997 UTXOs, naturally cleans up small values
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;This is self-healing&lt;/strong&gt; - no manual consolidation jobs required during normal operations. Tiers gets replenished by new deposits.&lt;/p&gt;

&lt;h3&gt;
  
  
  Gaussian Distribution Alignment
&lt;/h3&gt;

&lt;p&gt;Real-world withdrawal patterns follow a log-normal distribution (similar to Gaussian):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Distribution of withdrawals (from production data):
- 10th percentile: 0.002 BTC (tiny tier)
- 50th percentile: 0.02 BTC (medium tier)  ← most common
- 90th percentile: 0.15 BTC (xlarge tier)
- 99th percentile: 0.5 BTC (whale tier)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By sizing tiers around this distribution, we optimize for the common case while handling edge cases efficiently.&lt;/p&gt;




&lt;h2&gt;
  
  
  Operational Considerations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Tier Health Monitoring
&lt;/h3&gt;

&lt;p&gt;You need visibility into tier distribution to maintain system health:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;monitor_tier_health&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Track tier metrics for operational alerting
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;tier&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;TIER_HIERARCHY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;metrics&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utxo_count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;count_utxos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tier&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;total_balance&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;sum_balance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tier&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;avg_utxo_size&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;average_size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tier&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;daily_utilization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;withdrawals_from_tier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tier&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;# Alert on depletion risk
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;metrics&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;utxo_count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Tier &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;tier&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; depleting: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;metrics&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;utxo_count&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; UTXOs left&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Alert on imbalance
&lt;/span&gt;        &lt;span class="n"&gt;runway_days&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;metrics&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;total_balance&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;metrics&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;daily_utilization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;runway_days&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Tier &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;tier&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; has &amp;lt;2 days runway&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Strategic Rebalancing
&lt;/h3&gt;

&lt;p&gt;While the system is self-healing under normal operation, you need proactive rebalancing during quiet periods:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;rebalance_tiers_during_low_fees&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Run during low-fee periods (typically 2-6 AM UTC, weekends)
    Consolidate dust, split whales, rebalance distribution
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;current_fee_rate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_current_fee_rate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# Only rebalance when fees are low
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;current_fee_rate&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# sats/vB
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt;

    &lt;span class="c1"&gt;# Strategy 1: Consolidate dust and tiny tiers
&lt;/span&gt;    &lt;span class="n"&gt;dust_utxos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_tier_utxos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dust&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dust_utxos&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;consolidate_into_tier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dust_utxos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target_tier&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;small&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Strategy 2: Ensure minimum UTXO count per tier
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;tier&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;TIER_HIERARCHY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;count_utxos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tier&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;create_utxos_for_tier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tier&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target_count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;source_tier&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;whale&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;When to rebalance:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Daily during off-peak hours&lt;/li&gt;
&lt;li&gt;After major withdrawal spikes&lt;/li&gt;
&lt;li&gt;When tier depletion alerts trigger&lt;/li&gt;
&lt;li&gt;During extended low-fee periods (accumulate savings)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Database Implementation Notes
&lt;/h3&gt;

&lt;p&gt;The algorithm is implemented entirely in PostgreSQL for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Atomicity&lt;/strong&gt;: &lt;code&gt;BEGIN/COMMIT/ROLLBACK&lt;/code&gt; blocks ensure consistency&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Concurrency&lt;/strong&gt;: &lt;code&gt;SELECT FOR UPDATE SKIP LOCKED&lt;/code&gt; handles concurrent withdrawals&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: Indexed queries on &lt;code&gt;(tier, state, amount)&lt;/code&gt; enable sub-millisecond selection&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reliability&lt;/strong&gt;: ACID guarantees prevent double-spending&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This enables the database to instantly find the smallest available UTXOs in any tier.&lt;/p&gt;




&lt;h2&gt;
  
  
  Real-World Performance
&lt;/h2&gt;

&lt;p&gt;In production environments processing thousands of withdrawals daily:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Average inputs per transaction&lt;/strong&gt;: 2.1 UTXOs (down from 4.5 with naive approaches)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fee reduction&lt;/strong&gt;: 55% vs. simple consolidation approach&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UTXO selection latency&lt;/strong&gt;: &amp;lt;5ms (database-level selection)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tier cascade events&lt;/strong&gt;: &amp;lt;2% of withdrawals (most succeed on preferred tier)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Natural consolidation rate&lt;/strong&gt;: thousands of UTXOs/day consolidated without manual intervention&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;System uptime during rebalancing&lt;/strong&gt;: 100% (non-blocking background process)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cost Impact at Scale:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Platform: 10,000 withdrawals/day
Average fee savings: $2.50/withdrawal
Monthly savings: $750,000
Annual savings: $9,000,000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Limitations and Trade-offs
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What This Approach Sacrifices
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Theoretical Optimality&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Branch and Bound finds the &lt;em&gt;perfect&lt;/em&gt; UTXO combination&lt;/li&gt;
&lt;li&gt;Tier cascading finds a &lt;em&gt;good enough&lt;/em&gt; combination&lt;/li&gt;
&lt;li&gt;Trade-off: ~5% more change outputs for 10,000x faster selection&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Privacy Considerations&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Selecting multiple UTXOs from same tier can link addresses&lt;/li&gt;
&lt;li&gt;Common input ownership heuristic applies&lt;/li&gt;
&lt;li&gt;Mitigation: Use mixing services or CoinJoin for privacy-critical applications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Minimum Withdrawal Threshold&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dust tier prevents withdrawals &amp;lt; 50,000 sats (~$50)&lt;/li&gt;
&lt;li&gt;Necessary to avoid economically unspendable UTXOs&lt;/li&gt;
&lt;li&gt;Alternative: Lightning Network for micro-withdrawals&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  When This Approach May Not Fit
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Not suitable for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Personal wallets (use Bitcoin Core's Branch and Bound)&lt;/li&gt;
&lt;li&gt;Privacy-focused applications (use Wasabi/Samourai algorithms)&lt;/li&gt;
&lt;li&gt;&amp;lt; 10,000 UTXOs (simpler approaches work fine)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Ideal for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Exchanges and payment processors&lt;/li&gt;
&lt;li&gt;Cross-chain bridges&lt;/li&gt;
&lt;li&gt;Custodial services at scale&lt;/li&gt;
&lt;li&gt;Any platform managing 1M+ UTXOs&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Building a Bitcoin custodian at scale requires fundamentally different thinking than Ethereum-based solutions. The UTXO model, while more complex, can be efficiently managed using tier-based cascading strategies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key takeaways:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Standard algorithms don't scale&lt;/strong&gt; - Branch and Bound is O(2^n), impossible at millions of UTXOs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tier cascading UP&lt;/strong&gt; prevents fragmentation while maintaining availability&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fee-aware selection&lt;/strong&gt; can save millions annually at scale&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Natural consolidation&lt;/strong&gt; keeps the system healthy through smallest-first selection&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database-level implementation&lt;/strong&gt; provides atomicity and concurrency control&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Operational monitoring&lt;/strong&gt; is critical - track tier health and rebalance proactively&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By treating Bitcoin UTXOs like physical currency denominations and selecting them through intelligent tier traversal, custodians can process millions of transactions efficiently while minimizing fees and maintaining system health.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The real innovation isn't just the algorithm—it's designing a system that scales to millions of UTXOs while remaining operationally manageable.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>bitcoin</category>
      <category>infrastructureascode</category>
      <category>backend</category>
      <category>cryptocurrency</category>
    </item>
    <item>
      <title>10,000 Applicants. 28 Positions. The Brutal Math of Web3 Hiring in 2026.</title>
      <dc:creator>0xkniraj</dc:creator>
      <pubDate>Sun, 04 Jan 2026 10:46:51 +0000</pubDate>
      <link>https://dev.to/kniraj/10000-applicants-28-positions-the-brutal-math-of-web3-hiring-in-2026-58po</link>
      <guid>https://dev.to/kniraj/10000-applicants-28-positions-the-brutal-math-of-web3-hiring-in-2026-58po</guid>
      <description>&lt;p&gt;&lt;strong&gt;&lt;em&gt;The Web3 job market recovered 47% in 2025. So why does landing a role feel harder than ever?&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You refresh the job board. Another Solidity position at a promising L2. You've deployed contracts to mainnet, contributed to open-source repos, and spent six months mastering Foundry. You apply within hours of posting.&lt;/p&gt;

&lt;p&gt;Three weeks later: silence.&lt;/p&gt;

&lt;p&gt;You're not alone. That position likely received 400+ applications before the listing was 48 hours old. The hiring manager skimmed maybe 50 resumes, interviewed 8 candidates, and hired someone with a warm referral from a mutual connection on Crypto Twitter.&lt;/p&gt;

&lt;p&gt;Welcome to Web3 hiring in 2026—where the industry added 66,000 jobs last year, yet &lt;strong&gt;450 developers compete for every engineering position&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The numbers don't lie. But they don't tell the whole story either.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Ground Reality: Why It Feels Impossible
&lt;/h2&gt;

&lt;p&gt;Let's start with the uncomfortable truth. The Web3 job market has fundamentally changed, and most job seekers haven't caught up.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The recovery is real, but selective.&lt;/strong&gt; Yes, 66,494 new positions emerged in 2025—a 47% rebound from crypto winter. But this recovery favors specific roles, specific skills, and specific candidate profiles. If you're a generalist Solidity developer with a decent portfolio, you're competing in the most saturated talent pool in tech.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The competition ratios are brutal:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Smart contract developers: &lt;strong&gt;450 applicants per position&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Frontend Web3 engineers: &lt;strong&gt;300-400 applicants per position&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Compliance/regulatory roles: &lt;strong&gt;60-80 applicants per position&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Security auditors: &lt;strong&gt;80-120 applicants per position&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Read those numbers again. The difference between 450:1 and 60:1 isn't marginal—it's the difference between lottery odds and a real shot.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The "build phase" ended. You missed the memo.&lt;/strong&gt; Here's what nobody told you: Web3 stopped being about "what can we build?" sometime in late 2024. It's now about "how do we ship, scale, and not get sued?"&lt;/p&gt;

&lt;p&gt;Project management now represents &lt;strong&gt;27% of all Web3 job postings&lt;/strong&gt;—the single largest category. The industry doesn't need another developer who can fork Uniswap. It needs people who can coordinate launches, navigate regulations, and turn existing protocols into actual businesses.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI changed the math on junior roles.&lt;/strong&gt; Stanford research found a &lt;strong&gt;20% employment decline in software developers aged 22-25&lt;/strong&gt; between 2022-2025. In Web3, this hit harder. When AI can generate a standard ERC-20 token contract in seconds, why hire a junior developer to do it in hours?&lt;/p&gt;

&lt;p&gt;Coinbase reports &lt;strong&gt;90% speedup on simple coding tasks&lt;/strong&gt; using AI tools. That productivity gain came from somewhere—and it came from entry-level headcount.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Numbers Behind the Despair
&lt;/h2&gt;

&lt;p&gt;I pulled data from every major Web3 job platform, recruitment agency, and industry report. Here's what the market actually looks like:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Total active positions (January 2026):&lt;/strong&gt; ~8,000-12,000 globally&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Estimated active job seekers:&lt;/strong&gt; 150,000-200,000+&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where the jobs actually are:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;% of Postings&lt;/th&gt;
&lt;th&gt;Competition Level&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Project/Program Management&lt;/td&gt;
&lt;td&gt;27%&lt;/td&gt;
&lt;td&gt;Moderate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Engineering (all types)&lt;/td&gt;
&lt;td&gt;32%&lt;/td&gt;
&lt;td&gt;Severe&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Operations/Admin&lt;/td&gt;
&lt;td&gt;15%&lt;/td&gt;
&lt;td&gt;Low-Moderate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Compliance/Legal&lt;/td&gt;
&lt;td&gt;8%&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Marketing/Community&lt;/td&gt;
&lt;td&gt;10%&lt;/td&gt;
&lt;td&gt;Moderate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Security/Auditing&lt;/td&gt;
&lt;td&gt;5%&lt;/td&gt;
&lt;td&gt;Moderate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Research&lt;/td&gt;
&lt;td&gt;3%&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Geographic reality:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;United States: 21,612 positions (+26% YoY)&lt;/li&gt;
&lt;li&gt;Europe: 10,263 positions (+38% YoY)&lt;/li&gt;
&lt;li&gt;Asia: 10,420 positions (32% of global developers now here)&lt;/li&gt;
&lt;li&gt;Remote-only positions: &lt;strong&gt;Down 50% from 2024&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last stat matters. The "work from anywhere" Web3 dream is fading. Companies want hybrid. They want to see your face occasionally. The arbitrage play of living in Bali on a San Francisco salary is closing.&lt;/p&gt;

&lt;h2&gt;
  
  
  But Here's Where Hope Lives
&lt;/h2&gt;

&lt;p&gt;Okay, you've absorbed the brutal math. Now let's talk about the paths that actually work—because they exist, and they're more accessible than the competition ratios suggest.&lt;/p&gt;

&lt;h3&gt;
  
  
  Path 1: Go Where They Aren't
&lt;/h3&gt;

&lt;p&gt;The 450:1 ratio is for &lt;em&gt;smart contract developer&lt;/em&gt; positions. But look at what's undersaturated:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Regulatory fluency is becoming an engineering differentiator.&lt;/strong&gt; MiCA went live in Europe. The SEC is providing clarity in the US. This isn't just creating compliance jobs—it's reshaping what engineering teams need.&lt;/p&gt;

&lt;p&gt;RWA (Real World Assets) is the fastest-growing sector in DeFi, with protocols like Ondo, Centrifuge, and Maple Finance racing to tokenize treasuries, real estate, and private credit. These projects don't just need Solidity devs—they need engineers who understand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How token classifications affect smart contract architecture (security vs. utility vs. commodity)&lt;/li&gt;
&lt;li&gt;Why certain on-chain actions trigger reporting requirements&lt;/li&gt;
&lt;li&gt;How to build compliant transfer restrictions and whitelisting into token contracts&lt;/li&gt;
&lt;li&gt;The technical requirements for institutional custody and settlement&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;TradFi is moving in.&lt;/strong&gt; BlackRock, Franklin Templeton, and JPMorgan aren't experimenting anymore—they're shipping products. Every major fintech is building crypto rails. These institutions pay 20-30% premiums for engineers who speak both languages: blockchain &lt;em&gt;and&lt;/em&gt; traditional finance infrastructure (FIX protocol, SWIFT, securities settlement, custodial requirements).&lt;/p&gt;

&lt;p&gt;If you understand how a bond actually settles in TradFi and can architect an on-chain equivalent, you're not competing with 450 Solidity devs. You're competing with maybe 50 or less.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Security auditing&lt;/strong&gt; has a chronic talent shortage despite the fact that &lt;strong&gt;50% of blockchain projects still ship with vulnerabilities&lt;/strong&gt;. The barrier to entry is real—you need deep Solidity knowledge and security expertise—but the demand is insatiable.&lt;/p&gt;

&lt;p&gt;Starting path: Complete Cyfrin Updraft or Secureum bootcamp → Build a portfolio of practice audits on Code4rena → Apply to audit firms as junior auditor.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI-Web3 hybrid roles&lt;/strong&gt; increased &lt;strong&gt;60% since late 2024&lt;/strong&gt;. This intersection is so new that the talent pool barely exists. If you can build AI agents that interact with blockchain protocols, you're competing against maybe 1,000 people globally instead of 150,000.&lt;/p&gt;

&lt;h3&gt;
  
  
  Path 2: The Rust Premium
&lt;/h3&gt;

&lt;p&gt;Here's a cheat code hiding in plain sight: &lt;strong&gt;Rust developers command 25-40% salary premiums&lt;/strong&gt; and face dramatically less competition than Solidity developers.&lt;/p&gt;

&lt;p&gt;Why? Because Rust is hard. The learning curve is steep. Most developers bounce off the borrow checker and never come back.&lt;/p&gt;

&lt;p&gt;But Rust is eating Web3:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Solana (7,625 monthly active developers)&lt;/li&gt;
&lt;li&gt;Polkadot/Substrate&lt;/li&gt;
&lt;li&gt;All major ZK implementations (StarkWare, zkSync, Aztec)&lt;/li&gt;
&lt;li&gt;Cosmos SDK is increasingly Rust-influenced&lt;/li&gt;
&lt;li&gt;Even Ethereum tooling (Foundry, Reth) runs on Rust&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Solidity market is saturated. The Rust market is starving. &lt;strong&gt;83% year-over-year growth&lt;/strong&gt; in Rust job requirements, with nowhere near enough candidates to fill them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Path 3: Prove Work, Not Credentials
&lt;/h3&gt;

&lt;p&gt;Every recruiter and hiring manager I've encountered says the same thing: &lt;strong&gt;"In Web3, your GitHub is your resume."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This isn't a platitude. It's a tactical advantage for anyone willing to exploit it.&lt;/p&gt;

&lt;p&gt;What actually gets you hired:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Consistent commit history&lt;/strong&gt; (green GitHub activity graph)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deployed projects&lt;/strong&gt; with working demos (testnet counts, mainnet counts more)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open-source contributions&lt;/strong&gt; to protocols you want to work for&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Progressive complexity&lt;/strong&gt; showing growth (ERC-20 → ERC-721 → full DeFi protocol)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What doesn't matter as much as you think:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CS degree (nice to have, not required)&lt;/li&gt;
&lt;li&gt;Certifications (mostly ignored)&lt;/li&gt;
&lt;li&gt;Years of "experience" that can't be verified on-chain&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's the unlock: &lt;strong&gt;contribute to the repo of the company you want to work for.&lt;/strong&gt; Find their GitHub. Look at open issues. Submit a meaningful PR. When you apply, you're no longer applicant #347—you're "that person who fixed our indexer bug last month."&lt;/p&gt;

&lt;h3&gt;
  
  
  Path 4: Network in Crypto-Native Spaces
&lt;/h3&gt;

&lt;p&gt;"Elite Web3 talent does not hang out on LinkedIn."&lt;/p&gt;

&lt;p&gt;Read that again. The best jobs in Web3 are filled through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Crypto Twitter (now X) connections&lt;/li&gt;
&lt;li&gt;Discord server relationships&lt;/li&gt;
&lt;li&gt;DAO governance participation&lt;/li&gt;
&lt;li&gt;Conference and hackathon networks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your job search strategy is "apply on LinkedIn and wait," you're playing a game designed for you to lose. The real hiring happens in DMs, in Discord channels, in "hey, we need someone for this role—know anyone good?" conversations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tactical moves:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build a Twitter presence around your technical niche&lt;/li&gt;
&lt;li&gt;Become a recognized name in 2-3 project Discord servers&lt;/li&gt;
&lt;li&gt;Participate in governance discussions (even just voting and commenting)&lt;/li&gt;
&lt;li&gt;Attend ETHGlobal hackathons (these are explicit talent pipelines for protocols)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Path 5: The Security Auditor Arbitrage
&lt;/h3&gt;

&lt;p&gt;I'm going to be direct: if you're a competent Solidity developer struggling to find work, pivot to security.&lt;/p&gt;

&lt;p&gt;The numbers are absurd:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Base salary: &lt;strong&gt;$90,000-$200,000&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Top independent auditors earn &lt;strong&gt;$50,000+ monthly&lt;/strong&gt; through competitive platforms&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;50% of projects ship with vulnerabilities&lt;/strong&gt; → near-infinite demand&lt;/li&gt;
&lt;li&gt;Competition ratio: &lt;strong&gt;4-5x lower&lt;/strong&gt; than development roles&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The path isn't easy, but it's clear:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Master Solidity deeply (you should already be here)&lt;/li&gt;
&lt;li&gt;Learn common vulnerability patterns (reentrancy, flash loan attacks, oracle manipulation)&lt;/li&gt;
&lt;li&gt;Study tools: Slither, Mythril, Foundry fuzzing&lt;/li&gt;
&lt;li&gt;Practice on Code4rena, Sherlock, or Immunefi&lt;/li&gt;
&lt;li&gt;Build a track record of findings&lt;/li&gt;
&lt;li&gt;Apply to firms or go independent&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The market is paying &lt;strong&gt;$300-$500/hour&lt;/strong&gt; for senior audit work. The supply of qualified auditors has not kept up with the $30B+ TVL that needs protecting.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Salary Reality Check
&lt;/h2&gt;

&lt;p&gt;Let's ground expectations with actual compensation data:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;th&gt;Junior&lt;/th&gt;
&lt;th&gt;Mid&lt;/th&gt;
&lt;th&gt;Senior&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Smart Contract Engineer&lt;/td&gt;
&lt;td&gt;$80K-$120K&lt;/td&gt;
&lt;td&gt;$120K-$180K&lt;/td&gt;
&lt;td&gt;$180K-$250K&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ZK/Research Engineer&lt;/td&gt;
&lt;td&gt;$80K-$140K&lt;/td&gt;
&lt;td&gt;$140K-$220K&lt;/td&gt;
&lt;td&gt;$220K-$400K+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Full-Stack Web3&lt;/td&gt;
&lt;td&gt;$80K-$120K&lt;/td&gt;
&lt;td&gt;$120K-$175K&lt;/td&gt;
&lt;td&gt;$175K-$250K&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Protocol Engineer&lt;/td&gt;
&lt;td&gt;$100K-$140K&lt;/td&gt;
&lt;td&gt;$140K-$200K&lt;/td&gt;
&lt;td&gt;$200K-$350K&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Token compensation typically adds 50-100%&lt;/strong&gt; to these figures—but tokens are volatile, vesting takes 4 years, and many never materialize. Smart candidates now negotiate for hybrid packages (some tokens, some equity, higher base) to derisk.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Geographic arbitrage is real but shrinking:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;US average: $140K&lt;/li&gt;
&lt;li&gt;UK average: $77K&lt;/li&gt;
&lt;li&gt;Germany average: $58K (down 94% from 2022 peak!)&lt;/li&gt;
&lt;li&gt;India average: $56K&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The remote-only position decline means fewer opportunities to earn US salaries while living in low-cost regions. Plan accordingly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The AI Question: Friend or Foe?
&lt;/h2&gt;

&lt;p&gt;Here's the nuanced take: AI is simultaneously making you more productive and making junior hiring less necessary. How you respond determines whether AI helps or hurts your career.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What AI won't replace (yet):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Complex smart contract architecture&lt;/li&gt;
&lt;li&gt;Cross-chain bridge development (AI "enters endless cyclic arguments")&lt;/li&gt;
&lt;li&gt;Protocol-level security analysis&lt;/li&gt;
&lt;li&gt;Regulatory judgment calls&lt;/li&gt;
&lt;li&gt;Anything requiring deep context about a specific codebase&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What AI is already replacing:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Boilerplate contract generation&lt;/li&gt;
&lt;li&gt;Basic test writing&lt;/li&gt;
&lt;li&gt;Documentation&lt;/li&gt;
&lt;li&gt;Simple code refactoring&lt;/li&gt;
&lt;li&gt;Entry-level "write a function that does X" work&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The winning move:&lt;/strong&gt; Become the person who orchestrates AI tools, not the person whose work AI tools automate. Learn Cursor, GitHub Copilot, Claude—and learn to direct them effectively. The new skill isn't "write code." It's "architect solutions and direct AI to implement them."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;14% of Web3 job postings now explicitly require AI workflow proficiency.&lt;/strong&gt; That number was 2% in 2021. The trend is obvious.&lt;/p&gt;




&lt;h2&gt;
  
  
  Your 90-Day Action Plan
&lt;/h2&gt;

&lt;p&gt;Enough theory. Here's what to actually do:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Week 1-2: Audit Your Position&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Honestly assess: Am I in a saturated category?&lt;/li&gt;
&lt;li&gt;Identify your transferable skills toward undersaturated roles&lt;/li&gt;
&lt;li&gt;Set up GitHub contributions tracking (aim for daily commits)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Week 3-4: Pick Your Angle&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Choose ONE differentiation path (Rust? Security? AI-hybrid? Compliance?)&lt;/li&gt;
&lt;li&gt;Begin dedicated skill-building (4+ hours daily)&lt;/li&gt;
&lt;li&gt;Identify 5 companies you want to work for&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Week 5-8: Build Proof of Work&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deploy at least one meaningful project in your chosen niche&lt;/li&gt;
&lt;li&gt;Make contributions to target company repos&lt;/li&gt;
&lt;li&gt;Write 2-3 technical blog posts demonstrating expertise&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Week 9-10: Network Intentionally&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Become active in 3 relevant Discord servers&lt;/li&gt;
&lt;li&gt;Start engaging on Crypto Twitter with valuable technical takes&lt;/li&gt;
&lt;li&gt;Attend at least one virtual or IRL Web3 event&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Week 11-12: Apply Strategically&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Apply to roles with warm connections (Discord/Twitter relationships)&lt;/li&gt;
&lt;li&gt;Apply to undersaturated categories, not just what you "want"&lt;/li&gt;
&lt;li&gt;Follow up with hiring managers directly via Twitter DM&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Hopium: Why This Moment Actually Favors the Prepared
&lt;/h2&gt;

&lt;p&gt;Here's the thing about 450:1 competition: most of those 450 applicants are doing it wrong.&lt;/p&gt;

&lt;p&gt;They're applying with generic resumes. They have no GitHub activity. They've never contributed to the protocol's codebase. They're invisible on Crypto Twitter. They're applying to the same saturated Solidity roles as everyone else.&lt;/p&gt;

&lt;p&gt;You now know what they don't:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The undersaturated categories where competition drops to 60:1&lt;/li&gt;
&lt;li&gt;The Rust premium that pays 25-40% more with 5x less competition&lt;/li&gt;
&lt;li&gt;The proof-of-work portfolio strategy that actually gets interviews&lt;/li&gt;
&lt;li&gt;The crypto-native networking that surfaces opportunities before they're posted&lt;/li&gt;
&lt;li&gt;The AI-hybrid roles emerging at the intersection nobody's preparing for&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Web3 job market isn't broken—it's differentiated. The spray-and-pray approach fails. The strategic approach works.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The market added 66,000 jobs last year.&lt;/strong&gt; More are coming. The question isn't whether opportunities exist—it's whether you'll position yourself to capture them.&lt;/p&gt;

&lt;p&gt;The brutal math is real. But math can be solved.&lt;/p&gt;

&lt;p&gt;Now go solve it.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Data sourced from Coincub Web3 Jobs Report 2025, Electric Capital Developer Report 2024, Web3.Career Intelligence Report 2025, and aggregated job board analysis. All figures represent estimates based on available data as of January 2026.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>crypto</category>
      <category>job</category>
      <category>hiring</category>
      <category>career</category>
    </item>
    <item>
      <title>A Hacker’s Guide to Bitcoin: Exploring Bitcoin by Command Line - Part 1</title>
      <dc:creator>0xkniraj</dc:creator>
      <pubDate>Wed, 06 Aug 2025 18:56:57 +0000</pubDate>
      <link>https://dev.to/kniraj/a-hackers-guide-to-bitcoin-exploring-bitcoin-by-command-line-part-1-536i</link>
      <guid>https://dev.to/kniraj/a-hackers-guide-to-bitcoin-exploring-bitcoin-by-command-line-part-1-536i</guid>
      <description>&lt;p&gt;Most developers first encounter Bitcoin through polished mobile wallets or sleek web interfaces. But that's like learning programming by only using drag-and-drop tools—you miss the fundamental mechanics that make everything work.&lt;/p&gt;

&lt;p&gt;As programmers, we understand that true mastery comes from getting our hands dirty with the underlying systems. When you run your own Bitcoin node and interact with it directly via the command line, you're not just using Bitcoin—you're speaking its native language.&lt;/p&gt;

&lt;p&gt;This guide will take you from spinning up your first Bitcoin node to understanding UTXOs, crafting transactions, and managing multiple wallets. By the end, you'll have the foundation needed to build Bitcoin applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Command Line Bitcoin Matters
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;With command-line Bitcoin, you gain:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Unfiltered access&lt;/strong&gt; to Bitcoin's data structures as your node stores them&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complete sovereignty&lt;/strong&gt;—no third-party APIs, no rate limits, no downtime&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scripting capabilities&lt;/strong&gt; for automation and custom workflows
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deep understanding&lt;/strong&gt; of Bitcoin's UTXO model and transaction structure&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Foundation knowledge&lt;/strong&gt; for building Bitcoin applications&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;You'll need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Basic command-line comfort&lt;/li&gt;
&lt;li&gt;Understanding of JSON (Bitcoin Core returns data in JSON format)&lt;/li&gt;
&lt;li&gt;About 100MB disk space for our regtest experiments&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Part 1: Setting Up Your Bitcoin Laboratory
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Installing Bitcoin Core
&lt;/h3&gt;

&lt;p&gt;Bitcoin Core provides two essential tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;bitcoind&lt;/code&gt;: The full node daemon that validates and relays transactions&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;bitcoin-cli&lt;/code&gt;: Your command-line interface to the daemon&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Download the latest version from &lt;a href="https://bitcoin.org/en/download" rel="noopener noreferrer"&gt;bitcoin.org/en/download&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For this tutorial, we'll use &lt;strong&gt;regtest mode&lt;/strong&gt;—Bitcoin's built-in testing environment where you're the only miner, blocks generate instantly, and you can experiment safely.&lt;/p&gt;

&lt;h3&gt;
  
  
  Starting Your Private Bitcoin Network
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Start bitcoind in regtest mode&lt;/span&gt;
bitcoind &lt;span class="nt"&gt;-regtest&lt;/span&gt; &lt;span class="nt"&gt;-daemon&lt;/span&gt;

&lt;span class="c"&gt;# Verify it's running&lt;/span&gt;
bitcoin-cli &lt;span class="nt"&gt;-regtest&lt;/span&gt; getnetworkinfo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Pro tip&lt;/strong&gt;: Create an alias to save typing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;bcli&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"bitcoin-cli -regtest"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can use &lt;code&gt;bcli&lt;/code&gt; instead of typing the full command each time.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 2: Your First Bitcoin Genesis Moment
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Understanding Bitcoin's State
&lt;/h3&gt;

&lt;p&gt;Bitcoin doesn't track account balances like a traditional database. Instead, it tracks &lt;strong&gt;Unspent Transaction Outputs (UTXOs)&lt;/strong&gt;—chunks of bitcoin that can be spent.&lt;/p&gt;

&lt;p&gt;Check your initial state:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bcli getblockchaininfo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice &lt;code&gt;"blocks": 0&lt;/code&gt;—you're at the genesis block with no bitcoins in existence yet.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating Your First Wallet (Alice)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bcli createwallet &lt;span class="s2"&gt;"alice"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"alice"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"warning"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Your First Mining Operation
&lt;/h3&gt;

&lt;p&gt;Now for the magic moment—creating bitcoin from nothing through mining:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Generate a new address for Alice to receive mining rewards&lt;/span&gt;
&lt;span class="nv"&gt;ADDRESS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;bcli &lt;span class="nt"&gt;-rpcwallet&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;alice getnewaddress &lt;span class="s2"&gt;"mining-rewards"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Mining to Alice's address: &lt;/span&gt;&lt;span class="nv"&gt;$ADDRESS&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Mine 101 blocks (we need 101 to spend the first block's reward)&lt;/span&gt;
bcli generatetoaddress 101 &lt;span class="nv"&gt;$ADDRESS&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What just happened?&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Address Generation&lt;/strong&gt;: Created a Bitcoin address where coins can be sent&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Block Creation&lt;/strong&gt;: Created 101 new blocks, each paying 50 BTC to Alice's address&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Coinbase Maturity&lt;/strong&gt;: Bitcoin requires 100 confirmations before newly mined coins can be spent&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's verify Alice's balance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bcli &lt;span class="nt"&gt;-rpcwallet&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;alice getbalance
&lt;span class="c"&gt;# Output: 50.00000000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alice now has 50 BTC! (Only from the first block—the other rewards are still maturing)&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 3: Understanding Bitcoin's Data Structures
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Examining UTXOs
&lt;/h3&gt;

&lt;p&gt;Let's see what bitcoin "ownership" actually means:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bcli &lt;span class="nt"&gt;-rpcwallet&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;alice listunspent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll see something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"txid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"f3d7f85e0b3c91e4d8c4b7abc1d0e3f2a9b8c7d6e5f4a3b2c1d0e9f8a7b6c5d4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"vout"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bcrt1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;50.00000000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"confirmations"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"spendable"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This UTXO represents:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;txid&lt;/strong&gt;: The transaction that created this output (a coinbase transaction)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;vout&lt;/strong&gt;: Output index (0 for coinbase transactions)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;amount&lt;/strong&gt;: 50 BTC&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;confirmations&lt;/strong&gt;: How deep it is in the blockchain (must be &amp;gt;100 to spend)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Exploring Block Structure
&lt;/h3&gt;

&lt;p&gt;Let's examine the block containing Alice's first coinbase transaction:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Get the hash of block #1&lt;/span&gt;
&lt;span class="nv"&gt;BLOCK_HASH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;bcli getblockhash 1&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Block 1 hash: &lt;/span&gt;&lt;span class="nv"&gt;$BLOCK_HASH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Get detailed block information&lt;/span&gt;
bcli getblock &lt;span class="nv"&gt;$BLOCK_HASH&lt;/span&gt; 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Key observations from the output:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;coinbase&lt;/strong&gt;: The input field contains arbitrary data (no previous transaction)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;vout&lt;/strong&gt;: Single output paying 50 BTC to Alice's address&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;scriptPubKey&lt;/strong&gt;: The locking script that defines how this UTXO can be spent&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Part 4: Multi-Wallet Operations and Your First Transaction
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Creating Bob's Wallet
&lt;/h3&gt;

&lt;p&gt;Let's create a second wallet and demonstrate Bitcoin's peer-to-peer nature:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create Bob's wallet&lt;/span&gt;
bcli createwallet &lt;span class="s2"&gt;"bob"&lt;/span&gt;

&lt;span class="c"&gt;# Generate an address for Bob&lt;/span&gt;
&lt;span class="nv"&gt;BOB_ADDRESS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;bcli &lt;span class="nt"&gt;-rpcwallet&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;bob getnewaddress &lt;span class="s2"&gt;"received-from-alice"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Bob's address: &lt;/span&gt;&lt;span class="nv"&gt;$BOB_ADDRESS&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Alice Sends Bitcoin to Bob
&lt;/h3&gt;

&lt;p&gt;Now Alice will send some of her mined bitcoin to Bob:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Alice sends 10 BTC to Bob&lt;/span&gt;
&lt;span class="nv"&gt;TXID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;bcli &lt;span class="nt"&gt;-rpcwallet&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;alice sendtoaddress &lt;span class="nv"&gt;$BOB_ADDRESS&lt;/span&gt; 10.0&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Transaction ID: &lt;/span&gt;&lt;span class="nv"&gt;$TXID&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Mine a block to confirm the transaction&lt;/span&gt;
bcli generatetoaddress 1 &lt;span class="si"&gt;$(&lt;/span&gt;bcli &lt;span class="nt"&gt;-rpcwallet&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;alice getnewaddress&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Understanding What Happened
&lt;/h3&gt;

&lt;p&gt;Let's examine this transaction:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bcli getrawtransaction &lt;span class="nv"&gt;$TXID&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll see a transaction with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;vin&lt;/strong&gt;: Input spending Alice's 50 BTC UTXO&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;vout&lt;/strong&gt;: Two outputs:

&lt;ul&gt;
&lt;li&gt;10 BTC to Bob's address&lt;/li&gt;
&lt;li&gt;~40 BTC back to Alice as change (minus a small mining fee)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;This demonstrates Bitcoin's fundamental principle: &lt;strong&gt;UTXOs must be spent in full&lt;/strong&gt;. Alice couldn't spend just 10 BTC from her 50 BTC UTXO—she had to spend the entire UTXO and create new outputs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Checking Final Balances
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check Alice's balance&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Alice's balance: &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;bcli &lt;span class="nt"&gt;-rpcwallet&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;alice getbalance&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Check Bob's balance  &lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Bob's balance: &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;bcli &lt;span class="nt"&gt;-rpcwallet&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;bob getbalance&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# List Bob's UTXOs to see the received bitcoin&lt;/span&gt;
bcli &lt;span class="nt"&gt;-rpcwallet&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;bob listunspent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Alice: ~40 BTC (50 - 10 - small fee)&lt;/li&gt;
&lt;li&gt;Bob: 10 BTC&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Transaction History
&lt;/h3&gt;

&lt;p&gt;View the transaction from both perspectives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Alice's transaction history&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"=== Alice's Transactions ==="&lt;/span&gt;
bcli &lt;span class="nt"&gt;-rpcwallet&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;alice listtransactions

&lt;span class="c"&gt;# Bob's transaction history  &lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"=== Bob's Transactions ==="&lt;/span&gt;
bcli &lt;span class="nt"&gt;-rpcwallet&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;bob listtransactions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alice will see a "send" transaction with a negative amount, while Bob will see a "receive" transaction with a positive amount—the same transaction viewed from different wallets.&lt;/p&gt;




&lt;h2&gt;
  
  
  Cleanup
&lt;/h2&gt;

&lt;p&gt;When you're done experimenting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Stop the daemon&lt;/span&gt;
bcli stop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Congratulations! You've just experienced Bitcoin's core mechanics firsthand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Operated&lt;/strong&gt; your own full Bitcoin node in regtest mode&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mined&lt;/strong&gt; blocks and created bitcoin from nothing through coinbase transactions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Understood&lt;/strong&gt; UTXOs as Bitcoin's fundamental building blocks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Created&lt;/strong&gt; multiple wallets and sent bitcoin between them&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explored&lt;/strong&gt; Bitcoin's transaction structure and block anatomy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You now understand that Bitcoin isn't about account balances—it's about a graph of UTXOs that can be unlocked and spent using cryptographic signatures. Every transaction consumes existing UTXOs and creates new ones, forming an unbroken chain back to coinbase transactions.&lt;/p&gt;

&lt;p&gt;This command-line foundation is essential for any serious Bitcoin development work. Whether you're building wallets, payment processors, or blockchain analytics tools, understanding how Bitcoin works at this level will make you a more effective developer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In the next part of this series, we'll dig deep into Bitcoin scripting with JavaScript&lt;/strong&gt;, exploring how to programmatically create transactions, implement custom spending conditions, and build sophisticated Bitcoin applications using popular libraries like bitcoinjs-lib.&lt;/p&gt;

&lt;p&gt;The blockchain is yours to explore—one command at a time.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>MacOS: The Long-Running Task Notifier</title>
      <dc:creator>0xkniraj</dc:creator>
      <pubDate>Thu, 04 Apr 2024 13:09:31 +0000</pubDate>
      <link>https://dev.to/kniraj/macos-the-long-running-task-notifier-35o1</link>
      <guid>https://dev.to/kniraj/macos-the-long-running-task-notifier-35o1</guid>
      <description>&lt;p&gt;In the realm of software development, efficiency and productivity are paramount. MacOS, beloved by many developers for its robustness and sleek interface, offers ample opportunities for customization to enhance workflow. One area ripe for optimization is the handling of long-running tasks. Whether compiling code, processing large datasets, or deploying applications, these tasks can significantly interrupt the flow of work. This article introduces a simple, yet powerful solution: a Long-Running Task Notifier for MacOS. This tool notifies you when a task running in the terminal completes, allowing you to focus on other tasks without constant terminal checks.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Need for Notification
&lt;/h2&gt;

&lt;p&gt;Developers often switch contexts while waiting for a task to complete. Without a notification system, you might either check the terminal too frequently or return too late, wasting precious time either way. A notifier system streamlines this process by alerting you the moment a task is done, optimizing your workflow efficiency.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing the Notifier with &lt;code&gt;zsh&lt;/code&gt; and &lt;code&gt;osascript&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The notifier leverages &lt;code&gt;zsh&lt;/code&gt; (Z Shell) for its extensibility and &lt;code&gt;osascript&lt;/code&gt; for sending notifications in MacOS. The core idea is to hook into the shell's command execution lifecycle, detecting when a command starts and ends, and triggering a notification for long-running tasks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Setting Up the Hooks
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;zsh&lt;/code&gt; shell provides &lt;code&gt;preexec&lt;/code&gt; and &lt;code&gt;precmd&lt;/code&gt; functions that execute before and after a command runs, respectively. We use these to start a timer before a command and check its duration after completion.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Customizing the Notification
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;osascript&lt;/code&gt;, Apple's scripting utility, allows command-line interaction with the macOS Notification Center. By invoking &lt;code&gt;osascript&lt;/code&gt; with a specific message and title, we can generate notifications dynamically based on the command executed and its duration.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Script
&lt;/h3&gt;

&lt;p&gt;Here's a simplified version of the script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;function &lt;/span&gt;command_start &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;zsh_command_start_time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$SECONDS&lt;/span&gt;
    &lt;span class="nv"&gt;zsh_last_command&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;function &lt;/span&gt;command_end &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;duration&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;SECONDS &lt;span class="o"&gt;-&lt;/span&gt; zsh_command_start_time&lt;span class="k"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;((&lt;/span&gt; duration &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 5 &lt;span class="o"&gt;))&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;cmd_title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;zsh_last_command&lt;/span&gt;&lt;span class="p"&gt;%% *&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
        &lt;span class="nv"&gt;cmd_title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;tr&lt;/span&gt; &lt;span class="s1"&gt;'[:lower:]'&lt;/span&gt; &lt;span class="s1"&gt;'[:upper:]'&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;cmd_title&lt;/span&gt;:0:1&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;cmd_title&lt;/span&gt;:1&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
        &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;zsh_last_command&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; completed in &lt;/span&gt;&lt;span class="nv"&gt;$duration&lt;/span&gt;&lt;span class="s2"&gt; seconds"&lt;/span&gt;
        &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$cmd_title&lt;/span&gt;&lt;span class="s2"&gt; Command Finished"&lt;/span&gt;
        osascript &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"display notification &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="nv"&gt;$message&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; with title &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="nv"&gt;$title&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

autoload &lt;span class="nt"&gt;-U&lt;/span&gt; add-zsh-hook
add-zsh-hook preexec command_start
add-zsh-hook precmd command_end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Open &lt;code&gt;~/.zshrc&lt;/code&gt; in your favorite text editor.&lt;/li&gt;
&lt;li&gt;Copy and paste the script into the file.&lt;/li&gt;
&lt;li&gt;Save the changes and source the file with &lt;code&gt;source ~/.zshrc&lt;/code&gt; or restart the terminal.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Customization and Extension
&lt;/h2&gt;

&lt;p&gt;This basic notifier can be customized and extended in several ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adjust the duration threshold to define what constitutes a long-running task.&lt;/li&gt;
&lt;li&gt;Customize the notification message and title to include more detailed information.&lt;/li&gt;
&lt;li&gt;Extend the script to exclude certain commands or to work with specific applications.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By integrating a Long-Running Task Notifier into your MacOS development environment, you can significantly improve your productivity and focus. This tool bridges the gap between multitasking and efficiency, ensuring that you're promptly informed when it's time to return to the terminal. &lt;/p&gt;

&lt;p&gt;Happy coding, and may your tasks run smoothly and your notifications be timely!&lt;/p&gt;

</description>
      <category>macos</category>
      <category>softwaredevelopment</category>
      <category>terminal</category>
      <category>scripting</category>
    </item>
    <item>
      <title>Demystifying Bitcoin: A Guide in Simple Terms</title>
      <dc:creator>0xkniraj</dc:creator>
      <pubDate>Wed, 20 Mar 2024 11:30:03 +0000</pubDate>
      <link>https://dev.to/kniraj/demystifying-bitcoin-a-guide-in-simple-terms-1cgc</link>
      <guid>https://dev.to/kniraj/demystifying-bitcoin-a-guide-in-simple-terms-1cgc</guid>
      <description>&lt;p&gt;In the evolving world of finance, Bitcoin emerges as a digital marvel, often cloaked in technical jargon. Let's strip away the complexity and dive into the essence of Bitcoin, using straightforward analogies that bring its innovative nature to light.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Bitcoin?
&lt;/h2&gt;

&lt;p&gt;Think of Bitcoin as digital gold. Just as gold is mined from the earth, Bitcoin is "mined" through complex computations by computers. It exists in a digital form, and like gold, has a limited supply, making it valuable to those who possess it. However, unlike gold, which you can hold, Bitcoin lives on the internet.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Magic of Bitcoin: Simple Analogies
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Bitcoin Transactions: Passing Notes in Class
&lt;/h3&gt;

&lt;p&gt;Imagine you're in a classroom where everyone communicates by passing notes. When Alice wants to send Bitcoin to Bob, she writes a note that says, "I'm giving 1 Bitcoin to Bob." She signs it with a special code (her digital signature) that proves the note is genuinely from her. This note is then passed around the entire classroom (the Bitcoin network), so everyone knows about the transaction. This is how a Bitcoin transaction works—except, in this case, the classroom is the entire world.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Ledger: A Public Bulletin Board
&lt;/h3&gt;

&lt;p&gt;Every note passed in the classroom is pinned to a public bulletin board (the Bitcoin ledger), for everyone to see. This board keeps track of all transactions, ensuring that everyone knows who owns what. It prevents cheating, like someone trying to spend their Bitcoin twice. This bulletin board isn't controlled by any single person but is maintained collectively by the class (the decentralized Bitcoin network), making it transparent and secure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mining: The Puzzle Contest
&lt;/h3&gt;

&lt;p&gt;Now, how do we ensure that the notes (transactions) are valid and get added to the bulletin board correctly? Enter the Bitcoin miners. Imagine a contest where students (miners) solve a complex puzzle (the mining process). The first one to solve the puzzle gets to pin the notes on the board and, as a reward, receives a new note (newly minted Bitcoin). This not only validates transactions but also creates new Bitcoin, mimicking the mining of gold but in a digital form.&lt;/p&gt;

&lt;h3&gt;
  
  
  Security: A Chain of Sealed Envelopes
&lt;/h3&gt;

&lt;p&gt;Every time a batch of notes is pinned to the board, it's as if they're placed in a sealed envelope (a block) that is transparent yet unbreakable. Each new envelope is connected to the previous one, forming a chain (the blockchain). To alter a note inside an envelope, one would need to break open every subsequent envelope and reseal them—a task so difficult that it's considered impossible, ensuring the integrity and security of the history of notes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Bitcoin?
&lt;/h2&gt;

&lt;p&gt;Bitcoin is not just digital money; it's a new way of thinking about financial transactions. Unlike traditional banking, where transactions are controlled by banks, Bitcoin operates on a peer-to-peer network, similar to our classroom analogy. This means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Direct Transactions:&lt;/strong&gt; Alice can send Bitcoin to Bob directly, without needing a bank to approve or facilitate the transfer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lower Fees:&lt;/strong&gt; Without banks as middlemen, the transaction fees can be lower.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Global Currency:&lt;/strong&gt; Bitcoin is not tied to any country or subject to their regulations, making it a truly global currency.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security and Privacy:&lt;/strong&gt; Transactions are secure and private, thanks to the cryptographic techniques used.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Bitcoin is a pioneering form of digital currency that offers a new perspective on money and transactions. By understanding it through simple analogies, we can appreciate the genius behind its design and the potential it holds for transforming the financial landscape. Just as the internet revolutionized how we share information, Bitcoin is poised to redefine how we think about and use money.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>CVE Scanner GitHub Action</title>
      <dc:creator>0xkniraj</dc:creator>
      <pubDate>Thu, 03 Sep 2020 06:26:19 +0000</pubDate>
      <link>https://dev.to/kniraj/cve-scanner-github-action-5f60</link>
      <guid>https://dev.to/kniraj/cve-scanner-github-action-5f60</guid>
      <description>&lt;h3&gt;
  
  
  My Workflow
&lt;/h3&gt;

&lt;p&gt;I have created a GitHub action to scan CVEs(&lt;a href="https://en.wikipedia.org/wiki/Common_Vulnerabilities_and_Exposures" rel="noopener noreferrer"&gt;Common Vulnerabilities and Exposures&lt;/a&gt;) from binary packages. My action uses &lt;a href="https://github.com/intel/cve-bin-tool" rel="noopener noreferrer"&gt;cve-bin-tool&lt;/a&gt; to scan CVEs from binary packages and generates a detailed report and upload it as an &lt;a href="https://docs.github.com/en/rest/reference/actions#artifacts" rel="noopener noreferrer"&gt;artifact&lt;/a&gt; which can be downloaded anytime. I am also using &lt;a href="https://github.com/actions/cache" rel="noopener noreferrer"&gt;actions/cache&lt;/a&gt; to reduce the runtime of the action.&lt;/p&gt;

&lt;p&gt;If you are a developer who develops binary packages and libraries then I recommend integrating this action as a part of your CI pipeline so that you will get to know about common vulnerabilities found in the libraries you are using, and take actions to mitigate it. &lt;/p&gt;

&lt;p&gt;The most recommended way to fix a given CVE is to upgrade the package to a non-vulnerable version. Ideally, a CVE is only made public after a fix is available, although this is not always the case. If this is not possible for some reason, search for the CVE number to get information on possible workarounds and patches that could be backported to other versions. Note that neither workarounds nor backported fixes can be detected by this tool, so your binary will continue to show up as vulnerable even though it may now be safely mitigated and result in a false positive. To avoid this problem, I recommend classifying CVE as Mitigated. See &lt;a href="https://github.com/intel/cve-bin-tool/blob/master/doc/MANUAL.md" rel="noopener noreferrer"&gt;User Manual of the cve-bin-tool&lt;/a&gt; for more details.&lt;/p&gt;

&lt;h3&gt;
  
  
  Submission Category:
&lt;/h3&gt;

&lt;p&gt;Maintainer Must-Haves&lt;/p&gt;

&lt;h3&gt;
  
  
  Yaml File or Link to Code
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;CVE scanner&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="c1"&gt;#    You can customize this according to your need.&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;push&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;pull_request&lt;/span&gt;
&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build_and_scan&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Get date utility for caching database.&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Get Date&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;get-date&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;echo "::set-output name=date::$(/bin/date -u "+%Y%m%d")"&lt;/span&gt;
        &lt;span class="na"&gt;shell&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bash&lt;/span&gt;
    &lt;span class="c1"&gt;#  Let's first download dependencies for this action.&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up Python&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-python@v2&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;python-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3.8&lt;/span&gt;
    &lt;span class="c1"&gt;#  This second step is unnecessary but highly recommended because&lt;/span&gt;
    &lt;span class="c1"&gt;#  it will cache database and saves time redownloading it&lt;/span&gt;
    &lt;span class="c1"&gt;#  if database isn't stale.&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;get cached python packages&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/cache@v2&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;~/.cache/pip&lt;/span&gt;
          &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}&lt;/span&gt;
          &lt;span class="na"&gt;restore-keys&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
            &lt;span class="s"&gt;${{ runner.os }}-pip-&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;get cached database&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/cache@v2&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;~/.cache/cve-bin-tool&lt;/span&gt;
          &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ runner.os }}-cve-bin-tool-${{ steps.get-date.outputs.date }}&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install CVE Binary Tool&lt;/span&gt;
&lt;span class="c1"&gt;#          We are using the latest development version of cve-bin-tool&lt;/span&gt;
&lt;span class="c1"&gt;#          because current PyPI version don't have features like&lt;/span&gt;
&lt;span class="c1"&gt;#          config file support, generating an HTML report, etc.&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pip install git+https://github.com/intel/cve-bin-tool@master&lt;/span&gt;
&lt;span class="c1"&gt;#          In case you prefer current PyPI version, &lt;/span&gt;
&lt;span class="c1"&gt;#          you need to hard code CLI options&lt;/span&gt;
&lt;span class="c1"&gt;#          for cve-bin-tool in the action itself and &lt;/span&gt;
&lt;span class="c1"&gt;#          have to use CSV or JSON as output format.&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build package&lt;/span&gt;
&lt;span class="c1"&gt;#          Here, we are building a Python wheel for this example.&lt;/span&gt;
&lt;span class="c1"&gt;#          You need to replace this with your build process.&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;pip install wheel&lt;/span&gt;
          &lt;span class="s"&gt;python setup.py bdist_wheel&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Scan built package&lt;/span&gt;
&lt;span class="c1"&gt;#          Now, we will scan the built wheel &lt;/span&gt;
&lt;span class="c1"&gt;#          which is situated in "/dist" directory&lt;/span&gt;
&lt;span class="c1"&gt;#          Python stores built packages in /dist directory.&lt;/span&gt;
&lt;span class="c1"&gt;#          You need to replace it with the directory&lt;/span&gt;
&lt;span class="c1"&gt;#          where you have stored built package&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cve-bin-tool dist -f html -o cve-bin-tool-report.html -x&lt;/span&gt;
&lt;span class="c1"&gt;#          Alternatively if you have written config file&lt;/span&gt;
&lt;span class="c1"&gt;#          for cve-bin-tool you can use the following command&lt;/span&gt;
&lt;span class="c1"&gt;#          cve-bin-tool -C path/to/cve_bin_tool_config.toml&lt;/span&gt;
        &lt;span class="na"&gt;continue-on-error&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="c1"&gt;#          You need to set continue_on_error: true because &lt;/span&gt;
&lt;span class="c1"&gt;#          CVE Binary Tool sets the number of product with CVEs&lt;/span&gt;
&lt;span class="c1"&gt;#          as exit code. And GitHub terminate the action &lt;/span&gt;
&lt;span class="c1"&gt;#          when the process produces nonzero exit code status.&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Upload report as an artifact&lt;/span&gt;
&lt;span class="c1"&gt;#        This will upload the generated report as &lt;/span&gt;
&lt;span class="c1"&gt;#        a GitHub artifact which you can download later.&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/upload-artifact@v2&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cve_report&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;cve-bin-tool-report.html'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Additional Resources / Info
&lt;/h3&gt;

&lt;p&gt;I have also contributed this action to the cve-bin-tool. You can also find this in the &lt;a href="https://github.com/intel/cve-bin-tool/blob/master/doc/how_to_guides/cve_scanner_gh_action.yml" rel="noopener noreferrer"&gt;how-to-guides&lt;/a&gt; directory of the official cve-bin-tool repository. &lt;/p&gt;

&lt;p&gt;You can also see my pull-request to cve-bin-tool for this action &lt;a href="https://github.com/intel/cve-bin-tool/pull/894" rel="noopener noreferrer"&gt;here&lt;/a&gt; and discussion on the associated issue &lt;a href="https://github.com/intel/cve-bin-tool/issues/272" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I have also tested this action on my other project and it is working fine. You can see an example run of the action &lt;a href="https://github.com/Niraj-Kamdar/qpt_generator/actions/runs/219903197" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>actionshackathon</category>
      <category>security</category>
      <category>cve</category>
    </item>
    <item>
      <title>CVE Binary Tool: GSoC Final Report</title>
      <dc:creator>0xkniraj</dc:creator>
      <pubDate>Sat, 29 Aug 2020 12:08:46 +0000</pubDate>
      <link>https://dev.to/kniraj/cve-binary-tool-gsoc-final-report-4nlk</link>
      <guid>https://dev.to/kniraj/cve-binary-tool-gsoc-final-report-4nlk</guid>
      <description>&lt;p&gt;Google Summer of Code 2020 is finally coming to an end, and what an exciting experience it has been! In this post, I’ll be showing off the fruits of my labor.&lt;/p&gt;

&lt;p&gt;I have created an example GitHub action workflow last week, and that marks the last major milestone of my GSoC project &lt;a href="https://summerofcode.withgoogle.com/projects/#6087450172063744" rel="noopener noreferrer"&gt;Improve concurrency and input functionality&lt;/a&gt;. I’m very glad that I was able to finish all the major milestones in time. Below I’ll give a quick summary of my journey.&lt;/p&gt;

&lt;h2&gt;
  
  
  About the Project
&lt;/h2&gt;

&lt;p&gt;Before going into the details, I would like to give a brief introduction to the project for the uninitiated. You can skip this section if you are already familiar with it.&lt;/p&gt;

&lt;p&gt;My project was to &lt;strong&gt;Improve concurrency and input functionality&lt;/strong&gt; of &lt;em&gt;CVE Binary Tool&lt;/em&gt;. The &lt;em&gt;CVE Binary Tool&lt;/em&gt; scans for several common, vulnerable open source components such as OpenSSL, libpng, libxml2, etc. to let you know if a given directory or binary file includes common libraries with known vulnerabilities, known as CVEs (&lt;a href="https://en.wikipedia.org/wiki/Common_Vulnerabilities_and_Exposures" rel="noopener noreferrer"&gt;Common Vulnerabilities and Exposures&lt;/a&gt;). It is written in my favorite language &lt;strong&gt;Python&lt;/strong&gt;. It is available as a python package and you can get it from &lt;a href="https://pypi.org/project/cve-bin-tool/" rel="noopener noreferrer"&gt;PyPI&lt;/a&gt;. You can view the source code from &lt;a href="https://github.com/intel/cve-bin-tool" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt; and it's maintained by &lt;a href="https://github.com/terriko" rel="noopener noreferrer"&gt;Terri Oda&lt;/a&gt; and &lt;a href="https://github.com/pdxjohnny" rel="noopener noreferrer"&gt;John Andersen&lt;/a&gt;. They are also my mentors for this project.&lt;/p&gt;

&lt;p&gt;When I started working on the project, &lt;em&gt;CVE Binary Tool&lt;/em&gt; has &lt;a href="https://github.com/intel/cve-bin-tool/issues/369" rel="noopener noreferrer"&gt;some bugs&lt;/a&gt; under Windows platform and since I use Windows primarily, I have fixed all Windows bugs in the community bonding period. I have also written &lt;a href="https://github.com/intel/cve-bin-tool/pull/655" rel="noopener noreferrer"&gt;faster native python solution&lt;/a&gt; to replace the c-strings extension module and &lt;a href="https://github.com/intel/cve-bin-tool/pull/656" rel="noopener noreferrer"&gt;refactored whole checkers module&lt;/a&gt; to use &lt;strong&gt;object-oriented design&lt;/strong&gt; to reduce repetition of code in community bonding period. Since we have removed support for Python2 in the last release, I have also optimized the legacy Python2 code for Python3. &lt;/p&gt;

&lt;h2&gt;
  
  
  The First Milestone: Improve Test Suite
&lt;/h2&gt;

&lt;p&gt;I wanted to improve tests of CVE Binary Tool because CI runtime was too long and there was an initialization missing which was failing the test when we run tests locally.&lt;/p&gt;

&lt;p&gt;I have &lt;a href="https://github.com/intel/cve-bin-tool/pull/716" rel="noopener noreferrer"&gt;removed compiler dependencies from test suite&lt;/a&gt; in favor of native python solution. I have also fixed the tricky &lt;a href="https://github.com/intel/cve-bin-tool/pull/672" rel="noopener noreferrer"&gt;pytest initialization bug&lt;/a&gt; by researching and understanding the origin of the bug. I have also gradually improved the test suite of every module by migrating it to pytest from standard unittest and using &lt;code&gt;pytest-xdist&lt;/code&gt; to optimize runtime. (EX: &lt;a href="https://github.com/intel/cve-bin-tool/pull/772" rel="noopener noreferrer"&gt;parallelization of test_json&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Second Milestone: Improve Concurrency
&lt;/h2&gt;

&lt;p&gt;Previously, CVE Binary Tool was using multiprocessing for downloading &lt;a href="https://nvd.nist.gov/vuln/data-feeds" rel="noopener noreferrer"&gt;NVD data-feeds&lt;/a&gt;. Since downloading is an IO-bound task, I suggested that &lt;a href="https://docs.python.org/3/library/asyncio.html" rel="noopener noreferrer"&gt;asyncio&lt;/a&gt; would be the better choice for this use-case.&lt;/p&gt;

&lt;p&gt;I have refactored almost all IO-bound modules to use &lt;em&gt;asyncio&lt;/em&gt;. I have also developed many &lt;a href="https://github.com/intel/cve-bin-tool/blob/master/cve_bin_tool/async_utils.py" rel="noopener noreferrer"&gt;async-utilities&lt;/a&gt; for various modules. The following are all the pull-requests regarding my work on improving the concurrency of the tool.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/intel/cve-bin-tool/pull/741" rel="noopener noreferrer"&gt;Asynchronous extractor module&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/intel/cve-bin-tool/pull/746" rel="noopener noreferrer"&gt;Asynchronous strings module&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/intel/cve-bin-tool/pull/751" rel="noopener noreferrer"&gt;Asynchronous file module&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/intel/cve-bin-tool/pull/758" rel="noopener noreferrer"&gt;Asynchronous cvedb module&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The main performance gain was the reduction in downloading time by &lt;strong&gt;50%&lt;/strong&gt; after switching to &lt;em&gt;asyncio&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Third Milestone: Improve Input Functionality
&lt;/h2&gt;

&lt;p&gt;CVE Binary Tool had a command named &lt;em&gt;csv2cve&lt;/em&gt; to get CVEs from the CSV formatted input. My goal was to replace it with a generic &lt;em&gt;InputEngine&lt;/em&gt; module which can support various input types. Currently, It supports CSV and JSON as a valid input data type. I have also added support for specifying triage data for CVEs like remarks(Ex: Mitigated, Ignored, etc.), comments, custom severity, etc.&lt;/p&gt;

&lt;p&gt;Since CVE Binary Tool has several command-line arguments, I decided to add support for config files so that users don't have to repeatedly specify these arguments every time S/he wants to scan a directory. It can also be helpful in automated environments like CI/CD pipelines. Below is a list of my pull-requests related to this milestone.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/intel/cve-bin-tool/pull/777" rel="noopener noreferrer"&gt;Added InputEngine with remarks functionality&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/intel/cve-bin-tool/pull/827" rel="noopener noreferrer"&gt;InputEngine: comments and custom severity support&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/intel/cve-bin-tool/pull/860" rel="noopener noreferrer"&gt;Fixed path problem for InputEngine and reduce complexity of CVEScanner&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/intel/cve-bin-tool/pull/846" rel="noopener noreferrer"&gt;Added support for config files&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/intel/cve-bin-tool/pull/857" rel="noopener noreferrer"&gt;Documented usage of config file and input file&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Final Milestone: Improve User Experience
&lt;/h2&gt;

&lt;p&gt;We're lucky to have &lt;a href="https://github.com/anthonyharrison" rel="noopener noreferrer"&gt;Anthony&lt;/a&gt; (a user) who was willing to attend our weekly meeting. He suggested many features and documentation that would be helpful to him and other users. I have contributed &lt;a href="https://github.com/intel/cve-bin-tool/tree/master/doc/how_to_guides" rel="noopener noreferrer"&gt;how-to-guides&lt;/a&gt;(essentially a cookbook of recipes) for different use-cases. &lt;/p&gt;

&lt;p&gt;I have also created an error handler module to provide beautiful traceback using &lt;a href="https://pypi.org/project/rich/" rel="noopener noreferrer"&gt;rich&lt;/a&gt; library and set custom exit-code according to exception so that the user can know why program terminated under quiet mode or automation script.&lt;/p&gt;

&lt;p&gt;Here is the list of all my pull-requests related to this goal.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/intel/cve-bin-tool/pull/864" rel="noopener noreferrer"&gt;Documentation: Add how to guides&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/intel/cve-bin-tool/pull/894" rel="noopener noreferrer"&gt;Example yml workflow to run CVE Binary Tool in github actions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/intel/cve-bin-tool/pull/798" rel="noopener noreferrer"&gt;Improved error handling with beautiful trace and exit code in cli, input_engine and cvedb&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/intel/cve-bin-tool/pull/826" rel="noopener noreferrer"&gt;Improved error handling and readability of extractor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/intel/cve-bin-tool/pull/828" rel="noopener noreferrer"&gt;OutputEngine: Modernize error handling&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/intel/cve-bin-tool/pull/829" rel="noopener noreferrer"&gt;OutputEngine: Fix generate_filename args signature&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Future Work
&lt;/h2&gt;

&lt;p&gt;My original proposal was huge and due to limited time, I have to prioritize my goals according to user requirements. I have fully completed my core goal of improving input functionality and user experience but I still have many optimizations in my mind for the concurrency aspect of the project. So, I am going to continue my work on &lt;a href="https://github.com/intel/cve-bin-tool/issues/643" rel="noopener noreferrer"&gt;improving the performance of CVE Binary Tool&lt;/a&gt;. I also want to optimize runtime of the long tests because it is taking 30 minutes to run all tests and I believe we can optimize it significantly by caching and/or reducing the test data that need to be downloaded for testing. I also want to create a ready to use GitHub action for the tool so that developer can integrate it easily as a part of their CI/CD pipeline.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I gained from GSoC
&lt;/h2&gt;

&lt;p&gt;The amount of experience I gained from working on &lt;em&gt;CVE Binary Tool&lt;/em&gt; with Terri Oda and John Andersen is immeasurable. Both my mentors are kind, helpful, and extremely talented. They have given me many advice and suggestions from low-level working of language to the best practices about writing good code.&lt;/p&gt;

&lt;p&gt;Terri Oda helped me improve my PR(pull-request) quality by suggesting articles about best practices. She also helped me understand what tasks should be prioritized. While John Andersen helped me with a lot of things about python in general like metaclasses, asyncio, context-manager, etc. &lt;/p&gt;

&lt;p&gt;Before GSoC, I only knew basic git commands but now I can confidently say that I have mastered git. I also have a much better understanding of how programming languages work, when and how to choose third-party libraries, how to refer to documentation efficiently, how to write clean, readable and maintainable code, how to document and test code effectively, how to properly structure pull-requests and most importantly how &lt;em&gt;practical&lt;/em&gt; programming works, which I wouldn’t have known otherwise.&lt;/p&gt;

&lt;p&gt;Opensource has become my hobby now because being part of an opensource community, I have learned that as an opensource contributor apart from making code contributions, I also get to triage and resolve user issues and review other contributors' pull-requests. I can also guide and motivate new contributors. I won't get this kind of experience if I just do my personal projects.&lt;/p&gt;

&lt;p&gt;All these lessons are invaluable to me and I strongly believe it will be helpful to me throughout my career.&lt;/p&gt;

</description>
      <category>gsoc</category>
      <category>python</category>
      <category>security</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
