# Puzzles

A Wolfram Language paclet (`WolframInstitute/Puzzles`, context
`` WolframInstitute`Puzzles` ``) holding the **plumbing for cryptographic treasure
hunts**: the encodings, seed schemes, key derivations, candidate oracles, search
drivers, steganography extractors and chain lookups that puzzle work needs over
and over.

> Status: **all seven categories populated.** ~140 exported symbols, each with a
> usage message and a reference page, pinned by ~870 tests against published
> specification vectors.

## Published

The paclet is deployed publicly to the Wolfram Cloud. Install it:

```wolfram
PacletInstall[
  ResourceObject["https://www.wolframcloud.com/obj/nikm/DeployedResources/Paclet/WolframInstitute/Puzzles"],
  ForceVersionInstall -> True]

Needs["WolframInstitute`Puzzles`"]
```

- **Resource page** (install, usage, hero, hierarchical sidebar): <https://www.wolframcloud.com/obj/nikm/DeployedResources/Paclet/WolframInstitute/Puzzles>
- **Documentation site** (a single-page browser over every guide, tech note and symbol page): <https://www.wolframcloud.com/obj/nikm/Puzzles>
- **Raw archive** (a plain `.paclet` download): <https://www.wolframcloud.com/obj/nikm/Puzzles.paclet>

Both surfaces rebuild and redeploy from source with `scripts/publish.wls` (the
resource, with DocumentationBuild'd pages) and `scripts/build_docs.wls site` (the
documentation-site shell).

## The seven categories

The same seven names index the kernel code, the tests, the guide pages and the
symbol reference pages. The list is fixed.

| Category | Covers | Symbols |
| --- | --- | --- |
| `Encodings` | Base58 / Base58Check, Bech32 / Bech32m, WIF, hex / base64 / bit-list, varint, classical ciphers | 43 |
| `Seeds` | BIP39 mnemonics and checksums, Electrum v1/v2, brainwallet and passphrase schemes | 16 |
| `Derivation` | BIP32 HD derivation, BIP44/49/84/86 paths, secp256k1 pubkeys, every address form | 23 |
| `Oracles` | candidate-to-target checking: address matchers, hash chains, compiled batch verifiers | 7 |
| `Search` | candidate generators, sweep drivers, the negative-results ledger, and classical cryptanalysis | 30 |
| `Steganography` | LSB and bit-plane extraction, channel splitting, metadata and appended-data recovery | 11 |
| `Chain` | block-explorer queries: balance, unspent status, transaction history | 11 |

Two further symbols, `$WolframInstitutePuzzlesCategories` and
`$WolframInstitutePuzzlesVersion`, describe the paclet itself.

## What one chain of the plumbing looks like

Eleven known words, an unknown twelfth, and a published address as the only
evidence - `Seeds` proposes the checksum-valid completions, `Derivation` turns
each into an address, `Oracles` recognises the target and `Search` drives the
sweep:

```wolfram
first11 = ConstantArray["abandon", 11];
words = BIP39FinalWords[first11];                      (* the 128 valid completions *)

space = CandidateEnumeration[<|
  "Length" -> Length[words],
  "Generator" -> Function[i,
    BitcoinAddress[
      BIP32DeriveKey[BIP32MasterKey[BIP39Seed[Append[first11, words[[i]]]]], "m/84h/0h/0h/0/0"],
      "P2WPKH"]]
|>];

sweep = CandidateSweep[space, PuzzleOracle[{"bc1qcr8te4kr609gcawutmrza0j4xv80jy8z306fyu"}]];
words[[First[sweep["HitIndices"]]]]
(* "about" - the word the BIP84 test vector publishes *)
```

## Usage

```wolfram
PacletDirectoryLoad["/path/to/Puzzles"];

Needs["WolframInstitute`Puzzles`"];   (* loads the whole paclet *)

$WolframInstitutePuzzlesCategories
(* {"Chain", "Derivation", "Encodings", "Oracles", "Search", "Seeds", "Steganography"} *)
```

There is no supported way to load one category on its own: the paclet has a
single umbrella context and the category directories are organization only.

## The library side of a two-repo split

This paclet is the **library** side of the work. The **research** side lives
separately: one directory per puzzle, each holding the artifacts, notes, prior
attempts and negative results for that specific hunt.

Anything written twice in two different
puzzle directories - a Base58Check decoder, a mnemonic validator, an address
matcher - belongs here instead, verified once against published test vectors and
reused everywhere. Puzzle-specific narrative, evidence and dead ends stay in the
puzzle directory; only the reusable machinery is promoted.

## Correctness

This paclet computes things that decide whether real money is found, so every
function is pinned to an **independent published test vector** (BIP39 official
vectors, BIP32 test vectors, BIP173 / BIP350 Bech32 vectors, known address/key
pairs), with the vector source cited in the test file. A function that merely
looks right is a defect. See [AGENTS.md](AGENTS.md).

## Development

```bash
# load test - must print LOADED with no messages
wolframscript -code 'PacletDirectoryLoad["/path/to/Puzzles"]; Needs["WolframInstitute`Puzzles`"]; "LOADED"'

# run the test suite
wolframscript -f scripts/run_tests.wls

# build the documentation notebooks from docs/en/**.md
wolframscript -f scripts/build_notebooks.wls

# evaluate every ```wl cell in docs/en/**.md - nothing else runs them
wolframscript -f scripts/run_doc_examples.wls

# DocumentationBuild the authoring notebooks, then verify the built structure
wolframscript -f scripts/docbuild.wls
```

Each of these scripts runs its files across a small worker pool - four kernels by
default, never every core, because a routine test run should not take the machine
over. `PZ_TEST_KERNELS`, `PZ_DOC_KERNELS` and `PZ_DOCBUILD_KERNELS` override the
count for the three scripts respectively; set them to `1` on a busy machine.

`scripts/build_notebooks.wls` writes *authoring* notebooks. Before a page is
published it must also go through `DocumentationBuild`, which is what folds the
authoring `ExamplesInitializationSection` into a real Examples section; a page
deployed straight from the authoring notebook renders with a doubled section
rule and its examples collapsed under "Examples Initialization".

`scripts/docbuild.wls` is that stage. It builds each authoring notebook into a
copy of the paclet under `$TemporaryDirectory` - deliberately *outside* the
repository, since a nested `PacletInfo.wl` would register as a second paclet and
win resolution against the working tree - and then reads the result back and
asserts its structure:
a reference page must carry a `Usage` cell, a `PrimaryExamplesSection` and at
least one `ExampleSection`, and a guide a `GuideTitle` and a body section. A page
that builds without error but comes out missing its Examples section is reported
as a failure, because that is exactly the breakage the earlier stages cannot see.
It needs a Front End, so it is kept out of the plain test acceptance.

- **[AGENTS.md](AGENTS.md)** - the contributor and agent guide: taxonomy, the
  correctness rule, and the exact kernel / test / documentation skeletons.
- **`docs/en/`** - documentation sources (Markdown, built to notebooks). The
  Markdown is the source of truth; generated `.nb` are gitignored.

### The documentation tree

| Source | Page |
| --- | --- |
| `docs/en/Guides/Puzzles.md` | the root landing page, `PacletInfo.wl`'s `"MainPage"`; it links down to all seven category guides, which is what builds the sidebar tree |
| `docs/en/Guides/<Category>.md` | the seven category guides; each links back up to `Puzzles` through `RelatedGuides` |
| `docs/en/Tutorials/Overview.md` | the table of contents: every guide and all ~140 symbols |
| `docs/en/ReferencePages/Symbols/<Category>/<Symbol>.md` | one page per exported symbol |

Output notebooks are **flat by basename** regardless of source nesting, so two
pages may never share a basename.

### What the suite guards

Beyond each category's own vectors, two files pin the paclet as a whole:

- **`Tests/GeneralParameters.wlt`** - the taxonomy across all four trees, and the
  paclet-wide invariants: every export has a usage message, no export shadows a
  `System`` ` name, loading emits no messages, every export has a reference page and
  every reference page an export, page basenames are unique, and every `SeeAlso`,
  `RelatedGuides` and internal `paclet:` URI resolves to a page that exists.
- **`scripts/run_doc_examples.wls`** - evaluates all ~1345 `wl` cells in the 154
  documentation pages, each file's cells sequentially on shared state as a reader
  would run them. It checks that every example *evaluates without a message*; it
  does not yet compare the result against the page's `<!-- => ... -->` annotation.
- **`Tests/Integration.wlt`** - the seams between categories, each landing on a
  published value: the BIP84 and BIP86 chains from mnemonic to address, the genesis
  coinbase key through three categories' HASH160 routes, a full
  `Search` -> `Seeds` -> `Derivation` -> `Oracles` sweep that recovers a lost final
  word, and `Chain`'s offline safety property (an unanswerable prize check must be a
  `Failure`, never `False`).

## License

MIT
