docs: Add presentation deck

This commit is contained in:
Breno Brito
2026-02-27 11:07:25 -03:00
parent b8e4f03695
commit 87f56c14f9
5 changed files with 550 additions and 153 deletions
+7
View File
@@ -3,3 +3,10 @@ dist/
.env
.env.local
*.local
.DS_Store
.specstory
.cursorindexingignore
.cursor
.vscode
.pnpm-store
.qwen
+22
View File
@@ -0,0 +1,22 @@
<svg xmlns="http://www.w3.org/2000/svg" width="460" height="96" viewBox="0 0 460 96" role="img" aria-labelledby="title desc">
<title id="title">Chainalysis logo</title>
<desc id="desc">Chainalysis wordmark</desc>
<defs>
<linearGradient id="orange" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#ff8a34" />
<stop offset="100%" stop-color="#ff5a1f" />
</linearGradient>
</defs>
<text
x="8"
y="66"
font-family="Inter, Arial, sans-serif"
font-size="62"
font-weight="700"
letter-spacing="-1.4"
fill="#ff6f2c"
>
Chainalysis
</text>
</svg>

After

Width:  |  Height:  |  Size: 621 B

Binary file not shown.
+232 -99
View File
@@ -9,72 +9,133 @@ fonts:
lineNumbers: false
drawings:
persist: false
transition: slide
transition: fade
colorSchema: dark
mdc: true
---
# STEAL<span class="accent">TH</span>
### Bitcoin Wallet Privacy Analyzer
A privacy audit tool that surfaces vulnerabilities at the UTXO level.
<div class="hero-wrap">
<h1 class="hero-title">STEAL<span class="accent">TH</span></h1>
<p class="hero-subtitle">Bitcoin Wallet Privacy Analyzer</p>
<p class="hero-copy">A read-only audit engine that surfaces wallet exposure at the UTXO level before funds move.</p>
<div class="hero-chips">
<span class="chip chip-safe">No keys</span>
<span class="chip">UTXO-level findings</span>
<span class="chip">Self-hostable</span>
</div>
</div>
---
# The Problem
<div class="grid grid-cols-2 gap-8">
<div>
**Bitcoin privacy is fragile**
- Chain analysis firms track wallets
- Common heuristics link addresses
- Users rarely know their exposure
- One bad UTXO can taint the rest
</div>
<div>
**Today's tools**
- Complex, require expertise
- No UTXO-level visibility
- Hard to understand risk before spending
</div>
<br>
<div class="panel accent-panel">
<p class="kicker">Visibility gap</p>
<h3>Bitcoin privacy leaks are invisible to users</h3>
<ul class="list">
<li>Companies like <b>Chainalysis</b> can analyze wallet privacy</li>
<li><b>Users cannot</b></li>
<li>People may expose: full transaction history, identity links, and behavioral fingerprints</li>
</ul>
<br>
<p>Companies can analyze your privacy better than you can.
</p>
</div>
---
# What Stealth Does
# Why This Happens
<br>
<div class="panel accent-panel">
<h3>Privacy is broken by <b>patterns</b>, not hacks</h3>
<div class="grid grid-cols-2 gap-6">
Common wallet patterns that leak privacy:
<div>
- Multi-input transactions (CIOH / consolidation)
- Combining coins
- Address reuse
- Sending change to same input address
- Dust UTXOs
- Exchange linkage / taint signals
</div>
**Input**
- Paste wallet descriptor
- Supports `wpkh`, `pkh`, `sh(wpkh)`, `tr`, multisig
---
**Output**
- Structured findings + warnings
- Type/severity/description + evidence details
- Severity badges mapped from detector output
## Visibility Imbalance
<p class="footnote">Chainalysis users can see wallet-linkage signals that the average user cannot see about themselves.</p>
<div class="seesaw-wrap">
<div class="seesaw">
<div class="seesaw-beam-bar"></div>
<div class="seesaw-beam">
<div class="seesaw-side heavy">
<span class="chainalysis-wordmark">Chainalysis</span>
</div>
<div class="seesaw-pivot"></div>
<div class="seesaw-side light">
<span class="user-label">user</span>
</div>
</div>
</div>
</div>
---
## Privacy Parity
<p class="footnote">With Stealth, users gain visibility closer to institutional-grade analysis.</p>
<div class="seesaw-wrap">
<div class="seesaw seesaw-balanced">
<div class="seesaw-beam-bar"></div>
<div class="seesaw-beam">
<div class="seesaw-side heavy">
<span class="chainalysis-wordmark">Chainalysis</span>
</div>
<div class="seesaw-pivot"></div>
<div class="seesaw-side light">
<div class="user-stealth-stack">
<span class="user-label">user</span>
<span class="stealth-wordmark">STEAL<span class="accent">TH</span></span>
</div>
</div>
</div>
</div>
</div>
---
## What Stealth Does
<div class="split two">
<div class="panel">
<p class="kicker">Input</p>
<ul class="list">
<li>Paste a wallet descriptor</li>
<li>Supports <code>wpkh</code>, <code>pkh</code>, <code>sh(wpkh)</code>, <code>tr</code>, multisig</li>
</ul>
<p class="kicker mt">Output</p>
<ul class="list">
<li>Structured findings plus warnings</li>
<li>Type, severity, description, and evidence</li>
<li>Severity badges mapped directly from detectors</li>
</ul>
</div>
<div>
<div class="panel code-panel">
```bash
# One click
wpkh([xpub...]/0/*) Analyze
# one click
wpkh([xpub...]/0/*) -> Analyze
```
Full report with actionable insights
<p class="result-arrow">=> Full report with actionable, spend-aware insights</p>
</div>
@@ -82,49 +143,67 @@ wpkh([xpub...]/0/*) → Analyze
---
# Vulnerabilities Detected
## Vulnerabilities Detected
<br>
<table class="detector-table">
<thead>
<tr>
<th>Detector Type</th>
<th>Meaning</th>
</tr>
</thead>
<tbody>
<tr><td><code>ADDRESS_REUSE</code></td><td>Repeated receive address links payment history</td></tr>
<tr><td><code>CIOH</code></td><td>Multi-input ownership clustering signal</td></tr>
<tr><td><code>DUST</code> / <code>DUST_SPENDING</code></td><td>Dust + normal co-spend linkage pattern</td></tr>
<tr><td><code>CHANGE_DETECTION</code></td><td>Payment and change outputs become distinguishable</td></tr>
<tr><td><code>CONSOLIDATION</code> / <code>CLUSTER_MERGE</code></td><td>Input histories merged into one traceable cluster</td></tr>
<tr><td><code>SCRIPT_TYPE_MIXING</code></td><td>Mixed script families create a wallet fingerprint</td></tr>
<tr><td><code>UTXO_AGE_SPREAD</code></td><td>Old/new spread leaks dormancy behavior</td></tr>
<tr><td><code>EXCHANGE_ORIGIN</code></td><td>Probable exchange withdrawal origin signature</td></tr>
<tr><td><code>TAINTED_UTXO_MERGE</code></td><td>Tainted + clean merge propagates contamination</td></tr>
<tr><td><code>BEHAVIORAL_FINGERPRINT</code></td><td>Consistent transaction style re-identifies wallet</td></tr>
</tbody>
</table>
| Detector Type | Meaning |
|---------------|---------|
| `ADDRESS_REUSE` | Same address received multiple payments, linking history |
| `CIOH` | Multi-input ownership clustering signal |
| `DUST` / `DUST_SPENDING` | Dust detection and dust+normal co-spend linkage |
| `CHANGE_DETECTION` | Payment/change outputs become easy to distinguish |
| `CONSOLIDATION` / `CLUSTER_MERGE` | Input histories merged into one cluster |
| `SCRIPT_TYPE_MIXING` | Mixed input script families create fingerprint |
| `UTXO_AGE_SPREAD` | Old/new UTXO spread leaks dormancy patterns |
| `EXCHANGE_ORIGIN` | Probable exchange batch-withdrawal origin |
| `TAINTED_UTXO_MERGE` | Tainted + clean input merge propagates taint |
| `BEHAVIORAL_FINGERPRINT` | Transaction style consistency re-identifies wallet |
| Warnings: `DORMANT_UTXOS`, `DIRECT_TAINT` | Non-finding risk signals shown separately |
<p class="footnote">Warnings: <code>DORMANT_UTXOS</code> and <code>DIRECT_TAINT</code> are shown as contextual risk signals.</p>
---
# How It Works
## How It Works
<br>
<div class="split three">
<div class="grid grid-cols-3 gap-4">
<div class="panel step">
<div class="card p-4">
**1. Parse**
- Extract addresses from descriptor
- Support all common formats
<p class="step-index">01</p>
<h3>Parse</h3>
<ul class="list">
<li>Extract addresses from descriptor</li>
<li>Normalize all common formats</li>
</ul>
</div>
<div class="card p-4">
<div class="panel step">
**2. Fetch**
- On-chain history per address
- Uses Bitcoin node / API
<p class="step-index">02</p>
<h3>Fetch</h3>
<ul class="list">
<li>Load on-chain history per address</li>
<li>Use Bitcoin node or indexed API source</li>
</ul>
</div>
<div class="card p-4">
<div class="panel step">
**3. Analyze**
- Apply privacy heuristics
- Flag each UTXO with findings
<p class="step-index">03</p>
<h3>Analyze</h3>
<ul class="list">
<li>Apply privacy heuristics and warnings</li>
<li>Flag each UTXO with findings and evidence</li>
</ul>
</div>
@@ -132,51 +211,105 @@ wpkh([xpub...]/0/*) → Analyze
---
# Architecture
## Architecture
```
```txt
stealth/
├── frontend/ # React + Vite input, loading, report
└── backend/ # Java/Quarkus — descriptor parsing, chain data, analysis
|-- frontend/ # React + Vite: input, loading, report
`-- backend/ # Java/Quarkus: parsing, chain data, analysis
```
- **Read-only** — no keys, no storage, no transmission of descriptors
- **Self-hostable** — point at your own node for max privacy
<div class="split two">
<div class="panel">
<p class="kicker">Security Model</p>
<p class="strong">Read-only</p>
<p class="muted">No private keys, no descriptor storage, no hidden transmission path.</p>
</div>
<div class="panel">
<p class="kicker">Deployment</p>
<p class="strong">Self-hostable</p>
<p class="muted">Point to your own node for maximum privacy and deterministic trust.</p>
</div>
</div>
---
# Demo Flow
## Demo Flow
1. **Input screen** — paste descriptor, click Analyze
2. **Loading** — fetches and analyzes
3. **Report** — summary bar (findings / warnings / tx analyzed)
4. Expandable finding cards: type, severity, description, structured evidence
<div class="panel">
<ol class="flow">
<li><span>Input</span> Paste descriptor and trigger analysis</li>
<li><span>Load</span> Fetch + parse + detect in one pipeline</li>
<li><span>Report</span> Summary bar: findings / warnings / transactions</li>
<li><span>Inspect</span> Expand finding cards for severity and evidence payloads</li>
</ol>
</div>
---
# Why It Matters
## Demo
- **Users** — understand exposure before consolidating or spending
- **Wallets** — integrate as pre-spend check
- **Researchers** — study privacy heuristics at scale
- **Privacy-first** — no cloud, no logs, no tracking
<div class="panel">
<video
controls
autoplay
muted
loop
playsinline
src="/demo-2x-fast.mp4"
style="width: 100%; border-radius: 12px; border: 1px solid var(--border);"
></video>
<p class="footnote">2x playback and compressed for lightweight deck rendering.</p>
</div>
---
# Thank You
## Roadmap
**STEAL<span class="accent">TH</span>**
<div class="split two">
<div class="panel">
<p class="kicker">Expanded Heuristics</p>
<ul class="list">
<li><code>LEGACY_SCRIPT_EXPOSURE</code> — old script usage (<code>p2pkh</code> / nested-only flows) shrinking anonymity set</li>
<li><code>ADDRESS_GAP_LEAK</code> — sparse derivation usage exposing wallet generation behavior</li>
<li><code>AMOUNT_FINGERPRINT</code> — repeated denomination templates across spends</li>
<li><code>TIME_PATTERN_FINGERPRINT</code> — recurring timing cadence linking sessions</li>
</ul>
</div>
<div class="panel">
<p class="kicker">Improvements</p>
<ul class="list">
<li><b>Mainnet Support</b></li><br>
<li><b>Mobile Support</b></li><br>
<li><b>Cluster Visualization</b></li><br>
<li><b>One-click solution</b></li>
</ul>
</div>
</div>
Bitcoin Wallet Privacy Analyzer
<p class="footnote">Roadmap detectors are additive and keep the same read-only, no-key security model.</p>
---
# Appendix — Supported Descriptors
<div class="hero-wrap end">
<p class="eyebrow">Thank You</p>
<h1 class="hero-title">STEAL<span class="accent">TH</span></h1>
<p class="hero-subtitle">Bitcoin Wallet Privacy Analyzer</p>
<p class="hero-copy">Protect privacy before you broadcast intent.</p>
</div>
- `wpkh(...)` — native SegWit
- `pkh(...)` — legacy
- `sh(wpkh(...))` — nested SegWit
- `tr(...)` — Taproot
- Multisig variants
---
All analysis uses publicly available on-chain data.
## Appendix — Supported Descriptors
<div class="panel">
<ul class="list">
<li><code>wpkh(...)</code> — native SegWit</li>
<li><code>pkh(...)</code> — legacy</li>
<li><code>sh(wpkh(...))</code> — nested SegWit</li>
<li><code>tr(...)</code> — Taproot</li>
<li>Multisig variants</li>
</ul>
</div>
<p class="footnote">All analysis relies only on publicly available on-chain data.</p>
+289 -54
View File
@@ -1,84 +1,319 @@
/* Stealth theme overrides — matches frontend App.css */
/* Global Stealth deck skin */
:root {
--slidev-theme-primary: #00d4aa;
--slidev-theme-accent: #00d4aa;
--stealth-bg: #080c14;
--stealth-surface: #0f1623;
--stealth-surface-2: #162030;
--stealth-border: #1e2d45;
--stealth-accent: #00d4aa;
--stealth-danger: #ff4d6d;
--stealth-warning: #f4a261;
--stealth-safe: #2ec4b6;
--stealth-text: #e8edf5;
--stealth-text-muted: #6b7a99;
--bg: #080c14;
--surface: #0f1623;
--surface-2: #162030;
--border: #1e2d45;
--border-hover: #2a3f5e;
--accent: #00d4aa;
--accent-dim: rgba(0, 212, 170, 0.14);
--accent-glow: rgba(0, 212, 170, 0.32);
--danger: #ff4d6d;
--warning: #f4a261;
--text: #e8edf5;
--text-muted: #93a2bf;
}
.slidev-layout {
background-color: var(--stealth-bg) !important;
color: var(--stealth-text) !important;
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif !important;
background:
radial-gradient(1200px 500px at 90% -20%, rgba(0, 212, 170, 0.12), transparent 60%),
radial-gradient(900px 500px at -10% 110%, rgba(46, 196, 182, 0.08), transparent 60%),
var(--bg);
color: var(--text);
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
}
.slidev-layout h1,
.slidev-layout h2,
.slidev-layout h3 {
color: var(--stealth-text) !important;
font-weight: 700;
h1,
h2,
h3 {
letter-spacing: -0.02em;
}
.slidev-layout h1 {
font-size: 2.5rem !important;
h2 {
margin-bottom: 1rem;
font-size: 2.2rem;
}
.slidev-layout h1 .accent {
color: var(--stealth-accent) !important;
.hero-wrap {
display: grid;
gap: 0.9rem;
padding: 2.2rem;
border: 1px solid var(--border);
border-radius: 18px;
background: linear-gradient(145deg, rgba(22, 32, 48, 0.65), rgba(15, 22, 35, 0.9));
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.35), 0 0 0 1px rgba(0, 212, 170, 0.12) inset;
}
.slidev-layout p,
.slidev-layout li {
color: var(--stealth-text-muted) !important;
.hero-wrap.end {
margin-top: 2rem;
}
.slidev-layout a {
color: var(--stealth-accent) !important;
.eyebrow {
text-transform: uppercase;
letter-spacing: 0.14em;
color: var(--text-muted);
font-size: 0.72rem;
font-weight: 700;
}
.slidev-layout code {
font-family: 'JetBrains Mono', 'Fira Code', monospace !important;
background: var(--stealth-surface) !important;
color: var(--stealth-accent) !important;
border: 1px solid var(--stealth-border) !important;
border-radius: 6px !important;
.hero-title {
font-size: 4.4rem;
line-height: 0.95;
margin: 0;
}
.slidev-layout .badge-danger {
background: rgba(255, 77, 109, 0.15);
color: var(--stealth-danger);
border: 1px solid rgba(255, 77, 109, 0.3);
.accent {
color: var(--accent);
text-shadow: 0 0 20px var(--accent-glow);
}
.slidev-layout .badge-warning {
background: rgba(244, 162, 97, 0.15);
color: var(--stealth-warning);
border: 1px solid rgba(244, 162, 97, 0.3);
.hero-subtitle {
margin: 0;
color: #c7d2e7;
font-size: 1.25rem;
}
.slidev-layout .badge-safe {
background: rgba(46, 196, 182, 0.15);
color: var(--stealth-safe);
border: 1px solid rgba(46, 196, 182, 0.3);
.hero-copy {
margin: 0;
max-width: 70ch;
color: var(--text-muted);
}
.slidev-layout .card {
background: var(--stealth-surface) !important;
border: 1px solid var(--stealth-border) !important;
border-radius: 12px !important;
.hero-chips {
display: flex;
gap: 0.6rem;
flex-wrap: wrap;
}
.slidev-layout .btn-primary {
background: var(--stealth-accent) !important;
color: #080c14 !important;
font-weight: 700 !important;
.chip {
border: 1px solid var(--border);
border-radius: 999px;
padding: 0.2rem 0.65rem;
font-size: 0.78rem;
color: #c5d3eb;
background: rgba(22, 32, 48, 0.65);
}
.chip-safe {
border-color: rgba(0, 212, 170, 0.32);
color: var(--accent);
background: var(--accent-dim);
}
.split {
display: grid;
gap: 1rem;
}
.split.two {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.split.three {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
.panel {
border: 1px solid var(--border);
border-radius: 14px;
padding: 1rem;
background: linear-gradient(180deg, rgba(15, 22, 35, 0.95), rgba(13, 19, 31, 0.95));
}
.code-panel pre {
margin-top: 0.2rem;
}
.kicker {
margin: 0 0 0.45rem;
text-transform: uppercase;
letter-spacing: 0.1em;
font-size: 0.7rem;
color: var(--text-muted);
}
.strong {
margin: 0;
font-size: 1.1rem;
font-weight: 700;
}
.muted {
margin: 0.45rem 0 0;
color: var(--text-muted);
}
.list {
margin: 0;
padding-left: 1.1rem;
display: grid;
gap: 0.42rem;
}
.mt {
margin-top: 1rem;
}
.result-arrow {
margin: 0.6rem 0 0;
color: var(--accent);
font-family: 'JetBrains Mono', 'Fira Code', monospace;
font-size: 0.9rem;
}
.detector-table {
width: 100%;
border-collapse: collapse;
border: 1px solid var(--border);
border-radius: 10px;
overflow: hidden;
background: rgba(15, 22, 35, 0.88);
font-size: 0.86rem;
}
.detector-table th,
.detector-table td {
border-bottom: 1px solid rgba(30, 45, 69, 0.7);
padding: 0.5rem 0.62rem;
text-align: left;
vertical-align: top;
}
.detector-table th {
color: #b6c5de;
background: rgba(22, 32, 48, 0.85);
text-transform: uppercase;
letter-spacing: 0.06em;
font-size: 0.72rem;
}
.step-index {
font-family: 'JetBrains Mono', 'Fira Code', monospace;
color: var(--accent);
margin: 0;
}
.flow {
margin: 0;
padding-left: 1.2rem;
display: grid;
gap: 0.55rem;
}
.flow span {
color: var(--accent);
font-weight: 700;
margin-right: 0.3rem;
}
.accent-panel {
border-color: rgba(0, 212, 170, 0.26);
box-shadow: 0 0 0 1px rgba(0, 212, 170, 0.1) inset;
}
.footnote {
margin-top: 0.8rem;
color: var(--text-muted);
font-size: 0.83rem;
}
code {
font-family: 'JetBrains Mono', 'Fira Code', monospace;
}
/* Seesaw slide */
.seesaw-wrap {
display: flex;
justify-content: center;
align-items: center;
min-height: 340px;
padding: 1rem;
}
.seesaw {
position: relative;
width: 100%;
max-width: 560px;
}
.seesaw-beam-bar {
position: absolute;
left: 50%;
top: 58%;
transform: translate(-50%, -50%) rotate(-14deg);
width: 90%;
height: 8px;
background: linear-gradient(90deg, var(--border), var(--border-hover), var(--border));
border-radius: 4px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
}
.seesaw-beam {
display: flex;
align-items: flex-start;
justify-content: center;
position: relative;
height: 180px;
}
.seesaw-pivot {
position: absolute;
left: 50%;
bottom: 0;
transform: translateX(-50%);
width: 0;
height: 0;
border-left: 14px solid transparent;
border-right: 14px solid transparent;
border-bottom: 24px solid var(--border);
z-index: 2;
}
.seesaw-side {
display: flex;
align-items: center;
justify-content: center;
flex: 1;
min-height: 96px;
padding: 0.8rem;
transition: transform 0.4s ease;
}
.seesaw-side.heavy {
transform: translateY(28px) rotate(-16deg);
}
.seesaw-side.light {
transform: translateY(-28px) rotate(16deg);
}
.chainalysis-wordmark {
font-size: 2.4rem;
font-weight: 800;
letter-spacing: -0.02em;
color: #ff6f2c;
text-shadow: 0 0 14px rgba(255, 111, 44, 0.22);
}
.user-label {
font-size: 1.4rem;
font-weight: 700;
color: var(--accent);
text-shadow: 0 0 12px var(--accent-glow);
}
.user-stealth-stack {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.25rem;
}
.stealth-wordmark {
font-size: 1.65rem;
font-weight: 800;
letter-spacing: 0.04em;
color: var(--text);
}
.seesaw-balanced .seesaw-beam-bar {
transform: translate(-50%, -50%) rotate(0deg);
}
.seesaw-balanced .seesaw-side.heavy,
.seesaw-balanced .seesaw-side.light {
transform: translateY(0) rotate(0deg);
}