aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-09-03 22:01:21 -0700
committerAdam Soltys <[email protected]>2026-09-03 22:01:21 -0700
commit45fe7005b578d36ad462a9adc77f261808c48d20 (patch)
treede4ba94c9541d6780a8837e0687c53e20c1e6790
parente5b531f9b871125235da370c15f5de8646e68125 (diff)
downloadcoinosv3-45fe7005b578d36ad462a9adc77f261808c48d20.tar.gz
coinosv3-45fe7005b578d36ad462a9adc77f261808c48d20.zip
Ark key derivation gets memoized — the boot CPU hog. A profile of the first 9s after refresh showed ~800ms of secp256k1 (q0/mul/TJ) dominating the main thread; the source was _key(index) recomputing a BIP32 derive + a getPublicKey point-mul on every call, and reconcile() calls it for every spendable coin (56 here), with decode/send/exit/fee-math hitting it again. A key for an index is constant per wallet, so it's cached by index now (mailbox key too) — dozens of EC muls per boot collapse to one each
Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
-rw-r--r--src/ark/manager.js15
1 files changed, 13 insertions, 2 deletions
diff --git a/src/ark/manager.js b/src/ark/manager.js
index 59f9f09..4e9a62c 100644
--- a/src/ark/manager.js
+++ b/src/ark/manager.js
@@ -82,16 +82,27 @@ export class ArkManager {
this.state = null;
this.info = null;
this._lnDriving = new Set(); // re-entrancy guard: sync poll vs UI fast-poll vs mailbox push
+ // A derived key for an index never changes for this wallet, but computing
+ // it costs a BIP32 derive + a secp256k1 getPublicKey (a full point mul).
+ // reconcile() alone calls _keyForVtxo for every spendable coin, and decode/
+ // send/exit/fee-math hit it again — dozens of EC muls per boot burst, the
+ // dominant main-thread cost in a CPU profile. Memoize by index.
+ this._keyCache = new Map();
}
// ---- keys ----
_key(index) {
+ let k = this._keyCache.get(index);
+ if (k) return k;
const node = this.account.deriveChild(3).deriveChild(index);
- return { privkey: node.privateKey, pubkey: secp256k1.getPublicKey(node.privateKey, true) };
+ k = { privkey: node.privateKey, pubkey: secp256k1.getPublicKey(node.privateKey, true) };
+ this._keyCache.set(index, k);
+ return k;
}
_mailboxKey() {
+ if (this._mbKey) return this._mbKey;
const node = this.account.deriveChild(4).deriveChild(0);
- return { privkey: node.privateKey, pubkey: secp256k1.getPublicKey(node.privateKey, true) };
+ return (this._mbKey = { privkey: node.privateKey, pubkey: secp256k1.getPublicKey(node.privateKey, true) });
}
_keyForVtxo(v) { return this._key(v.keyIndex); }