@bsv/wallet-toolbox 2.10.3 → 2.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +68 -0
- package/LICENSES/Open-BSV-License-4-wallet-pre-2026.txt +28 -0
- package/README.md +50 -1
- package/THIRD_PARTY_NOTICES.md +35 -0
- package/docs/README.md +2 -3
- package/docs/managed-change-liquidity.md +7 -0
- package/docs/no-send-expiry.md +167 -0
- package/docs/prepared-beef.md +197 -0
- package/docs/setup.md +11 -0
- package/docs/storage.md +11 -0
- package/out/src/Setup.d.ts +3 -0
- package/out/src/Setup.d.ts.map +1 -1
- package/out/src/Setup.js +1 -0
- package/out/src/Setup.js.map +1 -1
- package/out/src/Wallet.d.ts.map +1 -1
- package/out/src/Wallet.js +11 -1
- package/out/src/Wallet.js.map +1 -1
- package/out/src/WalletPermissionsManager.d.ts +30 -6
- package/out/src/WalletPermissionsManager.d.ts.map +1 -1
- package/out/src/WalletPermissionsManager.js +84 -9
- package/out/src/WalletPermissionsManager.js.map +1 -1
- package/out/src/mockchain/MockServices.d.ts +2 -0
- package/out/src/mockchain/MockServices.d.ts.map +1 -1
- package/out/src/mockchain/MockServices.js +20 -0
- package/out/src/mockchain/MockServices.js.map +1 -1
- package/out/src/monitor/Monitor.d.ts +1 -0
- package/out/src/monitor/Monitor.d.ts.map +1 -1
- package/out/src/monitor/Monitor.js +19 -3
- package/out/src/monitor/Monitor.js.map +1 -1
- package/out/src/monitor/tasks/TaskNoSendExpiry.d.ts +19 -0
- package/out/src/monitor/tasks/TaskNoSendExpiry.d.ts.map +1 -0
- package/out/src/monitor/tasks/TaskNoSendExpiry.js +47 -0
- package/out/src/monitor/tasks/TaskNoSendExpiry.js.map +1 -0
- package/out/src/monitor/tasks/index.all.d.ts +1 -0
- package/out/src/monitor/tasks/index.all.d.ts.map +1 -1
- package/out/src/monitor/tasks/index.all.js +1 -0
- package/out/src/monitor/tasks/index.all.js.map +1 -1
- package/out/src/sdk/ActionBatch.interfaces.d.ts +4 -0
- package/out/src/sdk/ActionBatch.interfaces.d.ts.map +1 -1
- package/out/src/sdk/WalletStorage.interfaces.d.ts +35 -0
- package/out/src/sdk/WalletStorage.interfaces.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageKnex.d.ts +0 -1
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageKnex.d.ts.map +1 -1
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageKnex.js +23 -12
- package/out/src/services/chaintracker/chaintracks/Storage/ChaintracksStorageKnex.js.map +1 -1
- package/out/src/signer/methods/createNoSendExpiryAction.d.ts +7 -0
- package/out/src/signer/methods/createNoSendExpiryAction.d.ts.map +1 -0
- package/out/src/signer/methods/createNoSendExpiryAction.js +249 -0
- package/out/src/signer/methods/createNoSendExpiryAction.js.map +1 -0
- package/out/src/signer/methods/signAction.d.ts.map +1 -1
- package/out/src/signer/methods/signAction.js +9 -0
- package/out/src/signer/methods/signAction.js.map +1 -1
- package/out/src/storage/StorageIdb.d.ts +3 -0
- package/out/src/storage/StorageIdb.d.ts.map +1 -1
- package/out/src/storage/StorageIdb.js +37 -1
- package/out/src/storage/StorageIdb.js.map +1 -1
- package/out/src/storage/StorageKnex.d.ts +48 -3
- package/out/src/storage/StorageKnex.d.ts.map +1 -1
- package/out/src/storage/StorageKnex.js +234 -14
- package/out/src/storage/StorageKnex.js.map +1 -1
- package/out/src/storage/StorageProvider.d.ts +6 -1
- package/out/src/storage/StorageProvider.d.ts.map +1 -1
- package/out/src/storage/StorageProvider.js +147 -5
- package/out/src/storage/StorageProvider.js.map +1 -1
- package/out/src/storage/StorageReaderWriter.d.ts +2 -0
- package/out/src/storage/StorageReaderWriter.d.ts.map +1 -1
- package/out/src/storage/StorageReaderWriter.js +4 -0
- package/out/src/storage/StorageReaderWriter.js.map +1 -1
- package/out/src/storage/WalletStorageManager.d.ts +11 -0
- package/out/src/storage/WalletStorageManager.d.ts.map +1 -1
- package/out/src/storage/WalletStorageManager.js +77 -12
- package/out/src/storage/WalletStorageManager.js.map +1 -1
- package/out/src/storage/idbHelpers.d.ts.map +1 -1
- package/out/src/storage/idbHelpers.js +14 -2
- package/out/src/storage/idbHelpers.js.map +1 -1
- package/out/src/storage/index.all.d.ts +2 -0
- package/out/src/storage/index.all.d.ts.map +1 -1
- package/out/src/storage/index.all.js +2 -0
- package/out/src/storage/index.all.js.map +1 -1
- package/out/src/storage/methods/createAction.d.ts +57 -1
- package/out/src/storage/methods/createAction.d.ts.map +1 -1
- package/out/src/storage/methods/createAction.js +195 -49
- package/out/src/storage/methods/createAction.js.map +1 -1
- package/out/src/storage/methods/noSendExpiry.d.ts +11 -0
- package/out/src/storage/methods/noSendExpiry.d.ts.map +1 -0
- package/out/src/storage/methods/noSendExpiry.js +357 -0
- package/out/src/storage/methods/noSendExpiry.js.map +1 -0
- package/out/src/storage/methods/noSendExpiryLifecycle.d.ts +14 -0
- package/out/src/storage/methods/noSendExpiryLifecycle.d.ts.map +1 -0
- package/out/src/storage/methods/noSendExpiryLifecycle.js +691 -0
- package/out/src/storage/methods/noSendExpiryLifecycle.js.map +1 -0
- package/out/src/storage/methods/preparedBeef.d.ts +104 -0
- package/out/src/storage/methods/preparedBeef.d.ts.map +1 -0
- package/out/src/storage/methods/preparedBeef.js +525 -0
- package/out/src/storage/methods/preparedBeef.js.map +1 -0
- package/out/src/storage/methods/processAction.d.ts.map +1 -1
- package/out/src/storage/methods/processAction.js +109 -28
- package/out/src/storage/methods/processAction.js.map +1 -1
- package/out/src/storage/methods/purgeData.d.ts.map +1 -1
- package/out/src/storage/methods/purgeData.js +9 -0
- package/out/src/storage/methods/purgeData.js.map +1 -1
- package/out/src/storage/methods/validateSyncProof.d.ts +24 -0
- package/out/src/storage/methods/validateSyncProof.d.ts.map +1 -0
- package/out/src/storage/methods/validateSyncProof.js +116 -0
- package/out/src/storage/methods/validateSyncProof.js.map +1 -0
- package/out/src/storage/remoting/StorageClientBase.d.ts +4 -1
- package/out/src/storage/remoting/StorageClientBase.d.ts.map +1 -1
- package/out/src/storage/remoting/StorageClientBase.js +9 -0
- package/out/src/storage/remoting/StorageClientBase.js.map +1 -1
- package/out/src/storage/remoting/StorageServer.d.ts.map +1 -1
- package/out/src/storage/remoting/StorageServer.js +16 -3
- package/out/src/storage/remoting/StorageServer.js.map +1 -1
- package/out/src/storage/schema/KnexMigrations.d.ts +2 -0
- package/out/src/storage/schema/KnexMigrations.d.ts.map +1 -1
- package/out/src/storage/schema/KnexMigrations.js +66 -1
- package/out/src/storage/schema/KnexMigrations.js.map +1 -1
- package/out/src/storage/schema/StorageIdbSchema.d.ts +2 -0
- package/out/src/storage/schema/StorageIdbSchema.d.ts.map +1 -1
- package/out/src/storage/schema/entities/EntityOutput.d.ts.map +1 -1
- package/out/src/storage/schema/entities/EntityOutput.js +13 -0
- package/out/src/storage/schema/entities/EntityOutput.js.map +1 -1
- package/out/src/storage/schema/entities/EntityProvenTx.d.ts +2 -0
- package/out/src/storage/schema/entities/EntityProvenTx.d.ts.map +1 -1
- package/out/src/storage/schema/entities/EntityProvenTx.js +33 -3
- package/out/src/storage/schema/entities/EntityProvenTx.js.map +1 -1
- package/out/src/storage/schema/entities/EntityTransaction.d.ts +26 -0
- package/out/src/storage/schema/entities/EntityTransaction.d.ts.map +1 -1
- package/out/src/storage/schema/entities/EntityTransaction.js +221 -21
- package/out/src/storage/schema/entities/EntityTransaction.js.map +1 -1
- package/out/src/storage/schema/tables/TablePreparedBeef.interfaces.d.ts +23 -0
- package/out/src/storage/schema/tables/TablePreparedBeef.interfaces.d.ts.map +1 -0
- package/out/src/storage/schema/tables/TablePreparedBeef.interfaces.js +3 -0
- package/out/src/storage/schema/tables/TablePreparedBeef.interfaces.js.map +1 -0
- package/out/src/storage/schema/tables/TableTransaction.d.ts +16 -0
- package/out/src/storage/schema/tables/TableTransaction.d.ts.map +1 -1
- package/out/src/storage/schema/tables/TableTransaction.js +14 -1
- package/out/src/storage/schema/tables/TableTransaction.js.map +1 -1
- package/out/src/utility/Argon2idBackend.d.ts +36 -0
- package/out/src/utility/Argon2idBackend.d.ts.map +1 -0
- package/out/src/utility/Argon2idBackend.js +60 -0
- package/out/src/utility/Argon2idBackend.js.map +1 -0
- package/out/src/utility/brc177NoSendExpiry.d.ts +34 -0
- package/out/src/utility/brc177NoSendExpiry.d.ts.map +1 -0
- package/out/src/utility/brc177NoSendExpiry.js +81 -0
- package/out/src/utility/brc177NoSendExpiry.js.map +1 -0
- package/out/src/utility/hashWasm.d.ts +2 -1
- package/out/src/utility/hashWasm.d.ts.map +1 -1
- package/out/src/utility/hashWasm.js +83 -1
- package/out/src/utility/hashWasm.js.map +1 -1
- package/out/src/utility/index.all.d.ts +2 -0
- package/out/src/utility/index.all.d.ts.map +1 -1
- package/out/src/utility/index.all.js +2 -0
- package/out/src/utility/index.all.js.map +1 -1
- package/out/src/utility/index.client.d.ts +2 -0
- package/out/src/utility/index.client.d.ts.map +1 -1
- package/out/src/utility/index.client.js +2 -0
- package/out/src/utility/index.client.js.map +1 -1
- package/package.json +10 -7
- package/docs/open-rpc/index.html +0 -46
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,74 @@ attention to changes that materially alter behavior or extend functionality.
|
|
|
6
6
|
|
|
7
7
|
## wallet-toolbox (unreleased)
|
|
8
8
|
|
|
9
|
+
- Keep Argon2id-backed UMP v3 wallets available in React Native and other
|
|
10
|
+
runtimes without WebAssembly by falling back to an asynchronously yielding,
|
|
11
|
+
standards-compatible JavaScript implementation. The same KDF parameters and
|
|
12
|
+
derived bytes are preserved, so existing tokens require no migration and
|
|
13
|
+
WebAssembly-capable runtimes retain the faster path. The existing public
|
|
14
|
+
`hash-wasm`-compatible utility contract remains intact: secret-bearing,
|
|
15
|
+
non-binary-output, and non-byte-array requests stay on `hash-wasm` and are
|
|
16
|
+
never reinterpreted by a host backend or fallback. Native registration is
|
|
17
|
+
available from both mobile and client roots, concurrent cold callers share
|
|
18
|
+
one preload attempt, and both alternative implementations validate result
|
|
19
|
+
type and length. Unrelated validation errors propagate even without the
|
|
20
|
+
WebAssembly global. The current-main macOS
|
|
21
|
+
reference fixtures measure 1,690,925 raw / 398,461 gzip / 311,955 Brotli
|
|
22
|
+
bytes with Vite, 1,319,059 raw / 362,220 gzip / 291,206 Brotli bytes with
|
|
23
|
+
esbuild, 1,746,067 raw / 442,648 gzip / 343,342 Brotli bytes with Metro, and
|
|
24
|
+
3,542,034 raw / 1,419,515 gzip / 1,117,531 Brotli bytes as optimized Hermes
|
|
25
|
+
bytecode; hosted Linux measures 1,439,166 gzip bytes. The reviewed ceilings
|
|
26
|
+
advance to 1,693,000 / 400,000 / 314,000 Vite bytes, 1,321,000 / 364,000 /
|
|
27
|
+
293,000 esbuild bytes, 1,748,000 raw Metro bytes with the compressed ceilings
|
|
28
|
+
unchanged, and 3,547,000 / 1,441,000 / 1,123,000 Hermes bytes.
|
|
29
|
+
|
|
30
|
+
- Extend the BRC-98/99/111 permission-module interface with an optional semantic
|
|
31
|
+
`handleRequest` hook. A module can now return a conforming BRC-100 result
|
|
32
|
+
directly or invoke the underlying wallet operation at most once, while
|
|
33
|
+
existing `onRequest`/`onResponse` transformation modules remain compatible.
|
|
34
|
+
The companion `@bsv/ecpm-permission-module` uses this hook to implement
|
|
35
|
+
`p ecpm` point multiplication without adding a BRC-100 method or wire call.
|
|
36
|
+
|
|
37
|
+
- Add opt-in prepared BEEF storage for Knex-backed normal `createAction`
|
|
38
|
+
funding. COOK (Create Once, Output Kept) stores a user-scoped, exact,
|
|
39
|
+
independently verified and checksummed proof closure, merges valid hits
|
|
40
|
+
without invoking the canonical builder, and treats every miss or cache
|
|
41
|
+
failure as the existing canonical path. Missing roots and newly finalized
|
|
42
|
+
managed-change transactions are queued only after foreground action work is
|
|
43
|
+
complete; bounded writes, reads, and gradual backfill are separately
|
|
44
|
+
controlled and default off. Reorganizations stale derived artifacts, a
|
|
45
|
+
database proof epoch fences in-flight cross-process writes, purge removes
|
|
46
|
+
unused rows, and prepared data remains outside wallet sync. The
|
|
47
|
+
Knex worker is excluded from portable bundles. Reviewed Vite ceilings advance
|
|
48
|
+
to 1,610,250 raw / 379,750 gzip / 298,000 Brotli bytes and esbuild ceilings
|
|
49
|
+
to 1,255,000 raw / 346,250 gzip / 278,000 Brotli, covering local measurements
|
|
50
|
+
of 1,609,783 / 379,492 / 297,253 and 1,254,603 / 344,792 / 277,384 bytes;
|
|
51
|
+
hosted Linux Vite Brotli and esbuild gzip measured 297,585 and 345,711 bytes.
|
|
52
|
+
The Hermes raw / gzip ceilings advance to 3,374,500 / 1,369,000 bytes,
|
|
53
|
+
covering local measurements of 3,372,554 / 1,348,354 and hosted Linux
|
|
54
|
+
measurements of 3,373,560 / 1,368,128 bytes; Metro and Hermes Brotli
|
|
55
|
+
ceilings remain unchanged.
|
|
56
|
+
- Add the built-in BRC-177 `p nosend expiry` module for seconds, Unix timestamp,
|
|
57
|
+
and block-height deadlines. Protected actions are prefunded through an
|
|
58
|
+
accepted transaction, contain no wallet change, and retain a pre-signed
|
|
59
|
+
reclaim across restarts, synchronized storage, devices, and keyless remote
|
|
60
|
+
monitors. Atomic lifecycle transitions, active-storage ownership,
|
|
61
|
+
fail-closed status checks, backoff-controlled recovery of terminally rejected
|
|
62
|
+
reclaims, quarantined race outputs, and locally validated proof finality
|
|
63
|
+
prevent duplicate reclaim activation and unsafe state regression. Wallet
|
|
64
|
+
Permissions Manager authorizes module use and spending
|
|
65
|
+
before prefunding, attributes the funding fee to the requesting originator,
|
|
66
|
+
and rechecks the current monthly ledger before releasing the protected
|
|
67
|
+
action. Existing actions and ordinary `noSend` calls are unchanged. The
|
|
68
|
+
current-main macOS reference fixtures measure 1,662,220 raw / 388,763 gzip /
|
|
69
|
+
305,307 Brotli bytes with Vite, 1,297,621 raw / 355,579 gzip / 285,031 Brotli
|
|
70
|
+
bytes with esbuild, 1,710,494 raw / 430,613 gzip / 334,490 Brotli bytes with
|
|
71
|
+
Metro, and 3,474,604 raw / 1,406,878 gzip / 1,090,948 Brotli bytes as
|
|
72
|
+
optimized Hermes bytecode. The reviewed ceilings advance to 1,665,000 /
|
|
73
|
+
390,000 / 307,000 Vite bytes, 1,300,000 / 357,000 / 287,000 esbuild bytes,
|
|
74
|
+
1,712,000 / 455,000 / 360,000 Metro bytes, and 3,480,000 / 1,410,000 /
|
|
75
|
+
1,095,000 Hermes bytes.
|
|
76
|
+
|
|
9
77
|
- Report `listOutputs` `totalOutputs` as the size of the whole result set on
|
|
10
78
|
every page, in both the IndexedDB and Knex storage providers. A short final
|
|
11
79
|
page previously returned only that page's length, so a client paging a large
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Open BSV License version 4
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 BSV Blockchain Association ("Bitcoin Association")
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
1 - The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
2 - The Software, and any software that is derived from the Software or parts thereof,
|
|
16
|
+
can only be used on the Bitcoin SV blockchains. The Bitcoin SV blockchains are defined,
|
|
17
|
+
for purposes of this license, as the Bitcoin blockchain containing block height #556767
|
|
18
|
+
with the hash "000000000000000001d956714215d96ffc00e0afda4cd0a96c96f8d802b1662b" and
|
|
19
|
+
that contains the longest persistent chain of blocks accepted by this Software and which are valid under the rules set forth in the Bitcoin white paper (S. Nakamoto, Bitcoin: A Peer-to-Peer Electronic Cash System, posted online October 2008) and the latest version of this Software available in this repository or another repository designated by Bitcoin Association,
|
|
20
|
+
as well as the test blockchains that contain the longest persistent chains of blocks accepted by this Software and which are valid under the rules set forth in the Bitcoin whitepaper (S. Nakamoto, Bitcoin: A Peer-to-Peer Electronic Cash System, posted online October 2008) and the latest version of this Software available in this repository, or another repository designated by Bitcoin Association
|
|
21
|
+
|
|
22
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
23
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
24
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
25
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
26
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
27
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
28
|
+
THE SOFTWARE.
|
package/README.md
CHANGED
|
@@ -31,6 +31,15 @@ broadcast, so permission approval does not inherit network-broadcast latency.
|
|
|
31
31
|
The funding planner prefers settled change and uses queued permission ancestry
|
|
32
32
|
only as a last resort, keeping the application path fast without hiding funds.
|
|
33
33
|
|
|
34
|
+
Permission modules may transform calls with `onRequest` and `onResponse`, or
|
|
35
|
+
own a P-scheme's semantics with the optional `handleRequest(request, next)`
|
|
36
|
+
hook. A semantic handler can return the normal BRC-100 result directly; if it
|
|
37
|
+
needs the underlying wallet operation, `next` is guarded so it can be invoked
|
|
38
|
+
at most once. Existing transformation-only modules remain compatible. The
|
|
39
|
+
standalone `@bsv/ecpm-permission-module` demonstrates this extension by
|
|
40
|
+
implementing `p ecpm` point multiplication through `getPublicKey`, without a
|
|
41
|
+
new BRC-100 method or wire message.
|
|
42
|
+
|
|
34
43
|
Immediate actions prefer completed, then unproven, then sending change. A
|
|
35
44
|
pathological settled plan is compared with pending alternatives by exact
|
|
36
45
|
serialized BEEF plus transaction bytes; queued ancestry is used only when it is
|
|
@@ -56,6 +65,26 @@ requested at or past the end of the result set.
|
|
|
56
65
|
|
|
57
66
|
### UMP account continuity and phone changes
|
|
58
67
|
|
|
68
|
+
Argon2id password derivation uses a proven-ready host backend when one is
|
|
69
|
+
registered with `registerArgon2idBackend`. This lets React Native applications
|
|
70
|
+
perform the memory-hard operation asynchronously in native code. Browser and
|
|
71
|
+
Node runtimes prefer `hash-wasm`; when WebAssembly is unavailable, Wallet
|
|
72
|
+
Toolbox falls back to an asynchronously yielding JavaScript implementation
|
|
73
|
+
with the same parameters and output. Existing UMP v3 tokens remain
|
|
74
|
+
interoperable and do not need migration; users do not need to enable a device
|
|
75
|
+
or browser setting. A selected host backend is authoritative, so a derivation
|
|
76
|
+
error or malformed output is surfaced instead of silently changing
|
|
77
|
+
implementations. The existing `hash-wasm`-compatible utility export retains its
|
|
78
|
+
full input and output contract; requests with `secret`, non-binary output, or
|
|
79
|
+
non-`Uint8Array` input remain on `hash-wasm` rather than being reinterpreted by
|
|
80
|
+
a backend with narrower capabilities. Registration and unregistration are also
|
|
81
|
+
exported from the mobile and client package roots. Concurrent cold calls share
|
|
82
|
+
one background preload attempt; later calls can retry after it settles. Hosts
|
|
83
|
+
must make preload/readiness checks reentrant and cache permanent failures or
|
|
84
|
+
apply retry backoff. Unrelated `hash-wasm` errors propagate even when the
|
|
85
|
+
WebAssembly global is absent. Native and JavaScript results both pass the same
|
|
86
|
+
byte-type and exact-length validation.
|
|
87
|
+
|
|
59
88
|
`WalletAuthenticationManager` accepts an optional `umpTokenOutpoint` in the
|
|
60
89
|
backward-compatible WAB authentication response. Normal verified lookup and
|
|
61
90
|
lineage resolution always run first. The WAB pin is considered only when those
|
|
@@ -244,10 +273,21 @@ the 144-output / 5,000-satoshi defaults, gradual legacy-wallet migration,
|
|
|
244
273
|
pending-parent policy, exact BEEF comparison, operator tuning, action-batch
|
|
245
274
|
alignment, monitoring, and rollout guidance.
|
|
246
275
|
|
|
276
|
+
See [Prepared BEEF (COOK)](./docs/prepared-beef.md) for the opt-in Knex cache
|
|
277
|
+
that creates an exact, verified proof closure once and keeps it ready for a
|
|
278
|
+
future `createAction`. Reads, writes, and bounded backfill are separately
|
|
279
|
+
controlled and default off; cache misses and failures retain the canonical
|
|
280
|
+
BEEF builder.
|
|
281
|
+
|
|
247
282
|
See [In-memory action batch planning](./docs/action-batch-planning.md) for
|
|
248
283
|
capability-negotiated `noSend` planning, compact manifests, compressed binary
|
|
249
284
|
pack transport, atomic commit, compatibility behavior, and retained benchmarks.
|
|
250
285
|
|
|
286
|
+
See [Expiring `noSend` actions](./docs/no-send-expiry.md) for the built-in
|
|
287
|
+
BRC-111 `p nosend expiry` module, exact label forms, prefunding, durable
|
|
288
|
+
Node/browser/mobile monitoring, storage coordination, and proof-based race
|
|
289
|
+
resolution.
|
|
290
|
+
|
|
251
291
|
### `createAction` performance telemetry
|
|
252
292
|
|
|
253
293
|
Wallet Storage treats `inputBEEF` as proof data for the inputs declared in the
|
|
@@ -279,6 +319,13 @@ pnpm bench:create-action-funding
|
|
|
279
319
|
pnpm bench:create-action-beef
|
|
280
320
|
```
|
|
281
321
|
|
|
322
|
+
The proof-bearing benchmark includes a prepared-BEEF cohort and asserts that a
|
|
323
|
+
prepared hit does not invoke the canonical BEEF builder. A representative
|
|
324
|
+
local SQLite one-input run reported 8.04 ms on the cold canonical path and
|
|
325
|
+
4.39 ms on the prepared path. Local timings are noise-bound; the intended
|
|
326
|
+
production measurement is the authenticated remote/MySQL cohort, where
|
|
327
|
+
repeated proof reconstruction has materially higher cost.
|
|
328
|
+
|
|
282
329
|
Against unmodified commit `c212b5ee7`, a representative 102-input SQLite plan
|
|
283
330
|
fell from 622 queries, 102 database transactions, and 107.3 ms to 17 queries,
|
|
284
331
|
one transaction, and 8.8 ms. Query and transaction counts remain flat when the
|
|
@@ -449,4 +496,6 @@ for the full stack-wide policy.
|
|
|
449
496
|
|
|
450
497
|
## License
|
|
451
498
|
|
|
452
|
-
|
|
499
|
+
This package is released under the [Open BSV License Version 6](./LICENSE.txt).
|
|
500
|
+
The accompanying [THIRD_PARTY_NOTICES.md](./THIRD_PARTY_NOTICES.md) and
|
|
501
|
+
[LICENSES/](./LICENSES/) preserve the package's earlier Open BSV grant.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<!-- Generated by scripts/third-party-license-policy.mjs. Do not edit by hand. -->
|
|
2
|
+
|
|
3
|
+
# Third-Party Notices
|
|
4
|
+
|
|
5
|
+
The Open BSV License Version 6 in `LICENSE.txt` applies to current TS Stack
|
|
6
|
+
first-party contributions. It does not replace, narrow, or relicense historical
|
|
7
|
+
or third-party material identified below. Each identified portion remains available
|
|
8
|
+
under its stated terms.
|
|
9
|
+
|
|
10
|
+
Distributors must keep this file and the referenced `LICENSES/` files with source,
|
|
11
|
+
npm tarballs, browser bundles, WebAssembly artifacts, and container images that
|
|
12
|
+
contain the corresponding material. Ordinary dependency licenses remain with those
|
|
13
|
+
dependencies and are additionally inventoried in release SBOMs.
|
|
14
|
+
|
|
15
|
+
Registry: `governance/third-party-materials.json`
|
|
16
|
+
|
|
17
|
+
## Release clearance status
|
|
18
|
+
|
|
19
|
+
The notices below reduce attribution risk but do not create rights. A release is
|
|
20
|
+
blocked while any item marked `required` remains unresolved.
|
|
21
|
+
|
|
22
|
+
- **2026-stack-license-uniformization-authority — cleared:** The uniformization changed 107 total paths, including 55 license or policy texts; all 28 preexisting license/policy files are inventoried and every prior grant remains scoped to its snapshot code, so no blanket retroactive relicensing authority is relied upon.
|
|
23
|
+
Accepted evidence: governance/license-continuity.json, governance/license-evidence/pre-uniformization-root-policy.md, and the nine hash-pinned historical Open BSV texts.
|
|
24
|
+
|
|
25
|
+
## Wallet Toolbox pre-uniformization Open BSV License version 4 source (snapshot d215223af67b2b08ef628e8e07f5cff8b60ec9b3)
|
|
26
|
+
|
|
27
|
+
- License: `LicenseRef-Open-BSV-License-4`
|
|
28
|
+
- Use in this stack: license continuity for wallet source present before the 2026 license-file uniformization
|
|
29
|
+
- Upstream: https://github.com/bsv-blockchain/ts-stack/tree/d215223af67b2b08ef628e8e07f5cff8b60ec9b3/packages/wallet/wallet-toolbox
|
|
30
|
+
- License text: [Open-BSV-License-4-wallet-pre-2026.txt](./LICENSES/Open-BSV-License-4-wallet-pre-2026.txt)
|
|
31
|
+
- Incorporated paths:
|
|
32
|
+
- `packages/wallet/wallet-toolbox`
|
|
33
|
+
- `packages/wallet/wallet-toolbox-examples`
|
|
34
|
+
|
|
35
|
+
Copyright (c) 2023 BSV Blockchain Association (Bitcoin Association)
|
package/docs/README.md
CHANGED
|
@@ -22,9 +22,8 @@ The documentation is split into various pages, each covering a set of related fu
|
|
|
22
22
|
|
|
23
23
|
## Open RPC
|
|
24
24
|
|
|
25
|
-
StorageClient implements
|
|
26
|
-
|
|
27
|
-
- [StorageClient JSight UI](https://bsv-blockchain.github.io/wallet-toolbox/open-rpc)
|
|
25
|
+
`StorageClient` implements `WalletStorageProvider` over HTTPS using JSON-RPC.
|
|
26
|
+
Its maintained API documentation is in the [Storage reference](./storage.md#class-storageclient).
|
|
28
27
|
|
|
29
28
|
## Getting Started
|
|
30
29
|
|
|
@@ -216,6 +216,13 @@ unrelated action.
|
|
|
216
216
|
|
|
217
217
|
## Monitoring and rollout
|
|
218
218
|
|
|
219
|
+
Wallet Storage can optionally prepare the exact verified BEEF closure for a
|
|
220
|
+
managed-change source after the foreground action finishes. This COOK
|
|
221
|
+
(Create Once, Output Kept) optimization does not alter funding selection,
|
|
222
|
+
transaction state, or the canonical fallback. See
|
|
223
|
+
[Prepared BEEF (COOK)](./prepared-beef.md) for the asynchronous timing
|
|
224
|
+
contract, storage controls, proof-reorganization handling, and staged rollout.
|
|
225
|
+
|
|
219
226
|
`TaskReviewUtxos.reviewManagedChangeByIdentityKey(identityKey)` is a read-only
|
|
220
227
|
operator report. It returns:
|
|
221
228
|
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# Expiring `noSend` actions (BRC-177)
|
|
2
|
+
|
|
3
|
+
Wallet Toolbox implements the BRC-111 `nosend` module for wallet-enforced
|
|
4
|
+
expiry of BRC-100 `noSend` actions. It is built into the Node, browser, and
|
|
5
|
+
mobile Wallet Toolbox distributions; applications do not install a separate
|
|
6
|
+
permission module.
|
|
7
|
+
|
|
8
|
+
Use exactly one of these action labels:
|
|
9
|
+
|
|
10
|
+
```text
|
|
11
|
+
p nosend expiry seconds <duration>
|
|
12
|
+
p nosend expiry timestamp <unixSeconds>
|
|
13
|
+
p nosend expiry blockheight <height>
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Values are canonical unsigned base-10 integers. A relative duration must be
|
|
17
|
+
greater than zero. Absolute timestamps and block heights must still be in the
|
|
18
|
+
future when the protected action is activated.
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
const offer = await wallet.createAction({
|
|
22
|
+
description: 'Offer valid for five minutes',
|
|
23
|
+
labels: ['p nosend expiry seconds 300', 'offer 42'],
|
|
24
|
+
outputs: [
|
|
25
|
+
{
|
|
26
|
+
satoshis: 1000,
|
|
27
|
+
lockingScript: recipientLockingScript,
|
|
28
|
+
outputDescription: 'Offer payment'
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
options: {
|
|
32
|
+
noSend: true
|
|
33
|
+
}
|
|
34
|
+
})
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
The caller must set `noSend: true` and must not use `sendWith`,
|
|
38
|
+
`noSendChange`, or `returnTXIDOnly`. The wallet applies the same restrictions
|
|
39
|
+
when a signable action is completed through `signAction`.
|
|
40
|
+
|
|
41
|
+
When label permissions are enabled, Wallet Permissions Manager authorizes use
|
|
42
|
+
of the built-in module and obtains a spending preflight before creating its
|
|
43
|
+
on-chain funding transaction. Its normal amount-specific spending authorization
|
|
44
|
+
still applies to the protected action and always rechecks the current spending
|
|
45
|
+
ledger after prefunding. The funding transaction carries the same originator
|
|
46
|
+
and calendar-month attribution as the protected action, while accounting only
|
|
47
|
+
for its miner fee rather than its internal anchor output. This prevents an
|
|
48
|
+
unauthorized application from imposing even the funding transaction's miner
|
|
49
|
+
fee or evading monthly limits through repeated prefunding. The reserved labels
|
|
50
|
+
cannot be overridden by a custom permission module or asserted through
|
|
51
|
+
`internalizeAction`.
|
|
52
|
+
|
|
53
|
+
## What the wallet does
|
|
54
|
+
|
|
55
|
+
Before returning the protected action, Wallet Toolbox:
|
|
56
|
+
|
|
57
|
+
1. calculates the exact wallet funding required by its requested outputs,
|
|
58
|
+
explicit inputs, and fee;
|
|
59
|
+
2. creates and immediately broadcasts a normal funding transaction containing
|
|
60
|
+
a dedicated managed-change output;
|
|
61
|
+
3. requires processor acceptance of that funding transaction;
|
|
62
|
+
4. creates the protected transaction with that output as its only
|
|
63
|
+
automatically selected wallet input and with no wallet change; and
|
|
64
|
+
5. signs and durably stores a one-input reclaim transaction to a fresh
|
|
65
|
+
`default`-basket output.
|
|
66
|
+
|
|
67
|
+
The wallet returns the protected transaction to the caller but never
|
|
68
|
+
broadcasts it. The funding transaction may have ordinary change because it is
|
|
69
|
+
already on the network; significant wallet change is therefore not held inside
|
|
70
|
+
the unbroadcast transaction.
|
|
71
|
+
|
|
72
|
+
For `seconds`, activation occurs after prefunding and the absolute deadline is
|
|
73
|
+
stored before the action is returned. Restarting the wallet does not restart
|
|
74
|
+
the duration. A signable action is already active while it waits for
|
|
75
|
+
`signAction`, but an unsigned expiry can release its anchor locally because no
|
|
76
|
+
valid anchor signature has been exposed.
|
|
77
|
+
|
|
78
|
+
After a signed action expires, the active storage monitor first requires both
|
|
79
|
+
an explicit `unknown` target verdict and a conclusive unspent-anchor result.
|
|
80
|
+
Service errors or ambiguous status defer action. The monitor then atomically
|
|
81
|
+
activates the pre-signed reclaim and retries normal network submission. The
|
|
82
|
+
reclaim output remains unavailable for wallet funding until a locally
|
|
83
|
+
validated Merkle proof establishes that the reclaim won. A processor rejection
|
|
84
|
+
does not release the anchor: the lifecycle remains quarantined for proof
|
|
85
|
+
reconciliation because another submission may already have reached the network.
|
|
86
|
+
If the reclaim was terminally rejected, the target has never been observed, and
|
|
87
|
+
later checks still report the target as explicitly `unknown` and the anchor as
|
|
88
|
+
conclusively unspent, the monitor revives and resubmits that same pre-signed
|
|
89
|
+
reclaim after a persistent exponential backoff (30 seconds, doubling to one
|
|
90
|
+
hour). It never creates a different spend or releases the anchor during
|
|
91
|
+
recovery. A conclusive spent-anchor verdict is likewise quarantined; if the
|
|
92
|
+
conflicting spend later disappears, reclaim resumes only after fresh explicit
|
|
93
|
+
`unknown` target and unspent-anchor verdicts.
|
|
94
|
+
|
|
95
|
+
Seeing the protected transaction as known or mined permanently stops a new
|
|
96
|
+
reclaim and moves it into ordinary proof tracking. If a reclaim was already
|
|
97
|
+
submitted when the target appears, the monitor stops further reclaim retries
|
|
98
|
+
but retains both transactions for proof tracking. Only a locally validated
|
|
99
|
+
proof finalizes either winner. A processor status by itself is never reported
|
|
100
|
+
as final.
|
|
101
|
+
|
|
102
|
+
An observed target's `broadcast` state is intentionally sticky: BRC-177 makes
|
|
103
|
+
expiry a deadline for broadcast, not confirmation, so an automatic timeout
|
|
104
|
+
must not later double-spend a target that a recipient submitted on time. If an
|
|
105
|
+
operator establishes that `known` was a status-provider false positive, recovery
|
|
106
|
+
is therefore an explicit, security-sensitive repair rather than a timer:
|
|
107
|
+
|
|
108
|
+
1. stop every monitor and storage writer and snapshot each synchronized store;
|
|
109
|
+
2. verify independently that neither target nor reclaim has a validated proof,
|
|
110
|
+
that trusted services report the target `unknown`, and that the anchor is an
|
|
111
|
+
unspent output on the canonical chain;
|
|
112
|
+
3. remove or repair the provider that produced the false observation;
|
|
113
|
+
4. change only the protected row's lifecycle from `broadcast` to `conflicted`
|
|
114
|
+
in the active store and every synchronized copy, leaving transaction status,
|
|
115
|
+
request records, `spentBy`, and output spendability untouched; and
|
|
116
|
+
5. restart exactly one authoritative monitor and retain the snapshot until the
|
|
117
|
+
resulting race is proven.
|
|
118
|
+
|
|
119
|
+
A stale synchronized copy still carrying the higher-ranked `broadcast` state
|
|
120
|
+
can restore it during merge, so all copies must be repaired together. If any
|
|
121
|
+
proof or anchor-spend evidence is ambiguous, do not reset the lifecycle; repair
|
|
122
|
+
status/proof services and let ordinary reconciliation remain fail-closed.
|
|
123
|
+
|
|
124
|
+
`abortAction` cancels an unreleased action locally. For a released action it
|
|
125
|
+
durably requests immediate revocation through the same guarded reclaim path;
|
|
126
|
+
it does not clear the anchor reservation. An already observed target is
|
|
127
|
+
protected and returns `aborted: false`.
|
|
128
|
+
|
|
129
|
+
## Storage, monitors, and upgrades
|
|
130
|
+
|
|
131
|
+
Expiry metadata, the signed reclaim, and lifecycle state are synchronized with
|
|
132
|
+
the action. State merging is monotonic, so a backup with a newer wall clock
|
|
133
|
+
cannot revive an older lifecycle state. Only the provider named by the user's
|
|
134
|
+
synchronized `activeStorage` value may activate a reclaim, and compare-and-set
|
|
135
|
+
updates ensure that concurrent monitor processes intentionally create one
|
|
136
|
+
reclaim record. Synchronized reclaim outputs remain quarantined unless the
|
|
137
|
+
local lifecycle has proven the reclaim winner, even when transaction and output
|
|
138
|
+
updates arrive from different devices.
|
|
139
|
+
|
|
140
|
+
The default Wallet Toolbox monitor includes the expiry task. A remote active
|
|
141
|
+
storage service owns monitoring; browser and mobile clients do not compete
|
|
142
|
+
with it. Operators must migrate the active storage database and run the normal
|
|
143
|
+
default monitor before accepting BRC-177 actions. The capability handshake
|
|
144
|
+
rejects an older storage server before the wallet creates the funding
|
|
145
|
+
transaction.
|
|
146
|
+
|
|
147
|
+
Knex storage gains nullable transaction lifecycle columns plus expiry and
|
|
148
|
+
reclaim-transaction indexes. IndexedDB schema version 5 adds the corresponding
|
|
149
|
+
state and reclaim-transaction indexes. Existing actions and ordinary `noSend`
|
|
150
|
+
behavior are unchanged; no data rewrite is required.
|
|
151
|
+
|
|
152
|
+
Funding and reclaim network fees are paid by the wallet owner. Wallet Toolbox
|
|
153
|
+
reserves reclaim fees at the greater of its configured fee rate or 1,000
|
|
154
|
+
satoshis per kilobyte and rejects an anchor that would not leave an economic
|
|
155
|
+
reclaim output.
|
|
156
|
+
|
|
157
|
+
## Application responsibility
|
|
158
|
+
|
|
159
|
+
Action labels are wallet metadata and are not committed into the transaction
|
|
160
|
+
or automatically delivered in BEEF. An application that gives the transaction
|
|
161
|
+
to a recipient must communicate the deadline separately. If the deadline must
|
|
162
|
+
be authenticated, bind it to the transaction or anchor outpoint in the
|
|
163
|
+
application protocol.
|
|
164
|
+
|
|
165
|
+
Broadcast with enough margin for the wallet's configured status services to
|
|
166
|
+
observe acceptance. Expiry starts a double-spend reclaim; consensus finality
|
|
167
|
+
comes only from the transaction that is mined and proven.
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# Prepared BEEF (COOK)
|
|
2
|
+
|
|
3
|
+
COOK stands for **Create Once, Output Kept**. It is the project name for an
|
|
4
|
+
opt-in Wallet Storage optimization which builds reusable input proof material
|
|
5
|
+
before a later `createAction` needs it.
|
|
6
|
+
|
|
7
|
+
Production identifiers use `preparedBeef`, not cooking vocabulary. A
|
|
8
|
+
**prepared BEEF** is already ready to use: it has been reduced to one root
|
|
9
|
+
transaction and its exact dependency closure, independently verified,
|
|
10
|
+
serialized, checksummed, and stored. It does not mean “waiting to be cooked.”
|
|
11
|
+
|
|
12
|
+
## Latency contract
|
|
13
|
+
|
|
14
|
+
The optimization does not replace the canonical BEEF builder or make a cache
|
|
15
|
+
service a new dependency.
|
|
16
|
+
|
|
17
|
+
1. `createAction` starts proof prefetch while its normal planning and database
|
|
18
|
+
work continue.
|
|
19
|
+
2. With prepared reads enabled, a normal one-root call performs one user-scoped
|
|
20
|
+
indexed lookup. A fragmented call first runs a metadata-only aggregate and
|
|
21
|
+
bypasses prepared storage if matching BEEF blobs exceed `maxLookupBytes`.
|
|
22
|
+
Calls with more than 32 roots also bypass prepared storage. The canonical
|
|
23
|
+
builder therefore remains the bounded path for unusually broad actions.
|
|
24
|
+
3. A valid hit is parsed and merged directly. A missing, stale, corrupt,
|
|
25
|
+
oversized, or unsupported artifact is treated as a miss and the existing
|
|
26
|
+
canonical builder runs for only those roots.
|
|
27
|
+
4. The action result is completely assembled before any missing roots are
|
|
28
|
+
queued for preparation.
|
|
29
|
+
5. Admission validates and retains only bounded user/root identifiers, never
|
|
30
|
+
the source BEEF. No graph traversal, hashing, verification, serialization,
|
|
31
|
+
or persistence occurs in the foreground.
|
|
32
|
+
6. The bounded worker starts on a later event-loop turn. `createAction` and
|
|
33
|
+
`processAction` never await canonical reload, dependency selection,
|
|
34
|
+
verification, or persistence performed by that worker.
|
|
35
|
+
|
|
36
|
+
Prepared reads therefore add an indexed lookup on a cold cache, but that lookup
|
|
37
|
+
runs inside the existing early prefetch window and overlaps normal foreground
|
|
38
|
+
work. Preparation itself is strictly background work. All controls default to
|
|
39
|
+
off, so upgrading without enabling COOK preserves the existing normal-action
|
|
40
|
+
execution path.
|
|
41
|
+
|
|
42
|
+
`processAction` also queues a newly finalized transaction when it creates
|
|
43
|
+
wallet-managed change. This prepares the source most likely to fund a future
|
|
44
|
+
normal action without extending the current request.
|
|
45
|
+
|
|
46
|
+
## Storage and validity
|
|
47
|
+
|
|
48
|
+
Knex migrations add a `prepared_beefs` table keyed by `(userId, rootTxid)` and
|
|
49
|
+
a singleton `prepared_beef_metadata` proof epoch used to serialize worker
|
|
50
|
+
writes with reorganization invalidation. Artifacts are derived data, not wallet
|
|
51
|
+
authority:
|
|
52
|
+
|
|
53
|
+
- the authenticated storage user is part of every read and write key;
|
|
54
|
+
- canonical transaction, proof, and output rows remain the source of truth;
|
|
55
|
+
- proof rows received through authenticated RPC cannot establish global proof
|
|
56
|
+
authority on their own: the server recomputes the transaction ID and Merkle
|
|
57
|
+
root, checks the path position, and matches its active header/chain tracker.
|
|
58
|
+
In-process backup and conflict sync canonicalize hexadecimal identifiers and
|
|
59
|
+
apply the same active-chain validation before replacing an existing global
|
|
60
|
+
proof, so an orphaned backup cannot overwrite a repaired active proof. Any
|
|
61
|
+
inserted or replaced proof invalidates prepared artifacts in the same
|
|
62
|
+
storage transaction;
|
|
63
|
+
- each artifact contains one root transaction plus only its recursive proof
|
|
64
|
+
dependencies;
|
|
65
|
+
- the background worker verifies the exact BEEF against the configured chain
|
|
66
|
+
tracker before writing it;
|
|
67
|
+
- reads enforce format version, state, checksum, byte length, size ceiling, and
|
|
68
|
+
a complete root transaction;
|
|
69
|
+
- a reorganization notification first closes prepared reads synchronously in
|
|
70
|
+
that server process, then advances the shared proof epoch and marks ready
|
|
71
|
+
artifacts stale in one database transaction, before the aged replacement-
|
|
72
|
+
proof task performs network I/O. If invalidation fails, that process keeps
|
|
73
|
+
prepared reads closed and uses the canonical path until a later invalidation
|
|
74
|
+
succeeds (or the process restarts). A lookup whose
|
|
75
|
+
query begins after that transaction commits cannot read the old artifact. A
|
|
76
|
+
lookup overlapping the transaction may observe the preceding database
|
|
77
|
+
snapshot, as the canonical builder may, and is ordered before invalidation;
|
|
78
|
+
- the proof epoch fences background writes rather than reads. It prevents an
|
|
79
|
+
in-flight worker in another server process from writing
|
|
80
|
+
pre-reorganization material after invalidation commits. Copying the epoch to
|
|
81
|
+
each artifact would not strengthen an ordinary snapshot read because both
|
|
82
|
+
the artifact and metadata can belong to the same preceding snapshot;
|
|
83
|
+
- a failed verification leaves an unreadable rejection marker so optional
|
|
84
|
+
backfill does not hot-loop; a later canonical action can retry and replace
|
|
85
|
+
it organically;
|
|
86
|
+
- storage purge removes artifacts once no matching unspent managed output
|
|
87
|
+
remains; and
|
|
88
|
+
- prepared artifacts are deliberately excluded from wallet synchronization and
|
|
89
|
+
can always be rebuilt.
|
|
90
|
+
|
|
91
|
+
Knex (SQLite and MySQL) is the persistence implementation. The option is not
|
|
92
|
+
part of portable `StorageProvider` or IndexedDB configuration; those providers
|
|
93
|
+
retain the normal canonical fallback and do not bundle the background worker.
|
|
94
|
+
|
|
95
|
+
## Configuration
|
|
96
|
+
|
|
97
|
+
`StorageKnex` and `Setup.createWalletKnex` accept the same `preparedBeef`
|
|
98
|
+
settings:
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
const setup = await Setup.createWalletKnex({
|
|
102
|
+
...args,
|
|
103
|
+
preparedBeef: {
|
|
104
|
+
// Roll out writes before reads so the first read cohort is warm.
|
|
105
|
+
writeEnabled: true,
|
|
106
|
+
readEnabled: false,
|
|
107
|
+
backfillEnabled: false,
|
|
108
|
+
maxQueueSize: 32,
|
|
109
|
+
maxQueueSizePerUser: 4,
|
|
110
|
+
maxArtifactBytes: 2 * 1024 * 1024,
|
|
111
|
+
maxLookupBytes: 2 * 1024 * 1024,
|
|
112
|
+
maxArtifactTransactions: 256,
|
|
113
|
+
backfillBatchSize: 32,
|
|
114
|
+
backfillIntervalMs: 100
|
|
115
|
+
}
|
|
116
|
+
})
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
| Setting | Default | Meaning |
|
|
120
|
+
| ------------------------- | ------: | ----------------------------------------------------------------------------------------------------- |
|
|
121
|
+
| `writeEnabled` | `false` | Queue and persist verified artifacts after foreground action work. |
|
|
122
|
+
| `readEnabled` | `false` | Use valid artifacts on the `createAction` proof path. |
|
|
123
|
+
| `backfillEnabled` | `false` | Prepare eligible existing managed-change roots in bounded background passes. Requires writes. |
|
|
124
|
+
| `maxQueueSize` | `32` | Maximum roots queued or running globally. New work is safely dropped when full. |
|
|
125
|
+
| `maxQueueSizePerUser` | `4` | Maximum roots queued or running for one user, preventing one tenant from consuming the shared worker. |
|
|
126
|
+
| `maxArtifactBytes` | `2 MiB` | Maximum estimated source and exact prepared-artifact size. |
|
|
127
|
+
| `maxLookupBytes` | `2 MiB` | Maximum aggregate prepared BEEF bytes loaded for one fragmented foreground lookup. |
|
|
128
|
+
| `maxArtifactTransactions` | `256` | Maximum transactions in a source or exact prepared graph before expensive worker stages. |
|
|
129
|
+
| `backfillBatchSize` | `32` | Maximum roots selected in one backfill pass. |
|
|
130
|
+
| `backfillIntervalMs` | `100` | Delay between low-priority backfill passes. |
|
|
131
|
+
|
|
132
|
+
The queue is in-process and best effort. It retains bounded identifiers only,
|
|
133
|
+
applies global and per-user admission quotas, and serializes preparation work.
|
|
134
|
+
Before canonical reload, the worker first asks storage for the root's raw/proof
|
|
135
|
+
byte length across every canonical-load status (including `unconfirmed`), so an
|
|
136
|
+
oversized no-send `inputBEEF` is never loaded or parsed by
|
|
137
|
+
COOK. It then applies estimated byte and transaction-count limits before
|
|
138
|
+
dependency selection, verification, and exact serialization. A restart,
|
|
139
|
+
full queue, resource rejection, verification failure, or persistence failure
|
|
140
|
+
loses only an optimization opportunity. A later action can rebuild the same
|
|
141
|
+
artifact from authoritative storage.
|
|
142
|
+
|
|
143
|
+
## Rollout toward a 50 ms normal-action target
|
|
144
|
+
|
|
145
|
+
Use a staged rollout rather than enabling all controls at once:
|
|
146
|
+
|
|
147
|
+
1. Before release, run the additive migration against a disposable MySQL 8
|
|
148
|
+
schema. Confirm `prepared_beefs.beef` is a `LONGBLOB`, then exercise one
|
|
149
|
+
insert/upsert, prepared lookup, invalidation, and rebuild. This validates the
|
|
150
|
+
dialect-specific migration and basic Knex behavior even though all rollout
|
|
151
|
+
flags remain off.
|
|
152
|
+
2. Deploy the migration with all flags off and confirm existing latency and
|
|
153
|
+
error rates are unchanged.
|
|
154
|
+
3. Before enabling writes on PXC, run two storage processes against the same
|
|
155
|
+
non-production schema. Pause one worker after it reads the epoch, invalidate
|
|
156
|
+
from the other process, release the worker, and confirm it cannot commit the
|
|
157
|
+
old artifact. Also exercise concurrent upserts of the same root and record
|
|
158
|
+
any deadlock/retry behavior.
|
|
159
|
+
4. Enable writes for a small server cohort. Watch preparation success,
|
|
160
|
+
rejection, artifact bytes, queue pressure, and database load.
|
|
161
|
+
5. Once the normal managed-change roots are warm, enable reads for the same
|
|
162
|
+
cohort. Compare `createAction` p50/p95, prepared hit rate, canonical fetch
|
|
163
|
+
count, and returned BEEF bytes with the prior cohort.
|
|
164
|
+
6. Enable bounded backfill only if organic writes do not warm the active pool
|
|
165
|
+
quickly enough. Keep it off during database pressure.
|
|
166
|
+
7. Expand reads only while correctness fallbacks remain clean and the normal
|
|
167
|
+
one-input cohort moves toward the operator's 50 ms target.
|
|
168
|
+
|
|
169
|
+
The target is an end-to-end service objective, not a guarantee from this cache
|
|
170
|
+
alone. Authentication, HTTP, database commits, signing, and response
|
|
171
|
+
serialization still contribute to remote latency. COOK specifically removes
|
|
172
|
+
repeated canonical proof reconstruction from prepared hits.
|
|
173
|
+
|
|
174
|
+
Telemetry uses bounded-cardinality spans:
|
|
175
|
+
|
|
176
|
+
- `wallet.storage.prepared_beef.lookup` reports requested roots, hits, misses,
|
|
177
|
+
corrupt rows, bytes, and whether the lookup was bypassed by the root-count or
|
|
178
|
+
aggregate-byte foreground safety bound;
|
|
179
|
+
- `wallet.storage.prepared_beef.prepare` reports attempted roots, prepared and
|
|
180
|
+
rejected counts, and bytes; and
|
|
181
|
+
- `wallet.storage.prepared_beef.backfill` reports a failed backfill pass.
|
|
182
|
+
|
|
183
|
+
The existing `wallet.storage.create_action.beef_prefetch` span also reports
|
|
184
|
+
`beef.prepared_hit_count` and `beef.canonical_fetch_count`. No transaction ID,
|
|
185
|
+
user identity, script, key, or payload is emitted as a telemetry attribute.
|
|
186
|
+
|
|
187
|
+
## Rollback
|
|
188
|
+
|
|
189
|
+
Set `readEnabled`, `writeEnabled`, and `backfillEnabled` to `false`. New actions
|
|
190
|
+
immediately use the canonical path, queued work stops being accepted, and the
|
|
191
|
+
derived rows can remain in place for a later re-enable on the same COOK-aware
|
|
192
|
+
code or be removed by normal purge. Before downgrading to an older Wallet
|
|
193
|
+
Toolbox version, delete the derived rows (or drop both additive tables); older
|
|
194
|
+
code cannot advance the proof epoch during a reorganization. After returning
|
|
195
|
+
to a COOK-aware version, warm artifacts with writes before enabling reads. No
|
|
196
|
+
transaction, proof, output, synchronization, BRC-100, or Wallet Wire rollback
|
|
197
|
+
is required.
|
package/docs/setup.md
CHANGED
|
@@ -343,6 +343,8 @@ export interface SetupWalletArgs {
|
|
|
343
343
|
active?: WalletStorageProvider;
|
|
344
344
|
backups?: WalletStorageProvider[];
|
|
345
345
|
scriptVerifier?: SpendVerifierInterface;
|
|
346
|
+
managedChangePolicy?: ManagedChangePolicyOptions;
|
|
347
|
+
preparedBeef?: PreparedBeefOptions;
|
|
346
348
|
}
|
|
347
349
|
```
|
|
348
350
|
|
|
@@ -384,6 +386,15 @@ Defaults to undefined.
|
|
|
384
386
|
privilegedKeyGetter?: () => Promise<PrivateKey>
|
|
385
387
|
```
|
|
386
388
|
|
|
389
|
+
###### Property preparedBeef
|
|
390
|
+
|
|
391
|
+
Optional Knex prepared-BEEF (COOK) rollout controls. Reads, writes, and
|
|
392
|
+
backfill default off. See [Prepared BEEF (COOK)](./prepared-beef.md).
|
|
393
|
+
|
|
394
|
+
```ts
|
|
395
|
+
preparedBeef?: PreparedBeefOptions
|
|
396
|
+
```
|
|
397
|
+
|
|
387
398
|
###### Property scriptVerifier
|
|
388
399
|
|
|
389
400
|
Optional high-performance verifier for internal wallet and locally hosted
|