Commit Graph
871 Commits
Author SHA1 Message Date
DanSandClaude Opus 5 5634aed750 wallet: open salvaged wallets in a degraded mode, and detect a mismatched hdchain
A wallet.dat repaired by v1.0.3-or-earlier -salvagewallet could not be opened by
this build at all. Those builds' IsKeyType has no "hdchain" case, so salvage
dropped the record; LoadWallet then returned DB_CORRUPT and told the user to
restore from a seed phrase. There is no such recovery path: the node aborts
before the RPC server exists, -usemnemonic defaulted to 0 in v1.0.3 so many of
these wallets never had a phrase, and SetHDSeedFromMnemonic refuses a non-empty
wallet, so "move wallet.dat aside" discards every non-HD key salvage preserved.

The guard itself was right to refuse to DERIVE -- a missing hdchain falls back to
SetNull defaults, clearing fMnemonicSeed and switching derivation from the
64-byte BIP39 seed to the raw 32-byte entropy, an entirely different key tree.
It was wrong to refuse to OPEN. Split the two:

  - "hdchain" record ABSENT (the salvage signature, tracked by a new
    wss.fHDChainSeen set before any parse attempt) -> open DEGRADED.
  - "hdchain" record PRESENT but unreadable -> still DB_CORRUPT; that signals
    wider file damage.

Degraded means the wallet spends, receives and rescans normally but refuses to
derive any new HD key. Gated at the single choke point GetHDSeedForDerivation
rather than at the two generators, so z_getnewaddress/sendmany/shieldcoinbase
raise a clean error and autoshield skips. hdChain.seedFp is deliberately left
null, which keeps IsHDTransparentEnabled false so getnewaddress falls back to the
legacy random-key path -- gating it instead would break TopUpKeyPool, change
addresses and block templates. -rescan is soft-set because an old salvage also
dropped defaultkey and bestblock, which would otherwise look like a first run and
skip the rescan, leaving a permanently zero balance.

NEW DETECTOR, covering strictly more damage than the guard beside it. A wallet
salvaged by v1.0.3 and then USED on v1.0.3 persists a SetNull-derived hdchain
carrying seedFp=null. On this build fHDChainRead is then true, the guard never
fires, the node starts perfectly clean -- and derives into the wrong key tree
forever, silently. That state is unforgeable by any legitimate writer, since
InstallHDSeed always stores seedFp = seed.Fingerprint(), so compare the loaded
chain's seedFp against the fingerprint taken from the hdseed/chdseed record KEY
(which works while an encrypted wallet is locked) and degrade on mismatch.

Also:
  - init.cpp: abort in the DB_CORRUPT branch itself, as DB_NEED_REWRITE already
    does. Falling through ran several hundred more lines against a wallet just
    declared corrupt, including SetHDSeedOrigin(), which WRITES to it. Error text
    no longer advises -mnemonic (wrong twice over, see above).
  - rpcdump.cpp: z_exportwallet discarded GetHDSeedForDerivation's return and
    emitted the line regardless, so a failure wrote a blank seed next to a
    legitimate-looking BLAKE2b-of-empty fingerprint -- a backup that looks valid
    and restores nothing.
  - Corrected the guard's comment: the saplingAccountCounter half was overstated.
    Both generators loop while(Have...Key(...)), so a low counter walks forward
    past existing accounts rather than colliding with them.

qa/r4-salvaged-wallet-harness.sh builds the victim wallets with the on-disk
v1.0.1 release binary and asserts the behaviour end to end. It REFUSES to run
outside a network namespace and re-checks getconnectioncount==0, because those
old binaries predate the regtest seed-injection fix and would otherwise dial the
live network. 11/11 pass:

  C healthy wallet opens and is NOT flagged   (no false positives)
  A salvaged wallet opens, flagged, persists no hdchain, z_getnewaddress refused,
    getnewaddress still works, z_exportwallet emits no bogus HDSeed line
  B poisoned wallet opens and the seedFp detector fires

Note the harness asserts "no hdchain synthesised", NOT "wallet.dat unchanged":
a control run showed normal startup rewrites wallet.dat for healthy wallets too.

This is the access/detection half. Proving fMnemonicSeed by re-deriving against
held keys, and repairing the record, is deliberately left out: it requires a
write, and the affected population is unmeasured. dev's own salvage already
preserves hdchain, so the class is closed going forward.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FU87LdsJZiZkfq1eXubpeo
2026-08-31 13:29:43 -05:00
DanSandClaude Opus 5 c5fde12485 qa: port 12 wallet/mining tests to python3 and fix three framework blockers
Ports qa/rpc-tests from 6 python3 files to 18. Ran every ported test against
the freshly built v1.3.0 dragonxd. Results, honestly:

  PASS (1)            getblocktemplate_proposals.py
  NOT APPLICABLE (7)  wallet.py, walletbackup.py, wallet_protectcoinbase.py,
                      wallet_listnotes.py, wallet_mergetoaddress.py,
                      getblocktemplate.py, wallet_shieldcoinbase.py
  BLOCKED (4)         wallet_sapling, wallet_nullifiers, wallet_persistence,
                      wallet_treestate

The "not applicable" seven are inherited Zcash/Hush-era tests that exercise
features DragonX deliberately removed. They assume transparent t->t value
transfer, but ASSETCHAINS_PRIVATE=1 (hush_utils.h:1826) makes sendtoaddress
and sendmany consensus-refuse; they assume Sprout joinsplits, which are gone
from the RPC layer entirely; and they hardcode Bitcoin economics (10 coin/block,
100-block maturity) against DragonX's 3 DRGX and COINBASE_MATURITY=1. They are
ported and left in place rather than deleted, but they cannot pass on this chain
without being rewritten around z_shieldcoinbase/autoshield.

Three framework fixes in test_framework/util.py, each of which broke every
multi-node test:
  - initialize_chain() passed -connect=0, and init.cpp soft-sets -listen=0 when
    -connect is present, so cache node0 never opened its p2p port and nodes 1-3
    could never sync to it -- initialize_chain() hung forever in sync_blocks().
    Now passes -listen=1 -bind=127.0.0.1 -dnsseed=0 explicitly (an explicit arg
    beats SoftSetBoolArg) while keeping the cache nodes off the public network.
  - cache cleanup removed files from <datadir> when dragonxd writes them one
    level deeper into the net-specific <datadir>/regtest.
  - set_node_times() did print("..." + t) with t an int -> TypeError.
  - default binary paths corrected to src/dragonxd and src/dragonx-cli.

The four BLOCKED tests are blocked by a daemon assert, not by the port; see the
follow-up commit/report on BLOCK_VALID_CONTEXT.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FU87LdsJZiZkfq1eXubpeo
2026-08-31 01:53:43 -05:00
DanS 4cc7e0491a qa: finish the python3 port far enough to build the shared test chain
Follow-up to 5e0a70683, which got start_node() working. Three more
defects sat behind it:

- initialize_chain() builds the 4-node cache with its own daemon
  invocation, which 5e0a70683 did not touch. It therefore still omitted
  -regtest (so those cache nodes ran on MAINNET) and -asmap (so they
  refused to start at all). Every test that uses the cache -- which is
  most of the wallet suite -- died there.

- reindex.py and getblocktemplate_longpoll.py each carried a single
  python2 print statement, which is the whole reason they would not even
  parse under python3. Shebangs updated to match.

The suite still does not pass: initialize_chain hits a remaining py2
str+int concatenation, and getblocktemplate.py reaches a real test
assertion. Both are beyond this commit, but the harness now gets far
enough to start nodes, answer RPC and begin building the shared chain,
which it could not do before.
2026-08-30 21:29:08 -05:00
DanS 5e0a706839 qa: repair the rpc-test harness so it can start a DragonX node at all
The integration suite has never run against DragonX. Six independent
defects stacked up, each only visible once the previous was fixed:

1. test_framework used python2 implicit relative imports
   ("from authproxy import ..."), removed in python3, so every test died
   at import. Made explicit relative imports.

2. It wrote ZZZ.conf -- a Komodo assetchain convention -- while DragonX
   reads DRAGONX.conf. The daemon therefore never saw the generated
   config, fell back to mainnet defaults and tried to bind RPC 21769,
   which on a seed node is already held by the real node.

3. start_node() was hard-wired for the -ac_name=ZZZ assetchain tests: it
   took the RPC port from extra_args[3], passed extra_args[0] as argv[0]
   of the CLI, and only wrote a config when extra_args[0] matched. Any
   test that passes no extra args crashed on len(None). The generic path
   now takes the port from rpc_port(i) -- the same helper
   initialize_datadir() already used -- and drives the CLI with -datadir.

4. dragonxd refuses to start without an asmap file, which no test datadir
   had. initialize_datadir() now provisions one.

5. -asmap relative paths resolve against the NET-SPECIFIC datadir, so a
   copy in <datadir> is never found. Pass an absolute path.

6. Worst: -regtest was only ever set as "regtest=1" in the conf file,
   which DragonX ignores. Every "regtest" node therefore ran on MAINNET:
   real genesis, real seeds, real peers. An observed run synced 196,180
   live blocks and 679MB into /tmp before the test timed out. -regtest is
   now passed as a command-line flag, with -connect=0 so an isolated
   regtest node stays off the public network.

With these, nodes start, RPC answers, and tests run to a real result.
They do not all pass yet -- getblocktemplate.py reaches an assertion --
but that is now a test outcome rather than a harness failure.
2026-08-30 19:44:27 -05:00
DanSandClaude Opus 4.8 46693a355a docs: rebrand documentation, packaging, and helper scripts to DragonX
The docs/packaging were largely un-rebranded Hush3 content, with several
docs stating facts that are wrong for DragonX. This rewrites them against
the verified DragonX source state.

Corrections (not just branding):
- PoW: RandomX (CPU), not Equihash/ASIC — README, overview.md, randomx.md
- Privacy: private from genesis (ac_private=1, Sapling@height1), not "as of
  block 340000" — overview.md, payment-api.md
- Removed the false "coinbase must be shielded" consensus claim
  (shield-coinbase.md, payment-api.md); coinbase is directly spendable
- Fixed default fee 0.0001 (was 0.0010000, 10x); stratum port 22769 (was 19031)
- datadir ~/.hush/DRAGONX, DRAGONX.conf, dragonxd/dragonx-cli/dragonx-tx,
  git.dragonx.is throughout; branch model dev->dragonx
- Softened the inherited dPoW reorg claim (no live DragonX notary infra)

Packaging: fix build-debian-package.sh + gen-manpages.sh to use the dragonx
binaries/manpages; rename bash-completions to dragonx*; drop hush-arrakis-chain
from the package. Keep /usr/share/hush (hardcoded in the binary for params).

Also: README links/logo, ObsidianDragon + SilentDragonXAndroid wallets,
networking/init/dev-process/contrib/util rebrand, and leftover helper scripts.
Delete legacy duplicates (hushd.* init/service, HUSH3.conf examples,
OLD_WALLETS.md, hsc.md) and rename hush-uri.bat -> dragonx-uri.bat.

Out of scope (noted, not changed): historical changelog/copyright, the Hush
mainnet airdrop snapshot, seed data files, depends/ source mirrors, and the
in-code strCurrencyUnits="HUSH".

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-21 13:59:06 -05:00
Duke 37e35854ab Make tests always pass by ensuring there is only 1 coinbase utxo to shield 2025-10-16 01:10:33 -04:00
Duke 6069a49508 WIP donation tests
These tests sometimes fail because sometimes a different amount is shielded (3 vs 3+fee)
which makes the expected amounts of sendAmount and donationAmount incorrect. The code
to calculate donations seems to work correctly but the tests need a bit more improvement.

When the tests pass:
DEBUG:RPC:<-43- {"remainingUTXOs": 1, "remainingValue": "3.00010000", "shieldingUTXOs": 1, "shieldingValue": "3.00000000", "donation": 5, "opid": "opid-868c81ad-885b-42b4-af85-dafa54e695a2"}

When they fail:
DEBUG:RPC:<-43- {"remainingUTXOs": 1, "remainingValue": "3.00000000", "shieldingUTXOs": 1, "shieldingValue": "3.00010000", "donation": 5, "opid": "opid-143309b6-e25a-45d6-9c0c-311f1f61de78"}
2025-10-15 13:26:50 -04:00
Duke e73251ad92 WIP donation test 2025-10-14 22:29:10 -04:00
Duke fc7aa68203 Refactor donation test now that we are using just one node 2025-10-14 14:24:37 -04:00
Duke 69dadd1128 Better tests; use current drgx block reward and default fee 2025-10-14 13:19:18 -04:00
Duke ebde772ada WIP donation test 2025-10-14 11:52:05 -04:00
Duke caf7178ffd Allow donation=0 2025-10-14 10:57:40 -04:00
Duke 75564c82ac Failing test for shielded donation 2025-10-14 04:16:15 -04:00
Duke 61bae5fb7b WIP donation test 2025-10-14 03:49:06 -04:00
Duke 23ef00cfd7 WIP donation test 2025-10-13 18:21:51 -04:00
Duke cb81fc3b95 Less noise unless -debug is used 2025-09-24 09:30:33 -04:00
Duke a555f64ad9 Has the sleeper awakened? 2025-08-22 21:26:05 -04:00
Duke 04ec2be8c8 Add fullyNotified to getblockchaininfo and use it in tests 2025-08-22 13:17:36 -04:00
Duke 727f4d9a29 Sleep as a hack for lacking fullyNotified in some places 2025-08-22 11:33:13 -04:00
Duke 4ef3554307 Update authproxy 2025-08-22 06:47:27 -04:00
Duke 8148c4f625 More test logging 2025-08-21 16:26:55 -04:00
Duke fcd939978f More verbose logging in lockzins test 2025-08-21 16:15:11 -04:00
Duke 564ff0cb3a Update test_framework.py from upstream which fixes #476 2025-08-21 16:13:52 -04:00
Duke 80f48a9338 Run z_listlockunspent in tests so we can see which notes are locked 2025-08-21 01:56:24 -04:00
Duke bd9dc4d190 A test for lockzins branch which currently fails on dev branch 2025-08-13 01:13:10 -04:00
Duke 0f18946630 Add lockzins test 2025-08-12 23:30:06 -04:00
Duke 465fe58e6a ./test.sh now runs successfully and we can now write RPC tests 2025-08-12 22:17:18 -04:00
Duke c8e1b598bc Update authproxy.py to python3 version from upstream 2025-08-12 17:23:46 -04:00
Duke fb062d2849 Work towards getting RPC tests working again
So much has changed since I originally got the RPC tests working many years ago,
most notably modern Linux distros don't even have a way to install python2 via
packages, you have to install from source. Continuing with python2 does not seem
like a good idea, so we begin migrating thigns to Python 3.

Currently running ./test.sh will successfully spin up a test chain but then
the test suite crashes when attempting to send an RPC request, which looks
to be caused by the test suite internals still expecting python2.
2025-08-12 17:19:04 -04:00
Duke d1991e6454 It is called hush-arrakis-chain now 2024-03-15 15:14:26 -04:00
jahway603 4a3c335050 minor QA changes 2024-03-04 08:57:14 -05:00
onryo 58b65f9670 Update copyrights 2024-02-27 23:59:59 +01:00
Duke a581f8fc8e Fix compile error and remove some cryptocondition dingleberries 2024-02-15 11:03:05 -05:00
Duke 8a9677b337 Delete more CCs #381 2024-02-11 00:09:03 -05:00
Duke 9e26dac42a Remove libcryptoconditions dependency #381 2024-02-11 00:04:55 -05:00
jahway603 f5f52a7e81 ported Bitcoin PR 7229 to resolve Issue #16 2023-11-22 16:55:19 -05:00
Duke 84a0c2c35e antispam test 2023-10-07 14:16:59 -04:00
Duke b386cd1acf Scripts to test this branch 2023-10-07 14:15:12 -04:00
Duke e033a2e6eb Update copyrights to 2023 2023-02-09 18:06:03 -05:00
Duke 0d79d11a95 Use Tor v3 .onion in qa tests 2023-01-28 08:44:36 -08:00
zanzibar 512da314a5 BIP155 (addrv2)
Tor v3 + i2p
2023-01-06 15:23:22 +00:00
Duke ae64eb2392 Remove alerts 2022-12-18 08:24:49 -08:00
Jonathan "Duke" Leto 2a8dbbad7b Make shell scripts more portable by using /usr/bin/env bash 2022-09-19 16:30:39 -07:00
Jonathan "Duke" Leto 5d2307a709 Update copyrights to 2022 2022-09-19 15:45:30 -07:00
Duke Leto 19b65600c2 Delete a zmq dingleberry 2022-09-12 20:07:16 -04:00
Duke Leto 1799c6c9bf Remove zeromq support 2022-09-12 19:35:27 -04:00
Duke Leto b2cf132f0c Update binary name in tests and old example script 2021-10-21 10:06:25 -04:00
Duke Leto 2e52eea848 Update test runner to new default directory 2021-10-21 10:05:02 -04:00
Duke Leto 166036c01c update rpc test docs 2021-10-21 09:46:44 -04:00
Duke Leto 4a536d62dc Update copyrights 2021-04-17 13:03:22 -04:00