docs: align all markdown docs with current code (v0.6.1)
- CHANGELOG: add entries #47 (is_selected/is_valid fee bounds, extremes allowed) and #48 (merge_will crash fix on missing date_to_check) - HANDOFF: Electrum 4.7.2 and 4.8.0, current layout (qt.py, plugin.py, wallet_util/, docs/, bal_cli.py, 36-file ZIP), runtime/lint venv paths, standalone-script tests (427 collected), direct-to-main workflow, version history up to v0.6.1 - README: drop VERSION from layout, correct anticipate/expire/postpone behavior, update test commands - docs/manual/README.md: fix Tools menu label to Will-Executors, add BASIC/ADVANCED notes, extend chromatic status table (Partially signed, Updated) - docs/inheritance-options.md: add PARTIALLY_SIGNED status/transition/colour, version note to v0.6.1 - docs/README.md: make HTML-hosting instructions host-agnostic - bal/README.md: Prepare button lives on the WILL tab
This commit is contained in:
58
CHANGELOG.md
58
CHANGELOG.md
@@ -2510,3 +2510,61 @@ pre-commit hook. The version must be read at runtime from `manifest.json` only.
|
|||||||
`bitcoinafterlife-patch-5`). No functional change to inheritance behavior.
|
`bitcoinafterlife-patch-5`). No functional change to inheritance behavior.
|
||||||
|
|
||||||
**Outcome:** DONE.
|
**Outcome:** DONE.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 47. Willexecutors: fee-bound `is_valid` (extremes allowed), `is_selected` flag-only
|
||||||
|
|
||||||
|
**Date:** 2026-08-01
|
||||||
|
|
||||||
|
**Goal:** separate the "is this executor selected" question from the "is its fee
|
||||||
|
acceptable" question, and let the fee bounds be inclusive at both extremes so an
|
||||||
|
executor whose fee is *exactly* dust or *exactly* the max fee is valid.
|
||||||
|
|
||||||
|
**What changed (`bal/core/willexecutors.py`):**
|
||||||
|
- `is_selected()` no longer takes a `max_fee` parameter - it only reads/sets the
|
||||||
|
`"selected"` flag. The previous max-fee cut-off inside `is_selected` rejected
|
||||||
|
executors with `base_fee >= max_fee` even when they were otherwise valid.
|
||||||
|
- `is_valid()` bounds changed from strict (`<=`) to inclusive (`<` / `>`):
|
||||||
|
- `base_fee < dust` is invalid (was `<= dust`), so a fee exactly equal to
|
||||||
|
dust is now valid.
|
||||||
|
- `base_fee > max_fee` is invalid (was `>= max_fee`), so a fee exactly equal
|
||||||
|
to the max fee is now valid.
|
||||||
|
- Defensive `int(base_fee or 0)` in the fee-range import validation so a missing
|
||||||
|
or empty `base_fee` no longer raises.
|
||||||
|
|
||||||
|
**Verification:**
|
||||||
|
- New tests in `tests/test_no_willexecutor_karen7.py` (class
|
||||||
|
`TestNoWillexecutorKaren7`): `is_selected` only reads/sets the flag (setter,
|
||||||
|
default-False); `is_valid` accepts fee == max and fee == dust, rejects
|
||||||
|
fee > max and fee < dust, and requires a valid address.
|
||||||
|
- Existing `build_will` test confirms a fee above max still raises.
|
||||||
|
|
||||||
|
**Outcome:** DONE.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 48. Fix `merge_will` crash on missing `date_to_check`
|
||||||
|
|
||||||
|
**Date:** 2026-08-01
|
||||||
|
|
||||||
|
**Goal:** allow *Will → Merge → Import file* to work as the very first action
|
||||||
|
of a session, without requiring the normal wizard flow to have run first.
|
||||||
|
|
||||||
|
**What changed (`bal/gui/qt/window.py`):**
|
||||||
|
- `merge_will()` crashed with `AttributeError` when `self.date_to_check` was not
|
||||||
|
yet set (merge-from-file can run before `init_class_variables()`). It now
|
||||||
|
falls back to `datetime.now().timestamp()` when the attribute is missing or
|
||||||
|
`None`, so the local validity check and the trailing `update_all()` always
|
||||||
|
have a reference timestamp.
|
||||||
|
- Several `log_error(exec_info, self.bal_window)` calls inside `BalWindow`
|
||||||
|
methods (broadcast failure, will-building failure) pointed at a wrong object
|
||||||
|
(`self.bal_window` does not exist on a `BalWindow`); corrected to
|
||||||
|
`log_error(exec_info, self)` so the error-reporting path itself cannot fail.
|
||||||
|
|
||||||
|
**Verification:**
|
||||||
|
- New tests in `tests/test_import_will_details.py`:
|
||||||
|
`test_merge_will_missing_date_to_check_defaults_to_now` and
|
||||||
|
`test_merge_will_validity_error_logs_without_crashing`.
|
||||||
|
|
||||||
|
**Outcome:** DONE.
|
||||||
|
|||||||
121
HANDOFF.md
121
HANDOFF.md
@@ -10,7 +10,7 @@
|
|||||||
## 0. TL;DR — what this project is
|
## 0. TL;DR — what this project is
|
||||||
|
|
||||||
- **Product:** BAL ("Bitcoin After Life") — an inheritance plugin for the
|
- **Product:** BAL ("Bitcoin After Life") — an inheritance plugin for the
|
||||||
**Electrum 4.7.2** Bitcoin wallet (Qt / **PyQt6**).
|
**Electrum 4.7.2 and 4.8.0** Bitcoin wallet (Qt / **PyQt6**).
|
||||||
- **Form:** external **ZIP plugin** (not bundled in Electrum). The user
|
- **Form:** external **ZIP plugin** (not bundled in Electrum). The user
|
||||||
installs the ZIP from Electrum's plugin manager.
|
installs the ZIP from Electrum's plugin manager.
|
||||||
- **What it does:** lets a wallet owner pre-build, sign and (later) broadcast
|
- **What it does:** lets a wallet owner pre-build, sign and (later) broadcast
|
||||||
@@ -57,13 +57,15 @@ These are non-negotiable. They come from the owner directly.
|
|||||||
bal/ <- the plugin package (this is what ships in the ZIP)
|
bal/ <- the plugin package (this is what ships in the ZIP)
|
||||||
__init__.py <- package docstring (no version here anymore)
|
__init__.py <- package docstring (no version here anymore)
|
||||||
manifest.json <- plugin manifest, "version" field (SINGLE SOURCE OF TRUTH for the version)
|
manifest.json <- plugin manifest, "version" field (SINGLE SOURCE OF TRUTH for the version)
|
||||||
|
qt.py <- zipimport shim used when loaded as an external ZIP plugin
|
||||||
core/
|
core/
|
||||||
plugin_base.py <- get_version() reads the version from manifest.json (zip-safe)
|
plugin_base.py <- get_version() reads the version from manifest.json (zip-safe)
|
||||||
heirs.py <- HEIRS + transaction building (prepare_lists,
|
heirs.py <- HEIRS + transaction building (prepare_lists,
|
||||||
prepare_transactions, buildTransactions). CORE LOGIC.
|
prepare_transactions, buildTransactions). CORE LOGIC.
|
||||||
will.py <- Will/WillItem, validation (check_amounts, check_will),
|
will.py <- Will/WillItem, validation (check_amounts, check_will),
|
||||||
exceptions (AmountException, WillExpiredException, ...).
|
exceptions (AmountException, WillExpiredException, ...).
|
||||||
willexecutors.py <- remote will-executor services handling.
|
willexecutors.py <- remote will-executor services handling (is_selected / is_valid,
|
||||||
|
parallel push/check).
|
||||||
util.py <- locktime parsing/most helpers (timestamps only).
|
util.py <- locktime parsing/most helpers (timestamps only).
|
||||||
gui/qt/
|
gui/qt/
|
||||||
common.py <- shared imports; every gui module does
|
common.py <- shared imports; every gui module does
|
||||||
@@ -71,12 +73,15 @@ bal/ <- the plugin package (this is what ships in the ZI
|
|||||||
dialogs.py <- the big build/sign/broadcast dialog
|
dialogs.py <- the big build/sign/broadcast dialog
|
||||||
(BalBuildWillDialog, task_phase1/2), wizard glue.
|
(BalBuildWillDialog, task_phase1/2), wizard glue.
|
||||||
widgets.py <- WillSettingsWidget + wizard widgets/labels.
|
widgets.py <- WillSettingsWidget + wizard widgets/labels.
|
||||||
window.py <- BalWalletWindow (build_will, check_will, get_transactions).
|
window.py <- BalWindow, the per-wallet controller (build_will, check_will,
|
||||||
lists.py, calendar.py, theme.py, window_utils.py, ...
|
get_transactions, merge_will, on_close, menubar wiring).
|
||||||
tests/ <- pytest suite (see run command below).
|
plugin.py <- Electrum @hooks entry point (init_qt, tools menu, settings dialog).
|
||||||
electrum-src/ <- a copy of Electrum source, used ONLY for tests
|
lists.py, calendar.py, theme.py (status colours), window_utils.py
|
||||||
(PYTHONPATH=electrum-src). NOT shipped in the ZIP.
|
wallet_util/ <- standalone wallet-inspection helpers, no Qt
|
||||||
build_zip.py <- builds the shippable ZIP (37 files).
|
tests/ <- standalone test scripts (see Section 3).
|
||||||
|
docs/ <- user manual + inheritance-options guide (.md sources).
|
||||||
|
bal_cli.py <- headless CLI (heirs/will build/sign/push/check), no Qt.
|
||||||
|
build_zip.py <- builds the shippable ZIP (36 files).
|
||||||
CHANGELOG.md <- numbered task log (English).
|
CHANGELOG.md <- numbered task log (English).
|
||||||
.agent_memory_tasks.md <- terse internal memory notes per task batch.
|
.agent_memory_tasks.md <- terse internal memory notes per task batch.
|
||||||
HANDOFF.md <- this file.
|
HANDOFF.md <- this file.
|
||||||
@@ -86,32 +91,56 @@ HANDOFF.md <- this file.
|
|||||||
|
|
||||||
## 3. How to build, test and lint
|
## 3. How to build, test and lint
|
||||||
|
|
||||||
Run everything from `/home/user/webapp`.
|
Two separate venvs — using the wrong one is the #1 mistake:
|
||||||
|
|
||||||
|
- **Runtime env** (Electrum + PyQt6, has `electrum` importable):
|
||||||
|
`source /home/steal/devel/bal/electrum/env/bin/activate` — an editable
|
||||||
|
install of the Electrum **4.8.0** checkout at
|
||||||
|
`/home/steal/devel/bal/electrum`. Use it for anything that imports
|
||||||
|
`electrum`, runs GUI code, or runs tests. The plugin's `bal/` directory is
|
||||||
|
symlinked into `electrum/electrum/plugins/bal` (internal-plugin install used
|
||||||
|
during dev).
|
||||||
|
- **Lint venv** (repo-local `venv/`): ruff, black, flake8 only. It cannot
|
||||||
|
import `electrum` or `PyQt6`. Do NOT use it to run tests.
|
||||||
|
|
||||||
|
Run everything from `/home/steal/devel/bal/bal-electrum-plugin`.
|
||||||
|
|
||||||
|
**Tests are standalone scripts (not pytest):** each `tests/test_*.py` runs its
|
||||||
|
`test_*` functions from `if __name__ == "__main__"`. Run a file directly:
|
||||||
|
|
||||||
**Full test suite (expected: 266 passed as of v0.4.8):**
|
|
||||||
```bash
|
```bash
|
||||||
QT_QPA_PLATFORM=offscreen PYTHONPATH=electrum-src python3 -m pytest \
|
source /home/steal/devel/bal/electrum/env/bin/activate
|
||||||
tests/test_core_*.py tests/test_gui_*.py \
|
python3 tests/test_core_heirs.py # core, no Qt needed
|
||||||
tests/test_anticipate_past_locktime.py tests/test_anticipate_manual_locktime.py \
|
QT_QPA_PLATFORM=offscreen python3 tests/test_gui_common.py # GUI tests need offscreen
|
||||||
tests/test_group_b_auto_sign.py tests/test_group_c_settings.py \
|
|
||||||
tests/test_group_d_alarms.py tests/test_group_e_mock_karen7.py \
|
|
||||||
tests/test_group_f_heir_change_rebuild.py tests/test_group_g_basic_calendar.py \
|
|
||||||
tests/test_group_h_v048.py -q
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Most core tests run offline (no wallet/network). Some files
|
||||||
|
(`tests/test_group_*.py`, `tests/test_no_willexecutor_karen7.py`,
|
||||||
|
`parallel_ping_test.py`) exercise will-executor/network flows and need the live
|
||||||
|
servers — don't rely on them for quick verification.
|
||||||
|
|
||||||
|
**Current state of the suite: 427 tests collected.** The offline subset passes
|
||||||
|
(414 passed) apart from pre-existing failures that are NOT yours to fix without
|
||||||
|
asking: 13 failures in `tests/test_core_will_invalidate.py` (a `None` fee when a
|
||||||
|
UTXO has no fee value, `bal/core/will.py:482`) and 1 collection error in
|
||||||
|
`tests/test_group_i_basic_checkalive.py` (missing
|
||||||
|
`BalWindow.BASIC_MODE_CHECK_ALIVE_OFFSET_SECONDS`).
|
||||||
|
|
||||||
**Lint (only NEW errors matter; ignore pre-existing noise):**
|
**Lint (only NEW errors matter; ignore pre-existing noise):**
|
||||||
```bash
|
```bash
|
||||||
ruff check <files> | grep -oE "^[^ ]+\.py:[0-9]+:[0-9]+: [A-Z][0-9]+" \
|
/home/steal/devel/bal/bal-electrum-plugin/venv/bin/ruff check <files> \
|
||||||
| grep -vE "F401|F403|F405|F841"
|
| grep -oE "^[^ ]+\.py:[0-9]+:[0-9]+: [A-Z][0-9]+" | grep -vE "F401|F403|F405|F841"
|
||||||
```
|
```
|
||||||
Pre-existing, KNOWN-OK ruff noise: `F401/F403/F405` (star-imports via
|
Ruff is NOT clean repo-wide (hundreds of pre-existing errors in `bal/` and
|
||||||
|
`tests/`); do NOT run `--fix` wholesale — just avoid adding new violations.
|
||||||
|
Pre-existing, KNOWN-OK noise: `F401/F403/F405` (star-imports via
|
||||||
`from .common import *`) and 2× `F841` (an unused `e` in two `except` blocks).
|
`from .common import *`) and 2× `F841` (an unused `e` in two `except` blocks).
|
||||||
Do NOT "fix" these unless asked — they are intentional / out of scope.
|
Do NOT "fix" these unless asked — they are intentional / out of scope.
|
||||||
|
|
||||||
**Build the ZIP (always clear caches first so zipimport doesn't ship stale .pyc):**
|
**Build the ZIP (always clear caches first so zipimport doesn't ship stale .pyc):**
|
||||||
```bash
|
```bash
|
||||||
find bal -name "__pycache__" -type d -exec rm -rf {} + ; find bal -name "*.pyc" -delete
|
find bal -name "__pycache__" -type d -exec rm -rf {} + ; find bal -name "*.pyc" -delete
|
||||||
python3 build_zip.py bal-electrum-plugin-vX.Y.Z.zip # produces 37 files
|
python3 build_zip.py # -> bal-electrum-plugin.zip (deterministic, prints sha256; 36 files)
|
||||||
```
|
```
|
||||||
|
|
||||||
**Bump version — ONE file only (single source of truth):**
|
**Bump version — ONE file only (single source of truth):**
|
||||||
@@ -226,14 +255,13 @@ See Section 5 for details.
|
|||||||
|
|
||||||
## 5. Git / delivery workflow
|
## 5. Git / delivery workflow
|
||||||
|
|
||||||
- **Branch:** work on `genspark_ai_developer`. Open PRs into `main`.
|
- **Branch:** work directly on `main` (no PR flow anymore). Push straight to
|
||||||
|
`origin/main` (Gitea).
|
||||||
- **Commit policy:** ZIP-FIRST — build a test ZIP, let the owner confirm it
|
- **Commit policy:** ZIP-FIRST — build a test ZIP, let the owner confirm it
|
||||||
works, THEN commit. (This differs from "commit after every change"; the owner
|
works, THEN commit. (This differs from "commit after every change"; the owner
|
||||||
explicitly prefers ZIP-first because they manually test each build.)
|
explicitly prefers ZIP-first because they manually test each build.)
|
||||||
- Before opening/updating a PR: `git fetch origin main`, rebase, resolve
|
- Before pushing: check `git status`/`git diff`, stage only the intended files
|
||||||
conflicts preferring remote `main` unless a local change is essential,
|
(never secrets), commit with a concise message, then push to `origin/main`.
|
||||||
squash local commits into ONE comprehensive commit, push (force if needed),
|
|
||||||
then create/update the PR and SHARE the PR URL with the owner.
|
|
||||||
- **ZIPs are NOT committed** (`.gitignore` excludes `*.zip`). They are
|
- **ZIPs are NOT committed** (`.gitignore` excludes `*.zip`). They are
|
||||||
distributed via **Gitea Releases** using `make-release.sh`.
|
distributed via **Gitea Releases** using `make-release.sh`.
|
||||||
- **Release process** (`make-release.sh`):
|
- **Release process** (`make-release.sh`):
|
||||||
@@ -265,9 +293,11 @@ See Section 5 for details.
|
|||||||
```
|
```
|
||||||
- **Auth note:** if `git push` or Gitea API fails with "invalid credentials",
|
- **Auth note:** if `git push` or Gitea API fails with "invalid credentials",
|
||||||
update `GITEA_TOKEN` env var or `~/.git-credentials`, then retry.
|
update `GITEA_TOKEN` env var or `~/.git-credentials`, then retry.
|
||||||
- PR history for this line of work: **#13** (v0.4.7), **#14** (docs/DUST section +
|
- Older PR history (pre-`main` direct workflow): **#13** (v0.4.7), **#14**
|
||||||
translation), **#15** (v0.4.8). All merged into `main`.
|
(docs/DUST section + translation), **#15** (v0.4.8), **#4** (v0.6.1 —
|
||||||
- Releases: latest is **v0.6.1**; v0.4.7, v0.4.8 kept in history.
|
manifest.json version). All merged into `main`.
|
||||||
|
- Releases: latest is **v0.6.1**; v0.6.0 and v0.5.18 before it; the older
|
||||||
|
v0.2.x line is kept in history.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -296,6 +326,26 @@ See Section 5 for details.
|
|||||||
(#7b) "Balance is too low… Skipped" recoloured ORANGE + space fix; Reset button
|
(#7b) "Balance is too low… Skipped" recoloured ORANGE + space fix; Reset button
|
||||||
renamed "Reset to Default Setting". 8 new tests (`test_group_h_v048.py`).
|
renamed "Reset to Default Setting". 8 new tests (`test_group_h_v048.py`).
|
||||||
266 tests pass.
|
266 tests pass.
|
||||||
|
- **v0.5.1 — v0.5.10** — BASIC/ADVANCED ("user type") mode work: Windows
|
||||||
|
settings-dialog flicker fix; Check Alive shown read-only in BASIC; BASIC
|
||||||
|
builds the will against "now" (`date_to_check = now()`, Check Alive fully
|
||||||
|
ignored); ADVANCED defaults to RAW (1y/30d); consistent Raw/Date default per
|
||||||
|
mode; Check Alive red-highlight fixes; clearer "could not build the will"
|
||||||
|
message; CHECK no longer resets a manual Date/RAW choice.
|
||||||
|
- **v0.5.11** — Electrum **4.8.0** compatibility (the `json_db.register_dict`
|
||||||
|
DB-registration API was removed in 4.8; the plugin now supports 4.7.2 and
|
||||||
|
4.8.0).
|
||||||
|
- **v0.5.12 — v0.5.18** — Check Alive soft-red highlight removed; short Tor
|
||||||
|
(.onion) will-executor URLs; KeyError fix on .onion executor actions; skip
|
||||||
|
.onion executors from download when Electrum is not on Tor; crash fix on a
|
||||||
|
non-dict welist response; clearer message when the list download
|
||||||
|
fails/times out over Tor.
|
||||||
|
- **v0.6.0** — version bump for the official repository release.
|
||||||
|
- **v0.6.1** — version read from `bal/manifest.json` (single source of truth);
|
||||||
|
`bal/VERSION` file removed.
|
||||||
|
- **#47 / #48 (post-v0.6.1)** — `is_selected`/`is_valid` fee bounds (extremes
|
||||||
|
allowed) and the `merge_will` missing-`date_to_check` crash fix (see
|
||||||
|
CHANGELOG).
|
||||||
|
|
||||||
### Open / suspended / backlog items (see `.agent_memory_tasks.md` for detail)
|
### Open / suspended / backlog items (see `.agent_memory_tasks.md` for detail)
|
||||||
- **SUSPENDED — "(UTC)" label in the wizard.** The owner asked to show an
|
- **SUSPENDED — "(UTC)" label in the wizard.** The owner asked to show an
|
||||||
@@ -317,12 +367,15 @@ See Section 5 for details.
|
|||||||
|
|
||||||
1. Read this file, then `CHANGELOG.md` (last entries) and `.agent_memory_tasks.md`.
|
1. Read this file, then `CHANGELOG.md` (last entries) and `.agent_memory_tasks.md`.
|
||||||
2. Confirm the environment: `git status`, current branch, and the `"version"` field of `bal/manifest.json`.
|
2. Confirm the environment: `git status`, current branch, and the `"version"` field of `bal/manifest.json`.
|
||||||
3. Run the full test suite (Section 3) — expect all green (266 as of v0.4.8).
|
3. Run the offline test files (Section 3) — expect the offline subset to pass
|
||||||
|
(414 passed; the 13 pre-existing failures in `test_core_will_invalidate.py`
|
||||||
|
and the 1 collection error in `test_group_i_basic_checkalive.py` are NOT
|
||||||
|
yours to fix without asking).
|
||||||
4. Talk to the owner in **Italian**, write everything else in **English**.
|
4. Talk to the owner in **Italian**, write everything else in **English**.
|
||||||
5. For any change: present a PLAN, wait for "OK" (R4), then implement, test,
|
5. For any change: present a PLAN, wait for "OK" (R4), then implement, test,
|
||||||
build a ZIP, let the owner test, and only commit after explicit confirmation.
|
build a ZIP, let the owner test, and only commit after explicit confirmation.
|
||||||
6. Keep credit usage low: summarize, don't paste big code blocks; batch work.
|
6. Keep credit usage low: summarize, don't paste big code blocks; batch work.
|
||||||
7. When the owner confirms a ZIP works: commit (ZIP-first), sync with `main`,
|
7. When the owner confirms a ZIP works: commit (ZIP-first) directly on `main`,
|
||||||
squash to one commit, push, open a PR, merge it, then create/refresh a GitHub
|
push to `origin/main`, then run `./make-release.sh` to create the Gitea
|
||||||
**Release** with the ZIP attached (it becomes the owner's "Latest" download).
|
**Release** with the ZIP + signatures attached (it becomes the owner's
|
||||||
Always give the owner the PR URL and the Release URL.
|
"Latest" download). Always give the owner the Release URL.
|
||||||
|
|||||||
28
README.md
28
README.md
@@ -31,7 +31,7 @@ bal/ the installable Electrum plugin package
|
|||||||
│ ├── lists.py tree/list views
|
│ ├── lists.py tree/list views
|
||||||
│ ├── window.py per-wallet GUI controller
|
│ ├── window.py per-wallet GUI controller
|
||||||
│ └── plugin.py Plugin (Electrum @hooks → GUI)
|
│ └── plugin.py Plugin (Electrum @hooks → GUI)
|
||||||
├── icons/ wallet_util/ LICENSE VERSION README.md
|
├── icons/ wallet_util/ LICENSE README.md
|
||||||
build_zip.py builds a clean, zipimport-friendly distribution zip
|
build_zip.py builds a clean, zipimport-friendly distribution zip
|
||||||
tests/ smoke + external-zip regression tests
|
tests/ smoke + external-zip regression tests
|
||||||
```
|
```
|
||||||
@@ -85,12 +85,17 @@ to broadcast it (they collect fees). Because the locktime is baked into the
|
|||||||
signed transaction, simply changing the delivery time later is **not enough**:
|
signed transaction, simply changing the delivery time later is **not enough**:
|
||||||
the old, already-signed transaction keeps living on the will-executors.
|
the old, already-signed transaction keeps living on the will-executors.
|
||||||
|
|
||||||
The plugin handles the two cases as follows (triggered when you press
|
The plugin handles the cases as follows (triggered when you press
|
||||||
**Tools → Prepare**):
|
**Prepare** on the **WILL** tab):
|
||||||
|
|
||||||
* **Anticipate** (new delivery time *earlier* than the signed locktime): the
|
* **Anticipate** (new delivery time *earlier* than the signed locktime, still
|
||||||
will is treated as expired and you are asked to **invalidate** the old
|
in the future): a plain **rebuild** — the transactions are re-created with
|
||||||
transaction on-chain, then rebuild.
|
the new, earlier locktime. **No on-chain invalidation and no Bitcoin fee**,
|
||||||
|
even if the will was already signed/sent: moving the date earlier only makes
|
||||||
|
the inheritance available *sooner*, so there is no early-execution risk.
|
||||||
|
* **Expire** (new delivery time now in the **past**): the will is genuinely
|
||||||
|
expired and you are asked to **invalidate** the old transaction on-chain,
|
||||||
|
then rebuild.
|
||||||
* **Postpone** (new delivery time *later* than the signed locktime) on a will
|
* **Postpone** (new delivery time *later* than the signed locktime) on a will
|
||||||
that was already **signed and/or pushed**: the previously committed coins
|
that was already **signed and/or pushed**: the previously committed coins
|
||||||
must be invalidated on-chain **first**, otherwise a will-executor could
|
must be invalidated on-chain **first**, otherwise a will-executor could
|
||||||
@@ -121,14 +126,15 @@ state.
|
|||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|
||||||
|
Run the tests with the **runtime environment** active (see `HANDOFF.md` §3 for
|
||||||
|
the two venvs and how to activate them):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# imports + behavior
|
# imports + behavior
|
||||||
QT_QPA_PLATFORM=offscreen PYTHONPATH=<electrum-src> \
|
QT_QPA_PLATFORM=offscreen python3 tests/smoke_test.py electrum.plugins.bal
|
||||||
python3 tests/smoke_test.py electrum.plugins.bal
|
|
||||||
|
|
||||||
# external-zip loading regression
|
# external-zip loading regression (run after build_zip.py)
|
||||||
QT_QPA_PLATFORM=offscreen PYTHONPATH=<electrum-src> \
|
QT_QPA_PLATFORM=offscreen python3 tests/external_zip_test.py bal-electrum-plugin.zip
|
||||||
python3 tests/external_zip_test.py bal-electrum-plugin.zip
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## ⚠️ Safety
|
## ⚠️ Safety
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ servers.
|
|||||||
already-signed will is handled safely. Postponing a signed/sent will first
|
already-signed will is handled safely. Postponing a signed/sent will first
|
||||||
asks you to invalidate the old transaction on-chain (so a will-executor can
|
asks you to invalidate the old transaction on-chain (so a will-executor can
|
||||||
never broadcast the earlier-locktime transaction and execute the inheritance
|
never broadcast the earlier-locktime transaction and execute the inheritance
|
||||||
too early), then lets you rebuild and re-send the new one via
|
too early), then lets you rebuild and re-send the new one via the
|
||||||
**Tools → Prepare**.
|
**Prepare** button on the **WILL** tab.
|
||||||
- **"Server" column**: the will transaction list shows whether each transaction
|
- **"Server" column**: the will transaction list shows whether each transaction
|
||||||
is actually stored on the will-executor servers
|
is actually stored on the will-executor servers
|
||||||
(`Confirmed on server`, `Sent (not checked)`, `Send failed`,
|
(`Confirmed on server`, `Sent (not checked)`, `Send failed`,
|
||||||
|
|||||||
@@ -6,11 +6,12 @@
|
|||||||
|
|
||||||
Documentation for the **BAL** open‑source Electrum plugin for Bitcoin digital
|
Documentation for the **BAL** open‑source Electrum plugin for Bitcoin digital
|
||||||
inheritance. Everything here is plain Markdown + images (and optional styled
|
inheritance. Everything here is plain Markdown + images (and optional styled
|
||||||
HTML), so it renders directly on GitHub and via GitHub Pages — **no PDF needed**.
|
HTML), so it renders directly on any forge (Gitea/GitHub) and in any browser —
|
||||||
|
**no PDF needed**.
|
||||||
|
|
||||||
## Contents
|
## Contents
|
||||||
|
|
||||||
| Document | Markdown (GitHub) | Styled HTML |
|
| Document | Markdown | Styled HTML |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| **User Manual (revB)** — full plugin manual with screenshots | [`manual/README.md`](./manual/README.md) | [`manual/manual.html`](./manual/manual.html) |
|
| **User Manual (revB)** — full plugin manual with screenshots | [`manual/README.md`](./manual/README.md) | [`manual/manual.html`](./manual/manual.html) |
|
||||||
| **Inheritance Options Guide** — every change (date earlier/later, add/remove heir, change %, fees, executors) + decision flow chart + transaction states & server effects | [`inheritance-options.md`](./inheritance-options.md) | [`inheritance-options.html`](./inheritance-options.html) |
|
| **Inheritance Options Guide** — every change (date earlier/later, add/remove heir, change %, fees, executors) + decision flow chart + transaction states & server effects | [`inheritance-options.md`](./inheritance-options.md) | [`inheritance-options.html`](./inheritance-options.html) |
|
||||||
@@ -23,9 +24,8 @@ HTML), so it renders directly on GitHub and via GitHub Pages — **no PDF needed
|
|||||||
|
|
||||||
## Viewing the HTML versions
|
## Viewing the HTML versions
|
||||||
|
|
||||||
- On GitHub Pages: enable Pages for this repository (Settings → Pages → deploy
|
- Online: serve the `docs/` folder as static files (e.g. Pages on Gitea or
|
||||||
from branch, folder `/docs`), then open
|
GitHub) and open `manual/manual.html`.
|
||||||
`https://<owner>.github.io/<repo>/manual/manual.html`.
|
|
||||||
- Offline: download the `docs/` folder and open the `.html` files in any browser
|
- Offline: download the `docs/` folder and open the `.html` files in any browser
|
||||||
(the styled manual works fully offline; the inheritance‑options page loads
|
(the styled manual works fully offline; the inheritance‑options page loads
|
||||||
Mermaid from a CDN for the live diagram, and also ships a static SVG fallback).
|
Mermaid from a CDN for the live diagram, and also ships a static SVG fallback).
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ important ones:
|
|||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `VALID` | The item is the current, usable plan | default `True`; cleared by INVALIDATED/REPLACED/CONFIRMED/MEMPOOL |
|
| `VALID` | The item is the current, usable plan | default `True`; cleared by INVALIDATED/REPLACED/CONFIRMED/MEMPOOL |
|
||||||
| `COMPLETE` (*Signed*) | The transaction has been **signed** | after you press **Sign** |
|
| `COMPLETE` (*Signed*) | The transaction has been **signed** | after you press **Sign** |
|
||||||
|
| `PARTIALLY_SIGNED` | Only **some** of the required signatures are present | a multisig will after a partial sign (cleared by `COMPLETE`) |
|
||||||
| `PUSHED` | The signed tx was **sent to the will‑executor(s)** | after **Broadcast** to executors |
|
| `PUSHED` | The signed tx was **sent to the will‑executor(s)** | after **Broadcast** to executors |
|
||||||
| `CHECKED` | The will‑executor **confirmed** it holds the tx | after a successful server **Check** (implies `PUSHED`) |
|
| `CHECKED` | The will‑executor **confirmed** it holds the tx | after a successful server **Check** (implies `PUSHED`) |
|
||||||
| `CHECK_FAIL` | The server **check failed** | a queried executor did not return the tx |
|
| `CHECK_FAIL` | The server **check failed** | a queried executor did not return the tx |
|
||||||
@@ -65,6 +66,7 @@ Flag transitions enforced by `set_status` (the safety rules baked in the code):
|
|||||||
- Setting `CONFIRMED` / `MEMPOOL` → clears `INVALIDATED`.
|
- Setting `CONFIRMED` / `MEMPOOL` → clears `INVALIDATED`.
|
||||||
- Setting `PUSHED` → clears `PUSH_FAIL` **and** `CHECK_FAIL`.
|
- Setting `PUSHED` → clears `PUSH_FAIL` **and** `CHECK_FAIL`.
|
||||||
- Setting `CHECKED` → implies `PUSHED` (and clears `PUSH_FAIL`).
|
- Setting `CHECKED` → implies `PUSHED` (and clears `PUSH_FAIL`).
|
||||||
|
- Setting `COMPLETE` → clears `PARTIALLY_SIGNED`.
|
||||||
|
|
||||||
### How states map to row colour in the list
|
### How states map to row colour in the list
|
||||||
|
|
||||||
@@ -83,7 +85,8 @@ wins:
|
|||||||
| 7 | `CHECKED` | green | `#8afa6c` |
|
| 7 | `CHECKED` | green | `#8afa6c` |
|
||||||
| 8 | `PUSH_FAIL` | red | `#e83845` |
|
| 8 | `PUSH_FAIL` | red | `#e83845` |
|
||||||
| 9 | `PUSHED` | teal | `#73f3c8` |
|
| 9 | `PUSHED` | teal | `#73f3c8` |
|
||||||
| 10 | `COMPLETE` (signed, **not** yet pushed) | blue | `#2bc8ed` |
|
| 10 | `PARTIALLY_SIGNED` | amber | `#ffb347` |
|
||||||
|
| 11 | `COMPLETE` (signed, **not** yet pushed) | blue | `#2bc8ed` |
|
||||||
| — | none of the above (e.g. plain `VALID`, prepared) | default white | `#ffffff` |
|
| — | none of the above (e.g. plain `VALID`, prepared) | default white | `#ffffff` |
|
||||||
|
|
||||||
> **Note (v0.3.3 fix):** a will that is *signed but not yet broadcast*
|
> **Note (v0.3.3 fix):** a will that is *signed but not yet broadcast*
|
||||||
@@ -354,5 +357,5 @@ that limit.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
*This document reflects BAL plugin v0.4.7. Behaviour is derived directly from
|
*This document reflects the current BAL plugin (v0.6.1). Behaviour is derived
|
||||||
`core/will.py`, `core/heirs.py` and `gui/qt/window.py`.*
|
directly from `core/will.py`, `core/heirs.py` and `gui/qt/window.py`.*
|
||||||
|
|||||||
@@ -76,6 +76,22 @@ inheritance cases.
|
|||||||
*Figure 2 — the parameters on the HEIRS tab: (1) Delivery Time, (2) Check Alive,
|
*Figure 2 — the parameters on the HEIRS tab: (1) Delivery Time, (2) Check Alive,
|
||||||
(3) Fees.*
|
(3) Fees.*
|
||||||
|
|
||||||
|
### User type: BASIC / ADVANCED
|
||||||
|
|
||||||
|
The plugin has two usage modes, chosen from the plugin settings
|
||||||
|
(**Tools → Plugins → BAL**, *User Type* selector):
|
||||||
|
|
||||||
|
- **BASIC** (default) — hides the advanced controls: the **Delivery Time** is
|
||||||
|
entered only as a precise **Date** (the relative **RAW** durations and the
|
||||||
|
Raw/Date selector are hidden), the **Check Alive** field is hidden, and the
|
||||||
|
postpone-on-open behaviour is disabled.
|
||||||
|
- **ADVANCED** — reveals the **Raw/Date selector** (relative durations such as
|
||||||
|
`1y` or `30d`) and the **Check Alive** field, and enables the postpone
|
||||||
|
behaviour described below. Switching to ADVANCED requires typing the
|
||||||
|
confirmation phrase **"at My Risk"**.
|
||||||
|
|
||||||
|
The rest of this section describes the full (ADVANCED) parameter set.
|
||||||
|
|
||||||
### 1 — Delivery Time (Locktime)
|
### 1 — Delivery Time (Locktime)
|
||||||
|
|
||||||
Indicates the date on which the inheritance of your wallet on the blockchain
|
Indicates the date on which the inheritance of your wallet on the blockchain
|
||||||
@@ -94,6 +110,11 @@ If you choose **Raw**, you can insert various options based on a suffix:
|
|||||||
|
|
||||||
*(i.e. check whether you are still alive, and then postpone the inheritance.)*
|
*(i.e. check whether you are still alive, and then postpone the inheritance.)*
|
||||||
|
|
||||||
|
> **NB:** the **Check Alive** parameter is available only in **ADVANCED** mode.
|
||||||
|
> In **BASIC** (default) it is hidden and the plugin re-evaluates the will
|
||||||
|
> against "now" every time you open Electrum, so the postpone behaviour
|
||||||
|
> described here does not apply.
|
||||||
|
|
||||||
This parameter — settable as relative (`RAW`) or absolute (`DATE`) — indicates
|
This parameter — settable as relative (`RAW`) or absolute (`DATE`) — indicates
|
||||||
the time by which the inheritance will **not** be changed by postponing it.
|
the time by which the inheritance will **not** be changed by postponing it.
|
||||||
|
|
||||||
@@ -223,6 +244,9 @@ plugin will notify you that you need to update the inheritance.
|
|||||||
|
|
||||||
## RAW settings
|
## RAW settings
|
||||||
|
|
||||||
|
> **NB:** relative (**RAW**) durations are available only in **ADVANCED** mode;
|
||||||
|
> in **BASIC** the Delivery Time is entered only as a precise date.
|
||||||
|
|
||||||
If you set, for example, `RAW‑1d` and it is, say, 5 p.m., the plugin will not
|
If you set, for example, `RAW‑1d` and it is, say, 5 p.m., the plugin will not
|
||||||
execute the inheritance precisely 24 hours later (5 p.m. the next day) but will
|
execute the inheritance precisely 24 hours later (5 p.m. the next day) but will
|
||||||
roughly estimate the blockchain block number corresponding to that time — so
|
roughly estimate the blockchain block number corresponding to that time — so
|
||||||
@@ -239,7 +263,8 @@ with a tolerance of a few hours.
|
|||||||
If you want a quick test run, enter an upcoming legacy date/time (e.g. 18 hours
|
If you want a quick test run, enter an upcoming legacy date/time (e.g. 18 hours
|
||||||
later). For such short intervals the **Check Alive** could create problems, so
|
later). For such short intervals the **Check Alive** could create problems, so
|
||||||
set the Check Alive parameter **in the past** (a date before today) — e.g. a
|
set the Check Alive parameter **in the past** (a date before today) — e.g. a
|
||||||
previous month.
|
previous month. *(The Check Alive only exists in **ADVANCED** mode; in
|
||||||
|
**BASIC** this is not needed.)*
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -335,7 +360,7 @@ inheritance:
|
|||||||
|
|
||||||
## Will‑Executor service list
|
## Will‑Executor service list
|
||||||
|
|
||||||
This window opens from the Electrum menu, **Tools → Will‑executor**, and shows
|
This window opens from the Electrum menu, **Tools → Will‑Executors**, and shows
|
||||||
the official list of will‑executor servers.
|
the official list of will‑executor servers.
|
||||||
|
|
||||||
If you want to make changes — such as adding an additional will‑executor server —
|
If you want to make changes — such as adding an additional will‑executor server —
|
||||||
@@ -409,14 +434,16 @@ transactions can have in the WILL tab, on each will‑executor that is online.
|
|||||||
| # | Status | Meaning | Colour | HEX |
|
| # | Status | Meaning | Colour | HEX |
|
||||||
|---|--------|---------|--------|-----|
|
|---|--------|---------|--------|-----|
|
||||||
| 1 | **New** | TX new inheritance | White (transparent) | `#FFFFFF` |
|
| 1 | **New** | TX new inheritance | White (transparent) | `#FFFFFF` |
|
||||||
| 2 | **Signed** | TX inheritance signed into the wallet | Azure | `#2BC8ED` |
|
| 2 | **Partially signed** | TX has some, but not all, of the required signatures | Amber | `#FFB347` |
|
||||||
| 3 | **Pushed** | TX sent to will‑executor | Azure‑green | `#73F3C8` |
|
| 3 | **Signed** | TX inheritance signed into the wallet | Azure | `#2BC8ED` |
|
||||||
| 4 | **Checked** | TX actually present in the will‑executor | Bright green | `#8AFA6C` |
|
| 4 | **Pushed** | TX sent to will‑executor | Azure‑green | `#73F3C8` |
|
||||||
| 5 | **Confirmed** | TX confirmed in the blockchain | Gray | `#BFBFBF` |
|
| 5 | **Checked** | TX actually present in the will‑executor | Bright green | `#8AFA6C` |
|
||||||
| 6 | **Pending** | TX awaiting confirmation on blockchain | Yellow | `#FFCE30` |
|
| 6 | **Confirmed** | TX confirmed in the blockchain | Gray | `#BFBFBF` |
|
||||||
| 7 | **Failed** | Communication failure with will‑executor | Red | `#E83845` |
|
| 7 | **Pending** | TX awaiting confirmation on blockchain | Yellow | `#FFCE30` |
|
||||||
| 8 | **Invalidated** | UTXO input is no longer available | Orange | `#F87838` |
|
| 8 | **Failed** | Communication failure with will‑executor | Red | `#E83845` |
|
||||||
| 9 | **Replaced** | A backdated‑locktime transaction spends the same input | Violet | `#FF97E9` |
|
| 9 | **Invalidated** | UTXO input is no longer available | Orange | `#F87838` |
|
||||||
|
| 10 | **Replaced** | A backdated‑locktime transaction spends the same input | Violet | `#FF97E9` |
|
||||||
|
| 11 | **Updated** | TX re‑issued keeping the same locktime and heirs | Light violet | `#B266B2` |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user