Skip to content

feat(rushwallet): add 30 RushWallet brainwallet contest puzzles#152

Open
oritwoen wants to merge 4 commits into
mainfrom
rushwallet-collection
Open

feat(rushwallet): add 30 RushWallet brainwallet contest puzzles#152
oritwoen wants to merge 4 commits into
mainfrom
rushwallet-collection

Conversation

@oritwoen
Copy link
Copy Markdown
Owner

@oritwoen oritwoen commented May 9, 2026

Adds the RushWallet brainwallet contest collection: Dmitri Kryptokov / Kryptokit 2014, 30 targets funded by 1GShq18eb4V6uBtqgwxkmuPTUHCtyBcNYA, derivation sha256(passphrase) -> uncompressed P2PKH. 28 passphrases recovered locally; 3 unsolved (#26, #30).

Includes data, schema entries, codegen wiring, and tests.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 9, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 4133ebe7-bbaf-4982-b1ac-eaee3c01f7ca

📥 Commits

Reviewing files that changed from the base of the PR and between 1e84eac and 2433a9d.

📒 Files selected for processing (2)
  • build.rs
  • scripts/src/bin/generate_wif.rs
📜 Recent review details
🧰 Additional context used
📓 Path-based instructions (2)
scripts/src/**/*.rs

📄 CodeRabbit inference engine (scripts/AGENTS.md)

scripts/src/**/*.rs: Use JSON caching in ../data/cache/ to avoid repeated API calls when fetching data with Cargo binaries in the scripts project
Skip failures and continue processing when updating JSONC data files instead of halting on errors
Use serde_json for JSONC file manipulation when modifying ../data/*.jsonc files
Include console log progress output for per-puzzle status during data computation and fetching operations
Never hardcode API keys; use .env file for configuration (see .env.example for reference)

Files:

  • scripts/src/bin/generate_wif.rs
build.rs

📄 CodeRabbit inference engine (AGENTS.md)

Cryptographic key validation in build.rs must verify: key bits match hex, WIF↔hex consistency, and h160/script_hash correctness

Use cargo:rerun-if-changed in build.rs to trigger rebuilds when JSONC data or schema files change

Files:

  • build.rs
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: oritwoen/boha

Timestamp: 2026-05-13T18:51:54.413Z
Learning: When adding a new puzzle collection, follow the b1000 pattern: add JSONC data file, update `build.rs` codegen, and create module in `src/collections/`
Learnt from: CR
Repo: oritwoen/boha

Timestamp: 2026-05-13T18:51:54.413Z
Learning: Do not add runtime configuration; all puzzle data must be embedded at compile time via the codegen process
🔇 Additional comments (7)
scripts/src/bin/generate_wif.rs (1)

62-81: LGTM!

Also applies to: 83-114, 116-138, 177-177, 183-185

build.rs (6)

36-106: LGTM!


715-746: LGTM!


1079-1087: LGTM!


1284-1284: LGTM!

Also applies to: 1326-1329, 1346-1346


2293-2323: LGTM!


2325-2458: LGTM!


📝 Walkthrough

Walkthrough

Adds a new "rushwallet" puzzle collection: 30-puzzle JSONC data, schema-aware build-time generator that emits static Rust data, a runtime collection module with standard accessors, Collection enum/dispatch wiring, updates to supporting scripts, CLI test expectations, and docs.

Changes

Rushwallet Collection Registration

Layer / File(s) Summary
Data file and schema changes
data/rushwallet.jsonc, data/schemas/collection.schema.json, build.rs
Adds the rushwallet JSONC with 30 puzzles, removes a schema allOf requiring key.bits, and adds schema/deserialization helpers used to parse the new file.
Build-time code generation
build.rs
Includes data/rushwallet.jsonc in DATA_HASH and cargo triggers, tightens key.hex vs key.wif.decrypted consistency, and implements generate_rushwallet() to validate metadata and emit rushwallet_data.rs.
Runtime collection module
src/collections/rushwallet.rs, src/collections/mod.rs
New module that includes generated PUZZLES and exposes author(), get(name), slice()/all()/solved()/unsolved(), and count().
Core Collection registry and dispatch
src/lib.rs
Exports the new module, adds Collection::Rushwallet, expands Collection::ALL to 10 entries, and routes name/parse/slice/author/get to the rushwallet module.
Build & data processing scripts
scripts/src/bin/add_timestamps.rs, scripts/src/bin/extract_pubkey.rs, scripts/src/bin/generate_h160.rs, scripts/src/bin/generate_transactions.rs, scripts/src/bin/generate_wif.rs, scripts/src/main.rs
Adds rushwallet to default collection lists and input file arrays; generate_wif now derives WIF compression from puzzle.pubkey.format and handles per-file errors without aborting.
CLI tests
src/cli.rs
Update test expectations to include rushwallet in collection-name help outputs.
Documentation and knowledge base
AGENTS.md, skills/boha/SKILL.md, skills/boha/references/collections.md, Cargo.toml
Bump collections count to ten, add rushwallet entry and contest/derivation metadata, include a usage example, and add jsonschema build-dependency.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • oritwoen/boha#101: Prior JSONC + JSON Schema parsing work that this PR builds on.
  • oritwoen/boha#141: Related central Collection registry/dispatch changes this PR extends.
  • oritwoen/boha#103: Related pubkey/claim extraction tooling that this change extends to rushwallet.

Suggested reviewers

  • cubic-dev-ai
  • aeitwoen

A wallet's secrets walk the chain,
Thirty puzzles stamped by sha256,
Build turns JSONC into static Rust,
Registry grows, scripts now include the set,
Docs and tests updated — new collection live.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 8.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: adding the RushWallet brainwallet contest collection with 30 puzzles.
Description check ✅ Passed The description explains what was added (RushWallet collection, 30 targets, derivation method, recovery status) and aligns with the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch rushwallet-collection
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch rushwallet-collection

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.

Warning

Billing warning: we have not been able to collect payment for this subscription for more than 72 hours. Please update the payment method or pay any pending invoices in Billing to avoid service interruption.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot added the enhancement New feature or request label May 9, 2026
@oritwoen oritwoen self-assigned this May 9, 2026
@augmentcode
Copy link
Copy Markdown

augmentcode Bot commented May 9, 2026

🤖 Augment PR Summary

Summary: Adds the rushwallet collection to boha, capturing Dmitri Kryptokov / Kryptokit’s 2014 RushWallet brainwallet contest.

Changes:

  • Introduces data/rushwallet.jsonc with 30 Bitcoin P2PKH targets, funding/claim tx history, and recovered keys/passphrases (27 solved, 3 still unknown).
  • Extends build.rs codegen to parse RushWallet JSONC, validate pubkeys for claimed puzzles, and emit rushwallet_data.rs.
  • Adds src/collections/rushwallet.rs and wires it into src/collections/mod.rs and public exports in src/lib.rs.
  • Updates CLI collection registry/help text to include rushwallet.
  • Updates maintenance scripts to include rushwallet.jsonc in timestamp/tx/h160/wif/pubkey workflows.
  • Refreshes skill/reference docs to document the new collection and ID format.

Technical Notes: Keys are derived as sha256(passphrase) → uncompressed pubkey → P2PKH; all contest UTXOs were funded by 1GShq18eb4V6uBtqgwxkmuPTUHCtyBcNYA (per metadata/docs).

🤖 Was this summary useful? React with 👍 or 👎

Copy link
Copy Markdown

@augmentcode augmentcode Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. 1 suggestion posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

Comment thread data/rushwallet.jsonc Outdated
"kind": "p2pkh",
"value": "1GwQ9ik3PH6g4BzwShFdwf2AEhUyfQVBpn"
},
"status": "unsolved",
Copy link
Copy Markdown

@augmentcode augmentcode Bot May 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

status is "unsolved" here but the puzzle has a "claim" transaction; that makes it look like an active bounty and also bypasses the build-time/script pubkey expectations for claimed/swept puzzles. Consider whether this should be tracked as claimed (and record the revealed pubkey) so Status::is_active()/stats and pubkey extraction behave correctly.

Severity: medium

Other Locations
  • data/rushwallet.jsonc:969

Fix This in Augment

🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
scripts/src/bin/generate_wif.rs (1)

126-135: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

WIF generation is hardcoded to compressed keys, which conflicts with RushWallet

With Line 134 adding RushWallet, the hardcoded hex_to_wif(&hex, true) path (Line 70, Line 87) can generate wrong WIFs for uncompressed keys if any wif.decrypted is missing later.

Targeted fix
-                        if let Some(wif) = hex_to_wif(&hex, true) {
+                        let compressed = puzzle
+                            .get("pubkey")
+                            .and_then(|p| p.get("format"))
+                            .and_then(|f| f.as_str())
+                            .map(|f| f != "uncompressed")
+                            .unwrap_or(true);
+                        if let Some(wif) = hex_to_wif(&hex, compressed) {
                             add_wif_to_key(key_item, &wif);
                             count += 1;
                         }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/src/bin/generate_wif.rs` around lines 126 - 135, The WIF generation
currently calls hex_to_wif(&hex, true) with a hardcoded compressed=true which
breaks support for uncompressed keys (e.g., RushWallet); change the hex_to_wif
calls in this file to pass the correct compression flag instead of true by
extracting or inferring it from the parsed wallet data (e.g., check each
wallet's metadata such as wif.decrypted or a compressed flag on the parsed
entry) so hex_to_wif(&hex, compressed_flag) uses the actual key form for each
entry; update both call sites (the ones around where hex and wif.decrypted are
used) to use that computed boolean.
build.rs (1)

1234-1248: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Schema rule edits won’t retrigger codegen.

build.rs watches data/*.jsonc, but not data/schemas/*. If a schema changes, generated output can stay stale until a manual clean build.

Suggested fix
 fn main() {
+    println!("cargo:rerun-if-changed=data/schemas");
     println!("cargo:rerun-if-changed=data/arweave.jsonc");
     println!("cargo:rerun-if-changed=data/b1000.jsonc");
     println!("cargo:rerun-if-changed=data/hash_collision.jsonc");

As per coding guidelines "build.rs: Use cargo:rerun-if-changed directives in build.rs to watch data/schemas/ and trigger rebuilds when JSON Schema validation rules change".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@build.rs` around lines 1234 - 1248, The build script build.rs currently
watches data/*.jsonc but not schema files, so add cargo:rerun-if-changed
directives to watch the schema directory; update build.rs to include lines like
println!("cargo:rerun-if-changed=data/schemas"); and also watch the files inside
(e.g. println!("cargo:rerun-if-changed=data/schemas/*.json");
println!("cargo:rerun-if-changed=data/schemas/*.jsonc")) alongside the existing
println! calls so changes to JSON Schema files in data/schemas will retrigger
codegen and rebuild.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@AGENTS.md`:
- Line 8: The STRUCTURE block is out of sync: update the module count from nine
to ten and add the missing "rushwallet" entry to the data/*.jsonc list and to
the list of modules so the documented inventory matches the text stating ten
collections (also verify the per-collection counts if shown); specifically edit
the STRUCTURE section to include "rushwallet" alongside arweave, b1000, ballet,
bitaps, bitimage, gsmg, hash_collision, warp, and zden and increment the total
collection/module number to ten.

In `@build.rs`:
- Around line 2214-2216: The build step currently deserializes
data/rushwallet.jsonc directly into WithSchema<RushwalletFile> (variables
wrapped and data) without JSON Schema or semantic checks; update build.rs to
first validate the raw JSONC content against the appropriate schema(s) in
data/schemas/ (using a JSON Schema validator) and only then deserialize into
WithSchema<RushwalletFile>, and add post-deserialization semantic checks that
verify key hex formats and WIF↔hex consistency for the fields on RushwalletFile
(e.g., the inner keys referenced by wrapped.inner). Ensure any schema or
semantic validation failures cause a clear panic/error from build.rs so codegen
fails fast.

In `@data/rushwallet.jsonc`:
- Around line 489-503: The JSON entries currently have "status": "unsolved"
while their transactions include a "type": "claim" (e.g., the object containing
txid "14710d11301c0ce117eca620051e81e919470989b74fbfcaa6172ff5cd9e2b40"); update
the "status" field to "claimed" for any puzzle objects whose "transactions"
array contains a "type":"claim" entry (apply the same change to the other
similar object referenced in the comment), and ensure future data handling
distinguishes Solver vs Claimer by preserving solver-related fields while
marking claimer activity via "claimed" status.

---

Outside diff comments:
In `@build.rs`:
- Around line 1234-1248: The build script build.rs currently watches
data/*.jsonc but not schema files, so add cargo:rerun-if-changed directives to
watch the schema directory; update build.rs to include lines like
println!("cargo:rerun-if-changed=data/schemas"); and also watch the files inside
(e.g. println!("cargo:rerun-if-changed=data/schemas/*.json");
println!("cargo:rerun-if-changed=data/schemas/*.jsonc")) alongside the existing
println! calls so changes to JSON Schema files in data/schemas will retrigger
codegen and rebuild.

In `@scripts/src/bin/generate_wif.rs`:
- Around line 126-135: The WIF generation currently calls hex_to_wif(&hex, true)
with a hardcoded compressed=true which breaks support for uncompressed keys
(e.g., RushWallet); change the hex_to_wif calls in this file to pass the correct
compression flag instead of true by extracting or inferring it from the parsed
wallet data (e.g., check each wallet's metadata such as wif.decrypted or a
compressed flag on the parsed entry) so hex_to_wif(&hex, compressed_flag) uses
the actual key form for each entry; update both call sites (the ones around
where hex and wif.decrypted are used) to use that computed boolean.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 53ade7e4-151b-43ef-b673-af12ee05d2bf

📥 Commits

Reviewing files that changed from the base of the PR and between 8a3813a and 0a46621.

📒 Files selected for processing (15)
  • AGENTS.md
  • build.rs
  • data/rushwallet.jsonc
  • scripts/src/bin/add_timestamps.rs
  • scripts/src/bin/extract_pubkey.rs
  • scripts/src/bin/generate_h160.rs
  • scripts/src/bin/generate_transactions.rs
  • scripts/src/bin/generate_wif.rs
  • scripts/src/main.rs
  • skills/boha/SKILL.md
  • skills/boha/references/collections.md
  • src/cli.rs
  • src/collections/mod.rs
  • src/collections/rushwallet.rs
  • src/lib.rs
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: test
🧰 Additional context used
📓 Path-based instructions (8)
scripts/src/**/*.rs

📄 CodeRabbit inference engine (scripts/AGENTS.md)

scripts/src/**/*.rs: Use JSON caching in ../data/cache/ to avoid repeated API calls when fetching data with Cargo binaries in the scripts project
Skip failures and continue processing when updating JSONC data files instead of halting on errors
Use serde_json for JSONC file manipulation when modifying ../data/*.jsonc files
Include console log progress output for per-puzzle status during data computation and fetching operations
Never hardcode API keys; use .env file for configuration (see .env.example for reference)

Files:

  • scripts/src/main.rs
  • scripts/src/bin/generate_h160.rs
  • scripts/src/bin/generate_wif.rs
  • scripts/src/bin/add_timestamps.rs
  • scripts/src/bin/extract_pubkey.rs
  • scripts/src/bin/generate_transactions.rs
AGENTS.md

📄 CodeRabbit inference engine (CLAUDE.md)

AGENTS.md: Document agent responsibilities and capabilities in AGENTS.md
Maintain clear agent interface definitions and behavioral specifications

Files:

  • AGENTS.md
src/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

Ensure all strings in compiled Rust code are &'static str to support static data allocation without heap allocation

Use Option<T> for all optional fields to represent missing or undefined puzzle data

Files:

  • src/collections/mod.rs
  • src/collections/rushwallet.rs
  • src/cli.rs
  • src/lib.rs
src/collections/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

Use static PUZZLES: &[Puzzle] for compiled puzzle data in generated collection modules under src/collections/

Files:

  • src/collections/mod.rs
  • src/collections/rushwallet.rs
src/cli.rs

📄 CodeRabbit inference engine (AGENTS.md)

CLI functionality must be implemented in src/cli.rs using clap derive macros, not in main.rs

Add new CLI commands using clap derive macros in src/cli.rs

Files:

  • src/cli.rs
build.rs

📄 CodeRabbit inference engine (AGENTS.md)

Use build.rs to validate JSONC→Rust codegen: verify key bits match hex, WIF↔hex consistency, and apply JSON Schema validation from data/schemas/

Trigger cargo:rerun-if-changed in build.rs for JSONC files so that changes to data/*.jsonc automatically trigger rebuilds

Use cargo:rerun-if-changed directives in build.rs to watch data/schemas/ and trigger rebuilds when JSON Schema validation rules change

Files:

  • build.rs
data/*.jsonc

📄 CodeRabbit inference engine (AGENTS.md)

Store all puzzle data in JSONC format in data/*.jsonc files, not hardcoded in Rust source code

Define puzzle IDs using the format collection/identifier (e.g., b1000/66, bitimage/kitten), with exceptions for gsmg and bitaps which have no slash

Define solvers once in data/solvers.jsonc and reference them by ID in puzzle files, rather than duplicating solver definitions

Files:

  • data/rushwallet.jsonc
scripts/src/bin/generate_transactions.rs

📄 CodeRabbit inference engine (scripts/AGENTS.md)

Provide ETHERSCAN_API_KEY environment variable for Ethereum transaction fetching with the generate-transactions binary

Files:

  • scripts/src/bin/generate_transactions.rs
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
Repo: oritwoen/boha

Timestamp: 2026-05-09T16:00:49.050Z
Learning: Distinguish between Solver (who revealed/found the key) and Claimer (who swept the funds) - track both as they may be different people
Learnt from: CR
Repo: oritwoen/boha

Timestamp: 2026-05-09T16:00:49.050Z
Learning: Synchronize modifications to the Puzzle struct between `src/puzzle.rs` and `build.rs` to ensure codegen matches struct definition
Learnt from: CR
Repo: oritwoen/boha

Timestamp: 2026-05-09T16:00:49.050Z
Learning: When adding a new puzzle collection, follow the b1000 pattern: add JSONC data in `data/*.jsonc`, update `build.rs`, and create corresponding module in `src/collections/`
📚 Learning: 2026-02-21T06:17:12.647Z
Learnt from: oritwoen
Repo: oritwoen/boha PR: 111
File: data/arweave.jsonc:21-21
Timestamp: 2026-02-21T06:17:12.647Z
Learning: In data/*.jsonc puzzle data files, enforce that the 'name' field contains only the puzzle identifier (e.g., 'weave1', 'kitten', 'Level 1'), not the full 'collection/identifier' format. The full ID (e.g., 'arweave/weave1', 'bitimage/kitten') should be constructed at build time or runtime by the Rust code in build.rs and related collection modules. During code reviews, verify that 'name' does not contain the collection prefix and that the build/runtime logic assembles the complete ID consistently from these identifiers.

Applied to files:

  • data/rushwallet.jsonc
🪛 markdownlint-cli2 (0.22.1)
skills/boha/SKILL.md

[warning] 9-9: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)

🔇 Additional comments (11)
scripts/src/bin/generate_transactions.rs (1)

454-461: Default collection wiring looks correct

Line 459 includes rushwallet in the no-args path, so transaction generation behavior stays in sync with the new collection rollout.

scripts/src/bin/add_timestamps.rs (1)

539-541: Default timestamp pass now includes RushWallet

Line 540 is the right place to add it, and it keeps timestamp backfills consistent with other scripts.

scripts/src/bin/extract_pubkey.rs (1)

511-511: RushWallet scan inclusion is correct

Line 511 wires the new dataset into pubkey extraction without changing existing safety filters.

scripts/src/main.rs (1)

152-152: File list update is correct

Line 152 keeps the start-date fetch script aligned with the new collection inventory.

scripts/src/bin/generate_h160.rs (1)

93-93: Collection list update is in the right place

Line 93 correctly includes RushWallet in H160 generation coverage.

skills/boha/SKILL.md (1)

9-35: No issues in this doc update.

Counts and the new rushwallet ID example are consistent with the new collection wiring.

src/collections/rushwallet.rs (1)

15-52: Collection module wiring looks correct.

get/slice/all/solved/unsolved/count matches the expected collection surface and uses the generated static dataset correctly.

src/collections/mod.rs (1)

8-8: Module export is correct.

This exposes the new rushwallet collection module in the registry namespace.

src/lib.rs (1)

14-157: Registry integration is complete for rushwallet.

Enum, parser, naming, slice/author/get dispatch, and Collection::ALL are all updated consistently.

src/cli.rs (1)

1907-1911: Test expectations are correctly updated.

Including rushwallet here keeps collection_help assertions aligned with Collection::ALL.

skills/boha/references/collections.md (1)

61-68: Rushwallet reference section is clear and consistent.

The usage example and collection description align with the new module/API surface.

Comment thread AGENTS.md
Comment thread build.rs
Comment thread data/rushwallet.jsonc Outdated
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 15 files

Confidence score: 3/5

  • There is a concrete data-consistency risk in data/rushwallet.jsonc: puzzles #13 and #26 are marked status: "unsolved" despite having claim transactions, which can cause unsolved() to include already-spent puzzles.
  • Given the medium severity (6/10) and high confidence (9/10), this is likely user-impacting behavior rather than a purely cosmetic issue, so the merge risk is moderate.
  • Pay close attention to data/rushwallet.jsonc - correct puzzle status/claim alignment so runtime puzzle selection and build-time pubkey validation stay accurate.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="data/rushwallet.jsonc">

<violation number="1" location="data/rushwallet.jsonc:489">
P2: Puzzle #13 has `status: "unsolved"` but records a claim transaction (txid `14710d...2b40`). Same for #26. This makes `unsolved()` return puzzles whose funds are already spent, and skips the build-time pubkey validation that applies to claimed puzzles. These should be `"claimed"` (the passphrase/solver is unknown, but the UTXO is gone).</violation>
</file>
Architecture diagram
sequenceDiagram
    participant Dev as Developer
    participant Build as build.rs
    participant Rustc as Rust Compiler
    participant Lib as lib.rs
    participant App as Application

    Note over Dev,App: Build-Time Data Ingestion (compile-time embedded)

    Dev->>Build: Cargo build triggers main()
    Build->>Build: Register rerun-if-changed for data/rushwallet.jsonc
    Build->>Build: Read data/rushwallet.jsonc, strip comments
    Build->>Build: Parse JSONC into RushwalletFile struct
    Build->>Build: Validate puzzle pubkeys against claimed status
    Build->>Build: Generate static PUZZLES array with all 30 puzzles
    Build->>Build: Write generated rushwallet_data.rs to OUT_DIR
    Build->>Rustc: Compile rushwallet_data.rs into library
    Rustc-->>Rustc: Include generated code via include! macro

    Note over Lib,App: Runtime API (consumer-facing)

    App->>Lib: rushwallet::get("9") or Collection::Rushwallet.get("9")
    Lib->>Lib: Format search_id as "rushwallet/9"
    Lib->>Lib: Iterate over static PUZZLES array
    alt Puzzle found
        Lib-->>App: &Puzzle with status, key, passphrase, transactions
    else Not found
        Lib-->>App: Error::NotFound
    end
    App->>Lib: rushwallet::slice() or Collection::Rushwallet.puzzles()
    Lib-->>App: &[Puzzle] with all 30 entries
    App->>Lib: rushwallet::solved() or unsolved()
    Lib->>Lib: Filter PUZZLES by status
    Lib-->>App: Iterator over Solved or Unsolved puzzles
    App->>Lib: rushwallet::author()
    Lib-->>App: &Author (Dmitri Kryptokov)
    App->>Lib: rushwallet::count()
    Lib-->>App: const 30

    Note over App: Consumer queries puzzle details
    App->>App: Access key.wif.passphrase for solved puzzles
    App->>App: Access transactions (funding/claim txids, amounts)
    App->>App: Access pubkey (uncompressed format)
    App->>App: Access address (hash160, value for P2PKH)
    alt Puzzle is solved
        App-->>App: Passphrase available
    else Puzzle unsolved (#13, #26, #30)
        App-->>App: No key or passphrase data
    end
Loading

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread data/rushwallet.jsonc Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
scripts/src/bin/generate_wif.rs (1)

145-151: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don't let one bad file abort the rest of the batch.

process_jsonc_file(&path)? exits on the first parse or write error. With another input file added here, one broken JSONC now prevents every later file from being updated. Log and continue instead.

Possible fix
     for file in &files {
         let path = data_dir.join(file);
         if path.exists() {
-            process_jsonc_file(&path)?;
+            if let Err(err) = process_jsonc_file(&path) {
+                eprintln!("Failed to process {}: {err}", path.display());
+            }
         } else {
             eprintln!("File not found: {}", path.display());
         }
     }
As per coding guidelines, "Skip failures and continue processing when updating JSONC data files instead of halting on errors".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/src/bin/generate_wif.rs` around lines 145 - 151, The loop calling
process_jsonc_file(&path)? will abort the entire batch on the first error;
change it to handle the Result returned by process_jsonc_file for each file (the
for file in &files { let path = data_dir.join(file); if path.exists() { ... } }
block) by matching or using if let Err(e) = process_jsonc_file(&path) { log the
error with context (include path/display and the error) and continue } so a
single bad JSONC file is skipped while the rest are processed.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@build.rs`:
- Around line 715-724: Add explicit metadata fields for solved_count and
total_puzzles to RushwalletMetadata and, after deserializing each RushwalletFile
in build.rs, validate those counts: ensure metadata.total_puzzles matches the
deserialized puzzles.len() and metadata.solved_count matches the number of
RushwalletPuzzle entries marked solved (use the solved flag on
RushwalletPuzzle). If the metadata is missing or counts mismatch, emit a
build-time error (panic or eprintln + exit) so codegen fails fast; update
RushwalletMetadata and any parsing/validation logic in build.rs to perform this
check.

In `@scripts/src/bin/generate_wif.rs`:
- Around line 76-83: Add per-puzzle progress logging inside the loop that
iterates "for puzzle in array.iter_mut()" in generate_wif.rs: before/when
calling needs_wif/compressed_for_puzzle, compute an identifying label (try
puzzle.get("name") or fall back to the loop index) and print/log it for every
branch—on success (after add_wif_to_key and incrementing count), on skip when
needs_wif returns None, and on failure when hex_to_wif returns None—so each
puzzle yields a clear breadcrumb; apply the same per-puzzle logging changes to
the similar code block referenced around lines 93-100.
- Around line 62-69: The helper compressed_for_puzzle currently treats any
unknown pubkey.format as compressed because it uses format != "uncompressed";
change compressed_for_puzzle to explicitly match accepted values: return
Some(true) for "compressed", Some(false) for "uncompressed", and None (or Err)
for any other or missing format so callers can skip or surface an error; update
its signature from fn compressed_for_puzzle(puzzle: &Value) -> bool to return
Option<bool> or Result<bool, _> and update the code paths that call
compressed_for_puzzle (the WIF generation/write logic) to skip or error when
None/Err is returned instead of writing a possibly-wrong compressed WIF.

---

Outside diff comments:
In `@scripts/src/bin/generate_wif.rs`:
- Around line 145-151: The loop calling process_jsonc_file(&path)? will abort
the entire batch on the first error; change it to handle the Result returned by
process_jsonc_file for each file (the for file in &files { let path =
data_dir.join(file); if path.exists() { ... } } block) by matching or using if
let Err(e) = process_jsonc_file(&path) { log the error with context (include
path/display and the error) and continue } so a single bad JSONC file is skipped
while the rest are processed.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 793c120e-01b2-48a9-903b-1b3fbe892a34

📥 Commits

Reviewing files that changed from the base of the PR and between 0a46621 and 1e84eac.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (8)
  • AGENTS.md
  • Cargo.toml
  • build.rs
  • data/rushwallet.jsonc
  • data/schemas/collection.schema.json
  • scripts/src/bin/generate_wif.rs
  • skills/boha/references/collections.md
  • src/collections/rushwallet.rs
💤 Files with no reviewable changes (1)
  • data/schemas/collection.schema.json
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: cubic · AI code reviewer
🧰 Additional context used
📓 Path-based instructions (7)
AGENTS.md

📄 CodeRabbit inference engine (CLAUDE.md)

AGENTS.md: Document agent responsibilities and capabilities in AGENTS.md
Maintain clear agent interface definitions and behavioral specifications

Files:

  • AGENTS.md
scripts/src/**/*.rs

📄 CodeRabbit inference engine (scripts/AGENTS.md)

scripts/src/**/*.rs: Use JSON caching in ../data/cache/ to avoid repeated API calls when fetching data with Cargo binaries in the scripts project
Skip failures and continue processing when updating JSONC data files instead of halting on errors
Use serde_json for JSONC file manipulation when modifying ../data/*.jsonc files
Include console log progress output for per-puzzle status during data computation and fetching operations
Never hardcode API keys; use .env file for configuration (see .env.example for reference)

Files:

  • scripts/src/bin/generate_wif.rs
**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

Store puzzle data in JSONC files in data/ directory, not hardcoded in Rust source code

Use &'static str for all string values in Rust structs; do not use heap-allocated strings

Files:

  • scripts/src/bin/generate_wif.rs
  • src/collections/rushwallet.rs
  • build.rs
src/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

Make all data types use &'static references for no heap allocation; embed all data at compile time

Files:

  • src/collections/rushwallet.rs
src/collections/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

Use include!() macro in generated src/collections/*.rs files to import static puzzle arrays from build output

Files:

  • src/collections/rushwallet.rs
build.rs

📄 CodeRabbit inference engine (AGENTS.md)

Use build-time JSONC→Rust codegen via build.rs to compile puzzle data from data/*.jsonc into Rust

Validate puzzle data during build-time codegen: verify key bits match hex, ensure WIF↔hex consistency, validate address hashes

Use cargo:rerun-if-changed in build.rs to trigger rebuild when JSONC files change

Files:

  • build.rs
data/*.jsonc

📄 CodeRabbit inference engine (AGENTS.md)

Define solvers once in data/solvers.jsonc and reference by ID in puzzle files rather than duplicating solver definitions

Follow the ID convention collection/identifier (e.g., b1000/66, bitimage/kitten); exceptions are gsmg and bitaps which omit the slash

Track both Solver (who revealed the key/found the solution) and Claimer (who swept the funds) separately; these may be different people

Files:

  • data/rushwallet.jsonc
🧠 Learnings (1)
📚 Learning: 2026-02-21T06:17:12.647Z
Learnt from: oritwoen
Repo: oritwoen/boha PR: 111
File: data/arweave.jsonc:21-21
Timestamp: 2026-02-21T06:17:12.647Z
Learning: In data/*.jsonc puzzle data files, enforce that the 'name' field contains only the puzzle identifier (e.g., 'weave1', 'kitten', 'Level 1'), not the full 'collection/identifier' format. The full ID (e.g., 'arweave/weave1', 'bitimage/kitten') should be constructed at build time or runtime by the Rust code in build.rs and related collection modules. During code reviews, verify that 'name' does not contain the collection prefix and that the build/runtime logic assembles the complete ID consistently from these identifiers.

Applied to files:

  • data/rushwallet.jsonc
🔇 Additional comments (5)
AGENTS.md (1)

8-8: LGTM!

Also applies to: 20-23, 133-133

skills/boha/references/collections.md (1)

66-67: ⚡ Quick win

The example code compiles as-is — all field types are Copy

The Key, Wif, Seed, and Entropy structs all derive Copy (confirmed in src/puzzle.rs). When you call .and_then() on Option<Key>, the closure receives a copy of Key, not a reference. No borrowing issues, no need for .as_ref() or .and_then() chains. The snippet is correct.

			> Likely an incorrect or invalid review comment.
data/rushwallet.jsonc (1)

1-1149: LGTM!

Cargo.toml (1)

146-146: LGTM!

src/collections/rushwallet.rs (1)

16-53: LGTM!

Comment thread build.rs
Comment thread scripts/src/bin/generate_wif.rs Outdated
Comment thread scripts/src/bin/generate_wif.rs Outdated
Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 9 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="scripts/src/bin/generate_wif.rs">

<violation number="1" location="scripts/src/bin/generate_wif.rs:67">
P2: This negative match (`format != "uncompressed"`) silently treats any typo (e.g. `"uncompresssed"`, `"Uncompressed"`) as compressed, which would generate a valid-looking but wrong WIF. Match `"compressed"` and `"uncompressed"` explicitly and error/skip on anything else so bad data doesn't sneak through.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread scripts/src/bin/generate_wif.rs Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant