Bitcoin Pocket Node

Full node on your phone in under 20 minutes
No days-long sync. No trusted third parties.

~13 GB
Total disk (11 GB chainstate + 2 GB blocks)
20 min
Zero to full node
v28.1
Bitcoin Core

The Problem

Running a node on a phone shouldn't take days

🐌
Traditional Sync
3–7 days
Download entire blockchain
Validate every block since 2009
~600 GB of data
AssumeUTXO
3 hours
Faster start, but still needs
full background validation
Uses more disk space
Chainstate Copy
20 min
Copy verified state from
your own trusted node
Instant full validation

Prerequisites

What you need

🖥️
Source Node
Any Bitcoin Core node
Umbrel, RaspiBlitz, etc.
unpruned preferred
+
📱
Android Phone
ARM64 (Pixel, Samsung, etc.)
~15 GB free space
same WiFi network

Both devices on the same local network. The phone copies directly from your own node - no external servers involved.

Step 1

Stop the source node & copy chainstate

📂 bitcoin/
  📂 chainstate/ ~11 GB
    UTXO database (own internal key)
  📂 blocks/index/ ~500 MB
    Block location index
  🔑 blocks/xor.dat 8 bytes
    Block file obfuscation key
  📂 blocks/ ~600 GB ✗
    NOT copied (too large)
1
Chainstate (~11 GB)
The UTXO set - every unspent output on the network. This is Bitcoin's current state.
2
XOR Key (8 bytes)
Since Core 28, xor.dat is used for block file data obfuscation - each node generates a unique key. The key must travel with the block files. (The chainstate has its own separate internal obfuscation key.)
Without this file, the block data can't be decoded correctly - bitcoind sees corrupt block files and refuses to start!
3
Block Index (~500 MB)
Maps block hashes to file locations. Needed so bitcoind knows what it has.

Step 2

The stub file trick

The block index references hundreds of blk*.dat files. If they're missing, bitcoind crashes.

But we don't need the actual block data - just the files to exist.

Solution: create empty stub files for every block file the index expects.

Bitcoind reads the stub files, finds them empty, and begins backfilling them in pruned mode - only keeping the most recent blocks and discarding old ones as it goes.
📂 blocks/
  📂 index/ copied
  📄 blk00000.dat 0 bytes
  📄 blk00001.dat 0 bytes
  📄 blk00002.dat 0 bytes
  📄 ...
  📄 blk00734.dat 0 bytes
  📄 rev00000.dat 0 bytes
  📄 rev00001.dat 0 bytes
  📄 ...
  📄 blk00734.dat tip blocks
~1,470 stub files = 0 bytes total

Step 3

Copy the tip blocks

?
Why not just chainstate?
Bitcoind needs the most recent blocks to verify the chain tip. Without them, it can't validate new incoming blocks.
4
Copy last ~10 blocks
Only the blocks in the final blk*.dat file. Usually 10-50 MB - tiny compared to 600 GB.
5
Plus matching rev*.dat
Undo data for the tip blocks. Needed for reorg handling.
The block index tells us which blk*.dat file has the chain tip. We only need that one file - everything else is stubs.
What gets copied
11 GB
Chainstate
500 MB
Block Index
~50 MB
Tip Blocks
Total: ~11.5 GB
vs 600+ GB full blockchain

Step 4

Transfer over local network

🖥️
Source Node
Umbrel / raspi / PC
📱
Phone
Pixel 7 Pro
📡
WiFi LAN Transfer
~11.5 GB over local WiFi. At 50 MB/s = ~4 minutes. At 10 MB/s = ~20 minutes. No internet needed.
🔒
Trust Model
You're copying from your own node that already validated everything. No trusted third party. Same security as running the source node.

Step 5

Start bitcoind & catch up

1
Loading block index...
Bitcoind reads the index, sees all block references. Stub files satisfy existence checks.
2
Verifying chainstate...
Quick validation of the UTXO database integrity. Takes seconds.
Pruning takes over
This is normal pruned node behaviour - bitcoind finds empty block files, recognises them as pruned, and continues forward keeping only recent blocks. With prune=2048 it maintains ~2 GB of recent block data. Total disk usage is ~13 GB including the 11 GB chainstate (UTXO set).
We're deliberately creating the conditions that trigger standard pruning. No hacks - just giving bitcoind a valid chainstate and letting its built-in pruning logic do the rest.
4
Catching up to chain tip
Downloads and validates only the blocks mined since the copy. Usually minutes' worth.
Fully synced!
Your phone is now a fully-validating Bitcoin node. Verifies every transaction. Trusts no one.

Making it work on mobile

Challenges solved

4
Why only 4 peers?
Default Bitcoin Core connects to 8-10 peers. On a phone, each peer costs battery and bandwidth. maxconnections=4 keeps the node fully validated while cutting resource use in half.
🔄
Orphan process survival
Android kills apps aggressively. If the app dies, bitcoind keeps running as an orphan holding the lock file. On restart, the app detects and re-attaches via RPC instead of crashing.
📱
Auto-start on boot
Phones restart nightly (GrapheneOS). A boot receiver re-launches the node automatically - zero downtime without user intervention.
📶
Metered network detection
VPN over cellular looks like WiFi to Android. We detect metered connections and warn before syncing over mobile data - blocks are ~2 MB each.
🔮
Sovereign price discovery
UTXOracle derives the BTC/USD price from on-chain transaction patterns. Zero external APIs. Updates incrementally with each new block (~4 seconds).
Built-in Electrum server
Pure Kotlin Electrum server runs alongside bitcoind, serving your wallet over localhost. BlueWallet connects directly - your keys, your node, your rules.

Result

A real node in your pocket

📱
✅ Synced
Block 937,162
4 peers connected
~13 GB total
Validates every transaction Enforces consensus rules
Built-in Electrum server BlueWallet compatible
UTXOracle price feed No external APIs
Auto-start on boot Metered network detection

From zero to sovereign in 20 minutes.
github.com/FreeOnlineUser/bitcoin-pocket-node

1 / 10