js-randomness-predictor
Version:
Predict Math.random output in Node, Deno, Bun, Chrome, Firefox, and Safari
2 lines (1 loc) • 10.8 kB
JavaScript
import*as p from"z3-solver-jsrp";function i(e){return e&0xffffffffffffffffn}class o{constructor(){}static symbolic(t){let n=t[0];n=n.xor(n.shl(23)),n=n.xor(n.lshr(17)),n=n.xor(t[1]),n=n.xor(t[1].lshr(26)),t[0]=t[1],t[1]=n}static symbolicArithmeticShiftRight(t){let n=t[0];n=n.xor(n.shl(23)),n=n.xor(n.shr(17)),n=n.xor(t[1]),n=n.xor(t[1].shr(26)),t[0]=t[1],t[1]=n}static concreteBackwards(t){let n=t[1]^t[0]>>26n^t[0];n=i(n^n>>17n^n>>34n^n>>51n),n=i(n^n<<23n^n<<46n),t[1]=t[0],t[0]=n}static concrete(t){let n=t[0];n^=i(n<<23n),n^=i(n>>17n),n^=t[1],n^=i(t[1]>>26n),t[0]=t[1],t[1]=n}static concreteArithmeticShiftRight(t){let n=i(t[0]);n^=i(n<<23n),n^=this.#e(n,17n),n^=t[1],n^=this.#e(t[1],26n),t[0]=t[1],t[1]=i(n)}static#e(t,n){const r=i(t>>n);if((t&1n<<63n)===0n)return r;const c=(1n<<n)-1n<<64n-n;return r|c}}class d extends Error{constructor(t){t=t===void 0?"Cannot solve state. Unable to make accurate predictions.":t,super(t),this.name="UnsatError",Object.setPrototypeOf(this,new.target.prototype)}}class I extends Error{constructor(t){super(t),this.name="InsufficientSequenceLengthError",Object.setPrototypeOf(this,new.target.prototype)}}class S extends Error{constructor(t){super(t),this.name="UnexpectedRuntimeError",Object.setPrototypeOf(this,new.target.prototype)}}class v{sequence;#e=[0n,0n];#n;#t;constructor(t,n){if(n.length<=0)throw new Error("V8EnginePredictor requires at least one solvingStrategy in solvingStrategies");this.sequence=t,this.#n=n,this.#t=this.#n[0]}async predictNext(){this.#e[0]===0n&&this.#e[1]===0n&&await this.#o();const t=this.#t.toDouble(this.#e);return this.#t.concreteXorShift(this.#e),t}async#r(){try{const{Context:t}=await p.init(),n=t("main"),r=new n.Solver,s=n.BitVec.const("ss0",64),c=n.BitVec.const("ss1",64),a=[s,c],h=[...this.sequence].reverse();for(const l of h){this.#t.symbolicXorShift(a);const m=this.#t.recoverMantissa(l);this.#t.constrainMantissa(m,a,r,n)}if(await r.check()!=="sat")throw new d;const f=r.model();this.#e=[f.get(s).value(),f.get(c).value()]}catch(t){return Promise.reject(t)}}async#o(){let t;for(const n of this.#n)try{return this.#t=n,await this.#r()}catch(r){if(!(r instanceof d))throw r;t=r}throw t??new Error("V8EnginePredictor : no strategies attempted")}}const E=Math.pow(2,53),j=[{recoverMantissa:e=>{const t=Math.floor(e*E);return BigInt(t)},toDouble:e=>Number(e[0]>>11n)/E,constrainMantissa:(e,t,n,r)=>{n.add(t[0].lshr(11).eq(r.BitVec.val(e,64)))},symbolicXorShift:e=>o.symbolic(e),concreteXorShift:e=>o.concreteBackwards(e)},{recoverMantissa:e=>{const t=Math.floor(e*E);return BigInt(t)},toDouble:e=>{const t=i(e[0]+e[1]);return Number(t>>11n)/E},constrainMantissa:(e,t,n,r)=>{const s=t[0].add(t[1]);n.add(s.lshr(11).eq(r.BitVec.val(e,64)))},symbolicXorShift:e=>o.symbolic(e),concreteXorShift:e=>o.concreteBackwards(e)}];class _ extends v{constructor(t){super(t,j)}}class J{sequence;#e=[0n,0n];#n;#t;constructor(t,n){if(n.length<=0)throw new Error("SpiderMonkeyPredictor requires at least one solvingStrategy in solvingStrategies");this.sequence=t,this.#n=n,this.#t=this.#n[0]}async predictNext(){return this.#e[0]===0n&&this.#e[1]===0n&&await this.#o(),this.#t.concreteXorShift(this.#e),this.#t.toDouble(this.#e)}async#r(){try{const{Context:t}=await p.init(),n=t("main"),r=new n.Solver,s=n.BitVec.const("ss0",64),c=n.BitVec.const("ss1",64),a=[s,c];for(const l of this.sequence){this.#t.symbolicXorShift(a);const m=this.#t.recoverMantissa(l);this.#t.constrainMantissa(m,a,r,n)}if(await r.check()!=="sat")throw new d;const h=r.model(),f=[h.get(s).value(),h.get(c).value()];for(const l of this.sequence)this.#t.concreteXorShift(f);this.#e=f}catch(t){return Promise.reject(t)}}async#o(){let t;for(const n of this.#n)try{return this.#t=n,await this.#r()}catch(r){if(!(r instanceof d))throw r;t=r}throw t??new Error("SpiderMonkeyPredictor : no strategies attempted")}}const N=0x1fffffffffffffn,T=Math.pow(2,53),K=[{recoverMantissa:e=>BigInt(Math.floor(e*T)),toDouble:e=>{const t=i(e[0]+e[1]);return Number(t&N)/T},constrainMantissa:(e,t,n,r)=>{const s=t[0].add(t[1]).and(r.BitVec.val(N,64));n.add(s.eq(r.BitVec.val(e,64)))},symbolicXorShift:e=>o.symbolic(e),concreteXorShift:e=>o.concrete(e)}];class x extends J{constructor(t){super(t,K)}}class y{constructor(){}static isDeno(){return typeof globalThis.Deno<"u"&&typeof Deno.version<"u"&&typeof Deno.version.deno=="string"}static isBun(){return typeof globalThis.Bun<"u"&&typeof Bun.version<"u"&&typeof process.versions.bun=="string"}static isNode(){return!this.isDeno()&&!this.isBun()&&typeof process.versions.node<"u"&&typeof process.versions.node=="string"}static isFirefox(){return typeof window<"u"&&navigator.userAgent.indexOf("Firefox")>-1}static isChrome(){return typeof window<"u"&&navigator.userAgent.indexOf("Chrome")>-1}static isSafari(){return typeof window<"u"&&navigator.userAgent.indexOf("Safari")>-1}static type(){if(this.isNode())return"node";if(this.isDeno())return"deno";if(this.isBun())return"bun";if(this.isChrome())return"chrome";if(this.isSafari())return"safari";if(this.isFirefox())return"firefox";throw new S}}const A=["node","bun","deno","chrome","firefox","safari"],Q=["node","bun","deno"],W=["chrome","safari","firefox"];Object.fromEntries(A.map(e=>[e,Q.includes(e)])),Object.fromEntries(A.map(e=>[e,W.includes(e)]));const H={node:"v8",bun:"javascriptcore",deno:"v8",chrome:"v8",firefox:"spidermonkey",safari:"javascriptcore"};Object.entries(H).reduce((e,[t,n])=>((e[n]||=[]).push(t),e),{});const B={node:5},R=64,g=0x000fffffffffffffn,X=0x3ff0000000000000n,w=Math.pow(2,53),Y=[{recoverMantissa:e=>{const t=Math.floor(e*w);return BigInt(t)},toDouble:e=>{const t=i(e[0]+e[1]);return Number(t>>11n)/w},constrainMantissa:(e,t,n,r)=>{const s=t[0].add(t[1]);n.add(s.lshr(11).eq(r.BitVec.val(e,64)))},symbolicXorShift:e=>o.symbolic(e),concreteXorShift:e=>o.concreteBackwards(e)},{recoverMantissa:e=>{const t=Math.floor(e*w);return BigInt(t)},toDouble:e=>Number(e[0]>>11n)/w,constrainMantissa:(e,t,n,r)=>{n.add(t[0].lshr(11).eq(r.BitVec.val(e,64)))},symbolicXorShift:e=>o.symbolic(e),concreteXorShift:e=>o.concreteBackwards(e)},{recoverMantissa:e=>{const t=Buffer.alloc(8);return t.writeDoubleLE(e+1,0),t.readBigUInt64LE(0)&g},toDouble:e=>{const t=Buffer.alloc(8);return t.writeBigUInt64LE(e[0]>>12n|X,0),t.readDoubleLE(0)-1},constrainMantissa:(e,t,n,r)=>{n.add(t[0].lshr(12).eq(r.BitVec.val(e,64)))},symbolicXorShift:e=>o.symbolic(e),concreteXorShift:e=>o.concreteBackwards(e)},{recoverMantissa:e=>{const t=Buffer.alloc(8);return t.writeDoubleLE(e+1,0),t.readBigUInt64LE(0)&g},toDouble:e=>{const t=e[0]+e[1],n=Buffer.alloc(8);return n.writeBigUInt64LE(t&g|X,0),n.readDoubleLE(0)-1},constrainMantissa:(e,t,n,r)=>{const s=t[0].add(t[1]).and(r.BitVec.val(g,64));n.add(s.eq(r.BitVec.val(e,64)))},symbolicXorShift:e=>o.symbolic(e),concreteXorShift:e=>o.concreteBackwards(e)}];class D extends v{constructor(t){if(t){if(t.length>=R)throw new Error(`sequence.length must be less than '${R}', got '${t.length}'`);if(t.length<B.node)throw new Error(`sequence.length must be at least '${B.node}', got '${t.length}'`)}if(!t){if(!y.isNode())throw new S("Expected NodeJS runtime! Unable to auto-generate sequence, please provide one.");t=Array.from({length:B.node},Math.random)}super(t,Y)}}class C{sequence;#e=[0n,0n];#n;#t;constructor(t,n){if(n.length<=0)throw new Error("JavaScriptCorePredictor requires at least one solvingStrategy in solvingStrategies");this.sequence=t,this.#n=n,this.#t=this.#n[0]}async predictNext(){return this.#e[0]===0n&&this.#e[1]===0n&&await this.#o(),this.#t.concreteXorShift(this.#e),this.#t.toDouble(this.#e)}async#r(){try{const{Context:t}=await p.init(),n=t("main"),r=new n.Solver,s=n.BitVec.const("ss0",64),c=n.BitVec.const("ss1",64),a=[s,c];for(const l of this.sequence){this.#t.symbolicXorShift(a);const m=this.#t.recoverMantissa(l);this.#t.constrainMantissa(m,a,r,n)}if(await r.check()!=="sat")throw new d;const h=r.model(),f=[h.get(s).value(),h.get(c).value()];for(const l of this.sequence)this.#t.concreteXorShift(f);this.#e=f}catch(t){return Promise.reject(t)}}async#o(){let t;for(const n of this.#n)try{return this.#t=n,await this.#r()}catch(r){if(!(r instanceof d))throw r;t=r}throw t??new Error("JavaScriptCorePredictor : no strategies attempted")}}const P=6,V=0x1fffffffffffffn,O=Math.pow(2,53),U={recoverMantissa:e=>BigInt(Math.floor(e*O)),toDouble:e=>{const t=i(e[0]+e[1]);return Number(t&V)/O},constrainMantissa:(e,t,n,r)=>{const s=t[0].add(t[1]).and(r.BitVec.val(V,64));n.add(s.eq(r.BitVec.val(e,64)))}},z=[{...U,symbolicXorShift:e=>o.symbolicArithmeticShiftRight(e),concreteXorShift:e=>o.concreteArithmeticShiftRight(e)},{...U,symbolicXorShift:e=>o.symbolic(e),concreteXorShift:e=>o.concrete(e)}];class L extends C{constructor(t){if(t.length<P)throw new I(`sequence length must be >= ${P} : got ${t.length}`);super(t,z)}}function Z(e=1){const t=[];for(let n=0;n<e;n++)t.push(Math.random());return t}const M=6,q=0x1fffffffffffffn,k=Math.pow(2,53),$={recoverMantissa:e=>BigInt(Math.floor(e*k)),toDouble:e=>{const t=i(e[0]+e[1]);return Number(t&q)/k},constrainMantissa:(e,t,n,r)=>{const s=t[0].add(t[1]).and(r.BitVec.val(q,64));n.add(s.eq(r.BitVec.val(e,64)))}},tt=[{...$,symbolicXorShift:e=>o.symbolicArithmeticShiftRight(e),concreteXorShift:e=>o.concreteArithmeticShiftRight(e)},{...$,symbolicXorShift:e=>o.symbolic(e),concreteXorShift:e=>o.concrete(e)}];class G extends C{constructor(t){if(t&&t.length<M)throw new I(`sequence length must be >= ${M} : got ${t.length}`);if(!t){if(!y.isBun())throw new S("Expected Bun runtime! Unable to auto-generate sequence, please provide one.");t=Z(M)}super(t,tt)}}const b=Math.pow(2,53),et=[{recoverMantissa:e=>{const t=Math.floor(e*b);return BigInt(t)},toDouble:e=>Number(e[0]>>11n)/b,constrainMantissa:(e,t,n,r)=>{n.add(t[0].lshr(11).eq(r.BitVec.val(e,64)))},symbolicXorShift:e=>o.symbolic(e),concreteXorShift:e=>o.concreteBackwards(e)},{recoverMantissa:e=>{const t=Math.floor(e*b);return BigInt(t)},toDouble:e=>{const t=i(e[0]+e[1]);return Number(t>>11n)/b},constrainMantissa:(e,t,n,r)=>{const s=t[0].add(t[1]);n.add(s.lshr(11).eq(r.BitVec.val(e,64)))},symbolicXorShift:e=>o.symbolic(e),concreteXorShift:e=>o.concreteBackwards(e)}];class F extends v{constructor(t){if(!t){if(!y.isDeno())throw new S("Expected Deno runtime! Unable to auto-generate sequence, please provide one.");t=Array.from({length:4},Math.random)}super(t,et)}}const u={node:e=>new D(e),firefox:e=>new x(e),chrome:e=>new _(e),safari:e=>new L(e),bun:e=>new G(e),deno:e=>new F(e)},nt=u.node,rt=u.firefox,ot=u.chrome,st=u.safari,it=u.bun,ct=u.deno;export{G as BunRandomnessPredictor,_ as ChromeRandomnessPredictor,F as DenoRandomnessPredictor,x as FirefoxRandomnessPredictor,D as NodeRandomnessPredictor,L as SafariRandomnessPredictor,it as bun,ot as chrome,u as default,ct as deno,rt as firefox,nt as node,st as safari};