@devtion/actions 0.0.0-270e9e0 → 0.0.0-4088679
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/dist/index.mjs +86 -102
- package/dist/index.node.js +85 -101
- package/dist/types/src/helpers/constants.d.ts +6 -0
- package/dist/types/src/helpers/constants.d.ts.map +1 -1
- package/dist/types/src/helpers/security.d.ts +2 -2
- package/dist/types/src/helpers/security.d.ts.map +1 -1
- package/dist/types/src/helpers/utils.d.ts.map +1 -1
- package/package.json +2 -6
- package/src/helpers/constants.ts +6 -0
- package/src/helpers/security.ts +28 -50
- package/src/helpers/utils.ts +24 -37
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @module @
|
|
3
|
-
* @version 1.0.
|
|
2
|
+
* @module @devtion/actions
|
|
3
|
+
* @version 1.0.6
|
|
4
4
|
* @file A set of actions and helpers for CLI commands
|
|
5
5
|
* @copyright Ethereum Foundation 2022
|
|
6
6
|
* @license MIT
|
|
@@ -17,8 +17,7 @@ import crypto from 'crypto';
|
|
|
17
17
|
import blake from 'blakejs';
|
|
18
18
|
import { utils } from 'ffjavascript';
|
|
19
19
|
import winston from 'winston';
|
|
20
|
-
import {
|
|
21
|
-
import { pipeline, Readable } from 'stream';
|
|
20
|
+
import { pipeline } from 'stream';
|
|
22
21
|
import { promisify } from 'util';
|
|
23
22
|
import { initializeApp } from 'firebase/app';
|
|
24
23
|
import { signInWithCredential, initializeAuth, getAuth } from 'firebase/auth';
|
|
@@ -244,6 +243,12 @@ const commonTerms = {
|
|
|
244
243
|
verificationStartedAt: "verificationStartedAt"
|
|
245
244
|
}
|
|
246
245
|
},
|
|
246
|
+
avatars: {
|
|
247
|
+
name: "avatars",
|
|
248
|
+
fields: {
|
|
249
|
+
avatarUrl: "avatarUrl"
|
|
250
|
+
}
|
|
251
|
+
},
|
|
247
252
|
ceremonies: {
|
|
248
253
|
name: "ceremonies",
|
|
249
254
|
fields: {
|
|
@@ -1085,42 +1090,26 @@ const parseCeremonyFile = async (path, cleanup = false) => {
|
|
|
1085
1090
|
circuitArtifacts.push({
|
|
1086
1091
|
artifacts: artifacts
|
|
1087
1092
|
});
|
|
1088
|
-
const r1csPath = artifacts.r1csStoragePath;
|
|
1089
|
-
const wasmPath = artifacts.wasmStoragePath;
|
|
1090
1093
|
// where we storing the r1cs downloaded
|
|
1091
1094
|
const localR1csPath = `./${circuitData.name}.r1cs`;
|
|
1092
|
-
//
|
|
1093
|
-
|
|
1094
|
-
// just the correct region
|
|
1095
|
-
const s3 = new S3Client({ region: artifacts.region });
|
|
1096
|
-
try {
|
|
1097
|
-
await s3.send(new HeadObjectCommand({
|
|
1098
|
-
Bucket: artifacts.bucket,
|
|
1099
|
-
Key: r1csPath
|
|
1100
|
-
}));
|
|
1101
|
-
}
|
|
1102
|
-
catch (error) {
|
|
1103
|
-
throw new Error(`The r1cs file (${r1csPath}) seems to not exist. Please ensure this is correct and that the object is publicly available.`);
|
|
1104
|
-
}
|
|
1105
|
-
try {
|
|
1106
|
-
await s3.send(new HeadObjectCommand({
|
|
1107
|
-
Bucket: artifacts.bucket,
|
|
1108
|
-
Key: wasmPath
|
|
1109
|
-
}));
|
|
1110
|
-
}
|
|
1111
|
-
catch (error) {
|
|
1112
|
-
throw new Error(`The wasm file (${wasmPath}) seems to not exist. Please ensure this is correct and that the object is publicly available.`);
|
|
1113
|
-
}
|
|
1095
|
+
// where we storing the wasm downloaded
|
|
1096
|
+
const localWasmPath = `./${circuitData.name}.wasm`;
|
|
1114
1097
|
// download the r1cs to extract the metadata
|
|
1115
|
-
const command = new GetObjectCommand({ Bucket: artifacts.bucket, Key: artifacts.r1csStoragePath });
|
|
1116
|
-
const response = await s3.send(command);
|
|
1117
1098
|
const streamPipeline = promisify(pipeline);
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1099
|
+
// Make the call.
|
|
1100
|
+
const responseR1CS = await fetch(artifacts.r1csStoragePath);
|
|
1101
|
+
// Handle errors.
|
|
1102
|
+
if (!responseR1CS.ok && responseR1CS.status !== 200)
|
|
1103
|
+
throw new Error(`There was an error while trying to download the r1cs file for circuit ${circuitData.name}. Please check that the file has the correct permissions (public) set.`);
|
|
1104
|
+
await streamPipeline(responseR1CS.body, createWriteStream(localR1csPath));
|
|
1105
|
+
// Write the file locally
|
|
1122
1106
|
// extract the metadata from the r1cs
|
|
1123
1107
|
const metadata = getR1CSInfo(localR1csPath);
|
|
1108
|
+
// download wasm too to ensure it's available
|
|
1109
|
+
const responseWASM = await fetch(artifacts.wasmStoragePath);
|
|
1110
|
+
if (!responseWASM.ok && responseWASM.status !== 200)
|
|
1111
|
+
throw new Error(`There was an error while trying to download the WASM file for circuit ${circuitData.name}. Please check that the file has the correct permissions (public) set.`);
|
|
1112
|
+
await streamPipeline(responseWASM.body, createWriteStream(localWasmPath));
|
|
1124
1113
|
// validate that the circuit hash and template links are valid
|
|
1125
1114
|
const template = circuitData.template;
|
|
1126
1115
|
const URLMatch = template.source.match(urlPattern);
|
|
@@ -1168,39 +1157,58 @@ const parseCeremonyFile = async (path, cleanup = false) => {
|
|
|
1168
1157
|
// check that the timeout is provided for the correct configuration
|
|
1169
1158
|
let dynamicThreshold;
|
|
1170
1159
|
let fixedTimeWindow;
|
|
1160
|
+
let circuit = {};
|
|
1171
1161
|
if (data.timeoutMechanismType === "DYNAMIC" /* CeremonyTimeoutType.DYNAMIC */) {
|
|
1172
1162
|
if (circuitData.dynamicThreshold <= 0)
|
|
1173
1163
|
throw new Error("The dynamic threshold should be > 0.");
|
|
1174
1164
|
dynamicThreshold = circuitData.dynamicThreshold;
|
|
1165
|
+
// the Circuit data for the ceremony setup
|
|
1166
|
+
circuit = {
|
|
1167
|
+
name: circuitData.name,
|
|
1168
|
+
description: circuitData.description,
|
|
1169
|
+
prefix: circuitPrefix,
|
|
1170
|
+
sequencePosition: i + 1,
|
|
1171
|
+
metadata: metadata,
|
|
1172
|
+
files: files,
|
|
1173
|
+
template: template,
|
|
1174
|
+
compiler: compiler,
|
|
1175
|
+
verification: verification,
|
|
1176
|
+
dynamicThreshold: dynamicThreshold,
|
|
1177
|
+
avgTimings: {
|
|
1178
|
+
contributionComputation: 0,
|
|
1179
|
+
fullContribution: 0,
|
|
1180
|
+
verifyCloudFunction: 0
|
|
1181
|
+
},
|
|
1182
|
+
};
|
|
1175
1183
|
}
|
|
1176
1184
|
if (data.timeoutMechanismType === "FIXED" /* CeremonyTimeoutType.FIXED */) {
|
|
1177
1185
|
if (circuitData.fixedTimeWindow <= 0)
|
|
1178
1186
|
throw new Error("The fixed time window threshold should be > 0.");
|
|
1179
1187
|
fixedTimeWindow = circuitData.fixedTimeWindow;
|
|
1188
|
+
// the Circuit data for the ceremony setup
|
|
1189
|
+
circuit = {
|
|
1190
|
+
name: circuitData.name,
|
|
1191
|
+
description: circuitData.description,
|
|
1192
|
+
prefix: circuitPrefix,
|
|
1193
|
+
sequencePosition: i + 1,
|
|
1194
|
+
metadata: metadata,
|
|
1195
|
+
files: files,
|
|
1196
|
+
template: template,
|
|
1197
|
+
compiler: compiler,
|
|
1198
|
+
verification: verification,
|
|
1199
|
+
fixedTimeWindow: fixedTimeWindow,
|
|
1200
|
+
avgTimings: {
|
|
1201
|
+
contributionComputation: 0,
|
|
1202
|
+
fullContribution: 0,
|
|
1203
|
+
verifyCloudFunction: 0
|
|
1204
|
+
},
|
|
1205
|
+
};
|
|
1180
1206
|
}
|
|
1181
|
-
// the Circuit data for the ceremony setup
|
|
1182
|
-
const circuit = {
|
|
1183
|
-
name: circuitData.name,
|
|
1184
|
-
description: circuitData.description,
|
|
1185
|
-
prefix: circuitPrefix,
|
|
1186
|
-
sequencePosition: i + 1,
|
|
1187
|
-
metadata: metadata,
|
|
1188
|
-
files: files,
|
|
1189
|
-
template: template,
|
|
1190
|
-
compiler: compiler,
|
|
1191
|
-
verification: verification,
|
|
1192
|
-
fixedTimeWindow: fixedTimeWindow,
|
|
1193
|
-
// dynamicThreshold: dynamicThreshold,
|
|
1194
|
-
avgTimings: {
|
|
1195
|
-
contributionComputation: 0,
|
|
1196
|
-
fullContribution: 0,
|
|
1197
|
-
verifyCloudFunction: 0
|
|
1198
|
-
},
|
|
1199
|
-
};
|
|
1200
1207
|
circuits.push(circuit);
|
|
1201
|
-
// remove the local r1cs
|
|
1208
|
+
// remove the local r1cs and wasm downloads (if used for verifying the config only vs setup)
|
|
1202
1209
|
if (cleanup)
|
|
1203
1210
|
fs.unlinkSync(localR1csPath);
|
|
1211
|
+
fs.unlinkSync(localWasmPath);
|
|
1204
1212
|
}
|
|
1205
1213
|
const setupData = {
|
|
1206
1214
|
ceremonyInputData: {
|
|
@@ -2061,55 +2069,27 @@ const verifyCeremony = async (functions, firestore, ceremonyPrefix, outputDirect
|
|
|
2061
2069
|
};
|
|
2062
2070
|
|
|
2063
2071
|
/**
|
|
2064
|
-
* This function
|
|
2065
|
-
* @param user
|
|
2066
|
-
* @returns
|
|
2067
|
-
*/
|
|
2068
|
-
const getNumberOfPublicReposGitHub = async (user) => {
|
|
2069
|
-
const response = await fetch(`https://api.github.com/user/${user}/repos`, {
|
|
2070
|
-
method: "GET",
|
|
2071
|
-
headers: {
|
|
2072
|
-
Authorization: `token ${process.env.GITHUB_ACCESS_TOKEN}`
|
|
2073
|
-
}
|
|
2074
|
-
});
|
|
2075
|
-
if (response.status !== 200)
|
|
2076
|
-
throw new Error("It was not possible to retrieve the number of public repositories. Please try again.");
|
|
2077
|
-
const jsonData = await response.json();
|
|
2078
|
-
return jsonData.length;
|
|
2079
|
-
};
|
|
2080
|
-
/**
|
|
2081
|
-
* This function will return the number of followers of a user
|
|
2082
|
-
* @param user <string> The username of the user
|
|
2083
|
-
* @returns <number> The number of followers
|
|
2084
|
-
*/
|
|
2085
|
-
const getNumberOfFollowersGitHub = async (user) => {
|
|
2086
|
-
const response = await fetch(`https://api.github.com/user/${user}/followers`, {
|
|
2087
|
-
method: "GET",
|
|
2088
|
-
headers: {
|
|
2089
|
-
Authorization: `token ${process.env.GITHUB_ACCESS_TOKEN}`
|
|
2090
|
-
}
|
|
2091
|
-
});
|
|
2092
|
-
if (response.status !== 200)
|
|
2093
|
-
throw new Error("It was not possible to retrieve the number of followers. Please try again.");
|
|
2094
|
-
const jsonData = await response.json();
|
|
2095
|
-
return jsonData.length;
|
|
2096
|
-
};
|
|
2097
|
-
/**
|
|
2098
|
-
* This function will return the number of following of a user
|
|
2099
|
-
* @param user <string> The username of the user
|
|
2100
|
-
* @returns <number> The number of following users
|
|
2072
|
+
* This function queries the GitHub API to fetch users statistics
|
|
2073
|
+
* @param user {string} the user uid
|
|
2074
|
+
* @returns {any} the stats from the GitHub API
|
|
2101
2075
|
*/
|
|
2102
|
-
const
|
|
2103
|
-
const response = await fetch(`https://api.github.com/user/${user}
|
|
2076
|
+
const getGitHubStats = async (user) => {
|
|
2077
|
+
const response = await fetch(`https://api.github.com/user/${user}`, {
|
|
2104
2078
|
method: "GET",
|
|
2105
2079
|
headers: {
|
|
2106
2080
|
Authorization: `token ${process.env.GITHUB_ACCESS_TOKEN}`
|
|
2107
2081
|
}
|
|
2108
2082
|
});
|
|
2109
2083
|
if (response.status !== 200)
|
|
2110
|
-
throw new Error("It was not possible to retrieve the
|
|
2084
|
+
throw new Error("It was not possible to retrieve the user's statistic. Please try again.");
|
|
2111
2085
|
const jsonData = await response.json();
|
|
2112
|
-
|
|
2086
|
+
const data = {
|
|
2087
|
+
following: jsonData.following,
|
|
2088
|
+
followers: jsonData.followers,
|
|
2089
|
+
publicRepos: jsonData.public_repos,
|
|
2090
|
+
avatarUrl: jsonData.avatar_url
|
|
2091
|
+
};
|
|
2092
|
+
return data;
|
|
2113
2093
|
};
|
|
2114
2094
|
/**
|
|
2115
2095
|
* This function will check if the user is reputable enough to be able to use the app
|
|
@@ -2117,19 +2097,23 @@ const getNumberOfFollowingGitHub = async (user) => {
|
|
|
2117
2097
|
* @param minimumAmountOfFollowing <number> The minimum amount of following the user should have
|
|
2118
2098
|
* @param minimumAmountOfFollowers <number> The minimum amount of followers the user should have
|
|
2119
2099
|
* @param minimumAmountOfPublicRepos <number> The minimum amount of public repos the user should have
|
|
2120
|
-
* @returns <
|
|
2100
|
+
* @returns <any> Return the avatar URL of the user if the user is reputable, false otherwise
|
|
2121
2101
|
*/
|
|
2122
2102
|
const githubReputation = async (userLogin, minimumAmountOfFollowing, minimumAmountOfFollowers, minimumAmountOfPublicRepos) => {
|
|
2123
2103
|
if (!process.env.GITHUB_ACCESS_TOKEN)
|
|
2124
2104
|
throw new Error("The GitHub access token is missing. Please insert a valid token to be used for anti-sybil checks on user registation, and then try again.");
|
|
2125
|
-
const following = await
|
|
2126
|
-
const repos = await getNumberOfPublicReposGitHub(userLogin);
|
|
2127
|
-
const followers = await getNumberOfFollowersGitHub(userLogin);
|
|
2105
|
+
const { following, followers, publicRepos, avatarUrl } = await getGitHubStats(userLogin);
|
|
2128
2106
|
if (following < minimumAmountOfFollowing ||
|
|
2129
|
-
|
|
2107
|
+
publicRepos < minimumAmountOfPublicRepos ||
|
|
2130
2108
|
followers < minimumAmountOfFollowers)
|
|
2131
|
-
return
|
|
2132
|
-
|
|
2109
|
+
return {
|
|
2110
|
+
reputable: false,
|
|
2111
|
+
avatarUrl: ""
|
|
2112
|
+
};
|
|
2113
|
+
return {
|
|
2114
|
+
reputable: true,
|
|
2115
|
+
avatarUrl: avatarUrl
|
|
2116
|
+
};
|
|
2133
2117
|
};
|
|
2134
2118
|
|
|
2135
2119
|
/**
|
package/dist/index.node.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @module @
|
|
3
|
-
* @version 1.0.
|
|
2
|
+
* @module @devtion/actions
|
|
3
|
+
* @version 1.0.6
|
|
4
4
|
* @file A set of actions and helpers for CLI commands
|
|
5
5
|
* @copyright Ethereum Foundation 2022
|
|
6
6
|
* @license MIT
|
|
@@ -19,7 +19,6 @@ var crypto = require('crypto');
|
|
|
19
19
|
var blake = require('blakejs');
|
|
20
20
|
var ffjavascript = require('ffjavascript');
|
|
21
21
|
var winston = require('winston');
|
|
22
|
-
var clientS3 = require('@aws-sdk/client-s3');
|
|
23
22
|
var stream = require('stream');
|
|
24
23
|
var util = require('util');
|
|
25
24
|
var app = require('firebase/app');
|
|
@@ -246,6 +245,12 @@ const commonTerms = {
|
|
|
246
245
|
verificationStartedAt: "verificationStartedAt"
|
|
247
246
|
}
|
|
248
247
|
},
|
|
248
|
+
avatars: {
|
|
249
|
+
name: "avatars",
|
|
250
|
+
fields: {
|
|
251
|
+
avatarUrl: "avatarUrl"
|
|
252
|
+
}
|
|
253
|
+
},
|
|
249
254
|
ceremonies: {
|
|
250
255
|
name: "ceremonies",
|
|
251
256
|
fields: {
|
|
@@ -1087,42 +1092,26 @@ const parseCeremonyFile = async (path, cleanup = false) => {
|
|
|
1087
1092
|
circuitArtifacts.push({
|
|
1088
1093
|
artifacts: artifacts
|
|
1089
1094
|
});
|
|
1090
|
-
const r1csPath = artifacts.r1csStoragePath;
|
|
1091
|
-
const wasmPath = artifacts.wasmStoragePath;
|
|
1092
1095
|
// where we storing the r1cs downloaded
|
|
1093
1096
|
const localR1csPath = `./${circuitData.name}.r1cs`;
|
|
1094
|
-
//
|
|
1095
|
-
|
|
1096
|
-
// just the correct region
|
|
1097
|
-
const s3 = new clientS3.S3Client({ region: artifacts.region });
|
|
1098
|
-
try {
|
|
1099
|
-
await s3.send(new clientS3.HeadObjectCommand({
|
|
1100
|
-
Bucket: artifacts.bucket,
|
|
1101
|
-
Key: r1csPath
|
|
1102
|
-
}));
|
|
1103
|
-
}
|
|
1104
|
-
catch (error) {
|
|
1105
|
-
throw new Error(`The r1cs file (${r1csPath}) seems to not exist. Please ensure this is correct and that the object is publicly available.`);
|
|
1106
|
-
}
|
|
1107
|
-
try {
|
|
1108
|
-
await s3.send(new clientS3.HeadObjectCommand({
|
|
1109
|
-
Bucket: artifacts.bucket,
|
|
1110
|
-
Key: wasmPath
|
|
1111
|
-
}));
|
|
1112
|
-
}
|
|
1113
|
-
catch (error) {
|
|
1114
|
-
throw new Error(`The wasm file (${wasmPath}) seems to not exist. Please ensure this is correct and that the object is publicly available.`);
|
|
1115
|
-
}
|
|
1097
|
+
// where we storing the wasm downloaded
|
|
1098
|
+
const localWasmPath = `./${circuitData.name}.wasm`;
|
|
1116
1099
|
// download the r1cs to extract the metadata
|
|
1117
|
-
const command = new clientS3.GetObjectCommand({ Bucket: artifacts.bucket, Key: artifacts.r1csStoragePath });
|
|
1118
|
-
const response = await s3.send(command);
|
|
1119
1100
|
const streamPipeline = util.promisify(stream.pipeline);
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1101
|
+
// Make the call.
|
|
1102
|
+
const responseR1CS = await fetch(artifacts.r1csStoragePath);
|
|
1103
|
+
// Handle errors.
|
|
1104
|
+
if (!responseR1CS.ok && responseR1CS.status !== 200)
|
|
1105
|
+
throw new Error(`There was an error while trying to download the r1cs file for circuit ${circuitData.name}. Please check that the file has the correct permissions (public) set.`);
|
|
1106
|
+
await streamPipeline(responseR1CS.body, fs.createWriteStream(localR1csPath));
|
|
1107
|
+
// Write the file locally
|
|
1124
1108
|
// extract the metadata from the r1cs
|
|
1125
1109
|
const metadata = getR1CSInfo(localR1csPath);
|
|
1110
|
+
// download wasm too to ensure it's available
|
|
1111
|
+
const responseWASM = await fetch(artifacts.wasmStoragePath);
|
|
1112
|
+
if (!responseWASM.ok && responseWASM.status !== 200)
|
|
1113
|
+
throw new Error(`There was an error while trying to download the WASM file for circuit ${circuitData.name}. Please check that the file has the correct permissions (public) set.`);
|
|
1114
|
+
await streamPipeline(responseWASM.body, fs.createWriteStream(localWasmPath));
|
|
1126
1115
|
// validate that the circuit hash and template links are valid
|
|
1127
1116
|
const template = circuitData.template;
|
|
1128
1117
|
const URLMatch = template.source.match(urlPattern);
|
|
@@ -1170,39 +1159,58 @@ const parseCeremonyFile = async (path, cleanup = false) => {
|
|
|
1170
1159
|
// check that the timeout is provided for the correct configuration
|
|
1171
1160
|
let dynamicThreshold;
|
|
1172
1161
|
let fixedTimeWindow;
|
|
1162
|
+
let circuit = {};
|
|
1173
1163
|
if (data.timeoutMechanismType === "DYNAMIC" /* CeremonyTimeoutType.DYNAMIC */) {
|
|
1174
1164
|
if (circuitData.dynamicThreshold <= 0)
|
|
1175
1165
|
throw new Error("The dynamic threshold should be > 0.");
|
|
1176
1166
|
dynamicThreshold = circuitData.dynamicThreshold;
|
|
1167
|
+
// the Circuit data for the ceremony setup
|
|
1168
|
+
circuit = {
|
|
1169
|
+
name: circuitData.name,
|
|
1170
|
+
description: circuitData.description,
|
|
1171
|
+
prefix: circuitPrefix,
|
|
1172
|
+
sequencePosition: i + 1,
|
|
1173
|
+
metadata: metadata,
|
|
1174
|
+
files: files,
|
|
1175
|
+
template: template,
|
|
1176
|
+
compiler: compiler,
|
|
1177
|
+
verification: verification,
|
|
1178
|
+
dynamicThreshold: dynamicThreshold,
|
|
1179
|
+
avgTimings: {
|
|
1180
|
+
contributionComputation: 0,
|
|
1181
|
+
fullContribution: 0,
|
|
1182
|
+
verifyCloudFunction: 0
|
|
1183
|
+
},
|
|
1184
|
+
};
|
|
1177
1185
|
}
|
|
1178
1186
|
if (data.timeoutMechanismType === "FIXED" /* CeremonyTimeoutType.FIXED */) {
|
|
1179
1187
|
if (circuitData.fixedTimeWindow <= 0)
|
|
1180
1188
|
throw new Error("The fixed time window threshold should be > 0.");
|
|
1181
1189
|
fixedTimeWindow = circuitData.fixedTimeWindow;
|
|
1190
|
+
// the Circuit data for the ceremony setup
|
|
1191
|
+
circuit = {
|
|
1192
|
+
name: circuitData.name,
|
|
1193
|
+
description: circuitData.description,
|
|
1194
|
+
prefix: circuitPrefix,
|
|
1195
|
+
sequencePosition: i + 1,
|
|
1196
|
+
metadata: metadata,
|
|
1197
|
+
files: files,
|
|
1198
|
+
template: template,
|
|
1199
|
+
compiler: compiler,
|
|
1200
|
+
verification: verification,
|
|
1201
|
+
fixedTimeWindow: fixedTimeWindow,
|
|
1202
|
+
avgTimings: {
|
|
1203
|
+
contributionComputation: 0,
|
|
1204
|
+
fullContribution: 0,
|
|
1205
|
+
verifyCloudFunction: 0
|
|
1206
|
+
},
|
|
1207
|
+
};
|
|
1182
1208
|
}
|
|
1183
|
-
// the Circuit data for the ceremony setup
|
|
1184
|
-
const circuit = {
|
|
1185
|
-
name: circuitData.name,
|
|
1186
|
-
description: circuitData.description,
|
|
1187
|
-
prefix: circuitPrefix,
|
|
1188
|
-
sequencePosition: i + 1,
|
|
1189
|
-
metadata: metadata,
|
|
1190
|
-
files: files,
|
|
1191
|
-
template: template,
|
|
1192
|
-
compiler: compiler,
|
|
1193
|
-
verification: verification,
|
|
1194
|
-
fixedTimeWindow: fixedTimeWindow,
|
|
1195
|
-
// dynamicThreshold: dynamicThreshold,
|
|
1196
|
-
avgTimings: {
|
|
1197
|
-
contributionComputation: 0,
|
|
1198
|
-
fullContribution: 0,
|
|
1199
|
-
verifyCloudFunction: 0
|
|
1200
|
-
},
|
|
1201
|
-
};
|
|
1202
1209
|
circuits.push(circuit);
|
|
1203
|
-
// remove the local r1cs
|
|
1210
|
+
// remove the local r1cs and wasm downloads (if used for verifying the config only vs setup)
|
|
1204
1211
|
if (cleanup)
|
|
1205
1212
|
fs.unlinkSync(localR1csPath);
|
|
1213
|
+
fs.unlinkSync(localWasmPath);
|
|
1206
1214
|
}
|
|
1207
1215
|
const setupData = {
|
|
1208
1216
|
ceremonyInputData: {
|
|
@@ -2063,55 +2071,27 @@ const verifyCeremony = async (functions, firestore$1, ceremonyPrefix, outputDire
|
|
|
2063
2071
|
};
|
|
2064
2072
|
|
|
2065
2073
|
/**
|
|
2066
|
-
* This function
|
|
2067
|
-
* @param user
|
|
2068
|
-
* @returns
|
|
2069
|
-
*/
|
|
2070
|
-
const getNumberOfPublicReposGitHub = async (user) => {
|
|
2071
|
-
const response = await fetch(`https://api.github.com/user/${user}/repos`, {
|
|
2072
|
-
method: "GET",
|
|
2073
|
-
headers: {
|
|
2074
|
-
Authorization: `token ${process.env.GITHUB_ACCESS_TOKEN}`
|
|
2075
|
-
}
|
|
2076
|
-
});
|
|
2077
|
-
if (response.status !== 200)
|
|
2078
|
-
throw new Error("It was not possible to retrieve the number of public repositories. Please try again.");
|
|
2079
|
-
const jsonData = await response.json();
|
|
2080
|
-
return jsonData.length;
|
|
2081
|
-
};
|
|
2082
|
-
/**
|
|
2083
|
-
* This function will return the number of followers of a user
|
|
2084
|
-
* @param user <string> The username of the user
|
|
2085
|
-
* @returns <number> The number of followers
|
|
2086
|
-
*/
|
|
2087
|
-
const getNumberOfFollowersGitHub = async (user) => {
|
|
2088
|
-
const response = await fetch(`https://api.github.com/user/${user}/followers`, {
|
|
2089
|
-
method: "GET",
|
|
2090
|
-
headers: {
|
|
2091
|
-
Authorization: `token ${process.env.GITHUB_ACCESS_TOKEN}`
|
|
2092
|
-
}
|
|
2093
|
-
});
|
|
2094
|
-
if (response.status !== 200)
|
|
2095
|
-
throw new Error("It was not possible to retrieve the number of followers. Please try again.");
|
|
2096
|
-
const jsonData = await response.json();
|
|
2097
|
-
return jsonData.length;
|
|
2098
|
-
};
|
|
2099
|
-
/**
|
|
2100
|
-
* This function will return the number of following of a user
|
|
2101
|
-
* @param user <string> The username of the user
|
|
2102
|
-
* @returns <number> The number of following users
|
|
2074
|
+
* This function queries the GitHub API to fetch users statistics
|
|
2075
|
+
* @param user {string} the user uid
|
|
2076
|
+
* @returns {any} the stats from the GitHub API
|
|
2103
2077
|
*/
|
|
2104
|
-
const
|
|
2105
|
-
const response = await fetch(`https://api.github.com/user/${user}
|
|
2078
|
+
const getGitHubStats = async (user) => {
|
|
2079
|
+
const response = await fetch(`https://api.github.com/user/${user}`, {
|
|
2106
2080
|
method: "GET",
|
|
2107
2081
|
headers: {
|
|
2108
2082
|
Authorization: `token ${process.env.GITHUB_ACCESS_TOKEN}`
|
|
2109
2083
|
}
|
|
2110
2084
|
});
|
|
2111
2085
|
if (response.status !== 200)
|
|
2112
|
-
throw new Error("It was not possible to retrieve the
|
|
2086
|
+
throw new Error("It was not possible to retrieve the user's statistic. Please try again.");
|
|
2113
2087
|
const jsonData = await response.json();
|
|
2114
|
-
|
|
2088
|
+
const data = {
|
|
2089
|
+
following: jsonData.following,
|
|
2090
|
+
followers: jsonData.followers,
|
|
2091
|
+
publicRepos: jsonData.public_repos,
|
|
2092
|
+
avatarUrl: jsonData.avatar_url
|
|
2093
|
+
};
|
|
2094
|
+
return data;
|
|
2115
2095
|
};
|
|
2116
2096
|
/**
|
|
2117
2097
|
* This function will check if the user is reputable enough to be able to use the app
|
|
@@ -2119,19 +2099,23 @@ const getNumberOfFollowingGitHub = async (user) => {
|
|
|
2119
2099
|
* @param minimumAmountOfFollowing <number> The minimum amount of following the user should have
|
|
2120
2100
|
* @param minimumAmountOfFollowers <number> The minimum amount of followers the user should have
|
|
2121
2101
|
* @param minimumAmountOfPublicRepos <number> The minimum amount of public repos the user should have
|
|
2122
|
-
* @returns <
|
|
2102
|
+
* @returns <any> Return the avatar URL of the user if the user is reputable, false otherwise
|
|
2123
2103
|
*/
|
|
2124
2104
|
const githubReputation = async (userLogin, minimumAmountOfFollowing, minimumAmountOfFollowers, minimumAmountOfPublicRepos) => {
|
|
2125
2105
|
if (!process.env.GITHUB_ACCESS_TOKEN)
|
|
2126
2106
|
throw new Error("The GitHub access token is missing. Please insert a valid token to be used for anti-sybil checks on user registation, and then try again.");
|
|
2127
|
-
const following = await
|
|
2128
|
-
const repos = await getNumberOfPublicReposGitHub(userLogin);
|
|
2129
|
-
const followers = await getNumberOfFollowersGitHub(userLogin);
|
|
2107
|
+
const { following, followers, publicRepos, avatarUrl } = await getGitHubStats(userLogin);
|
|
2130
2108
|
if (following < minimumAmountOfFollowing ||
|
|
2131
|
-
|
|
2109
|
+
publicRepos < minimumAmountOfPublicRepos ||
|
|
2132
2110
|
followers < minimumAmountOfFollowers)
|
|
2133
|
-
return
|
|
2134
|
-
|
|
2111
|
+
return {
|
|
2112
|
+
reputable: false,
|
|
2113
|
+
avatarUrl: ""
|
|
2114
|
+
};
|
|
2115
|
+
return {
|
|
2116
|
+
reputable: true,
|
|
2117
|
+
avatarUrl: avatarUrl
|
|
2118
|
+
};
|
|
2135
2119
|
};
|
|
2136
2120
|
|
|
2137
2121
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../src/helpers/constants.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,sBAAsB,+CAA+C,CAAA;AAElF,eAAO,MAAM,mBAAmB,6BAA6B,CAAA;AAE7D,eAAO,MAAM,gBAAgB,UAAU,CAAA;AAEvC,eAAO,MAAM,gBAAgB,KAAK,CAAA;AAElC,eAAO,MAAM,eAAe,UAAU,CAAA;AAEtC,eAAO,MAAM,sBAAsB,UAAU,CAAA;AAE7C,eAAO,MAAM,sBAAsB,SAAS,CAAA;AAE5C,eAAO,MAAM,4BAA4B,aAAa,CAAA;AAEtD,eAAO,MAAM,cAAc,sBAAsB,CAAA;AAEjD,eAAO,MAAM,yBAAyB,iBAAiB,CAAA;AAEvD;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2ChC,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,gBAAgB;;;GA6G5B,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,WAAW
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../src/helpers/constants.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,sBAAsB,+CAA+C,CAAA;AAElF,eAAO,MAAM,mBAAmB,6BAA6B,CAAA;AAE7D,eAAO,MAAM,gBAAgB,UAAU,CAAA;AAEvC,eAAO,MAAM,gBAAgB,KAAK,CAAA;AAElC,eAAO,MAAM,eAAe,UAAU,CAAA;AAEtC,eAAO,MAAM,sBAAsB,UAAU,CAAA;AAE7C,eAAO,MAAM,sBAAsB,SAAS,CAAA;AAE5C,eAAO,MAAM,4BAA4B,aAAa,CAAA;AAEtD,eAAO,MAAM,cAAc,sBAAsB,CAAA;AAEjD,eAAO,MAAM,yBAAyB,iBAAiB,CAAA;AAEvD;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2ChC,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,gBAAgB;;;GA6G5B,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6HvB,CAAA"}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @param minimumAmountOfFollowing <number> The minimum amount of following the user should have
|
|
5
5
|
* @param minimumAmountOfFollowers <number> The minimum amount of followers the user should have
|
|
6
6
|
* @param minimumAmountOfPublicRepos <number> The minimum amount of public repos the user should have
|
|
7
|
-
* @returns <
|
|
7
|
+
* @returns <any> Return the avatar URL of the user if the user is reputable, false otherwise
|
|
8
8
|
*/
|
|
9
|
-
export declare const githubReputation: (userLogin: string, minimumAmountOfFollowing: number, minimumAmountOfFollowers: number, minimumAmountOfPublicRepos: number) => Promise<
|
|
9
|
+
export declare const githubReputation: (userLogin: string, minimumAmountOfFollowing: number, minimumAmountOfFollowers: number, minimumAmountOfPublicRepos: number) => Promise<any>;
|
|
10
10
|
//# sourceMappingURL=security.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../../../../src/helpers/security.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../../../../src/helpers/security.ts"],"names":[],"mappings":"AA4BA;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,cACd,MAAM,4BACS,MAAM,4BACN,MAAM,8BACJ,MAAM,KACnC,QAAQ,GAAG,CAsBb,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../src/helpers/utils.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAC9C,OAAW,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../src/helpers/utils.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAC9C,OAAW,EAAE,YAAY,EAAqB,MAAM,IAAI,CAAA;AAExD,OAAO,OAAO,EAAE,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAEzC,OAAO,EACH,eAAe,EACf,YAAY,EAGZ,oBAAoB,EACpB,oBAAoB,EACpB,iBAAiB,EAGpB,MAAM,gBAAgB,CAAA;AAmBvB;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,SAAgB,MAAM,YAAW,OAAO,KAAW,QAAQ,iBAAiB,CAuNzG,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,+BAA+B,iBAAkB,MAAM,UAAU,MAAM,KAAG,MAgBtF,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,oCAAoC,gBAAiB,MAAM,WAAW,MAAM,WAUxF,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,eAAe,aAAc,MAAM,KAAG,MASlD,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,wBAAyB,MAAM,KAAG,MACH,CAAA;AAElE;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,QAAS,MAAM,KAAG,MAEsC,CAAA;AAElF;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,cAAsE,CAAA;AAEtG;;;;;;;GAOG;AACH,eAAO,MAAM,4BAA4B,aAC3B,MAAM,oBAAoB,CAAC,oBACnB,MAAM,KACzB,oBAYF,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,cAAe,MAAM,WAAW,OAAO,KAAG,MAC1B,CAAA;AAEjD;;;;;;;;GAQG;AACH,eAAO,MAAM,sCAAsC,sBAC5B,SAAS,YAClB,MAAM,oBAAoB,CAAC,cACzB,MAAM,iBACH,MAAM,gBACP,OAAO,KACtB,QAAQ,MAAM,oBAAoB,CAAC,CAmCrC,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,0CAA0C,0BAC5B,MAAM,gBACf,MAAM,gBACN,OAAO,WAImF,CAAA;AAE5G;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,qCAAqC,sBAC3B,SAAS,YAClB,MAAM,oBAAoB,CAAC,cACzB,MAAM,iBACH,MAAM,4BACK,MAAM,YAAY,CAAC,yBACtB,MAAM,gBACf,MAAM,gBACN,OAAO,KACtB,QAAQ,MAAM,CA2DhB,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,aAAc,MAAM,UAAS,QAAQ,aAAa,CAAC,OAAO,CAAC,KAAY,MAQvG,CAAA;AAEN;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,kBACX,MAAM,UACb,MAAM,UACN,MAAM,YACJ,YAAY,KACvB,MAYF,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,WAAW,sBAAuB,MAAM,KAAG,eA0IvD,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,WAAY,MAAM,KAAG,MAA0D,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devtion/actions",
|
|
3
|
-
"version": "0.0.0-
|
|
3
|
+
"version": "0.0.0-4088679",
|
|
4
4
|
"description": "A set of actions and helpers for CLI commands",
|
|
5
5
|
"repository": "git@github.com:privacy-scaling-explorations/p0tion.git",
|
|
6
6
|
"homepage": "https://github.com/privacy-scaling-explorations/p0tion",
|
|
@@ -55,10 +55,6 @@
|
|
|
55
55
|
"firebase": "^9.21.0",
|
|
56
56
|
"firebase-admin": "^11.8.0",
|
|
57
57
|
"googleapis": "^118.0.0",
|
|
58
|
-
"puppeteer": "^20.1.2",
|
|
59
|
-
"puppeteer-extra": "^3.3.6",
|
|
60
|
-
"puppeteer-extra-plugin-anonymize-ua": "^2.4.6",
|
|
61
|
-
"puppeteer-extra-plugin-stealth": "^2.11.2",
|
|
62
58
|
"rimraf": "^5.0.0",
|
|
63
59
|
"rollup": "^3.21.6",
|
|
64
60
|
"snarkjs": "^0.6.11",
|
|
@@ -83,5 +79,5 @@
|
|
|
83
79
|
"publishConfig": {
|
|
84
80
|
"access": "public"
|
|
85
81
|
},
|
|
86
|
-
"gitHead": "
|
|
82
|
+
"gitHead": "29b7f515737e345691adf023491fe9930fbe861a"
|
|
87
83
|
}
|
package/src/helpers/constants.ts
CHANGED
package/src/helpers/security.ts
CHANGED
|
@@ -1,57 +1,29 @@
|
|
|
1
1
|
import fetch from "@adobe/node-fetch-retry"
|
|
2
2
|
/**
|
|
3
|
-
* This function
|
|
4
|
-
* @param user
|
|
5
|
-
* @returns
|
|
3
|
+
* This function queries the GitHub API to fetch users statistics
|
|
4
|
+
* @param user {string} the user uid
|
|
5
|
+
* @returns {any} the stats from the GitHub API
|
|
6
6
|
*/
|
|
7
|
-
const
|
|
8
|
-
const response = await fetch(`https://api.github.com/user/${user}
|
|
7
|
+
const getGitHubStats = async (user: string): Promise<any> => {
|
|
8
|
+
const response = await fetch(`https://api.github.com/user/${user}`, {
|
|
9
9
|
method: "GET",
|
|
10
10
|
headers: {
|
|
11
11
|
Authorization: `token ${process.env.GITHUB_ACCESS_TOKEN!}`
|
|
12
12
|
}
|
|
13
13
|
})
|
|
14
14
|
if (response.status !== 200)
|
|
15
|
-
throw new Error("It was not possible to retrieve the
|
|
16
|
-
const jsonData: any = await response.json()
|
|
17
|
-
return jsonData.length
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* This function will return the number of followers of a user
|
|
21
|
-
* @param user <string> The username of the user
|
|
22
|
-
* @returns <number> The number of followers
|
|
23
|
-
*/
|
|
24
|
-
const getNumberOfFollowersGitHub = async (user: string): Promise<number> => {
|
|
25
|
-
const response = await fetch(`https://api.github.com/user/${user}/followers`, {
|
|
26
|
-
method: "GET",
|
|
27
|
-
headers: {
|
|
28
|
-
Authorization: `token ${process.env.GITHUB_ACCESS_TOKEN!}`
|
|
29
|
-
}
|
|
30
|
-
})
|
|
31
|
-
if (response.status !== 200)
|
|
32
|
-
throw new Error("It was not possible to retrieve the number of followers. Please try again.")
|
|
33
|
-
const jsonData: any = await response.json()
|
|
34
|
-
return jsonData.length
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* This function will return the number of following of a user
|
|
38
|
-
* @param user <string> The username of the user
|
|
39
|
-
* @returns <number> The number of following users
|
|
40
|
-
*/
|
|
41
|
-
const getNumberOfFollowingGitHub = async (user: string): Promise<number> => {
|
|
42
|
-
const response = await fetch(`https://api.github.com/user/${user}/following`, {
|
|
43
|
-
method: "GET",
|
|
44
|
-
headers: {
|
|
45
|
-
Authorization: `token ${process.env.GITHUB_ACCESS_TOKEN!}`
|
|
46
|
-
}
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
if (response.status !== 200)
|
|
50
|
-
throw new Error("It was not possible to retrieve the number of following. Please try again.")
|
|
15
|
+
throw new Error("It was not possible to retrieve the user's statistic. Please try again.")
|
|
51
16
|
|
|
52
17
|
const jsonData: any = await response.json()
|
|
53
18
|
|
|
54
|
-
|
|
19
|
+
const data = {
|
|
20
|
+
following: jsonData.following,
|
|
21
|
+
followers: jsonData.followers,
|
|
22
|
+
publicRepos: jsonData.public_repos,
|
|
23
|
+
avatarUrl: jsonData.avatar_url
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return data
|
|
55
27
|
}
|
|
56
28
|
|
|
57
29
|
/**
|
|
@@ -60,27 +32,33 @@ const getNumberOfFollowingGitHub = async (user: string): Promise<number> => {
|
|
|
60
32
|
* @param minimumAmountOfFollowing <number> The minimum amount of following the user should have
|
|
61
33
|
* @param minimumAmountOfFollowers <number> The minimum amount of followers the user should have
|
|
62
34
|
* @param minimumAmountOfPublicRepos <number> The minimum amount of public repos the user should have
|
|
63
|
-
* @returns <
|
|
35
|
+
* @returns <any> Return the avatar URL of the user if the user is reputable, false otherwise
|
|
64
36
|
*/
|
|
65
37
|
export const githubReputation = async (
|
|
66
38
|
userLogin: string,
|
|
67
39
|
minimumAmountOfFollowing: number,
|
|
68
40
|
minimumAmountOfFollowers: number,
|
|
69
41
|
minimumAmountOfPublicRepos: number
|
|
70
|
-
): Promise<
|
|
42
|
+
): Promise<any> => {
|
|
71
43
|
if (!process.env.GITHUB_ACCESS_TOKEN)
|
|
72
44
|
throw new Error(
|
|
73
45
|
"The GitHub access token is missing. Please insert a valid token to be used for anti-sybil checks on user registation, and then try again."
|
|
74
46
|
)
|
|
75
|
-
|
|
76
|
-
const
|
|
77
|
-
const followers = await getNumberOfFollowersGitHub(userLogin)
|
|
47
|
+
|
|
48
|
+
const { following, followers, publicRepos, avatarUrl } = await getGitHubStats(userLogin)
|
|
78
49
|
|
|
79
50
|
if (
|
|
80
51
|
following < minimumAmountOfFollowing ||
|
|
81
|
-
|
|
52
|
+
publicRepos < minimumAmountOfPublicRepos ||
|
|
82
53
|
followers < minimumAmountOfFollowers
|
|
83
54
|
)
|
|
84
|
-
return
|
|
85
|
-
|
|
55
|
+
return {
|
|
56
|
+
reputable: false,
|
|
57
|
+
avatarUrl: ""
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
reputable: true,
|
|
62
|
+
avatarUrl: avatarUrl
|
|
63
|
+
}
|
|
86
64
|
}
|
package/src/helpers/utils.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Firestore } from "firebase/firestore"
|
|
2
|
-
import fs, { ReadPosition } from "fs"
|
|
2
|
+
import fs, { ReadPosition, createWriteStream } from "fs"
|
|
3
3
|
import { utils as ffUtils } from "ffjavascript"
|
|
4
4
|
import winston, { Logger } from "winston"
|
|
5
|
-
import
|
|
5
|
+
import fetch from "@adobe/node-fetch-retry"
|
|
6
6
|
import {
|
|
7
7
|
CircuitMetadata,
|
|
8
8
|
Contribution,
|
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
getZkeyStorageFilePath
|
|
30
30
|
} from "./storage"
|
|
31
31
|
import { blake512FromPath } from "./crypto"
|
|
32
|
-
import {
|
|
32
|
+
import { pipeline } from "stream"
|
|
33
33
|
import { promisify } from "util"
|
|
34
34
|
|
|
35
35
|
/**
|
|
@@ -87,49 +87,34 @@ export const parseCeremonyFile = async (path: string, cleanup: boolean = false):
|
|
|
87
87
|
circuitArtifacts.push({
|
|
88
88
|
artifacts: artifacts
|
|
89
89
|
})
|
|
90
|
-
const r1csPath = artifacts.r1csStoragePath
|
|
91
|
-
const wasmPath = artifacts.wasmStoragePath
|
|
92
90
|
|
|
93
91
|
// where we storing the r1cs downloaded
|
|
94
92
|
const localR1csPath = `./${circuitData.name}.r1cs`
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
// we don't need any privileges to download this
|
|
98
|
-
// just the correct region
|
|
99
|
-
const s3 = new S3Client({region: artifacts.region})
|
|
100
|
-
|
|
101
|
-
try {
|
|
102
|
-
await s3.send(new HeadObjectCommand({
|
|
103
|
-
Bucket: artifacts.bucket,
|
|
104
|
-
Key: r1csPath
|
|
105
|
-
}))
|
|
106
|
-
} catch (error: any) {
|
|
107
|
-
throw new Error(`The r1cs file (${r1csPath}) seems to not exist. Please ensure this is correct and that the object is publicly available.`)
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
try {
|
|
111
|
-
await s3.send(new HeadObjectCommand({
|
|
112
|
-
Bucket: artifacts.bucket,
|
|
113
|
-
Key: wasmPath
|
|
114
|
-
}))
|
|
115
|
-
} catch (error: any) {
|
|
116
|
-
throw new Error(`The wasm file (${wasmPath}) seems to not exist. Please ensure this is correct and that the object is publicly available.`)
|
|
117
|
-
}
|
|
93
|
+
// where we storing the wasm downloaded
|
|
94
|
+
const localWasmPath = `./${circuitData.name}.wasm`
|
|
118
95
|
|
|
119
96
|
// download the r1cs to extract the metadata
|
|
120
|
-
const command = new GetObjectCommand({ Bucket: artifacts.bucket, Key: artifacts.r1csStoragePath })
|
|
121
|
-
const response = await s3.send(command)
|
|
122
97
|
const streamPipeline = promisify(pipeline)
|
|
123
98
|
|
|
124
|
-
|
|
125
|
-
|
|
99
|
+
// Make the call.
|
|
100
|
+
const responseR1CS = await fetch(artifacts.r1csStoragePath)
|
|
126
101
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
102
|
+
// Handle errors.
|
|
103
|
+
if (!responseR1CS.ok && responseR1CS.status !== 200)
|
|
104
|
+
throw new Error(`There was an error while trying to download the r1cs file for circuit ${circuitData.name}. Please check that the file has the correct permissions (public) set.`)
|
|
105
|
+
|
|
106
|
+
await streamPipeline(responseR1CS.body!, createWriteStream(localR1csPath))
|
|
107
|
+
// Write the file locally
|
|
108
|
+
|
|
130
109
|
// extract the metadata from the r1cs
|
|
131
110
|
const metadata = getR1CSInfo(localR1csPath)
|
|
132
111
|
|
|
112
|
+
// download wasm too to ensure it's available
|
|
113
|
+
const responseWASM = await fetch(artifacts.wasmStoragePath)
|
|
114
|
+
if (!responseWASM.ok && responseWASM.status !== 200)
|
|
115
|
+
throw new Error(`There was an error while trying to download the WASM file for circuit ${circuitData.name}. Please check that the file has the correct permissions (public) set.`)
|
|
116
|
+
await streamPipeline(responseWASM.body!, createWriteStream(localWasmPath))
|
|
117
|
+
|
|
133
118
|
// validate that the circuit hash and template links are valid
|
|
134
119
|
const template = circuitData.template
|
|
135
120
|
|
|
@@ -244,8 +229,10 @@ export const parseCeremonyFile = async (path: string, cleanup: boolean = false):
|
|
|
244
229
|
|
|
245
230
|
circuits.push(circuit)
|
|
246
231
|
|
|
247
|
-
// remove the local r1cs
|
|
248
|
-
if (cleanup)
|
|
232
|
+
// remove the local r1cs and wasm downloads (if used for verifying the config only vs setup)
|
|
233
|
+
if (cleanup)
|
|
234
|
+
fs.unlinkSync(localR1csPath)
|
|
235
|
+
fs.unlinkSync(localWasmPath)
|
|
249
236
|
}
|
|
250
237
|
|
|
251
238
|
const setupData: SetupCeremonyData = {
|