functionalscript 0.24.0 → 0.26.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/fs/asserts/proof.f.d.ts +8 -0
- package/fs/asserts/proof.f.js +51 -0
- package/fs/bnf/data/proof.f.js +7 -17
- package/fs/bnf/module.f.d.ts +10 -0
- package/fs/bnf/module.f.js +10 -0
- package/fs/bnf/testlib.f.js +4 -9
- package/fs/cas/module.f.d.ts +2 -10
- package/fs/cas/module.f.js +48 -52
- package/fs/cas/proof.f.js +21 -12
- package/fs/ci/common/module.f.d.ts +2 -0
- package/fs/ci/common/module.f.js +4 -1
- package/fs/ci/config/module.f.d.ts +2 -2
- package/fs/ci/config/module.f.js +2 -2
- package/fs/ci/module.f.d.ts +2 -4
- package/fs/ci/module.f.js +11 -9
- package/fs/ci/node/module.f.js +4 -2
- package/fs/ci/proof.f.js +8 -5
- package/fs/cli/module.f.d.ts +9 -0
- package/fs/cli/module.f.js +24 -0
- package/fs/cli/proof.f.d.ts +9 -0
- package/fs/cli/proof.f.js +86 -0
- package/fs/crypto/sha2/module.f.js +32 -36
- package/fs/crypto/vdf/module.f.d.ts +21 -0
- package/fs/crypto/vdf/module.f.js +57 -0
- package/fs/crypto/vdf/proof.f.d.ts +32 -0
- package/fs/crypto/vdf/proof.f.js +135 -0
- package/fs/dev/index/module.f.d.ts +1 -8
- package/fs/dev/index/module.f.js +1 -1
- package/fs/effects/node/module.f.d.ts +1 -1
- package/fs/emergent_testing/module.f.d.ts +1 -1
- package/fs/emergent_testing/module.f.js +2 -2
- package/fs/emergent_testing/proof.f.js +1 -1
- package/fs/fjs/module.f.js +34 -24
- package/fs/json/module.f.d.ts +25 -9
- package/fs/json/module.f.js +25 -3
- package/fs/json/rpc/module.f.d.ts +109 -0
- package/fs/json/rpc/module.f.js +84 -0
- package/fs/json/rpc/proof.f.d.ts +35 -0
- package/fs/json/rpc/proof.f.js +68 -0
- package/fs/json/schema/module.f.d.ts +76 -0
- package/fs/json/schema/module.f.js +112 -0
- package/fs/json/schema/proof.f.d.ts +33 -0
- package/fs/json/schema/proof.f.js +71 -0
- package/fs/mcp/module.f.d.ts +88 -0
- package/fs/mcp/module.f.js +69 -0
- package/fs/sul/level/literal/proof.f.d.ts +1 -0
- package/fs/sul/level/literal/proof.f.js +6 -0
- package/fs/types/array/module.f.d.ts +7 -0
- package/fs/types/array/module.f.js +7 -0
- package/fs/types/prime_field/module.f.d.ts +8 -0
- package/fs/types/prime_field/module.f.js +37 -5
- package/fs/types/prime_field/proof.f.d.ts +3 -0
- package/fs/types/prime_field/proof.f.js +27 -2
- package/fs/types/rtti/parse/module.f.d.ts +28 -0
- package/fs/types/rtti/parse/module.f.js +35 -5
- package/fs/types/rtti/ts/module.f.d.ts +46 -3
- package/fs/types/rtti/validate/module.f.js +5 -0
- package/fs/website/module.f.d.ts +1 -2
- package/fs/website/module.f.js +1 -1
- package/fs/website/proof.f.d.ts +1 -1
- package/fs/website/proof.f.js +3 -3
- package/package.json +4 -4
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { pure } from "../effects/module.f.js";
|
|
2
|
+
import {} from "../effects/node/module.f.js";
|
|
3
|
+
import { emptyState, virtual } from "../effects/node/virtual/module.f.js";
|
|
4
|
+
import { dispatch } from "./module.f.js";
|
|
5
|
+
const makeOptions = (args) => ({
|
|
6
|
+
args,
|
|
7
|
+
env: {},
|
|
8
|
+
std: { stdout: { isTTY: false }, stderr: { isTTY: false } },
|
|
9
|
+
testContext: { test: async () => { } },
|
|
10
|
+
bunTestContext: { test: async () => { } },
|
|
11
|
+
playwrightTestContext: { test: async () => { } },
|
|
12
|
+
engine: 'node',
|
|
13
|
+
});
|
|
14
|
+
const echoCommands = [
|
|
15
|
+
{
|
|
16
|
+
names: ['echo', 'e'],
|
|
17
|
+
description: 'Print the first argument',
|
|
18
|
+
handler: ({ args: [arg = ''] }) => pure(arg.length),
|
|
19
|
+
},
|
|
20
|
+
];
|
|
21
|
+
const run = (commands) => (args) => virtual(emptyState)(dispatch(commands)(makeOptions(args)));
|
|
22
|
+
export const proof = {
|
|
23
|
+
knownCommand: () => {
|
|
24
|
+
const [, code] = run(echoCommands)(['echo', 'hello']);
|
|
25
|
+
if (code !== 5) {
|
|
26
|
+
throw ['expected length 5', code];
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
alias: () => {
|
|
30
|
+
const [, code] = run(echoCommands)(['e', 'hi']);
|
|
31
|
+
if (code !== 2) {
|
|
32
|
+
throw ['expected length 2', code];
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
noArgs: () => {
|
|
36
|
+
const [state, code] = run(echoCommands)([]);
|
|
37
|
+
if (code !== 1) {
|
|
38
|
+
throw ['expected exit 1', code];
|
|
39
|
+
}
|
|
40
|
+
if (state.stderr.length === 0) {
|
|
41
|
+
throw 'expected error in stderr';
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
unknownCommand: () => {
|
|
45
|
+
const [state, code] = run(echoCommands)(['bogus']);
|
|
46
|
+
if (code !== 1) {
|
|
47
|
+
throw ['expected exit 1', code];
|
|
48
|
+
}
|
|
49
|
+
if (state.stderr.length === 0) {
|
|
50
|
+
throw 'expected error in stderr';
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
help: () => {
|
|
54
|
+
const [state, code] = run(echoCommands)(['help']);
|
|
55
|
+
if (code !== 0) {
|
|
56
|
+
throw ['expected exit 0', code];
|
|
57
|
+
}
|
|
58
|
+
if (!state.stdout.includes('echo')) {
|
|
59
|
+
throw 'expected command name in stdout';
|
|
60
|
+
}
|
|
61
|
+
if (!state.stdout.includes('help')) {
|
|
62
|
+
throw 'expected help entry in stdout';
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
errorIncludesAvailable: () => {
|
|
66
|
+
const [state] = run(echoCommands)(['bogus']);
|
|
67
|
+
if (!state.stderr.includes('echo')) {
|
|
68
|
+
throw 'expected available commands in error';
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
handlerReceivesRemainingArgs: () => {
|
|
72
|
+
const captured = [];
|
|
73
|
+
const commands = [{
|
|
74
|
+
names: ['grab'],
|
|
75
|
+
description: 'Capture args',
|
|
76
|
+
handler: ({ args }) => {
|
|
77
|
+
captured.push(...args);
|
|
78
|
+
return pure(0);
|
|
79
|
+
},
|
|
80
|
+
}];
|
|
81
|
+
run(commands)(['grab', 'a', 'b', 'c']);
|
|
82
|
+
if (captured.join(',') !== 'a,b,c') {
|
|
83
|
+
throw ['unexpected args', captured];
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
};
|
|
@@ -9,47 +9,43 @@ const base = ({ logBitLen, k, bs0, bs1, ss0, ss1 }) => {
|
|
|
9
9
|
const r = bitLength - d;
|
|
10
10
|
return (n) => n >> d | n << r;
|
|
11
11
|
};
|
|
12
|
-
const
|
|
12
|
+
const sigma = third => (a, b, c) => {
|
|
13
13
|
const ra = rotr(a);
|
|
14
14
|
const rb = rotr(b);
|
|
15
|
-
const rc =
|
|
16
|
-
return
|
|
15
|
+
const rc = third(c);
|
|
16
|
+
return x => ra(x) ^ rb(x) ^ rc(x);
|
|
17
17
|
};
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
};
|
|
25
|
-
const smallSigma0 = smallSigma(ss0);
|
|
26
|
-
const smallSigma1 = smallSigma(ss1);
|
|
18
|
+
const bigSigma = sigma(rotr);
|
|
19
|
+
const smallSigma = sigma(c => x => x >> c);
|
|
20
|
+
const bigSigma0 = bigSigma(...bs0);
|
|
21
|
+
const bigSigma1 = bigSigma(...bs1);
|
|
22
|
+
const smallSigma0 = smallSigma(...ss0);
|
|
23
|
+
const smallSigma1 = smallSigma(...ss1);
|
|
27
24
|
const ch = (x, y, z) => x & y ^ ~x & z;
|
|
28
25
|
const maj = (x, y, z) => x & y ^ x & z ^ y & z;
|
|
29
26
|
const m = mask(bitLength);
|
|
30
|
-
const wi = (
|
|
31
|
-
const nextW = (
|
|
32
|
-
w0 = wi(
|
|
33
|
-
w1 = wi(
|
|
34
|
-
w2 = wi(
|
|
35
|
-
w3 = wi(
|
|
36
|
-
w4 = wi(
|
|
37
|
-
w5 = wi(
|
|
38
|
-
w6 = wi(
|
|
39
|
-
w7 = wi(
|
|
40
|
-
w8 = wi(
|
|
41
|
-
w9 = wi(
|
|
42
|
-
wA = wi(
|
|
43
|
-
wB = wi(
|
|
44
|
-
wC = wi(
|
|
45
|
-
wD = wi(
|
|
46
|
-
wE = wi(
|
|
47
|
-
wF = wi(
|
|
27
|
+
const wi = (a0, a1, a2, a3) => (smallSigma1(a0) + a1 + smallSigma0(a2) + a3) & m;
|
|
28
|
+
const nextW = (w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, wA, wB, wC, wD, wE, wF) => {
|
|
29
|
+
w0 = wi(wE, w9, w1, w0);
|
|
30
|
+
w1 = wi(wF, wA, w2, w1);
|
|
31
|
+
w2 = wi(w0, wB, w3, w2);
|
|
32
|
+
w3 = wi(w1, wC, w4, w3);
|
|
33
|
+
w4 = wi(w2, wD, w5, w4);
|
|
34
|
+
w5 = wi(w3, wE, w6, w5);
|
|
35
|
+
w6 = wi(w4, wF, w7, w6);
|
|
36
|
+
w7 = wi(w5, w0, w8, w7);
|
|
37
|
+
w8 = wi(w6, w1, w9, w8);
|
|
38
|
+
w9 = wi(w7, w2, wA, w9);
|
|
39
|
+
wA = wi(w8, w3, wB, wA);
|
|
40
|
+
wB = wi(w9, w4, wC, wB);
|
|
41
|
+
wC = wi(wA, w5, wD, wC);
|
|
42
|
+
wD = wi(wB, w6, wE, wD);
|
|
43
|
+
wE = wi(wC, w7, wF, wE);
|
|
44
|
+
wF = wi(wD, w8, w0, wF);
|
|
48
45
|
return [w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, wA, wB, wC, wD, wE, wF];
|
|
49
46
|
};
|
|
50
47
|
const kLength = k.length;
|
|
51
|
-
const compressV16 = (
|
|
52
|
-
let w = data;
|
|
48
|
+
const compressV16 = (a0, b0, c0, d0, e0, f0, g0, h0) => w => {
|
|
53
49
|
let a = a0;
|
|
54
50
|
let b = b0;
|
|
55
51
|
let c = c0;
|
|
@@ -77,7 +73,7 @@ const base = ({ logBitLen, k, bs0, bs1, ss0, ss1 }) => {
|
|
|
77
73
|
if (i === kLength) {
|
|
78
74
|
break;
|
|
79
75
|
}
|
|
80
|
-
w = nextW(w);
|
|
76
|
+
w = nextW(...w);
|
|
81
77
|
}
|
|
82
78
|
return [
|
|
83
79
|
(a0 + a) & m,
|
|
@@ -90,10 +86,10 @@ const base = ({ logBitLen, k, bs0, bs1, ss0, ss1 }) => {
|
|
|
90
86
|
(h0 + h) & m,
|
|
91
87
|
];
|
|
92
88
|
};
|
|
93
|
-
const at =
|
|
94
|
-
const compress =
|
|
89
|
+
const at = u => i => (u >> (i << logBitLen)) & m;
|
|
90
|
+
const compress = i => u => {
|
|
95
91
|
const a = at(u);
|
|
96
|
-
return compressV16(i)([
|
|
92
|
+
return compressV16(...i)([
|
|
97
93
|
a(15n),
|
|
98
94
|
a(14n),
|
|
99
95
|
a(13n),
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Nullable } from '../../types/nullable/module.f.ts';
|
|
2
|
+
/** Sloth VDF modulus (3072-bit safe prime, same as reference implementations). */
|
|
3
|
+
export declare const p = 170082004324204494273811327264862981553264701145937538369570764779791492622392118654022654452947093285873855529044371650895045691292912712699015605832276411308653107069798639938826015099738961427172366594187783204437869906954750443653318078358839409699824714551430573905637228307966826784684174483831608534979n;
|
|
4
|
+
/**
|
|
5
|
+
* Sloth VDF over prime `modulus` (`p ≡ 3 (mod 4)`).
|
|
6
|
+
*/
|
|
7
|
+
export type Sloth = {
|
|
8
|
+
readonly p: bigint;
|
|
9
|
+
readonly quadRes: (x: bigint) => boolean;
|
|
10
|
+
readonly modSqrt: (x: bigint) => bigint;
|
|
11
|
+
/** Sequential Sloth permutation; `null` when `steps < 0`. */
|
|
12
|
+
readonly eval: (steps: bigint) => (x: bigint) => Nullable<bigint>;
|
|
13
|
+
/** Fast verification of {@link Sloth.eval}; `false` when `steps < 0`. */
|
|
14
|
+
readonly verify: (steps: bigint) => (x: bigint) => (y: bigint) => boolean;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Builds Sloth VDF operations over `modulus`.
|
|
18
|
+
*/
|
|
19
|
+
export declare const sloth_vdf: (modulus: bigint) => Sloth;
|
|
20
|
+
/** Sloth VDF over {@link p}. */
|
|
21
|
+
export declare const sloth: Sloth;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sloth verifiable delay function over a fixed 3072-bit safe prime.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { sloth } from './module.f.ts'
|
|
10
|
+
*
|
|
11
|
+
* const steps = 4n
|
|
12
|
+
* const x = 42n
|
|
13
|
+
* const y = sloth.eval(steps)(x)
|
|
14
|
+
* if (y === null || !sloth.verify(steps)(x)(y)) { throw y }
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
import { modSqrt, prime_field } from "../../types/prime_field/module.f.js";
|
|
18
|
+
/** Sloth VDF modulus (3072-bit safe prime, same as reference implementations). */
|
|
19
|
+
export const p = 0xf2346eae06a233882814ff16f6a076d3b8f2161c5c92171c0b7b84eed4e9475bcce0c13bde34512afdf90f41ab9b86dcf834f85e04b27fadee712eed23a1d4e58cd1b09d9bfb10696d614f119179a40c49dc8762edc29e8115263913237e14718cbcd4dc6b35bace13f8cdb1b5156c50c47b4aaee0820c874e2864cb854367c3n;
|
|
20
|
+
const repeatSeq = (steps) => (f) => (value) => {
|
|
21
|
+
let v = value;
|
|
22
|
+
let i = 0n;
|
|
23
|
+
while (i < steps) {
|
|
24
|
+
v = f(v);
|
|
25
|
+
i = i + 1n;
|
|
26
|
+
}
|
|
27
|
+
return v;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Builds Sloth VDF operations over `modulus`.
|
|
31
|
+
*/
|
|
32
|
+
export const sloth_vdf = (modulus) => {
|
|
33
|
+
const field = prime_field(modulus);
|
|
34
|
+
const { neg, pow2, reduce, quadRes } = field;
|
|
35
|
+
const root = modSqrt(field);
|
|
36
|
+
const squareLoop = (steps) => (value) => repeatSeq(steps)(pow2)(reduce(value));
|
|
37
|
+
const modSqrtLoop = (steps) => (value) => repeatSeq(steps)(root)(reduce(value));
|
|
38
|
+
const evalSteps = (steps) => (x) => steps < 0n ? null : modSqrtLoop(steps)(x);
|
|
39
|
+
const verifySteps = (steps) => (x) => (y) => {
|
|
40
|
+
if (steps < 0n) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
const input = reduce(x);
|
|
44
|
+
const squared = squareLoop(steps)(y);
|
|
45
|
+
const value = quadRes(squared) ? squared : neg(squared);
|
|
46
|
+
return input === value || neg(input) === value;
|
|
47
|
+
};
|
|
48
|
+
return {
|
|
49
|
+
p: modulus,
|
|
50
|
+
quadRes,
|
|
51
|
+
modSqrt: root,
|
|
52
|
+
eval: evalSteps,
|
|
53
|
+
verify: verifySteps,
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
/** Sloth VDF over {@link p}. */
|
|
57
|
+
export const sloth = sloth_vdf(p);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export declare const proof: {
|
|
2
|
+
p: {
|
|
3
|
+
matchesField: () => void;
|
|
4
|
+
};
|
|
5
|
+
eval: {
|
|
6
|
+
steps100: () => void;
|
|
7
|
+
steps10: () => void;
|
|
8
|
+
steps6: () => void;
|
|
9
|
+
steps4: () => void;
|
|
10
|
+
zeroSteps: () => void;
|
|
11
|
+
negativeSteps: () => void;
|
|
12
|
+
};
|
|
13
|
+
verify: {
|
|
14
|
+
steps100: () => void;
|
|
15
|
+
steps10: () => void;
|
|
16
|
+
steps6: () => void;
|
|
17
|
+
steps4: () => void;
|
|
18
|
+
tampered: () => void;
|
|
19
|
+
wrongY: () => void;
|
|
20
|
+
zeroSteps: () => void;
|
|
21
|
+
negativeSteps: () => void;
|
|
22
|
+
invalidY: () => void;
|
|
23
|
+
};
|
|
24
|
+
modSqrt: {
|
|
25
|
+
roundTrip: () => void;
|
|
26
|
+
nonResidue: () => void;
|
|
27
|
+
};
|
|
28
|
+
quadRes: {
|
|
29
|
+
one: () => void;
|
|
30
|
+
nonResidue: () => void;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { sloth, p } from "./module.f.js";
|
|
2
|
+
const { eval: evalVdf, verify, modSqrt, quadRes } = sloth;
|
|
3
|
+
// `eval(steps)(x)` expected values for {@link p}; same Sloth algorithm as
|
|
4
|
+
// https://github.com/hyperhyperspace/pulsar/blob/main/src/model/SlothVDF.ts and
|
|
5
|
+
// https://github.com/jose-compu/dignity.js/blob/main/src/security/sloth-vdf.js
|
|
6
|
+
const sampleX = 123456789n;
|
|
7
|
+
const largeX = 12345678901234567890n;
|
|
8
|
+
const smallX = 42n;
|
|
9
|
+
const nonResidue = 2n;
|
|
10
|
+
const sampleY = 72412151236937799598582816305571618206681207952550127764586725290711141789888684237028784568532880529360450375677852568362636821341317217048062977639333459511661887862128325859969604061461913896412260750881385045152117694320409864730924775539555636460819549547999218170813228857928921642957426089461925313163n;
|
|
11
|
+
const smallY = 145151597037272685697451525487035431973338817762329243361437778785747534269376083577375382484815474368317818719265551745910148543423765263685177263740373969289084400977118144482329577335929842301331443392042760708529572252015473334998752211959790788326970269713683808382892472572910797612141527200051803670965n;
|
|
12
|
+
const y6 = 116287514643100261336025249676072556421566393377742705567032370320583145555855278910304225489766306768040386612082033279417845047304479679877515174322332386599890348932893235091525789175564701751964775040887336849457197662999383850490808701700264064812615988837073981567599117932005435532913423970502774287312n;
|
|
13
|
+
const y4 = 64401150265223443694244964595084197237814157534040219819342647664782563317539559768554855806938965782018778040933157632467146168153951260465261118025222264314070274636967492909984790708532033331622332323767105919809000393624013423095812833452440384602112677364631962445309757177309466319657219548312354433189n;
|
|
14
|
+
export const proof = {
|
|
15
|
+
p: {
|
|
16
|
+
matchesField: () => {
|
|
17
|
+
if (sloth.p !== p) {
|
|
18
|
+
throw [sloth.p, p];
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
eval: {
|
|
23
|
+
steps100: () => {
|
|
24
|
+
const y = evalVdf(100n)(sampleX);
|
|
25
|
+
if (y !== sampleY) {
|
|
26
|
+
throw [y, sampleY];
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
steps10: () => {
|
|
30
|
+
const y = evalVdf(10n)(smallX);
|
|
31
|
+
if (y !== smallY) {
|
|
32
|
+
throw [y, smallY];
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
steps6: () => {
|
|
36
|
+
const y = evalVdf(6n)(largeX);
|
|
37
|
+
if (y !== y6) {
|
|
38
|
+
throw [y, y6];
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
steps4: () => {
|
|
42
|
+
const y = evalVdf(4n)(smallX);
|
|
43
|
+
if (y !== y4) {
|
|
44
|
+
throw [y, y4];
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
zeroSteps: () => {
|
|
48
|
+
const y = evalVdf(0n)(sampleX);
|
|
49
|
+
if (y !== sampleX % p) {
|
|
50
|
+
throw [y, sampleX % p];
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
negativeSteps: () => {
|
|
54
|
+
const y = evalVdf(-1n)(sampleX);
|
|
55
|
+
if (y !== null) {
|
|
56
|
+
throw y;
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
verify: {
|
|
61
|
+
steps100: () => {
|
|
62
|
+
if (!verify(100n)(sampleX)(sampleY)) {
|
|
63
|
+
throw false;
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
steps10: () => {
|
|
67
|
+
if (!verify(10n)(smallX)(smallY)) {
|
|
68
|
+
throw false;
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
steps6: () => {
|
|
72
|
+
if (!verify(6n)(largeX)(y6)) {
|
|
73
|
+
throw false;
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
steps4: () => {
|
|
77
|
+
if (!verify(4n)(smallX)(y4)) {
|
|
78
|
+
throw false;
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
tampered: () => {
|
|
82
|
+
if (verify(4n)(smallX)((y4 + 1n) % p)) {
|
|
83
|
+
throw (y4 + 1n) % p;
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
wrongY: () => {
|
|
87
|
+
if (verify(100n)(sampleX)(sampleY + 1n)) {
|
|
88
|
+
throw sampleY + 1n;
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
zeroSteps: () => {
|
|
92
|
+
if (!verify(0n)(sampleX)(sampleX % p)) {
|
|
93
|
+
throw [sampleX % p];
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
negativeSteps: () => {
|
|
97
|
+
if (verify(-1n)(sampleX)(sampleY)) {
|
|
98
|
+
throw sampleY;
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
invalidY: () => {
|
|
102
|
+
if (verify(100n)(sampleX)(0n)) {
|
|
103
|
+
throw 0n;
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
modSqrt: {
|
|
108
|
+
roundTrip: () => {
|
|
109
|
+
const x = 999n;
|
|
110
|
+
if (!verify(1n)(x)(modSqrt(x))) {
|
|
111
|
+
throw modSqrt(x);
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
nonResidue: () => {
|
|
115
|
+
if (quadRes(nonResidue)) {
|
|
116
|
+
throw nonResidue;
|
|
117
|
+
}
|
|
118
|
+
if (!verify(1n)(nonResidue)(modSqrt(nonResidue))) {
|
|
119
|
+
throw modSqrt(nonResidue);
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
quadRes: {
|
|
124
|
+
one: () => {
|
|
125
|
+
if (!quadRes(1n)) {
|
|
126
|
+
throw 1n;
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
nonResidue: () => {
|
|
130
|
+
if (quadRes(nonResidue)) {
|
|
131
|
+
throw nonResidue;
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
};
|
|
@@ -1,8 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* Entry point for the `index` developer program: re-exports `index4` from the
|
|
3
|
-
* parent `dev` module as the default `NodeProgram`.
|
|
4
|
-
*
|
|
5
|
-
* @module
|
|
6
|
-
*/
|
|
7
|
-
import { index4 } from '../module.f.ts';
|
|
8
|
-
export default index4;
|
|
1
|
+
export declare const main: import("../../effects/node/module.f.ts").NodeProgram;
|
package/fs/dev/index/module.f.js
CHANGED
|
@@ -166,7 +166,7 @@ export type NodeEffect<T> = Effect<NodeOp, T>;
|
|
|
166
166
|
* "fail with a message" program for a `NodeProgram`. For non-`1` exit codes,
|
|
167
167
|
* compose `error(s).step(() => pure(n))` directly.
|
|
168
168
|
*/
|
|
169
|
-
export declare const errorExit: (s: string) => Effect<
|
|
169
|
+
export declare const errorExit: (s: string) => Effect<Write, number>;
|
|
170
170
|
export type NodeOperationMap = ToAsyncOperationMap<NodeOp>;
|
|
171
171
|
/**
|
|
172
172
|
* The environment variables.
|
|
@@ -117,7 +117,7 @@ export declare const defaultTest: (file: string, path: Path, { fn, throws }: Tes
|
|
|
117
117
|
/**
|
|
118
118
|
* The terminal/GitHub reporter used by `fjs t`. Output goes through
|
|
119
119
|
* `csiWrite`, so ANSI styles are stripped on non-TTY streams. When
|
|
120
|
-
* `
|
|
120
|
+
* `GITHUB_ACTIONS` is set, failures are emitted as `::error` workflow
|
|
121
121
|
* annotations instead of colored lines. Exported as a factory so the
|
|
122
122
|
* GitHub format path can be exercised directly from tests.
|
|
123
123
|
*/
|
|
@@ -220,7 +220,7 @@ const fmtResultLine = (file, path, color, label, duration) => `${fmtImport(file,
|
|
|
220
220
|
/**
|
|
221
221
|
* The terminal/GitHub reporter used by `fjs t`. Output goes through
|
|
222
222
|
* `csiWrite`, so ANSI styles are stripped on non-TTY streams. When
|
|
223
|
-
* `
|
|
223
|
+
* `GITHUB_ACTIONS` is set, failures are emitted as `::error` workflow
|
|
224
224
|
* annotations instead of colored lines. Exported as a factory so the
|
|
225
225
|
* GitHub format path can be exercised directly from tests.
|
|
226
226
|
*/
|
|
@@ -232,7 +232,7 @@ export const defaultReporter = (options) => {
|
|
|
232
232
|
};
|
|
233
233
|
const csiLog = line('stdout');
|
|
234
234
|
const csiError = line('stderr');
|
|
235
|
-
const isGitHub = options.env['
|
|
235
|
+
const isGitHub = options.env['GITHUB_ACTIONS'] !== undefined;
|
|
236
236
|
return {
|
|
237
237
|
// https://github.com/OndraM/ci-detector/blob/main/src/Ci/GitHubActions.php
|
|
238
238
|
result: (file, path, { result: [s, v], duration }, throws) => s === 'ok'
|
|
@@ -17,7 +17,7 @@ const makeReporter = () => {
|
|
|
17
17
|
const noopTestContext = { test: todo };
|
|
18
18
|
const options = (initCwd, github = false) => ({
|
|
19
19
|
args: [],
|
|
20
|
-
env: { INIT_CWD: initCwd, ...(github ? {
|
|
20
|
+
env: { INIT_CWD: initCwd, ...(github ? { GITHUB_ACTIONS: 'true' } : {}) },
|
|
21
21
|
std: { stdout: { isTTY: false }, stderr: { isTTY: false } },
|
|
22
22
|
testContext: noopTestContext,
|
|
23
23
|
bunTestContext: noopTestContext,
|
package/fs/fjs/module.f.js
CHANGED
|
@@ -6,32 +6,42 @@
|
|
|
6
6
|
import { compile } from "../djs/module.f.js";
|
|
7
7
|
import { main as testMain } from "../emergent_testing/module.f.js";
|
|
8
8
|
import { main as casMain } from "../cas/module.f.js";
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
9
|
+
import { main as ciMain } from "../ci/module.f.js";
|
|
10
|
+
import { import_ } from "../effects/node/module.f.js";
|
|
11
|
+
import { dispatch } from "../cli/module.f.js";
|
|
12
|
+
const commands = [
|
|
13
|
+
{
|
|
14
|
+
names: ['test', 't'],
|
|
15
|
+
description: 'Run the FunctionalScript test suite',
|
|
16
|
+
handler: testMain,
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
names: ['compile', 'c'],
|
|
20
|
+
description: 'Compile a FunctionalScript module to JavaScript',
|
|
21
|
+
handler: ({ args }) => compile(args),
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
names: ['cas', 's'],
|
|
25
|
+
description: 'Content-addressable storage operations',
|
|
26
|
+
handler: casMain,
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
names: ['ci', 'i'],
|
|
30
|
+
description: 'Generate the GitHub Actions CI workflow',
|
|
31
|
+
handler: ciMain,
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
names: ['run', 'r'],
|
|
35
|
+
description: 'Run a FunctionalScript module as a NodeProgram',
|
|
36
|
+
handler: options => {
|
|
37
|
+
const [file, ...args] = options.args;
|
|
25
38
|
return import_(file).step(([s, v]) => {
|
|
26
39
|
if (s === 'error') {
|
|
27
40
|
throw v;
|
|
28
41
|
}
|
|
29
|
-
return v.
|
|
42
|
+
return v.main({ ...options, args });
|
|
30
43
|
});
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
return errorExit(`Error: Unknown command "${command}"`);
|
|
36
|
-
}
|
|
37
|
-
};
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
];
|
|
47
|
+
export const main = dispatch(commands);
|
package/fs/json/module.f.d.ts
CHANGED
|
@@ -1,18 +1,34 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* JSON
|
|
3
|
-
* `setProperty` for immutable nested updates
|
|
4
|
-
*
|
|
2
|
+
* JSON value types, rtti schemas, and utilities: `serialize`, `stringify`,
|
|
3
|
+
* `parse`, and `setProperty` for immutable nested updates.
|
|
4
|
+
*
|
|
5
|
+
* The JSON value types (`Unknown`, `Primitive`) are derived from the rtti
|
|
6
|
+
* schemas defined here, so the schema is the single source of truth — no
|
|
7
|
+
* hand-written types to keep in sync.
|
|
5
8
|
*
|
|
6
9
|
* @module
|
|
7
10
|
*/
|
|
8
11
|
import { type List } from '../types/list/module.f.ts';
|
|
9
12
|
import { type Entry as ObjectEntry } from '../types/object/module.f.ts';
|
|
10
|
-
type
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
import type { Ts } from '../types/rtti/ts/module.f.ts';
|
|
14
|
+
/** rtti schema matching any JSON primitive: `null`, `boolean`, `number`, or `string`. */
|
|
15
|
+
export declare const primitive: import("../types/rtti/module.f.ts").Or<[null, import("../types/rtti/module.f.ts").Boolean, import("../types/rtti/module.f.ts").Number, import("../types/rtti/module.f.ts").String]>;
|
|
16
|
+
/**
|
|
17
|
+
* rtti schema matching any JSON value: a primitive, an array of JSON values,
|
|
18
|
+
* or an object whose values are JSON values. Self-referential via a thunk;
|
|
19
|
+
* rtti instantiates array/record item validators lazily so recursion terminates
|
|
20
|
+
* on acyclic input.
|
|
21
|
+
*
|
|
22
|
+
* A struct field typed `unknown` is **required when present** — unlike rtti
|
|
23
|
+
* core's `unknown`, the JSON `unknown` excludes `undefined`.
|
|
24
|
+
*/
|
|
25
|
+
export declare const unknown: () => readonly ["or", import("../types/rtti/module.f.ts").Or<[null, import("../types/rtti/module.f.ts").Boolean, import("../types/rtti/module.f.ts").Number, import("../types/rtti/module.f.ts").String]>, import("../types/rtti/module.f.ts").Type1<"record", () => readonly ["or", import("../types/rtti/module.f.ts").Or<[null, import("../types/rtti/module.f.ts").Boolean, import("../types/rtti/module.f.ts").Number, import("../types/rtti/module.f.ts").String]>, import("../types/rtti/module.f.ts").Type1<"record", /*elided*/ any>, import("../types/rtti/module.f.ts").Type1<"array", /*elided*/ any>]>, import("../types/rtti/module.f.ts").Type1<"array", () => readonly ["or", import("../types/rtti/module.f.ts").Or<[null, import("../types/rtti/module.f.ts").Boolean, import("../types/rtti/module.f.ts").Number, import("../types/rtti/module.f.ts").String]>, import("../types/rtti/module.f.ts").Type1<"record", /*elided*/ any>, import("../types/rtti/module.f.ts").Type1<"array", /*elided*/ any>]>];
|
|
26
|
+
/** rtti schema matching a JSON object: `{ readonly [k: string]: Unknown }`. */
|
|
27
|
+
export declare const object: import("../types/rtti/module.f.ts").Type1<"record", () => readonly ["or", import("../types/rtti/module.f.ts").Or<[null, import("../types/rtti/module.f.ts").Boolean, import("../types/rtti/module.f.ts").Number, import("../types/rtti/module.f.ts").String]>, import("../types/rtti/module.f.ts").Type1<"record", /*elided*/ any>, import("../types/rtti/module.f.ts").Type1<"array", /*elided*/ any>]>;
|
|
28
|
+
/** rtti schema matching a JSON array: `readonly Unknown[]`. */
|
|
29
|
+
export declare const array: import("../types/rtti/module.f.ts").Type1<"array", () => readonly ["or", import("../types/rtti/module.f.ts").Or<[null, import("../types/rtti/module.f.ts").Boolean, import("../types/rtti/module.f.ts").Number, import("../types/rtti/module.f.ts").String]>, import("../types/rtti/module.f.ts").Type1<"record", /*elided*/ any>, import("../types/rtti/module.f.ts").Type1<"array", /*elided*/ any>]>;
|
|
30
|
+
export type Primitive = Ts<typeof primitive>;
|
|
31
|
+
export type Unknown = Ts<typeof unknown>;
|
|
16
32
|
export declare const setProperty: (value: Unknown) => (path: List<string>) => (src: Unknown) => Unknown;
|
|
17
33
|
export type Entry = ObjectEntry<Unknown>;
|
|
18
34
|
type Entries = List<Entry>;
|
package/fs/json/module.f.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* JSON
|
|
3
|
-
* `setProperty` for immutable nested updates
|
|
4
|
-
*
|
|
2
|
+
* JSON value types, rtti schemas, and utilities: `serialize`, `stringify`,
|
|
3
|
+
* `parse`, and `setProperty` for immutable nested updates.
|
|
4
|
+
*
|
|
5
|
+
* The JSON value types (`Unknown`, `Primitive`) are derived from the rtti
|
|
6
|
+
* schemas defined here, so the schema is the single source of truth — no
|
|
7
|
+
* hand-written types to keep in sync.
|
|
5
8
|
*
|
|
6
9
|
* @module
|
|
7
10
|
*/
|
|
@@ -10,6 +13,25 @@ import { concat } from "../types/string/module.f.js";
|
|
|
10
13
|
import { at } from "../types/object/module.f.js";
|
|
11
14
|
import { compose, fn } from "../types/function/module.f.js";
|
|
12
15
|
import { objectWrap, arrayWrap, stringSerialize, numberSerialize, nullSerialize, boolSerialize } from "./serializer/module.f.js";
|
|
16
|
+
import { boolean as rttiBoolean, number as rttiNumber, string as rttiString, or, record, array as rttiArray } from "../types/rtti/module.f.js";
|
|
17
|
+
// ── rtti schemas ──────────────────────────────────────────────────────────────
|
|
18
|
+
/** rtti schema matching any JSON primitive: `null`, `boolean`, `number`, or `string`. */
|
|
19
|
+
export const primitive = or(null, rttiBoolean, rttiNumber, rttiString);
|
|
20
|
+
/**
|
|
21
|
+
* rtti schema matching any JSON value: a primitive, an array of JSON values,
|
|
22
|
+
* or an object whose values are JSON values. Self-referential via a thunk;
|
|
23
|
+
* rtti instantiates array/record item validators lazily so recursion terminates
|
|
24
|
+
* on acyclic input.
|
|
25
|
+
*
|
|
26
|
+
* A struct field typed `unknown` is **required when present** — unlike rtti
|
|
27
|
+
* core's `unknown`, the JSON `unknown` excludes `undefined`.
|
|
28
|
+
*/
|
|
29
|
+
export const unknown = () => ['or', primitive, object, array];
|
|
30
|
+
/** rtti schema matching a JSON object: `{ readonly [k: string]: Unknown }`. */
|
|
31
|
+
export const object = record(unknown);
|
|
32
|
+
/** rtti schema matching a JSON array: `readonly Unknown[]`. */
|
|
33
|
+
export const array = rttiArray(unknown);
|
|
34
|
+
// ── JSON utilities ────────────────────────────────────────────────────────────
|
|
13
35
|
const { entries } = Object;
|
|
14
36
|
export const setProperty = value => {
|
|
15
37
|
const f = path => src => {
|