Skip to content

Latest commit

 

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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:

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

Needs["WolframInstitute`Puzzles`"]

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:

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

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.

Development

# 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 - 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

About

Wolfram Language paclet: plumbing for cryptographic treasure hunts — encodings, seeds, key derivation, oracles, search, steganography and chain lookups

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages