Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce loading time #116

Merged
merged 14 commits into from
Aug 28, 2023
2 changes: 1 addition & 1 deletion MINA_COMMIT
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
The mina commit used to generate the backends for node and web is
867b24298d27a5f0203466194cf8f793dc1f35aa
e0a232de83f80cc830f709d2c53f93ae4e77173e
277,054 changes: 138,577 additions & 138,477 deletions compiled/node_bindings/snarky_js_node.bc.cjs

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion compiled/node_bindings/snarky_js_node.bc.map

Large diffs are not rendered by default.

431 changes: 176 additions & 255 deletions compiled/web_bindings/snarky_js_web.bc.js

Large diffs are not rendered by default.

14 changes: 14 additions & 0 deletions crypto/bindings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* This file contains bindings for JSOO written in TS and integrated with our normal code base.
* It is exposed to JSOO by populating a global variable with an object.
* It gets imported as the first thing in ../../snarky.js so that the global variable is ready by the time JSOO code gets executed.
*/
import { prefixHashes, prefixHashesLegacy } from '../crypto/constants.js';

const tsBindings = {
prefixHashes,
prefixHashesLegacy,
};

// this is put in a global variable so that ../kimchi/js/bindings.js finds it
(globalThis as any).__snarkyTsBindings = tsBindings;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is the new TS bindings file, explained here

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Depending how you feel on comments, you could argue the explanation could be added here, mostly just elaborating on the inline comment you have already. Could be helpful for others look at this file and wondering more, wdyt?

253 changes: 251 additions & 2 deletions crypto/constants.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// @gen this file is generated - don't edit it directly
export { prefixes, versionBytes, poseidonParamsKimchiFp, poseidonParamsLegacyFp, mocks }
// @gen this file is generated from `bindings/ocaml/snarky_js_constants.ml` - don't edit it directly
export { prefixes, prefixHashes, prefixHashesLegacy, versionBytes, poseidonParamsKimchiFp, poseidonParamsLegacyFp, mocks }

let prefixes = {
"event": "MinaZkappEvent******",
Expand All @@ -14,6 +14,255 @@ let prefixes = {
"zkappUri": "MinaZkappUri********",
"deriveTokenId": "MinaDeriveTokenId***"
};
let prefixHashes = {
"MinaReceiptUC*******": [
"17890046087060600378523962727948914890955845280331606421027576706277370812052",
"2013454333407534591106411126192774509000627947643864003868625362325108814274",
"11843535353803037930790320689348405921362689396018494249827525941843824404081"
],
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hard-coded hashes exposed to jsoo via the new TS bindings. we hard-code them to avoid computing them at the top level

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: If we could throw some inline comments when this (or similar) file(s) is generated that point to the OCaml file, it would really help context for other developers if debugging or adding features in this area.

"CodaReceiptZkapp****": [
"10173709693039436418323173817852473796760618468635274081106091878172355412495",
"8139892805413950771311540201181177376747817902069998595519899391903936767134",
"13514876620613630149351219463845257700223634963001020028151406467995275024594"
],
"Coinbase************": [
"16825847102297458526359719396083434368788313103713242309655412848174457920423",
"21732702256017917816272795771734458959259892802453584375610183841451053027064",
"20669950187190141732603807229833302926112666951294341954340514712643194206110"
],
"PendingCoinbases****": [
"16730315671906078134534118281698719603694322959719576832314142406897554025946",
"25168172107432119701402092802564698772609386283424806773354665411015030859956",
"20203823516569384790863281992678977204769111540506990077513414850340465376267"
],
"CoinbaseStackData***": [
"23795978781100345043289806728009175185120094645976380845310050347461663815988",
"22848259504294538625391413055517172710405127059374914145881816600826824598643",
"8292468073974572410325570929211069869427868613763277519881895337391418731450"
],
"CoinbaseStackStaHash": [
"335203117218289187585524630708440909952721586869179589604793956147132569543",
"27066428515933869709871979311099618239824992817474733219473754649926311088531",
"21249847167218596842529246266817628519376871370045151307329588726090940941283"
],
"CoinbaseStack*******": [
"10365018507282248303752506973112854406071106890516858854157506926717812932750",
"19289691782405010481159082968251292806607879795611766141901748131065655579721",
"8987039650233860747996941600635099179155585390854763935988086491644855810711"
],
"MinaCheckpoints*****": [
"15873130589302091361863210575263731242593763730169570459166821652327279429416",
"27741778946681194402252199348726997679847260280438775383573755416459042152245",
"7598438620402360345138640933713109733801127070065255775405685972203496634081"
],
"MinaMergeSnark******": [
"5465206932306554741198859294482250047374987110116571903153751264716396266207",
"28325265961862852836567844362114881306407823522046946129773393861560948847052",
"20049678444717746759028157787181298288785775657186008836042341914370292827996"
],
"MinaBaseSnark*******": [
"15502310217431654911062859746106286672455410530942120153504175184205809302248",
"3469045624943527165009161295743804688154058669917024998601801713171804105078",
"16667965011323249535055526937874001443515091810412343722400939445165393857780"
],
"MinaProtoState******": [
"5218970939948495870036503265499543025475317910763049867270287867667146978870",
"7663210626148314949787033187186036425676070286961909238040356477815169631084",
"19859188289320816036969227839574854326171440874550138016648548415357198703337"
],
"MinaProtoStateBody**": [
"3548547909990922956559515810876765435326873020883079662683136168632773655275",
"134182536761489093478066959027928272525080293912190881939140820794450385287",
"18910449726094816833941350890285540874861148441082116020102338532207375519343"
],
"MinaVrfMessage******": [
"24101363367502572671624471609928959797353672294440762288404204895418767914646",
"5171820881164007689309616183632792746219180909518238150637460314245246143263",
"10979796915023089328772347959806029121878467684484216605075459818053899045444"
],
"MinaSignatureMainnet": [
"28597293842583882050529337819282358444728515448690248936274177901465134844489",
"13029865398778858891320837481651890827971447635226272051516204921834229015884",
"2324960771278703080070347074343683653953770644553957353754880132143131569147"
],
"CodaSignature*******": [
"6547874669265470003564181123405173756111990160585052594027544303901364349512",
"22191763046611062479784309793717481299019591714391827084400612211604078633201",
"15360317550574394687602808211901764964514686767298144053612144955373862517277"
],
"MinaVrfOutput*******": [
"2251514781415689779315070305878469259850299612928948069881728941286436529416",
"28445424317765931437563566658155841532256907311948842353165636913979445243675",
"1697103740469522139030362533818365124680980524626250761960654638291888644330"
],
"MinaVrfEvaluation***": [
"28080055385183205248434069314913715411795750554846638282391132356635075327118",
"25018718747831549163470950235902703474807728450690404911050923194299837536932",
"3256623657773355300700179149632147114566124258546613752475489953689825740823"
],
"MinaEpochSeed*******": [
"7920024158807749362970659876749181530334941449960381128739613586571256360405",
"13756862713999441076472977832321298402266591073703520273734381195492800342833",
"16931743843465107540110860558687538825985475311420101960428698400767332393906"
],
"MinaTransitionSnark*": [
"11049595972041980914958840531625028328602860712038036656362464370121336040984",
"24369517789348117364784880800333031735213111703459853079908318927717982912175",
"996573540734206293061884582007205418029995442386259428924494388795357965385"
],
"MinaAccount*********": [
"21547009634669789644192675386133007766042650219024716227935570378579547706642",
"3869977418072959680344087467966431440327948593054069717779845397512987438978",
"17591003611016737523041467644989399067682599282318802410210271366172380277153"
],
"MinaSideLoadedVk****": [
"27153629295534844750482612843518005572402188741101822965689207110291504095805",
"11073437601016088346212553894160581939150688827288603152461976873708720172824",
"9169013693168830396847022454402673046094697740892173219744332585469764409612"
],
"MinaZkappAccount****": [
"11742420651603425685690711434636216727968618158667382343736587130720645535016",
"20917169788479399921968659996772666237321879817943938162255353371266230737562",
"20221577186851444354528754069740362935513598751580381763045954351047955571417"
],
"MinaZkappPayload****": [
"15735138827391397348912010094577234813869450438840158969759900004702547928125",
"25095612872941242247876048162039143509752212627701285511972307921367391645919",
"7245494597725009330136300549232949784423520250577599502394596645257342395146"
],
"MinaZkappBody*******": [
"11546850256467050428910345609144922097005052647538801208325011553730126447286",
"5364431257540416559421952454007866208752074433881022683169051644094135571798",
"7271648487325380257773162450796685842965273904153624038692922675357477109563"
],
"MinaZkappPred*******": [
"1288860557840839698672685006364179285130411098848600694737282320588924548492",
"24648295833336558525603848295184424886548932461541421142783307792871113347031",
"1330615836835056811243082335077124866238751435915242573993316916713469087050"
],
"MinaZkappPredAcct***": [
"16247099195538206941970428186933809576049890124762896310373916059400681012938",
"15171999803179862436296250357712424012107969488385552487664863256867849154640",
"4695118160519310765712802705640939163487421977728313886668234870398464448283"
],
"MinaZkappPredPS*****": [
"28115844434401213157045670864292277190427496512916771660477513364996586226191",
"17764239860871865704512758086410304367016330694375482081848267812860896213477",
"2608563583120825722034995217249250504732387097295075568312443453761249924462"
],
"MinaAcctUpdate******": [
"9957826900659629762430758497884049056160700317617514401594470658641671624663",
"21522332289022006332580136414542077768531348089748796477458065317183556250415",
"14710924552873755427800785557194619608345171929974642664081300821061672943053"
],
"MinaAcctUpdAcctPred*": [
"11173347481325879282537380504137543614432174467122278589147153842480174214350",
"22433785030516935555884954114999194863743668497200511950547006360846720681436",
"4261224905860522407514587942832658209487173552801239748203234114069543449134"
],
"MinaAcctUpdateCons**": [
"7974184247425786365466969127827083941281743695327546149120833518746435921046",
"1079147682067570431747049877519099849334832444581201545961023544596733431550",
"9670106619202136718451303928765479503313491401619698334696903962327538130992"
],
"MinaAcctUpdateNode**": [
"15921812961830232432174711488904180713275251781093575291539345321597011303739",
"5852213322332241594845871336918115662219071361771346507406094569679662937607",
"21122827334147180286039671993443893600964526985496742826857975683524856341379"
],
"MinaAcctUpdStckFrm**": [
"1223279431820750727612295994589444883292600761079562536688416996919972234987",
"1873141333924103856860857609363983758885824745969813373245393521390926426683",
"3550105212452130151915860825756512345408015936295894584118372238840612023788"
],
"MinaActUpStckFrmCons": [
"2363089775097766730570162674460603870980415123701610894146069429352874281636",
"8717086429614898734892919627864489205116600585932141922995487227707208282057",
"14660270392332597302006144557344641683528071714290878702086758222477469533211"
],
"MinaZkappUri********": [
"534822897390732927195976832726937157108052596941484097303405936433225931144",
"21308674973525253012607500915181592359821899373849668837401701284134790635210",
"19235616568963430752220890547731083898076295596325584947617173371158207986317"
],
"MinaZkappEvent******": [
"4144672248660824652311280789227568759501644435839088465487215978090977152836",
"16580012705864177241905923711864666027965216928284588602669501632136706453456",
"28268897103231723777184618409092967932555901943057586428182153116992131011025"
],
"MinaZkappEvents*****": [
"22941690192200157010958144262626906691861453230235765939870625581651903942109",
"8085194290973996063041942057794139208480036474122767282118588735695477304146",
"26729904183313179836453835886592671283117737890095730465188585661277543615385"
],
"MinaZkappSeqEvents**": [
"20111532619758468729019280527752703188436440291616049387250019116440725105679",
"28272901079534355755544153990297346241256584111406088887261772513761686581936",
"11593971643819429831651280663135869674712971584194549509498204047075895747923"
],
"MinaZkappMemo*******": [
"2662735671148484138098041239517130399444285195614926917304994766121342901330",
"1889560324711062089177091328630260720221153765601231238715650562289804935970",
"4150523804923664151142435309968051550133270766858171566059780615187901817023"
],
"MinaZkappTest*******": [
"23523101868899742954180674496902908392567863852999903167375927084079494055612",
"4491786955849351692402874941062803293792761915358826996649017458255778371918",
"18160445324611651688025194683090940451613686777550031421971998315243738422364"
],
"MinaDeriveTokenId***": [
"6192019453766080264591455948244350296532066491511280821771403784079613278630",
"3474280028978446563781013959252007045004226094384968366087940198662654278266",
"20434002876694963787609307807174199928279086350854834006718281273564667456637"
],
"CodaReceiptEmpty": [
"14564582992068613478915821183083107733064540968050799295374021047658500056219",
"21765043973285063733734239399942750176857972907855721619600674857294623000734",
"18519955733587546799174091248819038069762857427193969217428957100491271613694"
],
"MinaZkappEventsEmpty": [
"11558119263070965853863267079253872832625419457395008685779236645292569607921",
"25458142203119307439619503192644060065091275427503371449742352140981637359577",
"28343474290528262467651243371210869540984529302238754668057531270656874883506"
],
"MinaZkappActionsEmpty": [
"2965377540200775924504968637505084669999360240500907972788072774778139588064",
"17888733104410001265760460027725887240172765470923695174284923303416908725309",
"6155733123951817300356401771271939707310716210385193729101357561319788034953"
],
"MinaZkappActionStateEmptyElt": [
"25079927036070901246064867767436987657692091363973573142121686150614948079097",
"26431778411571512074795067173224334387034335867358343719815640998216694007738",
"25080775363764450744501815075506845022058095277795060631172637381645274354727"
],
"CoinbaseStack": [
"13478948633790621346997153068092516261975764161208078295837519850718904039733",
"23794571567771902109532327523992257297445027552423990566905688786749549749640",
"12437776415960587857483436445253285567999534294199440886476575966193776753527"
],
"PendingCoinbaseMerkleTree": [
"21962074494103541153175746450273873003299668759086391980006382367241943398196",
"2903435713642676558047328375873609628346075739786101737671585224825766548393",
"25831764682100331646870313396659195191400312071282528592914032765816857800473"
]
};
let prefixHashesLegacy = {
"MinaReceiptUC*******": [
"20070382753578399401327804098717363060981792725858206382885984326454503485317",
"9741317264439603248522437238966700420795613627770380489972854421227543398236",
"7781138462994911643117614691750702461577493967611677045054456828859235572948"
],
"MinaSignatureMainnet": [
"25220214331362653986409717908235786107802222826119905443072293294098933388948",
"7563646774167489166725044360539949525624365058064455335567047240620397351731",
"171774671134240704318655896509797243441784148630375331692878460323037832932"
],
"CodaSignature*******": [
"28132119227444686413214523693400847740858213284875453355294308721084881982354",
"24895072146662946646133617369498198544578131474807621989761680811592073367193",
"3216013753133880902260672769141972972810073620591719805178695684388949134646"
]
};
let versionBytes = {
"tokenIdKey": 28,
"receiptChainHash": 12,
Expand Down
45 changes: 28 additions & 17 deletions js/web/web-backend.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,23 @@ import snarkyJsWebSrc from 'string:../../../web_bindings/snarky_js_web.bc.js';
export { initSnarkyJS, withThreadPool };

let wasm = plonkWasm();
globalThis.plonk_wasm = wasm;

let init = wasm.default;
/**
* @type {Worker}
* @type {Promise<Worker>}
*/
let workerPromise;
/**
* @type {number | undefined}
*/
let worker;
let numWorkers = undefined;

async function initSnarkyJS() {
const memory = allocateWasmMemoryForUserAgent(navigator.userAgent);
await init(undefined, memory);

let module = init.__wbindgen_wasm_module;
let numWorkers = await getEfficientNumWorkers();
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change 1 to this file: we don't call getEfficientNumWorkers() right away, because it's very expensive (inspects the device GPU via WebGL). Instead, we call it before we need workers the first time, which is likely a slow operation anyway

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great optimization! Great for cases where we only need constants since that can all be done in JS, right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes!


worker = inlineWorker(srcFromFunctionModule(mainWorker));
await workerCall(worker, 'start', { memory, module, numWorkers });
globalThis.plonk_wasm = overrideBindings(wasm, worker);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change 2 to this file: creating the main worker and waiting for its promise to return (which is after all its child workers are started) is very slow. Therefore, we do this in a way that is not blocking our top-level await. This is fine, the main worker will only be needed when we do our first expensive operation and we await the promise at that time


// we have two approaches to run the .bc.js code after its dependencies are ready, without fetching an additional script:

Expand All @@ -39,11 +40,23 @@ async function initSnarkyJS() {
// 2. include the code as string and eval it:
// (this works because it breaks out of strict mode)
new Function(snarkyJsWebSrc)();

workerPromise = new Promise((resolve) => {
setTimeout(async () => {
let worker = inlineWorker(srcFromFunctionModule(mainWorker));
await workerCall(worker, 'start', { memory, module });
overrideBindings(globalThis.plonk_wasm, worker);
resolve(worker);
}, 0);
});
}

async function withThreadPool(run) {
if (worker === undefined) throw Error('need to initialize worker first');
await workerCall(worker, 'initThreadPool');
if (workerPromise === undefined)
throw Error('need to initialize worker first');
let worker = await workerPromise;
numWorkers ??= await getEfficientNumWorkers();
await workerCall(worker, 'initThreadPool', numWorkers);
let result;
try {
result = await run();
Expand All @@ -61,7 +74,7 @@ async function mainWorker() {

let isInitialized = false;
let data = await waitForMessage(self, 'start');
let { module, memory, numWorkers } = data.message;
let { module, memory } = data.message;

onMessage(self, 'run', ({ name, args, u32_ptr }) => {
let functionSpec = spec[name];
Expand All @@ -88,7 +101,7 @@ async function mainWorker() {
});

workerExport(self, {
async initThreadPool() {
async initThreadPool(numWorkers) {
if (!isInitialized) {
isInitialized = true;
await wasm.initThreadPool(numWorkers);
Expand All @@ -97,7 +110,7 @@ async function mainWorker() {
async exitThreadPool() {
if (isInitialized) {
isInitialized = false;
await wasm.exitThreadPool(numWorkers);
await wasm.exitThreadPool();
}
},
});
Expand All @@ -113,11 +126,10 @@ mainWorker.deps = [
waitForMessage,
];

function overrideBindings(wasm, worker) {
let spec = workerSpec(wasm);
let plonk_wasm_ = { ...wasm };
function overrideBindings(plonk_wasm, worker) {
let spec = workerSpec(plonk_wasm);
for (let key in spec) {
plonk_wasm_[key] = (...args) => {
plonk_wasm[key] = (...args) => {
let u32_ptr = wasm.create_zero_u32_ptr();
worker.postMessage({
type: 'run',
Expand All @@ -136,7 +148,6 @@ function overrideBindings(wasm, worker) {
}
};
}
return plonk_wasm_;
}

// helpers for main thread <-> worker communication
Expand Down
Loading