Skip to content

Commit

Permalink
add multithreading support
Browse files Browse the repository at this point in the history
  • Loading branch information
JohnDonavon committed Mar 8, 2023
1 parent 162b01e commit 679d456
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 95 deletions.
6 changes: 6 additions & 0 deletions .cargo/config
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
[target.'cfg(not(target_arch = "wasm32"))']
rustflags = ["-C", "target-cpu=native"]

[target.wasm32-unknown-unknown]
rustflags = ["-C", "target-feature=+atomics,+bulk-memory,+mutable-globals"]

[unstable]
build-std = ["panic_abort", "std"]
20 changes: 20 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 12 additions & 2 deletions wasm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,13 @@ features = [ "preserve_order" ]
path="../../snarkVM/synthesizer"
version = "0.9.13"
default-features = false
features = [ "wasm" ]
features = [ "wasm", "parallel", "web" ]

[dependencies.snarkvm-console]
path="../../snarkVM/console"
version = "0.9.13"
default-features = false
features = ["parallel"]

[dependencies.snarkvm-wasm]
path="../../snarkVM/wasm"
Expand Down Expand Up @@ -82,12 +83,21 @@ version = "0.1.7"
[dependencies.rand_chacha]
version = "0.3.1"

[dependencies.wasm-bindgen-rayon]
version = "1.0"

[dependencies.rayon]
version = "1.5"

[dev-dependencies.wasm-bindgen-test]
version = "0.3.33"

[profile.release]
opt-level = 3
lto = true

[package.metadata.wasm-pack.profile.debug]
wasm-opt = ["-O4"]

[package.metadata.wasm-pack.profile.release]
wasm-opt = ["-O4", "--fast-math"]
wasm-opt = ["-O4"]
1 change: 1 addition & 0 deletions wasm/rust-toolchain
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
nightly-2022-12-12
2 changes: 2 additions & 0 deletions wasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,5 @@ pub mod program;
pub use program::*;

pub(crate) mod types;

pub use wasm_bindgen_rayon::init_thread_pool;
184 changes: 93 additions & 91 deletions website/src/workers/worker.js
Original file line number Diff line number Diff line change
@@ -1,103 +1,105 @@
import "babel-polyfill";
import init, * as aleo from '@aleohq/wasm';

await init();

await aleo.initThreadPool(navigator.hardwareConcurrency);

let TRANSFER_KEY;
let INCLUSION_KEY;

import("@aleohq/wasm").then(aleo => {
self.addEventListener("message", ev => {
// Load Transfer Prover Key
if (ev.data.type == 'ALEO_LOAD_TRANSFER_KEY') {
console.log('Web worker: Deserialize Transfer Key...');
let startTime = performance.now();
TRANSFER_KEY = aleo.ProvingKey.from_bytes(ev.data.transferProverBytes);
console.log(`Web worker: Deserialized transfer proving key Completed: ${performance.now() - startTime} ms`);
self.postMessage({ type: 'TRANSFER_KEY_DESERIALIZED' });
}
// Load Inclusion Prover Key
else if (ev.data.type == 'ALEO_LOAD_INCLUSION_KEY') {
console.log('Web worker: Deserialize Inclusion Key...');
console.log(ev.data);
let startTime = performance.now();
INCLUSION_KEY = aleo.ProvingKey.from_bytes(ev.data.inclusionProverBytes);
console.log(`Web worker: Deserialized inclusion proving key Completed: ${performance.now() - startTime} ms`);
self.postMessage({ type: 'INCLUSION_KEY_DESERIALIZED' });
}
// Create Transition
else if (ev.data.type == 'ALEO_CREATE_TRANSITION') {
const {
privateKey,
toAddress,
amount,
plaintext
} = ev.data;
const program = aleo.Program.credits();
self.addEventListener("message", ev => {
// Load Transfer Prover Key
if (ev.data.type == 'ALEO_LOAD_TRANSFER_KEY') {
console.log('Web worker: Deserialize Transfer Key...');
let startTime = performance.now();
TRANSFER_KEY = aleo.ProvingKey.from_bytes(ev.data.transferProverBytes);
console.log(`Web worker: Deserialized transfer proving key Completed: ${performance.now() - startTime} ms`);
self.postMessage({ type: 'TRANSFER_KEY_DESERIALIZED' });
}
// Load Inclusion Prover Key
else if (ev.data.type == 'ALEO_LOAD_INCLUSION_KEY') {
console.log('Web worker: Deserialize Inclusion Key...');
console.log(ev.data);
let startTime = performance.now();
INCLUSION_KEY = aleo.ProvingKey.from_bytes(ev.data.inclusionProverBytes);
console.log(`Web worker: Deserialized inclusion proving key Completed: ${performance.now() - startTime} ms`);
self.postMessage({ type: 'INCLUSION_KEY_DESERIALIZED' });
}
// Create Transition
else if (ev.data.type == 'ALEO_CREATE_TRANSITION') {
const {
privateKey,
toAddress,
amount,
plaintext
} = ev.data;
const program = aleo.Program.credits();

console.log('Web worker: Building Transition for program: ', program.id());
let startTime = performance.now();
console.log('Web worker: Building Transition for program: ', program.id());
let startTime = performance.now();

// Prepare inputs
const pK = aleo.PrivateKey.from_string(privateKey);
const inputs = JSON.stringify([plaintext, toAddress, `${amount}u64`])
// Prepare inputs
const pK = aleo.PrivateKey.from_string(privateKey);
const inputs = JSON.stringify([plaintext, toAddress, `${amount}u64`])

const transition = aleo.TransactionBuilder.build_transition(
program,
'transfer',
inputs,
pK,
TRANSFER_KEY
);
console.log(`Web worker: Transition Completed: ${performance.now() - startTime} ms`);
console.log(`Transition: ${transition}`);
self.postMessage({ type: 'TRANSITION_COMPLETED', transition });
}
else if (ev.data.type == 'ALEO_CREATE_TRANSACTION') {
const {
transition,
inputIds,
stateRoot,
statePaths
} = ev.data;
const transition = aleo.TransactionBuilder.build_transition(
program,
'transfer',
inputs,
pK,
TRANSFER_KEY
);
console.log(`Web worker: Transition Completed: ${performance.now() - startTime} ms`);
console.log(`Transition: ${transition}`);
self.postMessage({ type: 'TRANSITION_COMPLETED', transition });
}
else if (ev.data.type == 'ALEO_CREATE_TRANSACTION') {
const {
transition,
inputIds,
stateRoot,
statePaths
} = ev.data;

console.log('Web worker: Building Transaction...');
let startTime = performance.now();
let transitionParsed = JSON.parse(transition);
let inputIdsParsed = JSON.parse(inputIds);
console.log('Web worker: Building Transaction...');
let startTime = performance.now();
let transitionParsed = JSON.parse(transition);
let inputIdsParsed = JSON.parse(inputIds);

const transaction = aleo.TransactionBuilder.build_transaction(
INCLUSION_KEY,
JSON.stringify([{ transition: transitionParsed, input_ids: inputIdsParsed}]),
stateRoot,
statePaths
);
console.log(`Web worker: Transaction Completed: ${performance.now() - startTime} ms`);
console.log(`Transaction: ${transaction}`);
self.postMessage({ type: 'TRANSACTION_COMPLETED', transaction });
}
else if (ev.data.type == 'ALEO_VERIFY_TRANSACTION') {
const {
transaction,
transferVerifierBytes,
inclusionVerifierBytes
} = ev.data;
console.log('Web worker: Verifying Transaction...');
let startTime = performance.now();
const transaction = aleo.TransactionBuilder.build_transaction(
INCLUSION_KEY,
JSON.stringify([{ transition: transitionParsed, input_ids: inputIdsParsed}]),
stateRoot,
statePaths
);
console.log(`Web worker: Transaction Completed: ${performance.now() - startTime} ms`);
console.log(`Transaction: ${transaction}`);
self.postMessage({ type: 'TRANSACTION_COMPLETED', transaction });
}
else if (ev.data.type == 'ALEO_VERIFY_TRANSACTION') {
const {
transaction,
transferVerifierBytes,
inclusionVerifierBytes
} = ev.data;
console.log('Web worker: Verifying Transaction...');
let startTime = performance.now();

const program = aleo.Program.credits();
const functionName = 'transfer';
const transferVerifyingKey = aleo.VerifyingKey.from_bytes(transferVerifierBytes);
const inclusionVerifyingKey = aleo.VerifyingKey.from_bytes(inclusionVerifierBytes);
const program = aleo.Program.credits();
const functionName = 'transfer';
const transferVerifyingKey = aleo.VerifyingKey.from_bytes(transferVerifierBytes);
const inclusionVerifyingKey = aleo.VerifyingKey.from_bytes(inclusionVerifierBytes);

const verified = aleo.TransactionBuilder.verify_transaction(
transaction,
program,
functionName,
transferVerifyingKey,
inclusionVerifyingKey,
true,
true
);
console.log(`Web worker: Transaction Verified: ${performance.now() - startTime} ms`);
console.log(verified);
}
});
const verified = aleo.TransactionBuilder.verify_transaction(
transaction,
program,
functionName,
transferVerifyingKey,
inclusionVerifyingKey,
true,
true
);
console.log(`Web worker: Transaction Verified: ${performance.now() - startTime} ms`);
console.log(verified);
}
});
10 changes: 8 additions & 2 deletions website/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ const appConfig = {
},
devServer: {
port: 3000,
headers: {
'Cross-Origin-Opener-Policy': 'same-origin',
'Cross-Origin-Embedder-Policy': 'require-corp'
},
},
module: {
rules: [
Expand All @@ -34,7 +38,8 @@ const appConfig = {
maxAssetSize: 8388608
},
experiments: {
asyncWebAssembly: true
asyncWebAssembly: true,
topLevelAwait: true
},
devtool: 'source-map',
}
Expand All @@ -51,7 +56,8 @@ const workerConfig = {
filename: "worker.js"
},
experiments: {
asyncWebAssembly: true
asyncWebAssembly: true,
topLevelAwait: true
},
devtool: 'source-map',
};
Expand Down

0 comments on commit 679d456

Please sign in to comment.