Skip to content

v0.8.3: wallet fixes (#141 #142 #147 #148) - #154

Merged
dendisuhubdy merged 4 commits into
mainfrom
fix/v083-wallet
Oct 28, 2026
Merged

dendisuhubdy merged 4 commits into
mainfrom
fix/v083-wallet

Conversation

@dendisuhubdy

Copy link
Copy Markdown
Member

Four wallet fixes from the chain-21 network experiment, one commit each. All are client-only: no node, RPC or chain change.

#141: rand no longer exits 1 after a successful submit

  • As soon as rand_sendTransaction returns a hash, rand prints submitted <kind> <hash> on stderr, before waiting. <kind> is the node's own action.kind, and a plain bundle is transfer. It goes to stderr so stdout contracts such as order <hash> and $(rand address) don't change. faucet keeps its existing submitted mint … line on stdout.
  • The commit wait (wait_for_transaction) and the receipt wait (wait_for_receipt) retry status polls that time out, are reset, or get a node error. The retry delay starts at 0.5 s and doubles up to 5 s, until the wait's deadline.
  • If the wait never sees the commit, it ends with the new ConfirmationUnknown error and rand exits 4. The message says "submitted, confirmation unknown" and gives the hash, the last poll's failure, and a rand tx <hash> hint. A rejection is still exit 1.
  • All commands use the same wait path: send, token create/mint/burn, program deploy/call/invoke, bond, bridge, multisig, perps, governance bundle-less actions, and faucet.
  • New global flag --wait-timeout <SECS> / RAND_WAIT_TIMEOUT.
  • A rescan or height read that fails after the commit was seen now says the transaction committed.
  • Exit codes (0/1/2/3/4) are documented in docs/cli.md.

#142: token create --initial / --fixed-supply take display units

  • Both flags now read display units at --decimals, the same as token mint --amount. --initial-units / --fixed-supply-units take base units; clap refuses a flag together with its -units twin.
  • On success, token create echoes minted <display> <SYMBOL> (<N> units) to <rand1…>.
  • This is a behaviour change, recorded in the CHANGELOG's Unreleased (v0.8.3) section. Updated docs/cli.md, docs/tokens.md and docs/shielded.md.

#147: the scan no longer reveals which leaves are the wallet's

  • leaf_page now reads rand_getCommitments(cursor, 500) and nothing else. The request sequence depends only on the cursor and the tree size, and ownership is decided locally after each page arrives.

  • Removed the heads/chunk path: rand_getScanLeaves reads, fetch_chunks, heads_page, may_be_ours, and RpcClient::{with_scan_chunk, scan_chunk}.

  • --scan-chunk is still accepted (now hidden) and ignored, with a warning.

  • Fixed the docs: docs/shielded.md's scanning bullet (it claimed the scan "reveals nothing about which leaves are yours"), the rand_getScanLeaves section and changelog in docs/rpc.md, and the --scan-chunk row in docs/cli.md.

  • Measured byte cost (test a_scan_reads_the_same_full_pages_for_every_wallet_and_measures_their_cost). Setup: 2 000 leaves with chain 21's 1 860-byte envelope; the wallet owns 6 leaves spread over 4 of the 8 chunks of 256 leaves.

    read bytes per leaf
    full pages (the new scan) 7 769 996 3 885
    heads only 3 439 991 1 720
    old path: heads + the 4 owned chunks read in full 7 231 597 —

    So a full row costs 2.26× a head. That is the whole increase for a wallet whose notes fell in no chunk. For this test's wallet, whose old scan already read half the envelopes, the increase is 1.07×.

#148: --proxy <URL> / RAND_PROXY

  • Enabled reqwest's socks feature. Cargo.lock is unchanged because reqwest 0.12.28 proxies through hyper-util, which is already a dependency.
  • Accepted schemes: socks5h:// (Tor: socks5h://127.0.0.1:9050), socks5://, http://, https://. Any other scheme is refused.
  • rand sets the proxy as the process default before any client exists, so every RPC client and every remote prover goes through it: --prover, prover pair, and the trusted pool.
  • An explicit proxy turns off the HTTP(S)_PROXY environment variables. If the proxy is down, the request fails; nothing falls back to a direct connection.
  • Added a Tor recipe to docs/cli.md (the repo has no docs/wallet.md) and a line to docs/shielded.md.

Tests

New tests:

Commands run (niced, 4 build jobs, RAYON_NUM_THREADS=4):

  • cargo test -p randprotocol-client --no-fail-fast: 347 passed, 0 failed, 2 ignored (the 2 are wallet_flow's existing #[ignore]d tests). Per binary: lib 248, rand bin 26, cli_perp 12, cli_rpc 29, cli_scripts 3, cli_token_bridge 9, rpc_methods 10, wallet_flow 10 + 2 ignored (real-node end-to-end with proving, 1 101 s), doc-tests 0
  • cargo clippy --no-deps -p randprotocol-client --all-targets -- -D warnings: clean.
  • cargo check -p randprotocol-node --all-targets: clean.

I did not run the full workspace suite.

Closes #141
Closes #142
Closes #147
Closes #148

🤖 Generated with Claude Code

https://claude.ai/code/session_01GFs5h141Ct6RTGGrCTQ1vy

dendisuhubdy and others added 4 commits October 28, 2026 00:42
Once rand_sendTransaction has answered with a hash, rand prints
`submitted <kind> <hash>` on stderr (kind = the node's action.kind,
`transfer` for a plain bundle) before it waits. The commit and receipt
waits retry polls that time out, are reset or get a node error, backing
off 0.5 s -> 5 s, until the deadline; a wait that never sees the commit
is ConfirmationUnknown, which rand exits 4 on ("submitted, confirmation
unknown", the hash, the last poll's failure and a `rand tx <hash>`
hint). A rejection is still exit 1. Covers every command on the shared
wait path: send, token create/mint/burn, program deploy/call/invoke,
bond, bridge, multisig, perps and governance bundle-less actions, and
faucet.

New global --wait-timeout <SECS> / RAND_WAIT_TIMEOUT. A rescan or
height read that fails after a seen commit now says it committed.
Exit codes documented in docs/cli.md.

Fixes #141

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GFs5h141Ct6RTGGrCTQ1vy
`--initial` and `--fixed-supply` now read display units at the token's
own --decimals, like `token mint --amount`, `token burn` and
`send --asset`: `--decimals 6 --initial 1000000` is a million tokens,
not one. The base-unit form moves to `--initial-units` /
`--fixed-supply-units`; clap refuses a flag together with its twin.
A fractional amount past --decimals is refused, naming the flag and
the -units alternative. On success `token create` echoes the mint as
`minted <display> <SYMBOL> (<N> units) to <rand1…>`.

Behaviour change, listed in CHANGELOG (Unreleased, v0.8.3); docs/cli.md,
docs/tokens.md and docs/shielded.md updated.

Fixes #142

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GFs5h141Ct6RTGGrCTQ1vy
…owns

Since scan heads (v0.8.0) `leaf_page` read `rand_getScanLeaves`, trial-
decrypted the heads, and then fetched full envelopes with
`rand_getCommitments` only around the leaves `may_be_ours` matched:
first by gap-merged span, from v0.8.2 by aligned 256-leaf chunk
(RPC-201). Either way the node serving the scan saw, keyed by IP, which
leaves (or chunks) were the wallet's, and a leaf index plus its height
names the transaction.

`leaf_page` now reads `rand_getCommitments(cursor, 500)` and nothing
else, so the request sequence depends only on the cursor and the tree's
size; ownership is decided locally after the page arrives. The
heads/chunk machinery (`fetch_chunks`, `heads_page`, `may_be_ours`,
`RpcClient::{with_scan_chunk, scan_chunk}`, DEFAULT/MAX_SCAN_CHUNK) is
gone; `--scan-chunk` is still parsed (hidden) and ignored with a
warning. `RpcClient::scan_leaves` stays for other callers.

Tests: two wallets, one owning every kind of leaf and one owning none,
make byte-identical request logs (every method, every param) over the
same chain, with full pages only and no heads read; the same over 2 000
leaves of chain 21's 1 860-byte envelope, which also measures the cost:
3 885 B of JSON a leaf vs 1 720 B for a head (2.26x, the whole increase
for a wallet whose notes sat in no chunk; 1.07x for this test's wallet,
whose notes sat in 4 of 8 chunks).

Docs: shielded.md's scanning bullet now says what the node sees;
rpc.md's scan-heads section and changelog; cli.md's --scan-chunk row.

Fixes #147

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GFs5h141Ct6RTGGrCTQ1vy
…KS5 or HTTP

Enables reqwest's `socks` feature in the client (no new crates: reqwest
0.12.28 proxies through hyper-util, already in the lock). New global
`--proxy <URL>` / `RAND_PROXY` takes socks5h:// (Tor:
socks5h://127.0.0.1:9050, names resolved at the proxy), socks5://,
http:// or https://; anything else is refused naming --proxy.

`rand` sets it as the process default before any client exists
(`set_default_proxy`), so every RpcClient and every RemoteProver
(--prover, `prover pair`, the trusted pool) goes through it; explicit
`RpcClient::with_proxy` / `RemoteProver::with_proxy` exist too. A proxy
is added with reqwest's `.proxy()`, which turns the HTTP(S)_PROXY
environment off, and a proxy that is down fails the request: nothing
falls back to a direct connection.

Tests, against a minimal SOCKS5 stub (no auth, CONNECT): the RPC client
and the remote prover reach their servers only as the stub's CONNECT
target; a dead proxy fails the call; the scheme check; and the `rand`
binary end to end with --proxy and with RAND_PROXY, plus a dead proxy
that leaves the node untouched.

Docs: --proxy row and a Tor recipe in docs/cli.md, a line in
docs/shielded.md, CHANGELOG.

Fixes #148

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GFs5h141Ct6RTGGrCTQ1vy
@codecov

codecov Bot commented Oct 27, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@dendisuhubdy
dendisuhubdy merged commit aacf2a0 into main Oct 28, 2026
23 checks passed
@dendisuhubdy
dendisuhubdy deleted the fix/v083-wallet branch October 28, 2026 01:25
dendisuhubdy added a commit that referenced this pull request Oct 28, 2026
- CHANGELOG.md, Unreleased v0.8.3, "Node": #156 (issues #151 #152 #153)
  carried no entry; its three items are added from the PR's own
  measurements.
- docs/rpc.md changelog, "newest first": the #147 wallet entry moves up
  beside the other v0.8.3 entries (#154 had put it under v0.8.2), and a
  v0.8.3 entry records the client-visible parts of #145 and #157 — the
  stem's `unknown` status, the meaning of the returned hash, `-32005`,
  and `rand_status.admission_bytes` / `admission_budget_bytes`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GFs5h141Ct6RTGGrCTQ1vy
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant