Added wallet-identity check before allocation

This commit is contained in:
2026-10-21 15:25:00 -04:00
parent c8cf8245fc
commit 0534cde1a9
6 changed files with 61 additions and 13 deletions
+10 -2
View File
@@ -17,6 +17,7 @@ import { CustodyMarket } from '../../server/market/custody.ts';
import { migrateCustody, grantCustodyRuntime, grantMoneroObserverRuntime, CUSTODY_SCHEMA_V1, CUSTODY_SCHEMA_V1_DIGEST,
CUSTODY_MIGRATION_V2, CUSTODY_SCHEMA_V2_DIGEST } from '../../server/market/postgres-schema.ts';
import { persistMoneroObservationScan } from '../../server/market/monero-observation-store.ts';
import { moneroWalletFingerprint } from '../../server/market/monero-observer.ts';
import { createOrRecoverMoneroDepositSubaddress, registerMoneroDepositSubaddress,
reserveMoneroDepositAllocation } from '../../server/market/monero-deposit-allocation-store.ts';
import { importSqliteCustody } from '../../server/market/custody-import.ts';
@@ -289,13 +290,16 @@ test('deposit allocation reserves unique beneficiary-bound indexes before RPC an
[first.allocation.allocationId, other.actor]), /identity is immutable/);
const recoveryGeneration = randomUUID();
const recoveryFingerprint = await moneroWalletFingerprint(ADDITIONAL_MARKET_FEE.address);
const recoveryReservation = await reserveMoneroDepositAllocation(f.admin, { ...input(randomUUID(), buyer.actor),
walletGenerationId: recoveryGeneration, walletFingerprint: 'a'.repeat(64) });
walletGenerationId: recoveryGeneration, walletFingerprint: recoveryFingerprint });
const walletAddresses = new Map<string, { address: string; label: string }>();
const recoveryAddress = await syntheticSubaddress(6);
let createCalls = 0;
let createCalls = 0, addressReads = 0, liveFingerprint = 'b'.repeat(64);
const fakeRpc = {
async verifyWallet() { return liveFingerprint; },
async getSubaddress(accountIndex: number, addressIndex: number) {
addressReads++;
return walletAddresses.get(`${accountIndex}:${addressIndex}`) ?? null;
},
async createSubaddress(accountIndex: number, label: string) {
@@ -306,6 +310,10 @@ test('deposit allocation reserves unique beneficiary-bound indexes before RPC an
return { address: row.address, addressIndex: recoveryReservation.allocation.addressIndex };
},
};
await assert.rejects(createOrRecoverMoneroDepositSubaddress(f.admin, fakeRpc,
recoveryReservation.allocation.allocationId, recoveryGeneration, reservedAt + 4), /identity differs/);
assert.equal(addressReads, 0); assert.equal(createCalls, 0, 'wallet mismatch must fail before address operations');
liveFingerprint = recoveryFingerprint;
await assert.rejects(createOrRecoverMoneroDepositSubaddress(f.admin, fakeRpc,
recoveryReservation.allocation.allocationId, recoveryGeneration, reservedAt + 5), /response lost/);
const recovered = await createOrRecoverMoneroDepositSubaddress(f.admin, fakeRpc,