Files
bal-electrum-plugin/docs/inheritance-options.html
2026-06-20 09:50:02 -04:00

268 lines
17 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>BAL — Inheritance Options Guide</title>
<style>
:root{
--bg:#0d1117; --panel:#161b22; --text:#e6edf3; --muted:#9da7b3;
--border:#30363d; --accent:#2bc8ed; --red:#e83845; --green:#2ea043;
--blue:#2bc8ed; --grey:#8b949e; --amber:#cfa808;
}
*{box-sizing:border-box}
body{
margin:0; background:var(--bg); color:var(--text);
font:16px/1.65 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
}
.wrap{max-width:980px;margin:0 auto;padding:32px 20px 80px}
h1{font-size:2rem;margin:.2em 0 .1em;border-bottom:2px solid var(--accent);padding-bottom:.3em}
h2{font-size:1.4rem;margin:2em 0 .4em;border-bottom:1px solid var(--border);padding-bottom:.25em}
h3{font-size:1.12rem;margin:1.6em 0 .3em;color:#cdd9e5}
p,li{color:var(--text)}
blockquote{
margin:1em 0;padding:.6em 1em;border-left:4px solid var(--accent);
background:var(--panel);border-radius:0 8px 8px 0;color:var(--muted)
}
blockquote strong{color:var(--text)}
code{background:#1f2630;padding:.12em .4em;border-radius:5px;font-size:.9em}
table{border-collapse:collapse;width:100%;margin:1em 0;font-size:.93rem;display:block;overflow-x:auto}
th,td{border:1px solid var(--border);padding:8px 10px;text-align:left;vertical-align:top}
th{background:var(--panel)}
tr:nth-child(even) td{background:#11161d}
.yes{color:var(--green);font-weight:700}
.no{color:var(--grey);font-weight:700}
.fee{color:var(--red);font-weight:700}
.pill{display:inline-block;padding:.05em .55em;border-radius:999px;font-size:.78em;font-weight:700;color:#0d1117}
.pill.red{background:var(--red);color:#fff}
.pill.blue{background:var(--blue)}
.pill.green{background:var(--green);color:#fff}
.pill.grey{background:var(--grey);color:#fff}
.mermaid{background:var(--panel);border:1px solid var(--border);border-radius:10px;padding:18px;margin:1.2em 0;overflow-x:auto}
.lead{color:var(--muted);font-size:1.05rem}
footer{margin-top:3em;color:var(--muted);font-size:.85rem;border-top:1px solid var(--border);padding-top:1em}
a{color:var(--accent)}
</style>
</head>
<body>
<div class="wrap">
<h1>BAL — Inheritance Options Guide</h1>
<p class="lead">How the <strong>Bitcoin After Life</strong> Electrum plugin reacts to every change you can make to
your will: changing the date (earlier / later), adding or removing an heir, changing percentages, fees or
willexecutors — and what happens to the transactions held by the willexecutor servers.</p>
<blockquote>This page reflects the <strong>actual behaviour of the code</strong>
(<code>core/will.py</code><code>is_will_valid</code> / <code>check_willexecutors_and_heirs</code> and
<code>gui/qt/window.py</code><code>build_inheritance_transaction</code>). It is meant for end users and
for anyone wanting to understand the onchain consequences of each action.</blockquote>
<h2>1. The mental model in one paragraph</h2>
<p>Your will is a <strong>tree of presigned Bitcoin transactions</strong>. Each leaf transaction sends your
coins to your heirs and is <strong>timelocked</strong> (<code>nLockTime</code>) so it can only be broadcast
<strong>after</strong> a future date/block. A copy of each signed transaction is handed to one or more
<strong>willexecutor servers</strong>. While you are alive you periodically prove you are alive (the
<em>CheckAlive threshold</em>). When you change anything, BAL chooses between three outcomes:</p>
<ol>
<li><strong>Do nothing</strong> — the will is still coherent.</li>
<li><strong>Rebuild</strong> (reprepare + resign, <em>no onchain cost</em>) — the will changed but
nothing dangerous is committed yet.</li>
<li><strong>Invalidate onchain first</strong> (costs a real Bitcoin fee) — a previously
<strong>signed/sent</strong> transaction must be neutralised by spending its inputs <em>before</em> a
new will can safely replace it.</li>
</ol>
<blockquote>The whole point of rule 3 is safety: <strong>a willexecutor must never be able to broadcast an old
transaction that would execute your inheritance too early.</strong></blockquote>
<h2>2. Transaction states (status flags)</h2>
<table>
<thead><tr><th>Status</th><th>Meaning</th><th>Set when</th></tr></thead>
<tbody>
<tr><td><code>VALID</code></td><td>The current, usable plan</td><td>default; cleared by INVALIDATED/REPLACED/CONFIRMED/PENDING</td></tr>
<tr><td><code>COMPLETE</code> (<em>Signed</em>)</td><td>The transaction has been <strong>signed</strong></td><td>after <strong>Sign</strong></td></tr>
<tr><td><code>PUSHED</code></td><td>Signed tx <strong>sent to executor(s)</strong></td><td>after <strong>Broadcast</strong> to executors</td></tr>
<tr><td><code>CHECKED</code></td><td>Executor <strong>confirmed</strong> it holds the tx</td><td>after a successful server <strong>Check</strong> (implies PUSHED)</td></tr>
<tr><td><code>CHECK_FAIL</code></td><td>Server <strong>check failed</strong></td><td>a queried executor did not return the tx</td></tr>
<tr><td><code>PUSH_FAIL</code></td><td>Sending to the executor failed</td><td>cleared when PUSHED becomes true</td></tr>
<tr><td><code>CONFIRMED</code></td><td>Tx <strong>mined onchain</strong></td><td>seen onchain, height &gt; 0</td></tr>
<tr><td><code>PENDING</code></td><td>Tx <strong>in the mempool</strong></td><td>seen onchain, height 0</td></tr>
<tr><td><code>INVALIDATED</code></td><td>Inputs spent → can never confirm</td><td>invalidation tx / inputs gone</td></tr>
<tr><td><code>REPLACED</code></td><td>Superseded by an earlierlocktime child</td><td>a replacing child found</td></tr>
<tr><td><code>EXPIRED</code></td><td>Locktime already in the past vs the check date</td><td><code>check_will_expired</code></td></tr>
</tbody>
</table>
<h3>Safety rules baked into <code>set_status</code></h3>
<ul>
<li>Setting <code>INVALIDATED</code> / <code>REPLACED</code> / <code>CONFIRMED</code> / <code>PENDING</code> → clears <code>VALID</code>.</li>
<li>Setting <code>CONFIRMED</code> / <code>PENDING</code> → clears <code>INVALIDATED</code>.</li>
<li>Setting <code>PUSHED</code> → clears <code>PUSH_FAIL</code> <strong>and</strong> <code>CHECK_FAIL</code>.</li>
<li>Setting <code>CHECKED</code> → implies <code>PUSHED</code>.</li>
</ul>
<h3>How states map to row colour</h3>
<table>
<thead><tr><th>State (first match wins)</th><th>Colour</th><th>Hex</th></tr></thead>
<tbody>
<tr><td><code>CHECK_FAIL</code></td><td><span class="pill red">red</span></td><td><code>#e83845</code></td></tr>
<tr><td><code>INVALIDATED</code> / <code>REPLACED</code></td><td><span class="pill grey">grey</span></td><td>muted</td></tr>
<tr><td><code>CONFIRMED</code></td><td><span class="pill green">green</span></td><td>confirmed</td></tr>
<tr><td><code>COMPLETE</code> (signed, not pushed)</td><td><span class="pill blue">blue</span></td><td><code>#2bc8ed</code></td></tr>
<tr><td><code>VALID</code> (prepared, not signed)</td><td>default</td><td></td></tr>
</tbody>
</table>
<blockquote><strong>v0.3.3 fix:</strong> a will that is <em>signed but not yet broadcast</em>
(<code>COMPLETE</code> and <strong>not</strong> <code>PUSHED</code>) is <strong>not</strong> queried on the
server, so it stays <strong>blue</strong> instead of turning red. Only <code>PUSHED</code> wills are checked.</blockquote>
<h2>3. The decision flow</h2>
<p>On <strong>Prepare</strong> (or the periodic <strong>Check</strong>, or on Electrum close) BAL runs
<code>is_will_valid</code>, raises a specific exception, and each maps to one action:</p>
<pre class="mermaid">
flowchart TD
A([You change something &amp; press Prepare / Check]) --> B{Heirs defined?}
B -- No --> Z1[/Show: Heirs are not defined — stop/]
B -- Yes --> C{Check-Alive threshold in the future?}
C -- "No, it's in the past" --> INV1[[Invalidate on-chain<br/>CheckAliveError]]
C -- Yes --> D{Any VALID tx with locktime earlier than the new date?}
D -- "Yes you moved the date EARLIER / anticipate" --> E{Was that tx already signed or sent?}
E -- "Not signed yet" --> R1[[Rebuild only<br/>no on-chain cost]]
E -- "Signed / sent" --> INV2[[Invalidate on-chain FIRST<br/>WillExpired]]
D -- No --> F{Will-executor / fee / heirs unchanged?}
F -- "Fee changed" --> R2[[Rebuild<br/>TxFeesChanged]]
F -- "Will-executor changed/absent" --> R3[[Rebuild<br/>WillExecutorNotPresent / Change]]
F -- "Heir added/removed, % or address changed" --> G{POSTPONE of an already signed/sent tx?}
G -- "Yes date later + signed/sent" --> INV3[[Invalidate on-chain FIRST then rebuild<br/>WillPostponed]]
G -- "No never signed, or pure heir/% change" --> R4[[Rebuild only<br/>HeirNotFound / HeirChange]]
F -- "Nothing changed" --> OK([Will still coherent — do nothing])
R1 --> SIGN
R2 --> SIGN
R3 --> SIGN
R4 --> SIGN
SIGN([Re-sign the new transactions]) --> PUSH([Broadcast to will-executors])
INV1 --> SB
INV2 --> SB
INV3 --> SB
SB([Sign &amp; broadcast the INVALIDATION tx on-chain]) --> WAIT{Invalidation confirmed?}
WAIT -- Yes --> REBUILD([Press Prepare again → build the new will])
REBUILD --> SIGN
</pre>
<h2>4. Every option, explained</h2>
<h3>4.1 Changing the CheckAlive date / heir locktime</h3>
<p>BAL compares the <strong>requested</strong> locktime against the locktime <strong>frozen inside the
alreadysigned transaction</strong> (<code>w.tx.locktime</code>) — exactly what the willexecutors hold.</p>
<table>
<thead><tr><th>You do…</th><th>Tx already signed/sent?</th><th>Result</th><th>Onchain fee?</th></tr></thead>
<tbody>
<tr><td>Move date <strong>LATER</strong> (postpone)</td><td>No (never signed)</td><td>Plain <strong>rebuild</strong></td><td class="no">No</td></tr>
<tr><td>Move date <strong>LATER</strong> (postpone)</td><td>Yes</td><td><strong>Invalidate first</strong>, then rebuild (WillPostponed)</td><td class="fee">Yes</td></tr>
<tr><td>Move date <strong>EARLIER</strong> (anticipate)</td><td>any</td><td>Old tx <strong>expired</strong> → invalidate (WillExpired)</td><td class="fee">Yes</td></tr>
<tr><td>CheckAlive threshold already passed</td><td></td><td><strong>Invalidate</strong> (CheckAliveError)</td><td class="fee">Yes</td></tr>
</tbody>
</table>
<blockquote><strong>Why postpone needs onchain invalidation:</strong> the executor still holds the <em>old</em>
transaction with the <em>earlier</em> locktime. Spending its inputs onchain makes it unminable, so it can
never execute the inheritance early. The plugin tells you this and offers to build the invalidation tx.</blockquote>
<h3>4.2 Adding an heir</h3>
<p>An heir present in your set but not yet in the will raises <code>HeirNotFoundException</code>.</p>
<ul><li><strong>Result:</strong> rebuild.</li>
<li><strong>Onchain fee:</strong> <span class="no">No</span> — unless the changed will was already signed/sent
and the change also moves a locktime later (then 4.1 applies).</li></ul>
<h3>4.3 Removing an heir</h3>
<p>The will still carries an heir no longer in your set → <code>HeirNotFoundException</code> (removedheir branch).</p>
<ul><li><strong>Result:</strong> rebuild, so the removed heir disappears.</li>
<li><strong>Onchain fee:</strong> <span class="no">No</span> for a preparedonly will; if it was signed/sent,
invalidate onchain first, then rebuild.</li></ul>
<blockquote><strong>v0.3.2 fix:</strong> removing an heir is now detected on <strong>Check</strong> and on
Electrum <strong>close</strong>, not only on Prepare.</blockquote>
<h3>4.4 Changing an heir's percentage or address</h3>
<p>A changed <code>[address, amount]</code> is treated like an heir change (<code>HeirChange</code> / <code>HeirNotFound</code>).</p>
<ul><li><strong>Result:</strong> rebuild with new amounts.</li>
<li><strong>Onchain fee:</strong> <span class="no">No</span> (unless signed/sent → invalidate first).</li></ul>
<blockquote>The wallet is always <strong>fully emptied</strong> by the inheritance; amounts must add up, or an
<code>AmountException</code> warns you to adjust.</blockquote>
<h3>4.5 Changing the transaction fee (sat/byte)</h3>
<p>A different rate raises <code>TxFeesChangedException</code>.</p>
<ul><li><strong>Result:</strong> rebuild at the new fee rate.</li>
<li><strong>Onchain fee:</strong> <span class="no">No</span> to rebuild (you pay only when broadcasting onchain).</li></ul>
<h3>4.6 Changing or removing a willexecutor</h3>
<ul>
<li>Selected executor not referenced → <code>WillExecutorNotPresent</code>.</li>
<li>Executor details changed → <code>WillexecutorChangeException</code>.</li>
<li>“No executor” mode without a backup tx → <code>NoWillExecutorNotPresent</code>.</li>
</ul>
<ul><li><strong>Result:</strong> rebuild &amp; redistribute to the new executor set.</li>
<li><strong>Onchain fee:</strong> <span class="no">No</span> to rebuild.</li></ul>
<h3>4.7 Nothing changed</h3>
<p>If heirs, percentages, fees, executors and locktimes all still match the signed transactions,
<code>is_will_valid</code> returns <code>True</code> and <strong>nothing happens</strong>.</p>
<h2>5. What happens on the willexecutor servers</h2>
<table>
<thead><tr><th>Your action</th><th>Effect on the servers</th></tr></thead>
<tbody>
<tr><td><strong>Prepare</strong> (rebuild)</td><td>Nothing yet — new txs are local until Sign + Broadcast.</td></tr>
<tr><td><strong>Sign</strong></td><td>Still local; tx becomes <code>COMPLETE</code> (<span class="pill blue">blue</span>).</td></tr>
<tr><td><strong>Broadcast to executors</strong></td><td>Signed txs uploaded; items become <code>PUSHED</code>.</td></tr>
<tr><td><strong>Check</strong></td><td>Each <code>PUSHED</code> will is queried; success → <code>CHECKED</code> (<span class="pill green">green</span>), failure → <code>CHECK_FAIL</code> (<span class="pill red">red</span>).</td></tr>
<tr><td><strong>Invalidate (onchain)</strong></td><td>You spend the committed inputs on the network. Once confirmed, the executor's stored tx can no longer be mined and is dropped on the next check.</td></tr>
<tr><td><strong>Rebroadcast a new will</strong></td><td>Executors replace the obsolete copy with the new signed tx.</td></tr>
</tbody>
</table>
<blockquote>A row turning <span class="pill red">red</span> (<code>CHECK_FAIL</code>) after a Check means an
executor that <em>should</em> hold your tx did not return it — reBroadcast or rebuild. A merely
<span class="pill blue">blue</span> row is signedbutnotyetsent and perfectly normal.</blockquote>
<h2>6. Quick reference — does it cost a Bitcoin fee?</h2>
<table>
<thead><tr><th>Change</th><th>Rebuild?</th><th>Onchain invalidation (real fee)?</th></tr></thead>
<tbody>
<tr><td>Add heir (only prepared)</td><td class="yes">Yes</td><td class="no">No</td></tr>
<tr><td>Remove heir (only prepared)</td><td class="yes">Yes</td><td class="no">No</td></tr>
<tr><td>Change % / address (only prepared)</td><td class="yes">Yes</td><td class="no">No</td></tr>
<tr><td>Change fee rate</td><td class="yes">Yes</td><td class="no">No</td></tr>
<tr><td>Change / remove willexecutor</td><td class="yes">Yes</td><td class="no">No</td></tr>
<tr><td>Move date <strong>earlier</strong> (anticipate)</td><td class="yes">Yes after</td><td class="fee">Yes</td></tr>
<tr><td>Move date <strong>later</strong> — will <strong>signed/sent</strong></td><td class="yes">Yes after</td><td class="fee">Yes</td></tr>
<tr><td>Move date <strong>later</strong> — will <strong>only prepared</strong></td><td class="yes">Yes</td><td class="no">No</td></tr>
<tr><td>CheckAlive threshold already passed</td><td class="yes">Yes after</td><td class="fee">Yes</td></tr>
<tr><td>Any change to an <strong>already signed/sent</strong> will</td><td class="yes">Yes after</td><td class="fee">Yes</td></tr>
<tr><td>Nothing changed</td><td class="no">No</td><td class="no">No</td></tr>
</tbody>
</table>
<h2>7. Golden rules</h2>
<ol>
<li><strong>Before it's signed</strong>, changing anything is free — just <strong>Prepare</strong> again.</li>
<li><strong>After it's signed/sent</strong>, moving the date or replacing it requires an <strong>onchain
invalidation first</strong> (a small Bitcoin fee) so an old transaction can never execute early.</li>
<li>Always finish with <strong>Sign → Broadcast → Check</strong> so executors hold the current plan (green).</li>
<li>The wallet is always <strong>fully emptied</strong> by the inheritance, so heir amounts must add up.</li>
</ol>
<footer>This document reflects BAL plugin v0.3.3. Behaviour is derived directly from
<code>core/will.py</code> and <code>gui/qt/window.py</code>.</footer>
</div>
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
mermaid.initialize({ startOnLoad: true, theme: 'dark', securityLevel: 'loose' });
</script>
</body>
</html>