Stagenet wallet rehearsal passed
This commit is contained in:
@@ -19,7 +19,7 @@ The operator has authorized proceeding with implementation instead of the previo
|
||||
|
||||
**Financial storage update:** [ADR 003](postgres-financial-storage.md) selects PostgreSQL and records the integrated asynchronous custody backend, restricted runtime/schema roles, deferred accounting constraints, explicit SQLite freeze/import, and full dump/restore rehearsal. SQLite remains an opt-in-compatible local sandbox default, not an automatic fallback. Real custody and production operating acceptance remain blocked.
|
||||
|
||||
**Monero observation and deposit-address allocation groundwork:** [server/market/monero-observer.ts](../server/market/monero-observer.ts) keeps the existing observer client strictly read-only: mainnet wallet validation and bounded incoming scans, authenticated requests, strict HTTPS/literal-loopback-only HTTP, no redirects, bounded response/deadline, JSON-RPC ID validation and lossless integer handling. A separate, narrow `createMoneroDepositAddressRpc()` capability requires `get_wallet_info` to identify a Mainnet, Watch only wallet; it checks `get_wallet_info` against `get_address` and derives a domain-separated fingerprint from the verified primary address. It can inspect one indexed subaddress or request exactly one labeled subaddress; it exposes no transfer, relay, sweep or withdrawal operation. [server/market/monero-deposit-allocation-store.ts](../server/market/monero-deposit-allocation-store.ts) combines PostgreSQL v3 beneficiary/index reservations with this capability: it reserves first, serializes cooperating allocators per wallet/account, checks that the live wallet fingerprint matches the durable generation, checks the exact reserved index, and recovers a lost `create_address` response by looking up the deterministic allocation label before retrying creation. Address registration is immutable and performed only after the wallet returns the expected index/address/label. If another wallet client consumes indexes outside this allocator, the operation fails for reconciliation rather than reassigning an address; the wallet RPC must therefore be dedicated to the allocator. The configured wallet-generation UUID still requires controlled operator enrollment and backup; the fingerprint/identity checks are implemented but only fixture-tested. Neither client nor orchestration is wired to startup, routes, UI, deposit scans or financial posting. The registry remains inaccessible to both custody API and observer roles. Observation storage continues to record reorg/reappearance evidence only; no credit, debit, reversal or journal can be posted. Schema v1→v3 is explicit and additive. The test-target build succeeded; **184/184** offline tests and **35/35** disposable PostgreSQL tests passed, including rejection of wallet identity mismatch and simulated create-success/response-loss/recovery without duplicate address creation or journal posting. No live wallet RPC, wallet credential or funds were used. This is not a public deposit allocator or live deposit processor; mainnet payments remain disabled.
|
||||
**Monero observation and deposit-address allocation groundwork:** [server/market/monero-observer.ts](../server/market/monero-observer.ts) keeps the existing observer client strictly read-only: mainnet wallet validation and bounded incoming scans, authenticated requests, strict HTTPS/literal-loopback-only HTTP, no redirects, bounded response/deadline, JSON-RPC ID validation and lossless integer handling. A separate, narrow `createMoneroDepositAddressRpc()` capability verifies a mainnet primary address with `get_address` plus `validate_address`, then derives a domain-separated fingerprint. It can inspect one indexed subaddress or request exactly one labeled subaddress; it exposes no transfer, relay, sweep or withdrawal operation. Actual testing against the verified Monero v0.18.5.4 Wallet RPC found that `get_wallet_info` returns JSON-RPC “Method not found” despite appearing in current docs; the implementation therefore does not depend on it. The allocator [server/market/monero-deposit-allocation-store.ts](../server/market/monero-deposit-allocation-store.ts) combines PostgreSQL v3 beneficiary/index reservations with this capability: it reserves first, serializes cooperating allocators per wallet/account, checks that the live wallet fingerprint matches the durable generation, checks the exact reserved index, and recovers a lost `create_address` response by looking up the deterministic allocation label before retrying creation. Actual v0.18.5.4 testing also confirmed that an unused address index returns RPC error `-15` (“address index is out of bound”), rather than an empty `addresses` array; the client recognizes only that exact error as “not created” and fails closed for other errors. Address registration is immutable and performed only after the wallet returns the expected index/address/label. The installed v0.18.5.4 interface does not provide a supported `get_wallet_info` query to attest the wallet type, so watch-only provisioning is an operator/deployment requirement, not a property this RPC client can prove. If another wallet client consumes indexes outside this allocator, the operation fails for reconciliation rather than reassigning an address; the wallet RPC must therefore be dedicated to the allocator. The configured wallet-generation UUID still requires controlled operator enrollment and backup. Neither client nor orchestration is wired to startup, routes, UI, deposit scans or financial posting. The registry remains inaccessible to both custody API and observer roles. Observation storage continues to record reorg/reappearance evidence only; no credit, debit, reversal or journal can be posted. Schema v1→v3 is explicit and additive. The test-target build succeeded; **185/185** offline tests and **35/35** disposable PostgreSQL tests passed, including rejection of wallet identity mismatch and simulated create-success/response-loss/recovery without duplicate address creation or journal posting. An actual wallet-RPC rehearsal on the authenticated official v0.18.5.4 archive passed in Docker `--network none`, `--stagenet`, `--offline`, loopback-only mode: it created a disposable watch-only wallet, allocated/labeled one subaddress, recovered by index after discarding the create response, and verified the same address/label after RPC restart. No daemon/network peers, funds, or production credentials were used; all generated wallet files were deleted with the temporary container. This remains test groundwork, not a public deposit allocator or live processor; mainnet payments remain disabled.
|
||||
|
||||
Validation: TypeScript/Vite build and 144 offline tests passed in the serial native-RandomX test run; the initial parallel run encountered a peer-gossip timeout. Browser smoke verified a disposable wallet's signed test credit, withdrawal hold and cancellation restoring the exact balance, plus a 390px viewport without horizontal overflow. No real funds were used. Tests and remaining acceptance gates are below; this is not launch readiness.
|
||||
|
||||
@@ -153,3 +153,5 @@ Required failure outcomes: duplicate deposit credits are impossible; insufficien
|
||||
- [Transfer history](https://docs.getmonero.org/rpc-library/wallet-rpc/#get_transfer_by_txid) and [rescan](https://docs.getmonero.org/rpc-library/wallet-rpc/#rescan_blockchain): wallet restore can lose outgoing destinations, transaction keys and notes. Blockchain replay is not a backup for customer accounting.
|
||||
|
||||
Source review: 2026-10-20; documentation is capability evidence, not an audited implementation of this design. No wallet/RPC credentials or funds were accessed.
|
||||
|
||||
**Actual RPC integration blocker:** The v0.18.5.4 process rehearsal confirmed a login-protected wallet RPC returns HTTP 401 with a Digest challenge; sending Basic auth still returns 401. The current client therefore cannot authenticate to that configuration. Keep authenticated wallet RPC disabled until a reviewed compatible transport is implemented; do not disable authentication outside a strictly isolated test.
|
||||
|
||||
@@ -20,7 +20,11 @@ Status: active engineering plan; **not launch or payment authorization**. Update
|
||||
|
||||
**Current design deliverable:** [custodial market design](custodial-market-design.md). Read the workstreams below with this update: pooled customer liabilities replace per-order incoming invoices and external sale payouts in the proposed architecture. Earlier trustless-first research gates are historical, not a prerequisite to investigating custody. Exact ledger, withdrawal, fee, custody/legal and host-attested NFT consensus rules still require approval and evidence; the existing mock domain cannot authorize real balance debits.
|
||||
|
||||
**Monero observation and allocation groundwork:** the disabled-by-default observer remains read-only. The separate address RPC capability now requires a Mainnet, Watch only wallet and compares `get_wallet_info` with the primary `get_address`; it derives the wallet fingerprint from that validated address. The internal allocator checks that fingerprint against the durable generation before reserving/creating, reserves the beneficiary/index first, serializes cooperating allocators, and recovers create-success/lost-response by checking a stable label at the reserved index. It refuses mismatched wallet identity/index instead of silently binding. This is fixture-tested only, not verified against an actual wallet binary or wallet generation. It is not wired to startup/routes/UI/scans/financial posting, and the registry remains inaccessible to custody API and observer roles. Operational assumptions still include a dedicated allocator wallet RPC, controlled generation enrollment/backups and wallet/database reconciliation. The registry cannot establish unique output identity. Missing scans remain review evidence, not automatic balance changes. Verification passed: Docker test-target build; **184/184** offline tests; **35/35** disposable PostgreSQL tests, including v1/v2 migrations, independent-pool allocator concurrency, replay, immutable registration, least-privilege isolation, zero journal postings, mismatched-wallet rejection and simulated response-loss recovery without duplicate address creation. No live RPC, wallet credential or funds were used. Remaining deposit milestone: rehearse against a disposable local Monero wallet on stagenet; persist and verify wallet-generation enrollment and restart recovery; establish stable per-output identity and canonical inclusion/lock/reorg semantics; then build exact idempotent journal crediting plus audited reversal/hold handling and independent accounting/security review before any real deposits.
|
||||
**Monero observation and allocation groundwork:** the disabled-by-default observer remains read-only. The separate address RPC capability verifies a mainnet primary address using `get_address` and `validate_address` and derives a wallet fingerprint; it does not claim to attest wallet type. Actual testing found `get_wallet_info` is unavailable as JSON-RPC in v0.18.5.4, and Monero’s `--rpc-login` requires HTTP Digest while the current client sends Basic auth. Therefore authenticated RPC integration is **not yet compatible**; do not enable the client against a login-protected RPC. Watch-only wallet provisioning and isolated network placement must be enforced by deployment until a reviewed compatible auth/provisioning design is implemented. The internal allocator checks the primary-address fingerprint against the durable generation before creating, reserves beneficiary/index first, serializes cooperating allocators, and recovers create-success/lost-response by checking a stable label at the reserved index. It recognizes only the observed “address index is out of bound” error as an unused slot and fails closed on other RPC errors. Actual RPC verification is limited to the offline disposable rehearsal below; no application startup/routes/UI/scans or financial posting are wired, and the registry remains inaccessible to custody API and observer roles. Operational assumptions still include a dedicated wallet RPC, controlled generation enrollment/backups, and wallet/database reconciliation. The registry cannot establish unique output identity. Missing scans remain review evidence, not automatic balance changes. Verification passed: Docker test-target build; **185/185** offline tests; **35/35** disposable PostgreSQL tests, including v1/v2 migrations, allocator concurrency, replay, immutable registration, role isolation, zero journal postings, wallet mismatch rejection, the official -15 index response, and simulated response-loss recovery. No live RPC credentials, funds or mainnet wallet were used. Remaining deposit milestone: resolve authenticated RPC transport and watch-only provisioning, establish durable wallet-generation enrollment and recovery, pin per-output identity and canonical inclusion/lock/reorg semantics, then implement idempotent credit journals and audited reversal/hold handling before stagenet deposit-credit rehearsal or any real deposits.
|
||||
|
||||
**Initial actual-wallet rehearsal blocker (2026-10-21, superseded below):** no Monero wallet binary or pinned image was present locally, so the RPC contract could not yet be exercised against a real process. This was resolved by obtaining and verifying the official v0.18.5.4 archive and running the disposable offline Stagenet rehearsal recorded below. The recorded evidence does not authorize mainnet access, deposits, credits, or payments.
|
||||
|
||||
**Actual Wallet RPC rehearsal completed (2026-10-21):** obtained Monero CLI v0.18.5.4 from the official downloads host. Verified the `binaryFate` GPG key fingerprint `81AC 591F E9C4 B65C 5806 AFC3 F0AF 4D46 2A0B DF92`, the GPG-signed canonical hashes file, and the Linux x64 archive SHA-256 `ba2928962c101b609434bf8c1b43ad59ebe96c5525977284ca599d8bf0f02d10`. Ran only the official `monero-wallet-rpc` executable in a disposable Docker container with `--network none --stagenet --offline`, loopback bind, and RPC login disabled only inside that network-isolated container. The rehearsal generated a temporary Stagenet wallet, derived a watch-only wallet from its view key (no key material or addresses logged), confirmed `validate_address` reports Stagenet, and verified watch-only behavior because `query_key(spend_key)` failed. It reserved the next index, observed v0.18.5.4 return error `-15` (“address index is out of bound”) for that unused index, created exactly one labeled subaddress, recovered by index after discarding the create response, stopped/restarted wallet RPC with the same wallet data, and verified the same address and label persisted. `get_wallet_info` returned Method not found. The release archive has no `monerod`, so there was no daemon, peer connection or chain sync. The run logic is captured by [scripts/monero-stagenet-rpc-rehearsal.mjs](../scripts/monero-stagenet-rpc-rehearsal.mjs). It does **not** test authenticated application transport (the fixture deliberately disables RPC login inside the isolated container), concurrent external wallet clients, hard power-loss durability, deposits, credits, withdrawals, mainnet, or live payment. Temporary wallet files and the verification/download directory are removed after preserving the signed hash/digest evidence; no production credentials or funds were used.
|
||||
|
||||
## 1A. MVP release boundary — proposed safe first production-hosted release
|
||||
|
||||
|
||||
Reference in New Issue
Block a user