<feed xmlns='http://www.w3.org/2005/Atom'>
<title>coinosv3.git/src/ark/refresh.js, branch fdroid-v1.9</title>
<subtitle>coinos v3 — bitcoin, Ark, Lightning and nostr wallet (web + Android)</subtitle>
<id>https://git.coinos.io/coinosv3.git/atom?h=fdroid-v1.9</id>
<link rel='self' href='https://git.coinos.io/coinosv3.git/atom?h=fdroid-v1.9'/>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/'/>
<updated>2026-09-14T06:52:39Z</updated>
<entry>
<title>The renewal happens whether or not anyone opens the app.</title>
<updated>2026-09-14T06:52:39Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-09-14T06:52:39Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=4131e5ee24c4891caffdd8f4ca903ee973d104f7'/>
<id>urn:sha1:4131e5ee24c4891caffdd8f4ca903ee973d104f7</id>
<content type='text'>
Every coin expires, and until now the only thing standing between a
balance and its expiry was maybeAutoRefresh: it renews when the wallet is
opened inside the last 96 blocks, roughly sixteen hours. Bark's own
developers say the same premise fails on mobile — people don't reliably
open a wallet at the right hour, which is why every mobile Ark client
they know of has moved to delegated refreshes and why they are building
server-driven renewal.

captaind already has it, and ark.coinos.io has been carrying the column
unused: SubmitRoundParticipation takes a scheduled_height, and the server
holds that participation out of every round until the height arrives,
then runs it with nobody online — the round tree branch is signed by the
server, which is the whole point of a delegated refresh. The fee is
priced at the height it will run at, so a standing order lands in the
free bracket rather than today's.

So each spendable coin now gets one registered 36 blocks before its
expiry, six hourly rounds of slack. It is deliberately not an action:
the coin stays spendable, the wallet never reads as busy, and spending it
simply kills the order — the server drops a participation whose input is
gone, and _driveScheduled drops ours. The claim comes later, whenever the
wallet next opens: the mailbox breadcrumb we already post wakes it, and
the leaf cosign and forfeit are the ordinary refresh path from there.

Nothing about the input's expiry blocks that claim, which is what makes
this worth having. A wallet that goes quiet for a month comes back to a
coin already renewed and anchored in a fresh tree, instead of one the ASP
has swept and would have to honor out of goodwill.

One cycle per visit is all it can buy — the replacement's id doesn't
exist yet, so its own backstop waits for the next time the app is opened.

tools/ark/scheduled-refresh-test.js covers the five behaviours on
regtest: the server holds the order until its height, runs it while the
wallet is closed, the wallet claims on return, a spend voids the order,
and a claim still works after the input has EXPIRED (the last one mines a
coin's whole lifetime, so it also re-refreshes the funding wallet first —
an expired vtxo can be renewed but not sent).

Riding along: the expired-coin notice that was already sitting in the
working tree, and manager-test's tampered-vtxo check, which had been
reading base64 vtxo bytes as hex since they moved to IndexedDB.

Co-Authored-By: Claude Opus 5 (1M context) &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_019fMdLypdg5JaU7bdeUFF8v
</content>
</entry>
<entry>
<title>Boot: price the Ark exit advisory by size only — no more 5s of secp256k1 on load.</title>
<updated>2026-09-10T05:44:24Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-09-10T05:44:24Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=9f2ce90f494a5b415bec0898e3185437126fc7d9'/>
<id>urn:sha1:9f2ce90f494a5b415bec0898e3185437126fc7d9</id>
<content type='text'>
The exit-depth advisory rebuilt every spendable coin's exit chain to learn
its fee, and each hop's input taproot key ran a musig key aggregation
(several secp256k1 multiplies on uncached points). With 27 coins of depth
up to 86 (1685 hops) that was ~5.3s of solid main-thread work on every
boot, laptop and phone alike — requestIdleCallback only delayed it, and
the Android wrapper hits a full boot whenever the OS evicts the app, so
"reopening the app" froze for seconds.

A fee only needs vsizes, and a taproot output script is 34 bytes whatever
key it holds: vtxoTransactions/transitionInputTxout gain a sizeOnly mode
with stand-in keys, exit.js exposes exitTxVsizes (same chain checks, no
EC, nothing broadcastable), and the advisory + coins page use it. Verified
against the real signed chain on the live coin set: identical vsizes on
all 27 coins, 9s → 26ms.

Also: the sync-slot replay at boot merged the ark snapshot and rewrote
~1MB of state (plus re-adopting it into the manager) twice per boot even
when the union brought nothing. Compare the serialized union to what's
stored and skip the write/adopt when unchanged.

Co-Authored-By: Claude Fable 5.1 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01Nw1Dijik1tLVKRM1WkU7xE
</content>
</entry>
<entry>
<title>A round's output can no longer strand: every refresh asks the server to drop its unlock hash in the mailbox, and any device that finds such a breadcrumb with no matching action adopts the claim itself (input ids now read from the status response — the rescue needs no operator). History learns to tell the whole truth and nothing more: coins the server saw spent elsewhere get a folded row (skipping coins a known renewal consumed), renewals fold across devices on their unlock hash and appear only when they cost something, and a rescue records the fee the round actually took. The account page keeps its header icons when reached from an open wallet; the messages page folds the control/guestbook replay once per burst instead of painting every intermediate state — no more blinking messages from superseded ban lists or member counts crawling to their total, which now paints from last session's settled figure</title>
<updated>2026-08-29T14:05:47Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-08-29T14:05:47Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=dd011c2c98033637829d83fc320ab4fdce4ede8c'/>
<id>urn:sha1:dd011c2c98033637829d83fc320ab4fdce4ede8c</id>
<content type='text'>
Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_019WboeoetMF3MTmgT7Ew8yi
</content>
</entry>
<entry>
<title>hal speaks pver 5: preimages prove their size, and fees round up as one</title>
<updated>2026-08-05T19:24:03Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-08-05T19:24:03Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=68fd614f8cb404904e1939ab711f7c7ba4350c32'/>
<id>urn:sha1:68fd614f8cb404904e1939ab711f7c7ba4350c32</id>
<content type='text'>
0.6.0 servers require the new hashlock clauses (OP_SIZE 32 guard) for
Lightning and rounds. New policies/transitions carry the v1 scripts and
type bytes; _v0 variants keep old vtxos reconstructing and exiting.
The retired third-party HTLC policy is dropped (upstream took 0x08).

Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01M5kFodm9azZJVTQxnkDdKe
</content>
</entry>
<entry>
<title>Add Ark &lt;-&gt; Lightning via the ASP (captaind-native submarine swaps)</title>
<updated>2026-07-31T07:49:21Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-07-31T07:49:21Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=78789e0b2eaf91e2de6b4e488324fbec0fcefb9d'/>
<id>urn:sha1:78789e0b2eaf91e2de6b4e488324fbec0fcefb9d</id>
<content type='text'>
The ASP is the HTLC counterparty (second.tech's protocol), so no external
swap provider is needed: paying a bolt11 converts pubkey vtxos into
ServerHtlcSend vtxos the server can only claim by revealing the invoice
preimage; receiving grants ServerHtlcRecv vtxos claimed by revealing ours.
Failure paths cosign the HTLC back (revocation) — proven end-to-end against
regtest captaind, which independently derives the HTLC taproots.

- ark/lightning.js: bolt11 decode, lightning fee schedules, all pay/receive
  gRPC-web wrappers (cosign, initiate, status, revocation, hold-invoice
  receive flow, anti-DoS attestation)
- ark/send.js: arkoor builder generalized to policy outputs (pubkey /
  serverHtlcSend / serverHtlcRecv), two-leaf taproot trees, HTLC clause
  scripts, reusable per-part cosign helpers for package RPCs
- ark/manager.js: ln-pay and ln-recv crash-safe action state machines
  (deterministic receive preimages from the seed, chain 5), mailbox
  lightning notifications, unpayable-invoice -&gt; instant revocation
- proto.js: lightning ArkInfo fields + mailbox lightning message decode
- validate/refresh: policy-aware vtxo validation and reconstruction
- features: bolt11 routes via ark when the balance covers it (Boltz stays
  the fallback), lightning-invoice receive on the Ark pane
- tools/ark/ln-test.js: harness proving HTLC cosign + revocation against
  captaind; manager-test.js updated for the consolidated bc-container chain

Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>Unilateral exit: put vtxos on-chain without the server</title>
<updated>2026-07-06T03:39:02Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-07-06T03:39:02Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=15e0b236e7ff2cafcb439c891c790deea8ec16a7'/>
<id>urn:sha1:15e0b236e7ff2cafcb439c891c790deea8ec16a7</id>
<content type='text'>
The trustless backstop behind the Ark card's promise. The vtxo's
genesis chain reconstructs to fully-signed txs (keyspend sigs for
cosigned/arkoor transitions, preimage script-path for hark leaves);
they are zero-fee v3 with P2A anchors, so each hop broadcasts as a
[parent, CPFP child] package via esplora POST /txs/package, one
confirmed hop at a time (TRUC allows a single unconfirmed parent).
After the vtxo tx confirms and the CSV exit delta passes, the claim
spends the delayed_sign leaf with only the user key into the wallet's
own receive address.

Settings gains 'Exit on-chain without the server' with live per-exit
status lines; the claim tx is labeled 'Ark exit' in History. Probing
uses /tx/:txid (definitive 404), never /tx/:txid/status, which answers
confirmed:false for unknown txids.

Also: a fresh visitor opening an ark gift link now adopts the gift's
network automatically instead of being sent to Settings.

Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>Ark: native-JS protocol client + persistent ArkManager</title>
<updated>2026-07-03T21:46:36Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-07-03T21:46:36Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=5b7f8ba40cbf5c8189147b6a37aadc1b230ac4e9'/>
<id>urn:sha1:5b7f8ba40cbf5c8189147b6a37aadc1b230ac4e9</id>
<content type='text'>
Speaks Second's bark/captaind Ark protocol directly from the browser —
gRPC-web over fetch with hand-rolled protobuf, no wasm, no new deps
(crypto via the existing @scure/@noble stack incl. btc-signer's BIP-327
musig2 module).

src/ark:
- proto.js    transport, ark address codec, mailbox blinding/auth,
              VTXO ProtocolEncoding v2 decode
- send.js     arkoor send: checkpoint+arkoor txs, BIP-341 sighashes,
              MuSig2 cosign ceremony, signed-VTXO assembly
- board.js    onchain -&gt; ark: funding taproot, exit-tx cosign
- refresh.js  delegated round (hArk): participation, tx-chain
              reconstruction, hash-locked leaf cosign, forfeit swap
- validate.js receive-side verification: chain must land on the vtxo
              point, anchor checked onchain, every transition sig verified
- manager.js  persistent wallet layer: storage-checkpointed step-machine
              actions (send/board/refresh) that survive crashes, mailbox
              sync with validation, multi-input consolidation refresh

tools/ark: end-to-end regtest tests (receive, send, board, refresh,
manager incl. crash-mid-send + resume), all passing against captaind
with the bark CLI as counterparty.

Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01QFAcD4V284DvYZZHP7Rxxy
</content>
</entry>
</feed>
