@totemsdk/txpow 1.0.0 → 1.0.1

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/README.md CHANGED
@@ -69,6 +69,94 @@ const estimatedMs = estimateMiningCost(targetDifficulty, hashesPerSecond);
69
69
  console.log(`Expected mining time: ${estimatedMs}ms`);
70
70
  ```
71
71
 
72
+ ## Machine Work Admission
73
+
74
+ Machine Work Admission allows applications to require computational proof before allocating scarce resources. The work is performed against a Minima block candidate so that application anti-spam work simultaneously searches for valid Minima blocks.
75
+
76
+ A receiver issues a `WorkChallenge` (unique, expiring, bound to the receiver and an application domain). A sender commits its application action into the TxPoW header's `customHash` field and mines the nonce space of a real current Minima block candidate. If the hash beats the receiver's admission target, the machine action is admissible. If the same hash also beats the current Minima block target, the candidate is a genuine Minima block (Super-0 … Super-31) and is relayable.
77
+
78
+ Ordinary admission proofs stay off-chain. Only actual Minima blocks are eligible for relay.
79
+
80
+ ```typescript
81
+ import {
82
+ createWorkChallenge,
83
+ mineWorkAdmission,
84
+ verifyWorkAdmission,
85
+ type MinimaWorkTemplateProvider,
86
+ type MinimaWorkRelay,
87
+ } from '@totemsdk/txpow';
88
+
89
+ // Receiver: issue a challenge (target chosen by receiver policy)
90
+ const challenge = createWorkChallenge(
91
+ 'receiver-address',
92
+ 'totem.compute.reserve',
93
+ admissionTargetHex,
94
+ );
95
+
96
+ // Sender: mine the admission proof against a real Minima block candidate
97
+ // The relay boundary keeps Minima networking out of the core primitive.
98
+ const relay: MinimaWorkRelay = {
99
+ submitBlock: async (envelope) => node.submitBlock(envelope),
100
+ };
101
+ const provider: MinimaWorkTemplateProvider = {
102
+ getCurrentTemplate: async () => node.fetchCurrentTemplate(),
103
+ getLatestTemplate: async () => node.fetchCurrentTemplate(),
104
+ };
105
+
106
+ // The challenge target is the single authoritative admission target.
107
+ const proof = await mineWorkAdmission(action, challenge, provider, { relay });
108
+
109
+ // Receiver: verify (never trusts sender-reported hardware speed)
110
+ const result = await verifyWorkAdmission(action, challenge, proof, provider);
111
+ if (result.valid) {
112
+ // allocate the scarce resource
113
+ }
114
+ ```
115
+
116
+ ### Minima Super level
117
+
118
+ A TxPoW is a Minima block when `txpowId < blockDifficulty`. Its strength is the exact Minima Super level:
119
+
120
+ ```text
121
+ superLevel = floor(log2(blockDifficulty / txpowId))
122
+ ```
123
+
124
+ with `MINIMA_CASCADE_LEVELS = 32`, clamped so the maximum represented value is 31.
125
+
126
+ | `superLevel` | Meaning |
127
+ |--------------|---------|
128
+ | `-1` | not a Minima block |
129
+ | `0` | ordinary/base Minima block (Super-0) |
130
+ | `1` | stronger block (Super-1) |
131
+ | … | |
132
+ | `31` | maximum represented Super level |
133
+
134
+ **Super-0 is an ordinary valid Minima block. Non-block TxPoWs have computed Super level -1.** Super level describes block strength — it is not a relay policy. Every valid current block (Super-0 … Super-31) is eligible for relay.
135
+
136
+ ### Three distinct claims
137
+
138
+ Verification distinguishes three claims that must never be confused:
139
+
140
+ | Claim | Meaning | Field |
141
+ |-------|---------|-------|
142
+ | **A. admission-valid** | the hash satisfies `challenge.target` | `valid` |
143
+ | **B. Minima block** | the hash beats the block difficulty encoded by the candidate template | `superLevel` / `isBlock` |
144
+ | **C. broadcastable** | a Minima block AND the template is still current AND a live template provider was supplied | `broadcastable` |
145
+
146
+ A stale candidate may remain `valid = true` (and `superLevel >= 0`) while `broadcastable = false`. Offline verification (no `MinimaWorkTemplateProvider`) leaves `broadcastable` undefined — it does **not** claim Minima block contribution.
147
+
148
+ `proof.superLevel`, `proof.isBlock`, and `proof.qualifiesAsMinimaBlock` are derived metadata recorded at mining time. Verification never trusts them — they are recomputed from the re-derived TxPoW ID and the template's block difficulty.
149
+
150
+ ### Distributed mining boundary
151
+
152
+ Machine Work Admission is primarily local/off-chain: the requesting machine performs the work, which keeps it attributable to the machine requesting admission. Native Minima distributed mining (`MSG_TXBLOCKMINE`, where receiving peers reset the body PRNG to create independent search spaces) is a separate, optional, rate-limited, integration-controlled mechanism. It is NOT used per machine action — broadcasting every machine action through `MSG_TXBLOCKMINE` would turn machine anti-spam into Minima network spam. The body PRNG is independent candidate entropy; it never changes the `customHash` application commitment.
153
+
154
+ ### Authentication boundary
155
+
156
+ `validateWorkChallenge()` validates structural/freshness/domain/recipient properties but does **not** prove that the claimed recipient actually issued the challenge. A `WorkChallenge` is a plain data object; anyone can construct one claiming any recipient. Proving the issuer requires authenticating the enclosing message (e.g. a signed machine-to-machine protocol message in the Edge negotiation layer). `@totemsdk/txpow` deliberately does not implement a parallel identity/signature system.
157
+
158
+ The primitive is generic — it knows only "there is an application action represented by canonical bytes". Domain-specific packages supply the action commitment for negotiation, compute, storage, mailbox, sensor, or rendezvous domains. It does NOT prove identity, authority, payment, or resource availability; higher-level layers must still perform those checks.
159
+
72
160
  ## Upstream Java source
73
161
 
74
162
  This package is a TypeScript port of Minima's TxPoW envelope structures. Canonical upstream references:
@@ -0,0 +1,66 @@
1
+ /**
2
+ * admission/challenge.ts — WorkChallenge creation and validation.
3
+ *
4
+ * The receiver controls the admission requirement. A challenge must be unique
5
+ * enough to prevent useful pre-mining, must expire, must bind to the intended
6
+ * receiver, and must bind to an application domain. Verification NEVER trusts
7
+ * sender-reported hardware speed — it only checks `hash < target`.
8
+ *
9
+ * ── AUTHENTICATION BOUNDARY ────────────────────────────────────────────────
10
+ * `validateWorkChallenge()` validates structural/freshness/domain/recipient
11
+ * properties but does NOT prove that the claimed recipient actually issued the
12
+ * challenge. A WorkChallenge is a plain data object; anyone can construct one
13
+ * claiming any recipient. Proving the issuer requires authenticating the
14
+ * enclosing message (e.g. a signed machine-to-machine protocol message in the
15
+ * Edge negotiation layer). @totemsdk/txpow deliberately does NOT implement a
16
+ * parallel identity/signature system — that belongs to the application layer.
17
+ * ───────────────────────────────────────────────────────────────────────────
18
+ */
19
+ import { type WorkChallenge } from './types.js';
20
+ /** Default challenge lifetime: 5 minutes. */
21
+ export declare const DEFAULT_CHALLENGE_TTL_MS: number;
22
+ /** Maximum challenge lifetime: 24 hours. */
23
+ export declare const MAX_CHALLENGE_TTL_MS: number;
24
+ /**
25
+ * Create a WorkChallenge.
26
+ *
27
+ * @param recipient The intended receiver the challenge binds to.
28
+ * @param domain Application domain (open-ended, e.g. "totem.compute.reserve").
29
+ * @param target Absolute 32-byte cryptographic target (hex).
30
+ * @param options Optional overrides (challengeId, nonce, ttl, issuedAt, network).
31
+ */
32
+ export declare function createWorkChallenge(recipient: string, domain: string, target: string, options?: {
33
+ challengeId?: string;
34
+ nonce?: string;
35
+ ttlMs?: number;
36
+ issuedAt?: number;
37
+ network?: string;
38
+ }): WorkChallenge;
39
+ /**
40
+ * Validate a WorkChallenge at verification time.
41
+ *
42
+ * Checks structural integrity, expiry, and that the challenge binds to the
43
+ * expected recipient/domain. Does NOT check the proof hash — that is the
44
+ * caller's job via verifyWorkAdmission.
45
+ */
46
+ export declare function validateWorkChallenge(challenge: WorkChallenge, expected?: {
47
+ recipient?: string;
48
+ domain?: string;
49
+ now?: number;
50
+ }): {
51
+ valid: boolean;
52
+ reason?: string;
53
+ };
54
+ /**
55
+ * Derive a stable challenge fingerprint (SHA3-256 of canonical challenge bytes).
56
+ * Useful for higher-level code that tracks already-consumed challenge IDs.
57
+ */
58
+ export declare function challengeFingerprint(challenge: WorkChallenge): string;
59
+ /**
60
+ * Canonical serialization of a WorkChallenge.
61
+ *
62
+ * Deterministic field ordering with length-prefixed strings so that no
63
+ * ambiguous concatenation is possible. Used for the commitment and for
64
+ * challenge fingerprints.
65
+ */
66
+ export declare function canonicalChallenge(challenge: WorkChallenge): string;
@@ -0,0 +1,155 @@
1
+ "use strict";
2
+ /**
3
+ * admission/challenge.ts — WorkChallenge creation and validation.
4
+ *
5
+ * The receiver controls the admission requirement. A challenge must be unique
6
+ * enough to prevent useful pre-mining, must expire, must bind to the intended
7
+ * receiver, and must bind to an application domain. Verification NEVER trusts
8
+ * sender-reported hardware speed — it only checks `hash < target`.
9
+ *
10
+ * ── AUTHENTICATION BOUNDARY ────────────────────────────────────────────────
11
+ * `validateWorkChallenge()` validates structural/freshness/domain/recipient
12
+ * properties but does NOT prove that the claimed recipient actually issued the
13
+ * challenge. A WorkChallenge is a plain data object; anyone can construct one
14
+ * claiming any recipient. Proving the issuer requires authenticating the
15
+ * enclosing message (e.g. a signed machine-to-machine protocol message in the
16
+ * Edge negotiation layer). @totemsdk/txpow deliberately does NOT implement a
17
+ * parallel identity/signature system — that belongs to the application layer.
18
+ * ───────────────────────────────────────────────────────────────────────────
19
+ */
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ exports.MAX_CHALLENGE_TTL_MS = exports.DEFAULT_CHALLENGE_TTL_MS = void 0;
22
+ exports.createWorkChallenge = createWorkChallenge;
23
+ exports.validateWorkChallenge = validateWorkChallenge;
24
+ exports.challengeFingerprint = challengeFingerprint;
25
+ exports.canonicalChallenge = canonicalChallenge;
26
+ const core_1 = require("@totemsdk/core");
27
+ const types_js_1 = require("./types.js");
28
+ /** Default challenge lifetime: 5 minutes. */
29
+ exports.DEFAULT_CHALLENGE_TTL_MS = 5 * 60 * 1000;
30
+ /** Maximum challenge lifetime: 24 hours. */
31
+ exports.MAX_CHALLENGE_TTL_MS = 24 * 60 * 60 * 1000;
32
+ function toHex(bytes) {
33
+ return Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join('');
34
+ }
35
+ function randomHex(bytes) {
36
+ const out = new Uint8Array(bytes);
37
+ if (typeof crypto === 'undefined' || !crypto.getRandomValues) {
38
+ throw new Error('SECURITY: crypto.getRandomValues unavailable — cannot generate secure random challenge');
39
+ }
40
+ crypto.getRandomValues(out);
41
+ return toHex(out);
42
+ }
43
+ /**
44
+ * Create a WorkChallenge.
45
+ *
46
+ * @param recipient The intended receiver the challenge binds to.
47
+ * @param domain Application domain (open-ended, e.g. "totem.compute.reserve").
48
+ * @param target Absolute 32-byte cryptographic target (hex).
49
+ * @param options Optional overrides (challengeId, nonce, ttl, issuedAt, network).
50
+ */
51
+ function createWorkChallenge(recipient, domain, target, options) {
52
+ if (!recipient)
53
+ throw new Error('WorkChallenge requires a recipient');
54
+ if (!domain)
55
+ throw new Error('WorkChallenge requires a domain');
56
+ if (!/^[0-9a-fA-F]{64}$/.test(target)) {
57
+ throw new Error('WorkChallenge target must be 32-byte hex (64 hex chars)');
58
+ }
59
+ const ttlMs = options?.ttlMs ?? exports.DEFAULT_CHALLENGE_TTL_MS;
60
+ if (ttlMs <= 0 || ttlMs > exports.MAX_CHALLENGE_TTL_MS) {
61
+ throw new Error(`WorkChallenge ttlMs must be in (0, ${exports.MAX_CHALLENGE_TTL_MS}]`);
62
+ }
63
+ const issuedAt = options?.issuedAt ?? Date.now();
64
+ const challengeId = options?.challengeId ?? randomHex(16);
65
+ const nonce = options?.nonce ?? randomHex(16);
66
+ return {
67
+ version: types_js_1.MACHINE_WORK_ADMISSION_VERSION,
68
+ challengeId,
69
+ recipient,
70
+ domain,
71
+ target,
72
+ nonce,
73
+ issuedAt,
74
+ expiresAt: issuedAt + ttlMs,
75
+ network: options?.network,
76
+ };
77
+ }
78
+ /**
79
+ * Validate a WorkChallenge at verification time.
80
+ *
81
+ * Checks structural integrity, expiry, and that the challenge binds to the
82
+ * expected recipient/domain. Does NOT check the proof hash — that is the
83
+ * caller's job via verifyWorkAdmission.
84
+ */
85
+ function validateWorkChallenge(challenge, expected) {
86
+ if (!challenge || typeof challenge !== 'object') {
87
+ return { valid: false, reason: 'challenge is not an object' };
88
+ }
89
+ if (challenge.version !== types_js_1.MACHINE_WORK_ADMISSION_VERSION) {
90
+ return { valid: false, reason: `unsupported challenge version ${challenge.version}` };
91
+ }
92
+ if (!challenge.challengeId) {
93
+ return { valid: false, reason: 'challenge is missing challengeId' };
94
+ }
95
+ if (!challenge.recipient) {
96
+ return { valid: false, reason: 'challenge is missing recipient' };
97
+ }
98
+ if (!challenge.domain) {
99
+ return { valid: false, reason: 'challenge is missing domain' };
100
+ }
101
+ if (!/^[0-9a-fA-F]{64}$/.test(challenge.target)) {
102
+ return { valid: false, reason: 'challenge target must be 32-byte hex' };
103
+ }
104
+ if (typeof challenge.issuedAt !== 'number' || typeof challenge.expiresAt !== 'number') {
105
+ return { valid: false, reason: 'challenge issuedAt/expiresAt must be numbers' };
106
+ }
107
+ const now = expected?.now ?? Date.now();
108
+ if (now > challenge.expiresAt) {
109
+ return { valid: false, reason: 'challenge has expired' };
110
+ }
111
+ if (now < challenge.issuedAt - 60000) {
112
+ return { valid: false, reason: 'challenge issuedAt is in the future' };
113
+ }
114
+ if (expected?.recipient && challenge.recipient !== expected.recipient) {
115
+ return { valid: false, reason: 'challenge recipient mismatch' };
116
+ }
117
+ if (expected?.domain && challenge.domain !== expected.domain) {
118
+ return { valid: false, reason: 'challenge domain mismatch' };
119
+ }
120
+ return { valid: true };
121
+ }
122
+ /**
123
+ * Derive a stable challenge fingerprint (SHA3-256 of canonical challenge bytes).
124
+ * Useful for higher-level code that tracks already-consumed challenge IDs.
125
+ */
126
+ function challengeFingerprint(challenge) {
127
+ const canonical = canonicalChallenge(challenge);
128
+ return toHex((0, core_1.sha3_256)(new TextEncoder().encode(canonical)));
129
+ }
130
+ /**
131
+ * Canonical serialization of a WorkChallenge.
132
+ *
133
+ * Deterministic field ordering with length-prefixed strings so that no
134
+ * ambiguous concatenation is possible. Used for the commitment and for
135
+ * challenge fingerprints.
136
+ */
137
+ function canonicalChallenge(challenge) {
138
+ const parts = [];
139
+ const push = (s) => {
140
+ parts.push(String(s.length).padStart(8, '0'));
141
+ parts.push(s);
142
+ };
143
+ push('totem.work-challenge');
144
+ push(String(challenge.version));
145
+ push(challenge.challengeId);
146
+ push(challenge.recipient);
147
+ push(challenge.domain);
148
+ push(challenge.target);
149
+ push(challenge.nonce);
150
+ push(String(challenge.issuedAt));
151
+ push(String(challenge.expiresAt));
152
+ if (challenge.network !== undefined)
153
+ push(challenge.network);
154
+ return parts.join('');
155
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * admission/commitment.ts — Canonical domain-separated action commitment.
3
+ *
4
+ * The commitment is a deterministic SHA3-256 over a length-prefixed canonical
5
+ * encoding of every security-relevant field. It changes if any of the
6
+ * following change:
7
+ * - protocol domain / version
8
+ * - action domain, sender, recipient, actionId, payloadHash, context
9
+ * - challenge challengeId, nonce, target, expiresAt
10
+ *
11
+ * The resulting 32-byte commitment is placed in the TxPoW header's customHash
12
+ * field, so the mined nonce commits the work to sender, recipient, action,
13
+ * challenge, target, and freshness.
14
+ */
15
+ import { type MachineWorkAction, type WorkChallenge } from './types.js';
16
+ /**
17
+ * Canonical serialization of a MachineWorkAction.
18
+ *
19
+ * Length-prefixed fields in a fixed order; context keys are sorted so that
20
+ * equivalent input produces identical output.
21
+ */
22
+ export declare function canonicalAction(action: MachineWorkAction): string;
23
+ /**
24
+ * Compute the canonical action commitment.
25
+ *
26
+ * commitment = SHA3-256(
27
+ * protocolDomain || protocolVersion ||
28
+ * canonicalAction(action) || canonicalChallenge(challenge)
29
+ * )
30
+ *
31
+ * @param action The application action.
32
+ * @param challenge The challenge the work is bound to.
33
+ */
34
+ export declare function computeActionCommitment(action: MachineWorkAction, challenge: WorkChallenge): string;
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ /**
3
+ * admission/commitment.ts — Canonical domain-separated action commitment.
4
+ *
5
+ * The commitment is a deterministic SHA3-256 over a length-prefixed canonical
6
+ * encoding of every security-relevant field. It changes if any of the
7
+ * following change:
8
+ * - protocol domain / version
9
+ * - action domain, sender, recipient, actionId, payloadHash, context
10
+ * - challenge challengeId, nonce, target, expiresAt
11
+ *
12
+ * The resulting 32-byte commitment is placed in the TxPoW header's customHash
13
+ * field, so the mined nonce commits the work to sender, recipient, action,
14
+ * challenge, target, and freshness.
15
+ */
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.canonicalAction = canonicalAction;
18
+ exports.computeActionCommitment = computeActionCommitment;
19
+ const core_1 = require("@totemsdk/core");
20
+ const types_js_1 = require("./types.js");
21
+ const challenge_js_1 = require("./challenge.js");
22
+ function toHex(bytes) {
23
+ return Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join('');
24
+ }
25
+ /**
26
+ * Canonical serialization of a MachineWorkAction.
27
+ *
28
+ * Length-prefixed fields in a fixed order; context keys are sorted so that
29
+ * equivalent input produces identical output.
30
+ */
31
+ function canonicalAction(action) {
32
+ const parts = [];
33
+ const push = (s) => {
34
+ parts.push(String(s.length).padStart(8, '0'));
35
+ parts.push(s);
36
+ };
37
+ push('totem.machine-work-action');
38
+ push(String(action.version));
39
+ push(action.domain);
40
+ push(action.sender);
41
+ push(action.recipient);
42
+ push(action.actionId);
43
+ push(action.payloadHash);
44
+ if (action.context) {
45
+ const keys = Object.keys(action.context).sort();
46
+ for (const key of keys) {
47
+ push(key);
48
+ push(action.context[key]);
49
+ }
50
+ }
51
+ return parts.join('');
52
+ }
53
+ /**
54
+ * Compute the canonical action commitment.
55
+ *
56
+ * commitment = SHA3-256(
57
+ * protocolDomain || protocolVersion ||
58
+ * canonicalAction(action) || canonicalChallenge(challenge)
59
+ * )
60
+ *
61
+ * @param action The application action.
62
+ * @param challenge The challenge the work is bound to.
63
+ */
64
+ function computeActionCommitment(action, challenge) {
65
+ const input = types_js_1.MACHINE_WORK_DOMAIN +
66
+ '|' +
67
+ String(types_js_1.MACHINE_WORK_ADMISSION_VERSION) +
68
+ '|' +
69
+ canonicalAction(action) +
70
+ '|' +
71
+ (0, challenge_js_1.canonicalChallenge)(challenge);
72
+ return toHex((0, core_1.sha3_256)(new TextEncoder().encode(input)));
73
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * admission/index.ts — Machine Work Admission public surface.
3
+ *
4
+ * Machine Work Admission allows applications to require computational proof
5
+ * before allocating scarce resources. The work is performed against a Minima
6
+ * block candidate so that application anti-spam work simultaneously searches
7
+ * for valid Minima L1 blocks.
8
+ */
9
+ export { createWorkChallenge, validateWorkChallenge, challengeFingerprint, canonicalChallenge, DEFAULT_CHALLENGE_TTL_MS, MAX_CHALLENGE_TTL_MS, } from './challenge.js';
10
+ export { computeActionCommitment, canonicalAction, } from './commitment.js';
11
+ export { mineWorkAdmission, type MineWorkAdmissionOptions, } from './mine.js';
12
+ export { verifyWorkAdmission, type VerifyWorkAdmissionOptions, } from './verify.js';
13
+ export { buildBlockHeaderTail, serializeSuperParents, isBlockWinner, computeSuperLevel, templateFreshness, computeBlockCandidateId, buildEmptyBlockBody, buildEmptyTransactionBytes, buildEmptyWitnessBytes, buildEmptyBurnTxBytes, buildEmptyBurnWitnessBytes, assembleTxPoWEnvelope, reconstructTxPoWEnvelope, } from './template.js';
14
+ export { MACHINE_WORK_ADMISSION_VERSION, MACHINE_WORK_DOMAIN, type WorkChallenge, type MachineWorkAction, type MinimaWorkTemplate, type MinimaWorkTemplateProvider, type MinimaWorkRelay, type MachineWorkAdmissionProof, type WorkAdmissionVerification, } from './types.js';
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ /**
3
+ * admission/index.ts — Machine Work Admission public surface.
4
+ *
5
+ * Machine Work Admission allows applications to require computational proof
6
+ * before allocating scarce resources. The work is performed against a Minima
7
+ * block candidate so that application anti-spam work simultaneously searches
8
+ * for valid Minima L1 blocks.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.MACHINE_WORK_DOMAIN = exports.MACHINE_WORK_ADMISSION_VERSION = exports.reconstructTxPoWEnvelope = exports.assembleTxPoWEnvelope = exports.buildEmptyBurnWitnessBytes = exports.buildEmptyBurnTxBytes = exports.buildEmptyWitnessBytes = exports.buildEmptyTransactionBytes = exports.buildEmptyBlockBody = exports.computeBlockCandidateId = exports.templateFreshness = exports.computeSuperLevel = exports.isBlockWinner = exports.serializeSuperParents = exports.buildBlockHeaderTail = exports.verifyWorkAdmission = exports.mineWorkAdmission = exports.canonicalAction = exports.computeActionCommitment = exports.MAX_CHALLENGE_TTL_MS = exports.DEFAULT_CHALLENGE_TTL_MS = exports.canonicalChallenge = exports.challengeFingerprint = exports.validateWorkChallenge = exports.createWorkChallenge = void 0;
12
+ var challenge_js_1 = require("./challenge.js");
13
+ Object.defineProperty(exports, "createWorkChallenge", { enumerable: true, get: function () { return challenge_js_1.createWorkChallenge; } });
14
+ Object.defineProperty(exports, "validateWorkChallenge", { enumerable: true, get: function () { return challenge_js_1.validateWorkChallenge; } });
15
+ Object.defineProperty(exports, "challengeFingerprint", { enumerable: true, get: function () { return challenge_js_1.challengeFingerprint; } });
16
+ Object.defineProperty(exports, "canonicalChallenge", { enumerable: true, get: function () { return challenge_js_1.canonicalChallenge; } });
17
+ Object.defineProperty(exports, "DEFAULT_CHALLENGE_TTL_MS", { enumerable: true, get: function () { return challenge_js_1.DEFAULT_CHALLENGE_TTL_MS; } });
18
+ Object.defineProperty(exports, "MAX_CHALLENGE_TTL_MS", { enumerable: true, get: function () { return challenge_js_1.MAX_CHALLENGE_TTL_MS; } });
19
+ var commitment_js_1 = require("./commitment.js");
20
+ Object.defineProperty(exports, "computeActionCommitment", { enumerable: true, get: function () { return commitment_js_1.computeActionCommitment; } });
21
+ Object.defineProperty(exports, "canonicalAction", { enumerable: true, get: function () { return commitment_js_1.canonicalAction; } });
22
+ var mine_js_1 = require("./mine.js");
23
+ Object.defineProperty(exports, "mineWorkAdmission", { enumerable: true, get: function () { return mine_js_1.mineWorkAdmission; } });
24
+ var verify_js_1 = require("./verify.js");
25
+ Object.defineProperty(exports, "verifyWorkAdmission", { enumerable: true, get: function () { return verify_js_1.verifyWorkAdmission; } });
26
+ var template_js_1 = require("./template.js");
27
+ Object.defineProperty(exports, "buildBlockHeaderTail", { enumerable: true, get: function () { return template_js_1.buildBlockHeaderTail; } });
28
+ Object.defineProperty(exports, "serializeSuperParents", { enumerable: true, get: function () { return template_js_1.serializeSuperParents; } });
29
+ Object.defineProperty(exports, "isBlockWinner", { enumerable: true, get: function () { return template_js_1.isBlockWinner; } });
30
+ Object.defineProperty(exports, "computeSuperLevel", { enumerable: true, get: function () { return template_js_1.computeSuperLevel; } });
31
+ Object.defineProperty(exports, "templateFreshness", { enumerable: true, get: function () { return template_js_1.templateFreshness; } });
32
+ Object.defineProperty(exports, "computeBlockCandidateId", { enumerable: true, get: function () { return template_js_1.computeBlockCandidateId; } });
33
+ Object.defineProperty(exports, "buildEmptyBlockBody", { enumerable: true, get: function () { return template_js_1.buildEmptyBlockBody; } });
34
+ Object.defineProperty(exports, "buildEmptyTransactionBytes", { enumerable: true, get: function () { return template_js_1.buildEmptyTransactionBytes; } });
35
+ Object.defineProperty(exports, "buildEmptyWitnessBytes", { enumerable: true, get: function () { return template_js_1.buildEmptyWitnessBytes; } });
36
+ Object.defineProperty(exports, "buildEmptyBurnTxBytes", { enumerable: true, get: function () { return template_js_1.buildEmptyBurnTxBytes; } });
37
+ Object.defineProperty(exports, "buildEmptyBurnWitnessBytes", { enumerable: true, get: function () { return template_js_1.buildEmptyBurnWitnessBytes; } });
38
+ Object.defineProperty(exports, "assembleTxPoWEnvelope", { enumerable: true, get: function () { return template_js_1.assembleTxPoWEnvelope; } });
39
+ Object.defineProperty(exports, "reconstructTxPoWEnvelope", { enumerable: true, get: function () { return template_js_1.reconstructTxPoWEnvelope; } });
40
+ var types_js_1 = require("./types.js");
41
+ Object.defineProperty(exports, "MACHINE_WORK_ADMISSION_VERSION", { enumerable: true, get: function () { return types_js_1.MACHINE_WORK_ADMISSION_VERSION; } });
42
+ Object.defineProperty(exports, "MACHINE_WORK_DOMAIN", { enumerable: true, get: function () { return types_js_1.MACHINE_WORK_DOMAIN; } });
@@ -0,0 +1,60 @@
1
+ /**
2
+ * admission/mine.ts — Machine Work Admission mining.
3
+ *
4
+ * Mines a real Minima block candidate whose customHash commits to the machine
5
+ * action. The mining loop reuses the existing TxPoW mining loop
6
+ * (`mineHeaderTail` from ../mine.js) — the same SHA3-256 nonce search that
7
+ * Minima uses for transaction/block mining.
8
+ *
9
+ * The admission target is ALWAYS `challenge.target` — the challenge is the
10
+ * single source of truth. There is no separate admission target argument.
11
+ *
12
+ * Two thresholds:
13
+ * - admission target (receiver-chosen, easier): hash < challenge.target
14
+ * - L1 block target (current Minima block difficulty): hash < blockTarget
15
+ *
16
+ * The loop stops as soon as the admission target is satisfied, unless the same
17
+ * search already discovered a block-target winner. Ordinary admission proofs
18
+ * stay off-chain; only genuine L1 winners are broadcast via the injected
19
+ * template provider.
20
+ */
21
+ import { type MachineWorkAction, type MachineWorkAdmissionProof, type MinimaWorkRelay, type MinimaWorkTemplateProvider, type WorkChallenge } from './types.js';
22
+ export interface MineWorkAdmissionOptions {
23
+ /** AbortSignal — rejects the Promise when aborted. */
24
+ signal?: AbortSignal;
25
+ /** Hard cap on total iterations (default: unlimited). */
26
+ maxIterations?: number;
27
+ /** Hash iterations per async yield (default: 10_000). */
28
+ chunkSize?: number;
29
+ /** Override the template timeMilli for deterministic testing. */
30
+ timeMilli?: bigint;
31
+ /** Force the pure-JS mining path (for testing). */
32
+ forceJs?: boolean;
33
+ /** Skip the Node.js worker_threads Worker (for testing). */
34
+ _skipWorker?: boolean;
35
+ /**
36
+ * Deterministic 32-byte PRNG for the TxBody (testing only). When omitted a
37
+ * cryptographically random PRNG is generated.
38
+ */
39
+ prng?: Uint8Array;
40
+ /**
41
+ * Preferred Minima block relay boundary. When supplied, a genuine current
42
+ * Minima block is submitted through the relay exactly once. Falls back to
43
+ * the deprecated provider.broadcastBlockCandidate only when no relay is set.
44
+ */
45
+ relay?: MinimaWorkRelay;
46
+ }
47
+ /**
48
+ * Mine a Machine Work Admission proof.
49
+ *
50
+ * The admission target is derived from `challenge.target` — the challenge is
51
+ * the single authoritative source. The miner searches the nonce space of a
52
+ * real Minima block candidate (from the injected template provider) whose
53
+ * customHash commits to the action.
54
+ *
55
+ * @param action The application action.
56
+ * @param challenge The receiver-issued challenge (target is authoritative).
57
+ * @param templateProvider Injected provider for the current Minima template.
58
+ * @param options Mining options.
59
+ */
60
+ export declare function mineWorkAdmission(action: MachineWorkAction, challenge: WorkChallenge, templateProvider: MinimaWorkTemplateProvider, options?: MineWorkAdmissionOptions): Promise<MachineWorkAdmissionProof>;