Merge pull request #14 from mCaptcha/js-bench
Collect JavaScript polyfill benchmark using mCaptcha/survey
This commit is contained in:
commit
4f224d782a
19 changed files with 1833 additions and 1322 deletions
.eslintrc.jsCargo.toml
config
migrations
package-lock.jsonpackage.jsonsrc
templates
webpack.config.jsyarn.lock
|
@ -12,6 +12,7 @@ module.exports = {
|
||||||
plugins: ["@typescript-eslint"],
|
plugins: ["@typescript-eslint"],
|
||||||
rules: {
|
rules: {
|
||||||
"@typescript-eslint/no-explicit-any": "off",
|
"@typescript-eslint/no-explicit-any": "off",
|
||||||
|
"@typescript-eslint/no-var-requires": "off",
|
||||||
"@typescript-eslint/ban-types": "off",
|
"@typescript-eslint/ban-types": "off",
|
||||||
indent: ["error", 2],
|
indent: ["error", 2],
|
||||||
"linebreak-style": ["error", "unix"],
|
"linebreak-style": ["error", "unix"],
|
||||||
|
|
|
@ -66,7 +66,7 @@ mime = "0.3.16"
|
||||||
|
|
||||||
#sailfish = "0.3.2"
|
#sailfish = "0.3.2"
|
||||||
tracing = { version = "0.1.37", features = ["log"] }
|
tracing = { version = "0.1.37", features = ["log"] }
|
||||||
tera = "1.17.1"
|
tera = { version="1.17.1", features=["builtins"]}
|
||||||
|
|
||||||
#tokio = "1.11.0"
|
#tokio = "1.11.0"
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
debug = true
|
debug = true
|
||||||
allow_registration = true
|
allow_registration = true
|
||||||
source_code = "https://github.com/mcaptcha/survey"
|
source_code = "https://github.com/mcaptcha/survey"
|
||||||
default_campaign = "b6b261fa-3ef9-4d7f-8852-339b8f81bb01"
|
default_campaign = "4e951e01-71ee-4a18-9b97-782965495ae3"
|
||||||
support_email="support@example.org"
|
support_email="support@example.org"
|
||||||
|
|
||||||
[server]
|
[server]
|
||||||
|
|
2
migrations/20230131114916_survey_bench_date.sql
Normal file
2
migrations/20230131114916_survey_bench_date.sql
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
ALTER TABLE survey_responses
|
||||||
|
ADD COLUMN submitted_at TIMESTAMPTZ NOT NULL DEFAULT now();
|
18
migrations/20230201101934_survey_bench_type.sql
Normal file
18
migrations/20230201101934_survey_bench_type.sql
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
CREATE TABLE IF NOT EXISTS survey_bench_type (
|
||||||
|
name VARCHAR(30) UNIQUE NOT NULL,
|
||||||
|
ID SERIAL PRIMARY KEY NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO survey_bench_type (name) VALUES ('wasm');
|
||||||
|
INSERT INTO survey_bench_type (name) VALUES ('js');
|
||||||
|
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION id_in_survey_bench_type(iname varchar)
|
||||||
|
RETURNS int LANGUAGE SQL AS $$
|
||||||
|
SELECT ID FROM survey_bench_type WHERE name = name;
|
||||||
|
$$;
|
||||||
|
|
||||||
|
|
||||||
|
ALTER TABLE survey_responses
|
||||||
|
ADD COLUMN submission_bench_type_id INTEGER references survey_bench_type(ID) NOT NULL
|
||||||
|
DEFAULT id_in_survey_bench_type('wasm');
|
45
package-lock.json
generated
45
package-lock.json
generated
|
@ -8,7 +8,8 @@
|
||||||
"name": "mcaptcha-survey",
|
"name": "mcaptcha-survey",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mcaptcha/pow-wasm": "0.1.0-alpha-1",
|
"@mcaptcha/pow_sha256-polyfill": "^0.1.0-alpha-1",
|
||||||
|
"@mcaptcha/pow-wasm": "^0.1.0-alpha-1",
|
||||||
"@mcaptcha/vanilla-glue": "^0.1.0-alpha-3"
|
"@mcaptcha/vanilla-glue": "^0.1.0-alpha-3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -18,7 +19,7 @@
|
||||||
"@types/sinon": "^10.0.0",
|
"@types/sinon": "^10.0.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.0.0",
|
"@typescript-eslint/eslint-plugin": "^5.0.0",
|
||||||
"@typescript-eslint/parser": "^5.0.0",
|
"@typescript-eslint/parser": "^5.0.0",
|
||||||
"@wasm-tool/wasm-pack-plugin": "^1.4.0",
|
"@wasm-tool/wasm-pack-plugin": "^1.6.0",
|
||||||
"dart-sass": "^1.25.0",
|
"dart-sass": "^1.25.0",
|
||||||
"eslint": "^8.0.1",
|
"eslint": "^8.0.1",
|
||||||
"jest": "^27.2.5",
|
"jest": "^27.2.5",
|
||||||
|
@ -1439,6 +1440,29 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"node_modules/@mcaptcha/pow_sha256-polyfill": {
|
||||||
|
"version": "0.1.0-alpha-1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@mcaptcha/pow_sha256-polyfill/-/pow_sha256-polyfill-0.1.0-alpha-1.tgz",
|
||||||
|
"integrity": "sha512-lnQNBCOnVI9BunHP8FGCsGs310GguQWdxSspXlvWcrLwgl86aq0hlBzZfOV+szG/jeTRAMry0He3MrD/kbqB/Q==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "individual",
|
||||||
|
"url": "http://mcaptcha.org/donate"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "liberapay",
|
||||||
|
"url": "https://liberapay.com/mcaptcha"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "individual",
|
||||||
|
"url": "http://batsense.net/donate"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "liberapay",
|
||||||
|
"url": "https://liberapay.com/realaravinth"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"node_modules/@mcaptcha/pow-wasm": {
|
"node_modules/@mcaptcha/pow-wasm": {
|
||||||
"version": "0.1.0-alpha-1",
|
"version": "0.1.0-alpha-1",
|
||||||
"resolved": "https://registry.npmjs.org/@mcaptcha/pow-wasm/-/pow-wasm-0.1.0-alpha-1.tgz",
|
"resolved": "https://registry.npmjs.org/@mcaptcha/pow-wasm/-/pow-wasm-0.1.0-alpha-1.tgz",
|
||||||
|
@ -2919,9 +2943,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/caniuse-lite": {
|
"node_modules/caniuse-lite": {
|
||||||
"version": "1.0.30001447",
|
"version": "1.0.30001448",
|
||||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001447.tgz",
|
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001448.tgz",
|
||||||
"integrity": "sha512-bdKU1BQDPeEXe9A39xJnGtY0uRq/z5osrnXUw0TcK+EYno45Y+U7QU9HhHEyzvMDffpYadFXi3idnSNkcwLkTw==",
|
"integrity": "sha512-tq2YI+MJnooG96XpbTRYkBxLxklZPOdLmNIOdIhvf7SNJan6u5vCKum8iT7ZfCt70m1GPkuC7P3TtX6UuhupuA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -11164,6 +11188,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/@mcaptcha/core-glue/-/core-glue-0.1.0-alpha-5.tgz",
|
"resolved": "https://registry.npmjs.org/@mcaptcha/core-glue/-/core-glue-0.1.0-alpha-5.tgz",
|
||||||
"integrity": "sha512-16qWm5O5X0Y9LXULULaAks8Vf9FNlUUBcR5KDt49aWhFhG5++JzxNmCwQM9EJSHNU7y0U+FdyAWcGmjfKlkRLA=="
|
"integrity": "sha512-16qWm5O5X0Y9LXULULaAks8Vf9FNlUUBcR5KDt49aWhFhG5++JzxNmCwQM9EJSHNU7y0U+FdyAWcGmjfKlkRLA=="
|
||||||
},
|
},
|
||||||
|
"@mcaptcha/pow_sha256-polyfill": {
|
||||||
|
"version": "0.1.0-alpha-1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@mcaptcha/pow_sha256-polyfill/-/pow_sha256-polyfill-0.1.0-alpha-1.tgz",
|
||||||
|
"integrity": "sha512-lnQNBCOnVI9BunHP8FGCsGs310GguQWdxSspXlvWcrLwgl86aq0hlBzZfOV+szG/jeTRAMry0He3MrD/kbqB/Q=="
|
||||||
|
},
|
||||||
"@mcaptcha/pow-wasm": {
|
"@mcaptcha/pow-wasm": {
|
||||||
"version": "0.1.0-alpha-1",
|
"version": "0.1.0-alpha-1",
|
||||||
"resolved": "https://registry.npmjs.org/@mcaptcha/pow-wasm/-/pow-wasm-0.1.0-alpha-1.tgz",
|
"resolved": "https://registry.npmjs.org/@mcaptcha/pow-wasm/-/pow-wasm-0.1.0-alpha-1.tgz",
|
||||||
|
@ -12363,9 +12392,9 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"caniuse-lite": {
|
"caniuse-lite": {
|
||||||
"version": "1.0.30001447",
|
"version": "1.0.30001448",
|
||||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001447.tgz",
|
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001448.tgz",
|
||||||
"integrity": "sha512-bdKU1BQDPeEXe9A39xJnGtY0uRq/z5osrnXUw0TcK+EYno45Y+U7QU9HhHEyzvMDffpYadFXi3idnSNkcwLkTw==",
|
"integrity": "sha512-tq2YI+MJnooG96XpbTRYkBxLxklZPOdLmNIOdIhvf7SNJan6u5vCKum8iT7ZfCt70m1GPkuC7P3TtX6UuhupuA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"chalk": {
|
"chalk": {
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
"@types/sinon": "^10.0.0",
|
"@types/sinon": "^10.0.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.0.0",
|
"@typescript-eslint/eslint-plugin": "^5.0.0",
|
||||||
"@typescript-eslint/parser": "^5.0.0",
|
"@typescript-eslint/parser": "^5.0.0",
|
||||||
"@wasm-tool/wasm-pack-plugin": "^1.4.0",
|
"@wasm-tool/wasm-pack-plugin": "^1.6.0",
|
||||||
"dart-sass": "^1.25.0",
|
"dart-sass": "^1.25.0",
|
||||||
"eslint": "^8.0.1",
|
"eslint": "^8.0.1",
|
||||||
"jest": "^27.2.5",
|
"jest": "^27.2.5",
|
||||||
|
@ -33,6 +33,7 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@mcaptcha/vanilla-glue": "^0.1.0-alpha-3",
|
"@mcaptcha/vanilla-glue": "^0.1.0-alpha-3",
|
||||||
"@mcaptcha/pow-wasm": "0.1.0-alpha-1"
|
"@mcaptcha/pow_sha256-polyfill": "^0.1.0-alpha-1",
|
||||||
|
"@mcaptcha/pow-wasm": "^0.1.0-alpha-1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,12 +24,15 @@ use uuid::Uuid;
|
||||||
|
|
||||||
use super::{get_admin_check_login, get_uuid};
|
use super::{get_admin_check_login, get_uuid};
|
||||||
use crate::api::v1::bench::Bench;
|
use crate::api::v1::bench::Bench;
|
||||||
|
use crate::api::v1::bench::SubmissionType;
|
||||||
use crate::errors::*;
|
use crate::errors::*;
|
||||||
use crate::AppData;
|
use crate::AppData;
|
||||||
|
|
||||||
pub mod routes {
|
pub mod routes {
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use super::ResultsPage;
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
|
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
|
||||||
pub struct Campaign {
|
pub struct Campaign {
|
||||||
pub add: &'static str,
|
pub add: &'static str,
|
||||||
|
@ -62,13 +65,33 @@ pub mod routes {
|
||||||
self.delete.replace("{uuid}", campaign_id)
|
self.delete.replace("{uuid}", campaign_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_results_route(&self, campaign_id: &str) -> String {
|
pub fn get_results_route(
|
||||||
self.results.replace("{uuid}", campaign_id)
|
&self,
|
||||||
|
campaign_id: &str,
|
||||||
|
modifier: Option<ResultsPage>,
|
||||||
|
) -> String {
|
||||||
|
let mut res = self.results.replace("{uuid}", campaign_id);
|
||||||
|
if let Some(modifier) = modifier {
|
||||||
|
if let Some(page) = modifier.page {
|
||||||
|
res = format!("{res}?page={page}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(bench_type) = modifier.bench_type {
|
||||||
|
if modifier.page.is_some() {
|
||||||
|
res = format!("{res}&bench_type={}", bench_type.to_string());
|
||||||
|
} else {
|
||||||
|
res = format!("{res}?bench_type={}", bench_type.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod runners {
|
pub mod runners {
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
use futures::try_join;
|
use futures::try_join;
|
||||||
|
|
||||||
use crate::api::v1::bench::Bench;
|
use crate::api::v1::bench::Bench;
|
||||||
|
@ -163,10 +186,12 @@ pub mod runners {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct InternalSurveyResp {
|
struct InternalSurveyResp {
|
||||||
id: i32,
|
id: i32,
|
||||||
|
submitted_at: OffsetDateTime,
|
||||||
user_id: Uuid,
|
user_id: Uuid,
|
||||||
threads: Option<i32>,
|
threads: Option<i32>,
|
||||||
device_user_provided: String,
|
device_user_provided: String,
|
||||||
device_software_recognised: String,
|
device_software_recognised: String,
|
||||||
|
name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -190,27 +215,76 @@ pub mod runners {
|
||||||
data: &AppData,
|
data: &AppData,
|
||||||
page: usize,
|
page: usize,
|
||||||
limit: usize,
|
limit: usize,
|
||||||
|
filter: Option<SubmissionType>,
|
||||||
) -> ServiceResult<Vec<SurveyResponse>> {
|
) -> ServiceResult<Vec<SurveyResponse>> {
|
||||||
let mut db_responses = sqlx::query_as!(
|
let mut db_responses = if let Some(filter) = filter {
|
||||||
|
sqlx::query_as!(
|
||||||
InternalSurveyResp,
|
InternalSurveyResp,
|
||||||
"SELECT
|
"SELECT
|
||||||
ID,
|
survey_responses.ID,
|
||||||
device_software_recognised,
|
survey_responses.device_software_recognised,
|
||||||
threads,
|
survey_responses.threads,
|
||||||
user_id,
|
survey_responses.user_id,
|
||||||
device_user_provided
|
survey_responses.submitted_at,
|
||||||
|
survey_responses.device_user_provided,
|
||||||
|
survey_bench_type.name
|
||||||
FROM
|
FROM
|
||||||
survey_responses
|
survey_responses
|
||||||
|
INNER JOIN survey_bench_type ON
|
||||||
|
survey_responses.submission_bench_type_id = survey_bench_type.ID
|
||||||
WHERE
|
WHERE
|
||||||
campaign_id = (
|
survey_bench_type.name = $3
|
||||||
|
AND
|
||||||
|
survey_responses.campaign_id = (
|
||||||
SELECT ID FROM survey_campaigns
|
SELECT ID FROM survey_campaigns
|
||||||
WHERE
|
WHERE
|
||||||
ID = $1
|
ID = $1
|
||||||
AND
|
AND
|
||||||
user_id = (SELECT ID FROM survey_admins WHERE name = $2)
|
user_id = (SELECT ID FROM survey_admins WHERE name = $2)
|
||||||
)
|
)
|
||||||
LIMIT $3 OFFSET $4
|
LIMIT $4 OFFSET $5",
|
||||||
",
|
uuid,
|
||||||
|
username,
|
||||||
|
filter.to_string(),
|
||||||
|
limit as i32,
|
||||||
|
page as i32,
|
||||||
|
)
|
||||||
|
.fetch_all(&data.db)
|
||||||
|
.await?
|
||||||
|
} else {
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct I {
|
||||||
|
id: Option<i32>,
|
||||||
|
submitted_at: Option<OffsetDateTime>,
|
||||||
|
user_id: Option<Uuid>,
|
||||||
|
threads: Option<i32>,
|
||||||
|
device_user_provided: Option<String>,
|
||||||
|
device_software_recognised: Option<String>,
|
||||||
|
name: Option<String>,
|
||||||
|
}
|
||||||
|
let mut i = sqlx::query_as!(
|
||||||
|
I,
|
||||||
|
"SELECT
|
||||||
|
survey_responses.ID,
|
||||||
|
survey_responses.device_software_recognised,
|
||||||
|
survey_responses.threads,
|
||||||
|
survey_responses.user_id,
|
||||||
|
survey_responses.submitted_at,
|
||||||
|
survey_responses.device_user_provided,
|
||||||
|
survey_bench_type.name
|
||||||
|
FROM
|
||||||
|
survey_responses
|
||||||
|
INNER JOIN survey_bench_type ON
|
||||||
|
survey_responses.submission_bench_type_id = survey_bench_type.ID
|
||||||
|
WHERE
|
||||||
|
survey_responses.campaign_id = (
|
||||||
|
SELECT ID FROM survey_campaigns
|
||||||
|
WHERE
|
||||||
|
ID = $1
|
||||||
|
AND
|
||||||
|
user_id = (SELECT ID FROM survey_admins WHERE name = $2)
|
||||||
|
)
|
||||||
|
LIMIT $3 OFFSET $4",
|
||||||
uuid,
|
uuid,
|
||||||
username,
|
username,
|
||||||
limit as i32,
|
limit as i32,
|
||||||
|
@ -219,6 +293,21 @@ pub mod runners {
|
||||||
.fetch_all(&data.db)
|
.fetch_all(&data.db)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
let mut res = Vec::with_capacity(i.len());
|
||||||
|
i.drain(0..).for_each(|x| {
|
||||||
|
res.push(InternalSurveyResp {
|
||||||
|
id: x.id.unwrap(),
|
||||||
|
submitted_at: x.submitted_at.unwrap(),
|
||||||
|
user_id: x.user_id.unwrap(),
|
||||||
|
threads: x.threads,
|
||||||
|
device_user_provided: x.device_user_provided.unwrap(),
|
||||||
|
device_software_recognised: x.device_software_recognised.unwrap(),
|
||||||
|
name: x.name.unwrap(),
|
||||||
|
})
|
||||||
|
});
|
||||||
|
res
|
||||||
|
};
|
||||||
|
|
||||||
let mut responses = Vec::with_capacity(db_responses.len());
|
let mut responses = Vec::with_capacity(db_responses.len());
|
||||||
for r in db_responses.drain(0..) {
|
for r in db_responses.drain(0..) {
|
||||||
let benches_fut = sqlx::query_as!(
|
let benches_fut = sqlx::query_as!(
|
||||||
|
@ -256,7 +345,9 @@ pub mod runners {
|
||||||
user,
|
user,
|
||||||
device_user_provided: r.device_user_provided,
|
device_user_provided: r.device_user_provided,
|
||||||
device_software_recognised: r.device_software_recognised,
|
device_software_recognised: r.device_software_recognised,
|
||||||
|
submitted_at: r.submitted_at.unix_timestamp(),
|
||||||
id: r.id as usize,
|
id: r.id as usize,
|
||||||
|
submission_type: SubmissionType::from_str(&r.name).unwrap(),
|
||||||
threads: r.threads.map(|t| t as usize),
|
threads: r.threads.map(|t| t as usize),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -314,6 +405,8 @@ pub struct SurveyResponse {
|
||||||
pub device_software_recognised: String,
|
pub device_software_recognised: String,
|
||||||
pub id: usize,
|
pub id: usize,
|
||||||
pub threads: Option<usize>,
|
pub threads: Option<usize>,
|
||||||
|
pub submitted_at: i64,
|
||||||
|
pub submission_type: SubmissionType,
|
||||||
pub benches: Vec<Bench>,
|
pub benches: Vec<Bench>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -364,12 +457,17 @@ pub fn services(cfg: &mut web::ServiceConfig) {
|
||||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
|
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
|
||||||
pub struct ResultsPage {
|
pub struct ResultsPage {
|
||||||
page: Option<usize>,
|
page: Option<usize>,
|
||||||
|
pub bench_type: Option<SubmissionType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ResultsPage {
|
impl ResultsPage {
|
||||||
pub fn page(&self) -> usize {
|
pub fn page(&self) -> usize {
|
||||||
self.page.unwrap_or(0)
|
self.page.unwrap_or(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn new(page: Option<usize>, bench_type: Option<SubmissionType>) -> Self {
|
||||||
|
Self { page, bench_type }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_web_codegen_const_routes::get(
|
#[actix_web_codegen_const_routes::get(
|
||||||
|
@ -383,9 +481,12 @@ pub async fn get_campaign_resutls(
|
||||||
data: AppData,
|
data: AppData,
|
||||||
) -> ServiceResult<impl Responder> {
|
) -> ServiceResult<impl Responder> {
|
||||||
let username = id.identity().unwrap();
|
let username = id.identity().unwrap();
|
||||||
|
let query = query.into_inner();
|
||||||
let page = query.page();
|
let page = query.page();
|
||||||
|
|
||||||
let results = runners::get_results(&username, &path, &data, page, 50).await?;
|
let results =
|
||||||
|
runners::get_results(&username, &path, &data, page, 50, query.bench_type)
|
||||||
|
.await?;
|
||||||
|
|
||||||
Ok(HttpResponse::Ok().json(results))
|
Ok(HttpResponse::Ok().json(results))
|
||||||
}
|
}
|
||||||
|
@ -408,6 +509,7 @@ async fn add(
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::api::v1::bench::Submission;
|
use crate::api::v1::bench::Submission;
|
||||||
|
use crate::api::v1::bench::SubmissionType;
|
||||||
use crate::errors::*;
|
use crate::errors::*;
|
||||||
use crate::tests::*;
|
use crate::tests::*;
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
@ -479,6 +581,7 @@ mod tests {
|
||||||
device_software_recognised: DEVICE_SOFTWARE_RECOGNISED.into(),
|
device_software_recognised: DEVICE_SOFTWARE_RECOGNISED.into(),
|
||||||
threads: THREADS,
|
threads: THREADS,
|
||||||
benches: BENCHES.clone(),
|
benches: BENCHES.clone(),
|
||||||
|
submission_type: SubmissionType::Wasm,
|
||||||
};
|
};
|
||||||
|
|
||||||
let _proof =
|
let _proof =
|
||||||
|
@ -493,6 +596,7 @@ mod tests {
|
||||||
&AppData::new(data.clone()),
|
&AppData::new(data.clone()),
|
||||||
0,
|
0,
|
||||||
50,
|
50,
|
||||||
|
None,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -503,6 +607,34 @@ mod tests {
|
||||||
let mut r = BENCHES.clone();
|
let mut r = BENCHES.clone();
|
||||||
r.sort_by(|a, b| a.difficulty.cmp(&b.difficulty));
|
r.sort_by(|a, b| a.difficulty.cmp(&b.difficulty));
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
super::runners::get_results(
|
||||||
|
NAME,
|
||||||
|
&uuid::Uuid::parse_str(&campaign.campaign_id).unwrap(),
|
||||||
|
&AppData::new(data.clone()),
|
||||||
|
0,
|
||||||
|
50,
|
||||||
|
Some(SubmissionType::Wasm),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap(),
|
||||||
|
responses
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
super::runners::get_results(
|
||||||
|
NAME,
|
||||||
|
&uuid::Uuid::parse_str(&campaign.campaign_id).unwrap(),
|
||||||
|
&AppData::new(data.clone()),
|
||||||
|
0,
|
||||||
|
50,
|
||||||
|
Some(SubmissionType::Js),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap(),
|
||||||
|
Vec::default()
|
||||||
|
);
|
||||||
|
|
||||||
assert_eq!(l, r);
|
assert_eq!(l, r);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
responses[0].device_software_recognised,
|
responses[0].device_software_recognised,
|
||||||
|
@ -515,7 +647,7 @@ mod tests {
|
||||||
&V1_API_ROUTES
|
&V1_API_ROUTES
|
||||||
.admin
|
.admin
|
||||||
.campaign
|
.campaign
|
||||||
.get_results_route(&campaign.campaign_id),
|
.get_results_route(&campaign.campaign_id, None),
|
||||||
cookies.clone()
|
cookies.clone()
|
||||||
);
|
);
|
||||||
assert_eq!(results_resp.status(), StatusCode::OK);
|
assert_eq!(results_resp.status(), StatusCode::OK);
|
||||||
|
|
|
@ -169,6 +169,28 @@ pub struct Submission {
|
||||||
pub device_software_recognised: String,
|
pub device_software_recognised: String,
|
||||||
pub threads: i32,
|
pub threads: i32,
|
||||||
pub benches: Vec<Bench>,
|
pub benches: Vec<Bench>,
|
||||||
|
pub submission_type: SubmissionType,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "lowercase")]
|
||||||
|
pub enum SubmissionType {
|
||||||
|
Wasm,
|
||||||
|
Js,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToString for SubmissionType {
|
||||||
|
fn to_string(&self) -> String {
|
||||||
|
let s = serde_json::to_string(&self).unwrap();
|
||||||
|
(&s[1..(s.len() - 1)]).to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for SubmissionType {
|
||||||
|
type Err = serde_json::Error;
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
serde_json::from_str(&format!("\"{}\"", s))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
@ -177,12 +199,11 @@ pub struct SubmissionProof {
|
||||||
pub proof: String,
|
pub proof: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_session_authenticated(r: &HttpRequest, mut pl: &mut Payload) -> bool {
|
fn is_session_authenticated(r: &HttpRequest, pl: &mut Payload) -> bool {
|
||||||
use actix_web::FromRequest;
|
use actix_web::FromRequest;
|
||||||
matches!(
|
matches!(
|
||||||
Session::from_request(r, pl).into_inner().map(|x| {
|
Session::from_request(r, pl).into_inner().map(|x| {
|
||||||
let val = x.get::<String>(SURVEY_USER_ID);
|
let val = x.get::<String>(SURVEY_USER_ID);
|
||||||
println!("{:#?}", val);
|
|
||||||
val
|
val
|
||||||
}),
|
}),
|
||||||
Ok(Ok(Some(_)))
|
Ok(Ok(Some(_)))
|
||||||
|
@ -214,6 +235,7 @@ async fn submit(
|
||||||
|
|
||||||
let user_id = Uuid::from_str(&username).unwrap();
|
let user_id = Uuid::from_str(&username).unwrap();
|
||||||
let payload = payload.into_inner();
|
let payload = payload.into_inner();
|
||||||
|
let now = OffsetDateTime::now_utc();
|
||||||
|
|
||||||
struct ID {
|
struct ID {
|
||||||
id: i32,
|
id: i32,
|
||||||
|
@ -225,14 +247,21 @@ async fn submit(
|
||||||
campaign_id,
|
campaign_id,
|
||||||
device_user_provided,
|
device_user_provided,
|
||||||
device_software_recognised,
|
device_software_recognised,
|
||||||
threads
|
threads,
|
||||||
) VALUES ($1, $2, $3, $4, $5)
|
submitted_at,
|
||||||
|
submission_bench_type_id
|
||||||
|
) VALUES (
|
||||||
|
$1, $2, $3, $4, $5, $6,
|
||||||
|
(SELECT ID FROM survey_bench_type WHERE name = $7)
|
||||||
|
)
|
||||||
RETURNING ID;",
|
RETURNING ID;",
|
||||||
&user_id,
|
&user_id,
|
||||||
&campaign_id,
|
&campaign_id,
|
||||||
&payload.device_user_provided,
|
&payload.device_user_provided,
|
||||||
&payload.device_software_recognised,
|
&payload.device_software_recognised,
|
||||||
&payload.threads
|
&payload.threads,
|
||||||
|
&now,
|
||||||
|
&payload.submission_type.to_string(),
|
||||||
)
|
)
|
||||||
.fetch_one(&data.db)
|
.fetch_one(&data.db)
|
||||||
.await?;
|
.await?;
|
||||||
|
@ -311,3 +340,14 @@ async fn fetch(data: AppData, path: web::Path<String>) -> ServiceResult<impl Res
|
||||||
.await?;
|
.await?;
|
||||||
Ok(HttpResponse::Ok().json(config))
|
Ok(HttpResponse::Ok().json(config))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn survey_response_type_no_panic_test() {
|
||||||
|
assert_eq!(SubmissionType::Wasm.to_string(), "wasm".to_string());
|
||||||
|
assert_eq!(SubmissionType::Js.to_string(), "js".to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -21,9 +21,11 @@ use actix_web::{HttpResponse, Responder};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tera::Context;
|
use tera::Context;
|
||||||
|
|
||||||
|
use crate::api::v1::admin::campaigns::ResultsPage;
|
||||||
use crate::api::v1::admin::campaigns::{
|
use crate::api::v1::admin::campaigns::{
|
||||||
runners::list_campaign_runner, ListCampaignResp,
|
runners::list_campaign_runner, ListCampaignResp,
|
||||||
};
|
};
|
||||||
|
use crate::api::v1::bench::SubmissionType;
|
||||||
use crate::pages::errors::*;
|
use crate::pages::errors::*;
|
||||||
use crate::AppData;
|
use crate::AppData;
|
||||||
use crate::Settings;
|
use crate::Settings;
|
||||||
|
@ -55,6 +57,8 @@ pub fn register_templates(t: &mut tera::Tera) {
|
||||||
pub mod routes {
|
pub mod routes {
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::api::v1::admin::campaigns::ResultsPage;
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
|
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
|
||||||
pub struct Campaigns {
|
pub struct Campaigns {
|
||||||
pub home: &'static str,
|
pub home: &'static str,
|
||||||
|
@ -64,6 +68,7 @@ pub mod routes {
|
||||||
pub delete: &'static str,
|
pub delete: &'static str,
|
||||||
pub results: &'static str,
|
pub results: &'static str,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Campaigns {
|
impl Campaigns {
|
||||||
pub const fn new() -> Campaigns {
|
pub const fn new() -> Campaigns {
|
||||||
Campaigns {
|
Campaigns {
|
||||||
|
@ -91,12 +96,23 @@ pub mod routes {
|
||||||
pub fn get_results_route(
|
pub fn get_results_route(
|
||||||
&self,
|
&self,
|
||||||
campaign_id: &str,
|
campaign_id: &str,
|
||||||
page: Option<usize>,
|
modifier: Option<ResultsPage>,
|
||||||
) -> String {
|
) -> String {
|
||||||
let mut res = self.results.replace("{uuid}", campaign_id);
|
let mut res = self.results.replace("{uuid}", campaign_id);
|
||||||
if let Some(page) = page {
|
if let Some(modifier) = modifier {
|
||||||
|
let page = modifier.page();
|
||||||
|
if page != 0 {
|
||||||
res = format!("{res}?page={page}");
|
res = format!("{res}?page={page}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(bench_type) = modifier.bench_type {
|
||||||
|
if page != 0 {
|
||||||
|
res = format!("{res}&bench_type={}", bench_type.to_string());
|
||||||
|
} else {
|
||||||
|
res = format!("{res}?bench_type={}", bench_type.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,7 +170,6 @@ impl From<ListCampaignResp> for TemplateCampaign {
|
||||||
impl CtxError for Campaigns {
|
impl CtxError for Campaigns {
|
||||||
fn with_error(&self, e: &ReadableError) -> String {
|
fn with_error(&self, e: &ReadableError) -> String {
|
||||||
self.ctx.borrow_mut().insert(ERROR_KEY, e);
|
self.ctx.borrow_mut().insert(ERROR_KEY, e);
|
||||||
|
|
||||||
self.render()
|
self.render()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,33 +44,88 @@ impl CtxError for CampaignResults {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const RESUTS_LIMIT: usize = 50;
|
const RESUTS_LIMIT: usize = 10;
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
|
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
|
||||||
pub struct ResultsPagePayload {
|
pub struct ResultsPagePayload {
|
||||||
next_page: Option<String>,
|
next_page: Option<String>,
|
||||||
submissions: Vec<SurveyResponse>,
|
submissions: Vec<SurveyResponse>,
|
||||||
|
pub wasm_only: Option<String>,
|
||||||
|
pub js_only: Option<String>,
|
||||||
|
pub all_benches: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ResultsPagePayload {
|
impl ResultsPagePayload {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
submissions: Vec<SurveyResponse>,
|
submissions: Vec<SurveyResponse>,
|
||||||
current_page: usize,
|
|
||||||
campaign_id: &Uuid,
|
campaign_id: &Uuid,
|
||||||
|
modifier: ResultsPage,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let next_page = if submissions.len() >= RESUTS_LIMIT {
|
let campaign_id_str = campaign_id.to_string();
|
||||||
|
|
||||||
|
let all_benches;
|
||||||
|
let wasm_only;
|
||||||
|
let js_only;
|
||||||
|
match modifier.bench_type {
|
||||||
|
Some(SubmissionType::Js) => {
|
||||||
|
all_benches = Some(
|
||||||
|
crate::PAGES
|
||||||
|
.panel
|
||||||
|
.campaigns
|
||||||
|
.get_results_route(&campaign_id_str, None),
|
||||||
|
);
|
||||||
|
|
||||||
|
wasm_only = Some(crate::PAGES.panel.campaigns.get_results_route(
|
||||||
|
&campaign_id_str,
|
||||||
|
Some(ResultsPage::new(None, Some(SubmissionType::Wasm))),
|
||||||
|
));
|
||||||
|
js_only = None;
|
||||||
|
}
|
||||||
|
Some(SubmissionType::Wasm) => {
|
||||||
|
js_only = Some(crate::PAGES.panel.campaigns.get_results_route(
|
||||||
|
&campaign_id_str,
|
||||||
|
Some(ResultsPage::new(None, Some(SubmissionType::Js))),
|
||||||
|
));
|
||||||
|
all_benches = Some(
|
||||||
|
crate::PAGES
|
||||||
|
.panel
|
||||||
|
.campaigns
|
||||||
|
.get_results_route(&campaign_id_str, None),
|
||||||
|
);
|
||||||
|
wasm_only = None;
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
all_benches = None;
|
||||||
|
js_only = Some(crate::PAGES.panel.campaigns.get_results_route(
|
||||||
|
&campaign_id_str,
|
||||||
|
Some(ResultsPage::new(None, Some(SubmissionType::Js))),
|
||||||
|
));
|
||||||
|
wasm_only = Some(crate::PAGES.panel.campaigns.get_results_route(
|
||||||
|
&campaign_id_str,
|
||||||
|
Some(ResultsPage::new(None, Some(SubmissionType::Wasm))),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let next_page = if submissions.len() == RESUTS_LIMIT {
|
||||||
|
let m = ResultsPage::new(Some(modifier.page() + 1), modifier.bench_type);
|
||||||
|
|
||||||
Some(
|
Some(
|
||||||
PAGES
|
PAGES
|
||||||
.panel
|
.panel
|
||||||
.campaigns
|
.campaigns
|
||||||
.get_results_route(&campaign_id.to_string(), Some(current_page + 1)),
|
.get_results_route(&campaign_id_str, Some(m)),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
next_page,
|
next_page,
|
||||||
submissions,
|
submissions,
|
||||||
|
js_only,
|
||||||
|
wasm_only,
|
||||||
|
all_benches,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,15 +160,22 @@ pub async fn results(
|
||||||
)),
|
)),
|
||||||
Ok(uuid) => {
|
Ok(uuid) => {
|
||||||
let username = id.identity().unwrap();
|
let username = id.identity().unwrap();
|
||||||
|
let query = query.into_inner();
|
||||||
let page = query.page();
|
let page = query.page();
|
||||||
|
|
||||||
let results =
|
let results = runners::get_results(
|
||||||
runners::get_results(&username, &uuid, &data, page, RESUTS_LIMIT)
|
&username,
|
||||||
|
&uuid,
|
||||||
|
&data,
|
||||||
|
page,
|
||||||
|
RESUTS_LIMIT,
|
||||||
|
query.bench_type.clone(),
|
||||||
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
PageError::new(CampaignResults::new(&data.settings, None), e)
|
PageError::new(CampaignResults::new(&data.settings, None), e)
|
||||||
})?;
|
})?;
|
||||||
let payload = ResultsPagePayload::new(results, page, &uuid);
|
let payload = ResultsPagePayload::new(results, &uuid, query);
|
||||||
|
|
||||||
let results_page =
|
let results_page =
|
||||||
CampaignResults::new(&data.settings, Some(payload)).render();
|
CampaignResults::new(&data.settings, Some(payload)).render();
|
||||||
|
|
|
@ -131,5 +131,7 @@
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<!--
|
||||||
<script src="{{ assets.glue }}"></script>
|
<script src="{{ assets.glue }}"></script>
|
||||||
|
-->
|
||||||
{% endblock body %}
|
{% endblock body %}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import ROUTES from "../api/v1/routes";
|
||||||
import genJsonPaylod from "../utils/genJsonPayload";
|
import genJsonPaylod from "../utils/genJsonPayload";
|
||||||
import isBlankString from "../utils/isBlankString";
|
import isBlankString from "../utils/isBlankString";
|
||||||
import createError from "../components/error/";
|
import createError from "../components/error/";
|
||||||
|
import { get_bench_type } from "./prove";
|
||||||
|
|
||||||
export const index = () => {
|
export const index = () => {
|
||||||
const ADV = <HTMLButtonElement>document.getElementById("advance");
|
const ADV = <HTMLButtonElement>document.getElementById("advance");
|
||||||
|
@ -67,12 +68,13 @@ export const index = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const submitBench = async () => {
|
const submitBench = async () => {
|
||||||
|
const submission_type = await get_bench_type();
|
||||||
const payload: Submission = {
|
const payload: Submission = {
|
||||||
device_user_provided: deviceName,
|
device_user_provided: deviceName,
|
||||||
threads: window.navigator.hardwareConcurrency,
|
threads: window.navigator.hardwareConcurrency,
|
||||||
device_software_recognised: window.navigator.userAgent,
|
device_software_recognised: window.navigator.userAgent,
|
||||||
|
|
||||||
benches: res,
|
benches: res,
|
||||||
|
submission_type,
|
||||||
};
|
};
|
||||||
|
|
||||||
const resp = await fetch(
|
const resp = await fetch(
|
||||||
|
@ -96,7 +98,6 @@ export const index = () => {
|
||||||
element.appendChild(proof);
|
element.appendChild(proof);
|
||||||
element.appendChild(proofText);
|
element.appendChild(proofText);
|
||||||
document.getElementById("submission-proof").appendChild(element);
|
document.getElementById("submission-proof").appendChild(element);
|
||||||
document.getElementById("winner-instructions").style.display = "block";
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
71
templates/bench/prove.ts
Normal file
71
templates/bench/prove.ts
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* mCaptcha is a PoW based DoS protection software.
|
||||||
|
* This is the frontend web component of the mCaptcha system
|
||||||
|
* Copyright © 2021 Aravinth Manivnanan <realaravinth@batsense.net>.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by Apache 2.0 or MIT license.
|
||||||
|
* You shoud have received a copy of MIT and Apache 2.0 along with
|
||||||
|
* this program. If not, see <https://spdx.org/licenses/MIT.html> for
|
||||||
|
* MIT or <http://www.apache.org/licenses/LICENSE-2.0> for Apache.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import * as p from "@mcaptcha/pow_sha256-polyfill";
|
||||||
|
import { PoWConfig, SubmissionType } from "./types";
|
||||||
|
|
||||||
|
export const get_bench_type = async (): Promise<SubmissionType> => {
|
||||||
|
console.log(`Wasm support says ${WasmSupported}`);
|
||||||
|
let submission_type: SubmissionType;
|
||||||
|
if (WasmSupported) {
|
||||||
|
submission_type = SubmissionType.wasm;
|
||||||
|
} else {
|
||||||
|
submission_type = SubmissionType.js;
|
||||||
|
}
|
||||||
|
return submission_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* proove work
|
||||||
|
* @param {PoWConfig} config - the proof-of-work configuration using which
|
||||||
|
* work needs to be computed
|
||||||
|
* */
|
||||||
|
const prove = async (config: PoWConfig): Promise<number> => {
|
||||||
|
console.log(`Wasm support says ${WasmSupported}`);
|
||||||
|
let duration: number;
|
||||||
|
if (WasmSupported) {
|
||||||
|
const wasm = await require("@mcaptcha/pow-wasm");
|
||||||
|
const t0 = performance.now();
|
||||||
|
wasm.gen_pow(config.salt, config.string, config.difficulty_factor);
|
||||||
|
const t1 = performance.now();
|
||||||
|
duration = t1 - t0;
|
||||||
|
} else {
|
||||||
|
console.log("WASM unsupported, expect delay during proof generation");
|
||||||
|
const t0 = performance.now();
|
||||||
|
|
||||||
|
await p.generate_work(config.salt, config.string, config.difficulty_factor);
|
||||||
|
const t1 = performance.now();
|
||||||
|
duration = t1 - t0;
|
||||||
|
}
|
||||||
|
return duration;
|
||||||
|
};
|
||||||
|
|
||||||
|
// credits: @jf-bastien on Stack Overflow
|
||||||
|
// https://stackoverflow.com/questions/47879864/how-can-i-check-if-a-browser-supports-webassembly
|
||||||
|
const WasmSupported = (() => {
|
||||||
|
try {
|
||||||
|
if (
|
||||||
|
typeof WebAssembly === "object" &&
|
||||||
|
typeof WebAssembly.instantiate === "function"
|
||||||
|
) {
|
||||||
|
const module = new WebAssembly.Module(
|
||||||
|
Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00)
|
||||||
|
);
|
||||||
|
if (module instanceof WebAssembly.Module)
|
||||||
|
return new WebAssembly.Instance(module) instanceof WebAssembly.Instance;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
})();
|
||||||
|
|
||||||
|
export default prove;
|
|
@ -15,35 +15,24 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { gen_pow } from "@mcaptcha/pow-wasm";
|
import { Bench, PoWConfig } from "./types";
|
||||||
import { Bench } from "./types";
|
import prove from "./prove";
|
||||||
|
|
||||||
type PoWConfig = {
|
|
||||||
string: string;
|
|
||||||
difficulty_factor: number;
|
|
||||||
salt: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
const SALT = "674243647f1c355da8607a8cdda05120d79ca5d1af8b3b49359d056a0a82";
|
const SALT = "674243647f1c355da8607a8cdda05120d79ca5d1af8b3b49359d056a0a82";
|
||||||
const PHRASE = "6e2a53dbc7d307970d7ba3c0000221722cb74f1c325137251ce8fa5c2240";
|
const PHRASE = "6e2a53dbc7d307970d7ba3c0000221722cb74f1c325137251ce8fa5c2240";
|
||||||
|
|
||||||
|
console.debug("worker registered");
|
||||||
|
|
||||||
|
onmessage = async (event) => {
|
||||||
|
console.debug("message received at worker");
|
||||||
|
const difficulty_factor = parseInt(event.data);
|
||||||
const config: PoWConfig = {
|
const config: PoWConfig = {
|
||||||
string: PHRASE,
|
string: PHRASE,
|
||||||
difficulty_factor: 1,
|
difficulty_factor,
|
||||||
salt: SALT,
|
salt: SALT,
|
||||||
};
|
};
|
||||||
|
|
||||||
console.debug("worker registered");
|
const duration = await prove(config);
|
||||||
|
|
||||||
onmessage = function (event) {
|
|
||||||
console.debug("message received at worker");
|
|
||||||
const difficulty_factor = parseInt(event.data);
|
|
||||||
config.difficulty_factor = difficulty_factor;
|
|
||||||
|
|
||||||
const t0 = performance.now();
|
|
||||||
gen_pow(config.salt, config.string, config.difficulty_factor);
|
|
||||||
const t1 = performance.now();
|
|
||||||
const duration = t1 - t0;
|
|
||||||
|
|
||||||
const msg: Bench = {
|
const msg: Bench = {
|
||||||
difficulty: difficulty_factor,
|
difficulty: difficulty_factor,
|
||||||
|
|
|
@ -25,6 +25,7 @@ export type Submission = {
|
||||||
device_software_recognised: String;
|
device_software_recognised: String;
|
||||||
threads: number;
|
threads: number;
|
||||||
benches: Array<Bench>;
|
benches: Array<Bench>;
|
||||||
|
submission_type: SubmissionType;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type SubmissionProof = {
|
export type SubmissionProof = {
|
||||||
|
@ -35,3 +36,14 @@ export type SubmissionProof = {
|
||||||
export type BenchConfig = {
|
export type BenchConfig = {
|
||||||
difficulties: Array<number>;
|
difficulties: Array<number>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type PoWConfig = {
|
||||||
|
string: string;
|
||||||
|
difficulty_factor: number;
|
||||||
|
salt: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export enum SubmissionType {
|
||||||
|
wasm = "wasm",
|
||||||
|
js = "js",
|
||||||
|
}
|
||||||
|
|
|
@ -7,26 +7,44 @@
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<body class="panel__body">
|
<body class="panel__body">
|
||||||
<main class="panel__container">
|
<main class="panel__container">
|
||||||
|
<ul>
|
||||||
|
<h2>Filters</h2>
|
||||||
|
{% if payload.js_only %}
|
||||||
|
<ol><a href="{{ payload.js_only }}">JavaScript polyfil only</a></ol>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if payload.wasm_only %}
|
||||||
|
<ol><a href="{{ payload.wasm_only }}">WASM only</a></ol>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if payload.all_benches %}
|
||||||
|
<ol><a href="{{ payload.all_benches }}">All Benchmarks</a></ol>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Submission ID</th>
|
<th>Submission ID</th>
|
||||||
|
<th>Time (UTC)</th>
|
||||||
<th>User ID</th>
|
<th>User ID</th>
|
||||||
<th>Device make (user provided)</th>
|
<th>Device make (user provided)</th>
|
||||||
<th>Device make (detected)</th>
|
<th>Device make (detected)</th>
|
||||||
<th>Threads</th>
|
<th>Threads</th>
|
||||||
|
<th>Benchmark Type</th>
|
||||||
<th>Benches</th>
|
<th>Benches</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for sub in payload.submissions %}
|
{% for sub in payload.submissions %}
|
||||||
<tr>
|
<tr>
|
||||||
<th>{{ sub.id }}</th>
|
<td>{{ sub.id }}</td>
|
||||||
<th>{{ sub.user.id }}</th>
|
<td>{{ sub.submitted_at | date(format="%Y-%m-%d %H:%M", timezone="GMT") }}</td>
|
||||||
<th>{{ sub.device_user_provided }}</th>
|
<td>{{ sub.user.id }}</td>
|
||||||
<th>{{ sub.device_software_recognised }}</th>
|
<td>{{ sub.device_user_provided }}</td>
|
||||||
<th>{{ sub.threads }}</th>
|
<td>{{ sub.device_software_recognised }}</td>
|
||||||
<th>
|
<td>{{ sub.threads }}</td>
|
||||||
|
<td>{{ sub.submission_type }}</td>
|
||||||
|
<td>
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<th>Difficulty</th>
|
<th>Difficulty</th>
|
||||||
|
@ -41,13 +59,14 @@
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
</td>
|
||||||
</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
{% if payload.next_page %}
|
||||||
<a href="{{payload.next_page}}">Next ></a>
|
<a href="{{payload.next_page}}">Next ></a>
|
||||||
|
{% endif %}
|
||||||
</main>
|
</main>
|
||||||
</body>
|
</body>
|
||||||
{% endblock body %}
|
{% endblock body %}
|
||||||
|
|
|
@ -1,30 +1,30 @@
|
||||||
'use strict';
|
"use strict";
|
||||||
const path = require('path');
|
const path = require("path");
|
||||||
//const WasmPackPlugin = require('@wasm-tool/wasm-pack-plugin');
|
//const WasmPackPlugin = require('@wasm-tool/wasm-pack-plugin');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
devtool: 'inline-source-map',
|
devtool: "inline-source-map",
|
||||||
mode: 'development',
|
mode: "production",
|
||||||
//mode: 'production',
|
//mode: 'production',
|
||||||
entry: {
|
entry: {
|
||||||
bundle: './templates/index.ts',
|
bundle: "./templates/index.ts",
|
||||||
bench: './templates/bench/service-worker.ts',
|
bench: "./templates/bench/service-worker.ts",
|
||||||
glue: './templates/bench/vendor.ts',
|
glue: "./templates/bench/vendor.ts",
|
||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
filename: '[name].js',
|
filename: "[name].js",
|
||||||
path: path.resolve(__dirname, './static/cache/bundle'),
|
path: path.resolve(__dirname, "./static/cache/bundle"),
|
||||||
},
|
},
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
test: /\.tsx?$/,
|
test: /\.tsx?$/,
|
||||||
loader: 'ts-loader',
|
loader: "ts-loader",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
extensions: ['.ts', '.tsx', '.js'],
|
extensions: [".ts", ".tsx", ".js"],
|
||||||
},
|
},
|
||||||
|
|
||||||
experiments: {
|
experiments: {
|
||||||
|
|
Loading…
Reference in a new issue