Part 3 of my anchor outputs learning series - getting the service running and seeing it in action
Quick Recap
Part 1: The problem - commitment transactions with outdated fees get stuck
Part 2: The solution - anchor outputs let you boost fees later using CPFP
Part 3 (this one): Actually building a service that does this
What We're Building
A service that:
- Monitors the Bitcoin mempool for commitment transactions
- Detects anchor outputs (330 sat outputs)
- Calculates CPFP fee requirements
- Provides a REST API to estimate and request fee bumps
Important: We're using Bitcoin regtest network for this.
GitHub Repository: lightning-anchor-fee-outputs
System Requirements
Before you start:
- Node.js 18 or higher
- Docker Desktop (for Bitcoin Core and LND)
Operating Systems: Works on macOS, Linux, and Windows (with WSL2)
Setup Instructions
Step 1: Clone and Install
git clone https://github.com/SusanGithaigaN/lightning-anchor-fee-outputs.git
cd lightning-anchor-fee-service
npm install
Step 2: Start Docker Services
docker compose up -d
This starts:
- Bitcoin Core (regtest network)
- LND (Lightning node)
- PostgreSQL
- Redis
Step 3: Setup Bitcoin Regtest
i) Create Bitcoin wallet
docker compose exec bitcoin bitcoin-cli -regtest -rpcuser=bitcoinrpc -rpcpassword=changeme createwallet "mywallet"
ii) Mine 101 blocks
docker compose exec bitcoin bitcoin-cli -regtest -rpcuser=bitcoinrpc -rpcpassword=changeme -generate 101
If you already created the LND wallet before (you'll get this error), just verify it's working:
docker compose exec lnd lncli --network=regtest getinfo
Step 4: Setup LND Wallet
docker compose exec lnd lncli --network=regtest create
Follow the prompts:
- Enter a password
- Select
nto create a new seed - Write down the 24 words (optional for regtest)
- Press Enter for cipher passphrase
Step 5: Start the Service
npm run dev
You should see:
Server running on port 3000
Connected to Bitcoin Core
Testing the Service
Test 1: Health Check
curl http://localhost:3000/health
Expected: {"status":"ok"}
Test 2: Bitcoin Connection
curl http://localhost:3000/api/v1/bitcoin/info
You should see: Chain info showing regtest network with 101 blocks.
Test 3: LND Connection
curl http://localhost:3000/api/v1/lightning/info
You should see: Node info with anchor outputs feature enabled (check for "anchors-zero-fee-htlc-tx").
Test 4: Start Monitoring
curl -X POST http://localhost:3000/api/v1/monitor/start \
-H "Content-Type: application/json" \
-d '{"intervalMs": 3000}'
Expected: {"success":true,"message":"Monitoring started","intervalMs":3000}
Test 5: Create Test Transaction
# Get a new address
ADDR=$(docker compose exec bitcoin bitcoin-cli -regtest -rpcuser=bitcoinrpc -rpcpassword=changeme getnewaddress)
# Send 330 sats (creates anchor-like output)
TXID=$(docker compose exec bitcoin bitcoin-cli -regtest -rpcuser=bitcoinrpc -rpcpassword=changeme sendtoaddress $ADDR 0.00000330)
echo "Transaction ID: $TXID"
Test 6: Check Monitor Status
Wait 5 seconds, then:
curl http://localhost:3000/api/v1/monitor/status
You should see: Your transaction being tracked with detected anchor output.
Example response:
{"success":true,"data":{"isMonitoring":true,"trackedCount":1,"transactions":[{"txid":"b3f593509ba7efa9eabeedd159bcc158980917f4804f6a1be8163708c5542c5b","hex":"02000000000101c1de4dab5c406faad339b4e7ed3998a2c9286ee8d7e08eecc4cdd56cb1f98d980000000000fdffffff0243f8029500000000160014ba6345572da5d28ea9830dfc0476826c4bb10c8b4a010000000000001600142935034b935612bc85089f89fca385ba9a78791e0247304402205abef31db372537d0f3ab2f4b5240dbdc6dd7367fe64384e1e58669f4a1a686e022049e7e8d418d18b8328070dad0251b6aefc6b0023b6ed914f34797a40111a9df5012103bb47542f3fe2dd313e221de0620dd733f0766e00d52eb90e222c06aa090aec9e30010000","fee":0,"size":141,"feeRate":0,"anchorOutputs":[{"vout":1,"value":330,"scriptPubKey":"00142935034b935612bc85089f89fca385ba9a78791e"}]}]}}
Test 7: Estimate Fee Bump
curl -X POST http://localhost:3000/api/v1/feebump/estimate \
-H "Content-Type: application/json" \
-d "{\"txid\": \"$TXID\", \"targetFeeRate\": 10}"
You should see: Fee calculations showing that 10 sats/vbyte is NOT feasible with just the 330 sat anchor alone. This proves the limitation.
Expected result: "feasible": false
This means you'd need to add ~2,180 sats from your own wallet to bump to 10 sats/vbyte.
Example result
susan@susan-githaiga:~/development/projects/lightning-anchor-fee-outputs$ curl -X POST http://localhost:3000/api/v1/feebump/estimate \uts$ curl -X POST http://localhost:3000/api/v1/feebump/estimate \
-H "Content-Type: application/json" \
-d "{\"txid\": \"$TXID\", \"targetFeeRate\": 10}"
{"success":true,"data":{"txid":"b3f593509ba7efa9eabeedd159bcc158980917f4804f6a1be8163708c5542c5b","parentSize":141,"parentFee":0,"parentFeeRate":0,"childSize":110,"totalSize":251,"targetFeeRate":10,"totalFeeNeeded":2510,"childFeeNeeded":2510,"anchorValue":330,"feasible":false}}
Test with a lower fee rate (should be feasible):
curl -X POST http://localhost:3000/api/v1/feebump/estimate \
-H "Content-Type: application/json" \
-d "{\"txid\": \"$TXID\", \"targetFeeRate\": 1}"
Result
susan@susan-githaiga:~/development/projects/lightning-anchor-fee-outputs$ # Test with 1 sat/vbyte (should be feasible)ts$ # Test with 1 sat/vbyte (should be feasible)
curl -X POST http://localhost:3000/api/v1/feebump/estimate \
-H "Content-Type: application/json" \
-d "{\"txid\": \"$TXID\", \"targetFeeRate\": 1}"
{"success":true,"data":{"txid":"b3f593509ba7efa9eabeedd159bcc158980917f4804f6a1be8163708c5542c5b","parentSize":141,"parentFee":0,"parentFeeRate":0,"childSize":110,"totalSize":251,"targetFeeRate":1,"totalFeeNeeded":251,"childFeeNeeded":251,"anchorValue":330,"feasible":true}}
This should show "feasible": true because 251 vbytes × 1 sat/vbyte = only 251 sats needed
Understanding the Results
When you check the monitor status, look for:
✅ trackedCount: 1 - Service detected your transaction
✅ value: 330 - Confirmed it's an anchor output
✅ anchorOutputs array - Shows which outputs are anchors
When you estimate fees:
✅ feasible: true - Can bump with just the anchor
❌ feasible: false - Need additional inputs from wallet
Key insight: 330 sats can only bump to about 10-20 sats/vbyte maximum.
Troubleshooting
Port conflicts?
sudo systemctl stop redis-server postgresql
docker compose restart
Services not starting?
docker compose logs bitcoin
docker compose logs lnd
Monitor not detecting transactions?
Make sure the transaction is in mempool (not confirmed yet). Don't mine blocks immediately after sending!
What We Built
Here's what the service does:
1. Bitcoin Integration
- Connects to Bitcoin Core via RPC
- Monitors mempool every 3-10 seconds
- Fetches transaction details
2. Anchor Detection
- Scans all transaction outputs
- Identifies 330 satoshi outputs
- Tracks them as potential anchors
3. Fee Estimation
- Calculates parent transaction size
- Estimates child transaction size (~110 vbytes)
- Computes package fee rate
- Determines if anchor alone is sufficient
4. REST API
- Start/stop monitoring
- Check status and tracked transactions
- Estimate fee bump requirements
- Bitcoin and Lightning info endpoints
Key Learnings
1. The 330 Sat Limitation is Real
Anchor outputs can only bump fees to ~10-20 sats/vbyte. For higher rates, you need additional UTXOs from your wallet.
Example:
- Target: 50 sats/vbyte
- Parent + Child: 330 vbytes
- Total fee needed: 16,500 sats
- Anchor provides: 330 sats
- Need to add: 16,170 sats from wallet
2. Regtest Makes Testing Easy
- Free Bitcoin (just mine blocks)
- Instant blocks (no waiting)
- No risk of losing real money
- Perfect for learning and development
3. Monitoring is the Easy Part
Detecting 330 sat outputs in the mempool is straightforward. The hard part comes next: signing and broadcasting CPFP transactions.
4. Production Needs Reserve Funds
Real implementations maintain a pool of UTXOs specifically for fee bumping. You can't rely on the anchor alone.
5. Docker Simplifies Setup
Bitcoin Core and LND in Docker means:
- No system pollution
- Easy cleanup
- Consistent environment
- Works everywhere
What's Next
Current Status: ✅ Monitoring and estimation work
Still Missing: ❌ Actual transaction signing and broadcasting
Part 4 will cover:
- Wallet integration for additional inputs
- Building and signing CPFP transactions
- Broadcasting to Bitcoin mainnet network
- Testing with real Lightning channels
- Accepting Lightning payments for the service
Future improvements:
- Automatic fee bumping (no manual trigger)
- Multiple channel support
- Reserve fund management
- Web dashboard
- Mainnet deployment
Resources
- GitHub:Repository
- Part 1: The Basics
- Part 2: Technical Deep Dive
- Bitcoin Regtest Guide
- LND Regtest Setup
If you have any questions or suggestions, drop them in the comments






Top comments (0)