From 6113cf567fa0830233d5c3d524361f24a3f78caa Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Thu, 10 Sep 2026 07:09:45 -0700 Subject: Ark: persist vtxo bytes as base64 (a third smaller than hex); hex still read, hex still on the wire. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The live coins' signed bytes are most of a deep wallet's state — 560KB of hex, which localStorage then holds as UTF-16. vtxoBytesToStr/FromStr in proto.js persist base64 and read either form, _addVtxo writes base64, and pruneArkState converts hex to base64 on every save, so an existing state migrates itself the first time it saves. Measured on a live deep wallet: 904KB → 665KB (-26%), all 41 coins decoding identically. The sync wire (slimArkForSync) keeps sending hex for now: a device still on an older build would otherwise fail to decode every coin merged from a newer one. Flip it once pre-2026-09-10 builds are gone. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01Nw1Dijik1tLVKRM1WkU7xE --- src/ark/proto.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'src/ark/proto.js') diff --git a/src/ark/proto.js b/src/ark/proto.js index b8c091d..829eba4 100644 --- a/src/ark/proto.js +++ b/src/ark/proto.js @@ -7,7 +7,17 @@ // Wire formats mirrored from github.com/ark-bitcoin/bark: // lib/src/address.rs, lib/src/mailbox.rs, lib/src/encode.rs, lib/src/vtxo/mod.rs -import { bech32m, hex } from '@scure/base'; +import { bech32m, hex, base64 } from '@scure/base'; + +// Persisted vtxo bytes are base64: a third smaller than hex, and half the +// UTF-16 cost in localStorage (a deep coin set was 560KB of hex). Readers +// accept the hex that older builds wrote — states are never migrated in +// place, they just re-save in the new form. +const isHexStr = (s) => s.length % 2 === 0 && /^[0-9a-f]*$/.test(s); +export const vtxoBytesToStr = (bytes) => base64.encode(bytes); +export const vtxoBytesFromStr = (s) => (isHexStr(s) ? hex.decode(s) : base64.decode(s)); +export const vtxoBytesToHex = (s) => (isHexStr(s) ? s : hex.encode(base64.decode(s))); +export const vtxoBytesNormalize = (s) => (isHexStr(s) ? base64.encode(hex.decode(s)) : s); import { sha256 } from '@noble/hashes/sha256'; import { schnorr, secp256k1 } from '@noble/curves/secp256k1'; -- cgit v1.2.3