@devtion/actions 0.0.0-7e983e3 → 0.0.0-8bb9489
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/README.md +1 -1
- package/dist/index.mjs +78 -95
- package/dist/index.node.js +78 -95
- 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/storage.d.ts +5 -2
- package/dist/types/src/helpers/storage.d.ts.map +1 -1
- package/dist/types/src/helpers/utils.d.ts.map +1 -1
- package/dist/types/src/helpers/vm.d.ts.map +1 -1
- package/dist/types/src/types/index.d.ts.map +1 -1
- package/package.json +2 -6
- package/src/helpers/constants.ts +7 -1
- package/src/helpers/functions.ts +1 -1
- package/src/helpers/security.ts +28 -50
- package/src/helpers/services.ts +1 -1
- package/src/helpers/storage.ts +15 -3
- package/src/helpers/utils.ts +77 -83
- package/src/helpers/vm.ts +9 -3
- package/src/index.ts +2 -2
- package/src/types/index.ts +9 -5
package/README.md
CHANGED
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module @p0tion/actions
|
|
3
|
-
* @version 1.0.
|
|
3
|
+
* @version 1.0.9
|
|
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: {
|
|
@@ -334,7 +339,7 @@ const commonTerms = {
|
|
|
334
339
|
finalizeCircuit: "finalizeCircuit",
|
|
335
340
|
finalizeCeremony: "finalizeCeremony",
|
|
336
341
|
downloadCircuitArtifacts: "downloadCircuitArtifacts",
|
|
337
|
-
transferObject: "transferObject"
|
|
342
|
+
transferObject: "transferObject"
|
|
338
343
|
}
|
|
339
344
|
};
|
|
340
345
|
|
|
@@ -685,11 +690,15 @@ const getChunksAndPreSignedUrls = async (cloudFunctions, bucketName, objectKey,
|
|
|
685
690
|
* @param cloudFunctions <Functions> - the Firebase Cloud Functions service instance.
|
|
686
691
|
* @param ceremonyId <string> - the unique identifier of the ceremony.
|
|
687
692
|
* @param alreadyUploadedChunks Array<ETagWithPartNumber> - the temporary information about the already uploaded chunks.
|
|
693
|
+
* @param logger <GenericBar> - an optional logger to show progress.
|
|
688
694
|
* @returns <Promise<Array<ETagWithPartNumber>>> - the completed (uploaded) chunks information.
|
|
689
695
|
*/
|
|
690
|
-
const uploadParts = async (chunksWithUrls, contentType, cloudFunctions, ceremonyId, alreadyUploadedChunks) => {
|
|
696
|
+
const uploadParts = async (chunksWithUrls, contentType, cloudFunctions, ceremonyId, alreadyUploadedChunks, logger) => {
|
|
691
697
|
// Keep track of uploaded chunks.
|
|
692
698
|
const uploadedChunks = alreadyUploadedChunks || [];
|
|
699
|
+
// if we were passed a logger, start it
|
|
700
|
+
if (logger)
|
|
701
|
+
logger.start(chunksWithUrls.length, 0);
|
|
693
702
|
// Loop through remaining chunks.
|
|
694
703
|
for (let i = alreadyUploadedChunks ? alreadyUploadedChunks.length : 0; i < chunksWithUrls.length; i += 1) {
|
|
695
704
|
// Consume the pre-signed url to upload the chunk.
|
|
@@ -721,6 +730,9 @@ const uploadParts = async (chunksWithUrls, contentType, cloudFunctions, ceremony
|
|
|
721
730
|
// nb. this must be done only when contributing (not finalizing).
|
|
722
731
|
if (!!ceremonyId && !!cloudFunctions)
|
|
723
732
|
await temporaryStoreCurrentContributionUploadedChunkData(cloudFunctions, ceremonyId, chunk);
|
|
733
|
+
// increment the count on the logger
|
|
734
|
+
if (logger)
|
|
735
|
+
logger.increment();
|
|
724
736
|
}
|
|
725
737
|
return uploadedChunks;
|
|
726
738
|
};
|
|
@@ -741,8 +753,9 @@ const uploadParts = async (chunksWithUrls, contentType, cloudFunctions, ceremony
|
|
|
741
753
|
* @param configStreamChunkSize <number> - size of each chunk into which the artifact is going to be splitted (nb. will be converted in MB).
|
|
742
754
|
* @param [ceremonyId] <string> - the unique identifier of the ceremony (used as a double-edge sword - as identifier and as a check if current contributor is the coordinator finalizing the ceremony).
|
|
743
755
|
* @param [temporaryDataToResumeMultiPartUpload] <TemporaryParticipantContributionData> - the temporary information necessary to resume an already started multi-part upload.
|
|
756
|
+
* @param logger <GenericBar> - an optional logger to show progress.
|
|
744
757
|
*/
|
|
745
|
-
const multiPartUpload = async (cloudFunctions, bucketName, objectKey, localFilePath, configStreamChunkSize, ceremonyId, temporaryDataToResumeMultiPartUpload) => {
|
|
758
|
+
const multiPartUpload = async (cloudFunctions, bucketName, objectKey, localFilePath, configStreamChunkSize, ceremonyId, temporaryDataToResumeMultiPartUpload, logger) => {
|
|
746
759
|
// The unique identifier of the multi-part upload.
|
|
747
760
|
let multiPartUploadId = "";
|
|
748
761
|
// The list of already uploaded chunks.
|
|
@@ -766,7 +779,7 @@ const multiPartUpload = async (cloudFunctions, bucketName, objectKey, localFileP
|
|
|
766
779
|
const chunksWithUrlsZkey = await getChunksAndPreSignedUrls(cloudFunctions, bucketName, objectKey, localFilePath, multiPartUploadId, configStreamChunkSize, ceremonyId);
|
|
767
780
|
// Step (2).
|
|
768
781
|
const partNumbersAndETagsZkey = await uploadParts(chunksWithUrlsZkey, mime.lookup(localFilePath), // content-type.
|
|
769
|
-
cloudFunctions, ceremonyId, alreadyUploadedChunks);
|
|
782
|
+
cloudFunctions, ceremonyId, alreadyUploadedChunks, logger);
|
|
770
783
|
// Step (3).
|
|
771
784
|
await completeMultiPartUpload(cloudFunctions, bucketName, objectKey, multiPartUploadId, partNumbersAndETagsZkey, ceremonyId);
|
|
772
785
|
};
|
|
@@ -1052,7 +1065,8 @@ const parseCeremonyFile = async (path, cleanup = false) => {
|
|
|
1052
1065
|
// read the data
|
|
1053
1066
|
const data = JSON.parse(fs.readFileSync(path).toString());
|
|
1054
1067
|
// verify that the data is correct
|
|
1055
|
-
if (data[
|
|
1068
|
+
if (data["timeoutMechanismType"] !== "DYNAMIC" /* CeremonyTimeoutType.DYNAMIC */ &&
|
|
1069
|
+
data["timeoutMechanismType"] !== "FIXED" /* CeremonyTimeoutType.FIXED */)
|
|
1056
1070
|
throw new Error("Invalid timeout type. Please choose between DYNAMIC and FIXED.");
|
|
1057
1071
|
// validate that we have at least 1 circuit input data
|
|
1058
1072
|
if (!data.circuits || data.circuits.length === 0)
|
|
@@ -1085,42 +1099,26 @@ const parseCeremonyFile = async (path, cleanup = false) => {
|
|
|
1085
1099
|
circuitArtifacts.push({
|
|
1086
1100
|
artifacts: artifacts
|
|
1087
1101
|
});
|
|
1088
|
-
const r1csPath = artifacts.r1csStoragePath;
|
|
1089
|
-
const wasmPath = artifacts.wasmStoragePath;
|
|
1090
1102
|
// where we storing the r1cs downloaded
|
|
1091
1103
|
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
|
-
}
|
|
1104
|
+
// where we storing the wasm downloaded
|
|
1105
|
+
const localWasmPath = `./${circuitData.name}.wasm`;
|
|
1114
1106
|
// 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
1107
|
const streamPipeline = promisify(pipeline);
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1108
|
+
// Make the call.
|
|
1109
|
+
const responseR1CS = await fetch(artifacts.r1csStoragePath);
|
|
1110
|
+
// Handle errors.
|
|
1111
|
+
if (!responseR1CS.ok && responseR1CS.status !== 200)
|
|
1112
|
+
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.`);
|
|
1113
|
+
await streamPipeline(responseR1CS.body, createWriteStream(localR1csPath));
|
|
1114
|
+
// Write the file locally
|
|
1122
1115
|
// extract the metadata from the r1cs
|
|
1123
1116
|
const metadata = getR1CSInfo(localR1csPath);
|
|
1117
|
+
// download wasm too to ensure it's available
|
|
1118
|
+
const responseWASM = await fetch(artifacts.wasmStoragePath);
|
|
1119
|
+
if (!responseWASM.ok && responseWASM.status !== 200)
|
|
1120
|
+
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.`);
|
|
1121
|
+
await streamPipeline(responseWASM.body, createWriteStream(localWasmPath));
|
|
1124
1122
|
// validate that the circuit hash and template links are valid
|
|
1125
1123
|
const template = circuitData.template;
|
|
1126
1124
|
const URLMatch = template.source.match(urlPattern);
|
|
@@ -1138,7 +1136,7 @@ const parseCeremonyFile = async (path, cleanup = false) => {
|
|
|
1138
1136
|
const wasmCompleteFilename = `${circuitData.name}.wasm`;
|
|
1139
1137
|
const smallestPowersOfTauCompleteFilenameForCircuit = `${potFilenameTemplate}${doubleDigitsPowers}.ptau`;
|
|
1140
1138
|
const firstZkeyCompleteFilename = `${circuitPrefix}_${genesisZkeyIndex}.zkey`;
|
|
1141
|
-
// storage paths
|
|
1139
|
+
// storage paths
|
|
1142
1140
|
const r1csStorageFilePath = getR1csStorageFilePath(circuitPrefix, r1csCompleteFilename);
|
|
1143
1141
|
const wasmStorageFilePath = getWasmStorageFilePath(circuitPrefix, wasmCompleteFilename);
|
|
1144
1142
|
const potStorageFilePath = getPotStorageFilePath(smallestPowersOfTauCompleteFilenameForCircuit);
|
|
@@ -1154,7 +1152,7 @@ const parseCeremonyFile = async (path, cleanup = false) => {
|
|
|
1154
1152
|
initialZkeyStoragePath: zkeyStorageFilePath,
|
|
1155
1153
|
r1csBlake2bHash: r1csBlake2bHash
|
|
1156
1154
|
};
|
|
1157
|
-
// validate that the compiler hash is a valid hash
|
|
1155
|
+
// validate that the compiler hash is a valid hash
|
|
1158
1156
|
const compiler = circuitData.compiler;
|
|
1159
1157
|
const compilerHashMatch = compiler.commitHash.match(commitHashPattern);
|
|
1160
1158
|
if (!compilerHashMatch || compilerHashMatch.length === 0 || compilerHashMatch.length > 1)
|
|
@@ -1189,7 +1187,7 @@ const parseCeremonyFile = async (path, cleanup = false) => {
|
|
|
1189
1187
|
contributionComputation: 0,
|
|
1190
1188
|
fullContribution: 0,
|
|
1191
1189
|
verifyCloudFunction: 0
|
|
1192
|
-
}
|
|
1190
|
+
}
|
|
1193
1191
|
};
|
|
1194
1192
|
}
|
|
1195
1193
|
if (data.timeoutMechanismType === "FIXED" /* CeremonyTimeoutType.FIXED */) {
|
|
@@ -1212,13 +1210,14 @@ const parseCeremonyFile = async (path, cleanup = false) => {
|
|
|
1212
1210
|
contributionComputation: 0,
|
|
1213
1211
|
fullContribution: 0,
|
|
1214
1212
|
verifyCloudFunction: 0
|
|
1215
|
-
}
|
|
1213
|
+
}
|
|
1216
1214
|
};
|
|
1217
1215
|
}
|
|
1218
1216
|
circuits.push(circuit);
|
|
1219
|
-
// remove the local r1cs
|
|
1217
|
+
// remove the local r1cs and wasm downloads (if used for verifying the config only vs setup)
|
|
1220
1218
|
if (cleanup)
|
|
1221
1219
|
fs.unlinkSync(localR1csPath);
|
|
1220
|
+
fs.unlinkSync(localWasmPath);
|
|
1222
1221
|
}
|
|
1223
1222
|
const setupData = {
|
|
1224
1223
|
ceremonyInputData: {
|
|
@@ -1372,7 +1371,9 @@ const getContributionsValidityForContributor = async (firestoreDatabase, circuit
|
|
|
1372
1371
|
* @param isFinalizing <boolean> - true when the coordinator is finalizing the ceremony, otherwise false.
|
|
1373
1372
|
* @returns <string> - the public attestation preamble.
|
|
1374
1373
|
*/
|
|
1375
|
-
const getPublicAttestationPreambleForContributor = (contributorIdentifier, ceremonyName, isFinalizing) => `Hey, I'm ${contributorIdentifier} and I have ${isFinalizing ? "finalized" : "contributed to"} the ${ceremonyName}
|
|
1374
|
+
const getPublicAttestationPreambleForContributor = (contributorIdentifier, ceremonyName, isFinalizing) => `Hey, I'm ${contributorIdentifier} and I have ${isFinalizing ? "finalized" : "contributed to"} the ${ceremonyName}${ceremonyName.toLowerCase().includes("trusted setup") || ceremonyName.toLowerCase().includes("ceremony")
|
|
1375
|
+
? "."
|
|
1376
|
+
: " MPC Phase2 Trusted Setup ceremony."}\nThe following are my contribution signatures:`;
|
|
1376
1377
|
/**
|
|
1377
1378
|
* Check and prepare public attestation for the contributor made only of its valid contributions.
|
|
1378
1379
|
* @param firestoreDatabase <Firestore> - the Firestore service instance associated to the current Firebase application.
|
|
@@ -1828,7 +1829,7 @@ const getFirestoreDatabase = (app) => getFirestore(app);
|
|
|
1828
1829
|
* @param app <FirebaseApp> - the Firebase application.
|
|
1829
1830
|
* @returns <Functions> - the Cloud Functions associated to the application.
|
|
1830
1831
|
*/
|
|
1831
|
-
const getFirebaseFunctions = (app) => getFunctions(app,
|
|
1832
|
+
const getFirebaseFunctions = (app) => getFunctions(app, "europe-west1");
|
|
1832
1833
|
/**
|
|
1833
1834
|
* Retrieve the configuration variables for the AWS services (S3, EC2).
|
|
1834
1835
|
* @returns <AWSVariables> - the values of the AWS services configuration variables.
|
|
@@ -2079,55 +2080,27 @@ const verifyCeremony = async (functions, firestore, ceremonyPrefix, outputDirect
|
|
|
2079
2080
|
};
|
|
2080
2081
|
|
|
2081
2082
|
/**
|
|
2082
|
-
* This function
|
|
2083
|
-
* @param user
|
|
2084
|
-
* @returns
|
|
2083
|
+
* This function queries the GitHub API to fetch users statistics
|
|
2084
|
+
* @param user {string} the user uid
|
|
2085
|
+
* @returns {any} the stats from the GitHub API
|
|
2085
2086
|
*/
|
|
2086
|
-
const
|
|
2087
|
-
const response = await fetch(`https://api.github.com/user/${user}
|
|
2087
|
+
const getGitHubStats = async (user) => {
|
|
2088
|
+
const response = await fetch(`https://api.github.com/user/${user}`, {
|
|
2088
2089
|
method: "GET",
|
|
2089
2090
|
headers: {
|
|
2090
2091
|
Authorization: `token ${process.env.GITHUB_ACCESS_TOKEN}`
|
|
2091
2092
|
}
|
|
2092
2093
|
});
|
|
2093
2094
|
if (response.status !== 200)
|
|
2094
|
-
throw new Error("It was not possible to retrieve the
|
|
2095
|
+
throw new Error("It was not possible to retrieve the user's statistic. Please try again.");
|
|
2095
2096
|
const jsonData = await response.json();
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
const getNumberOfFollowersGitHub = async (user) => {
|
|
2104
|
-
const response = await fetch(`https://api.github.com/user/${user}/followers`, {
|
|
2105
|
-
method: "GET",
|
|
2106
|
-
headers: {
|
|
2107
|
-
Authorization: `token ${process.env.GITHUB_ACCESS_TOKEN}`
|
|
2108
|
-
}
|
|
2109
|
-
});
|
|
2110
|
-
if (response.status !== 200)
|
|
2111
|
-
throw new Error("It was not possible to retrieve the number of followers. Please try again.");
|
|
2112
|
-
const jsonData = await response.json();
|
|
2113
|
-
return jsonData.length;
|
|
2114
|
-
};
|
|
2115
|
-
/**
|
|
2116
|
-
* This function will return the number of following of a user
|
|
2117
|
-
* @param user <string> The username of the user
|
|
2118
|
-
* @returns <number> The number of following users
|
|
2119
|
-
*/
|
|
2120
|
-
const getNumberOfFollowingGitHub = async (user) => {
|
|
2121
|
-
const response = await fetch(`https://api.github.com/user/${user}/following`, {
|
|
2122
|
-
method: "GET",
|
|
2123
|
-
headers: {
|
|
2124
|
-
Authorization: `token ${process.env.GITHUB_ACCESS_TOKEN}`
|
|
2125
|
-
}
|
|
2126
|
-
});
|
|
2127
|
-
if (response.status !== 200)
|
|
2128
|
-
throw new Error("It was not possible to retrieve the number of following. Please try again.");
|
|
2129
|
-
const jsonData = await response.json();
|
|
2130
|
-
return jsonData.length;
|
|
2097
|
+
const data = {
|
|
2098
|
+
following: jsonData.following,
|
|
2099
|
+
followers: jsonData.followers,
|
|
2100
|
+
publicRepos: jsonData.public_repos,
|
|
2101
|
+
avatarUrl: jsonData.avatar_url
|
|
2102
|
+
};
|
|
2103
|
+
return data;
|
|
2131
2104
|
};
|
|
2132
2105
|
/**
|
|
2133
2106
|
* This function will check if the user is reputable enough to be able to use the app
|
|
@@ -2135,19 +2108,23 @@ const getNumberOfFollowingGitHub = async (user) => {
|
|
|
2135
2108
|
* @param minimumAmountOfFollowing <number> The minimum amount of following the user should have
|
|
2136
2109
|
* @param minimumAmountOfFollowers <number> The minimum amount of followers the user should have
|
|
2137
2110
|
* @param minimumAmountOfPublicRepos <number> The minimum amount of public repos the user should have
|
|
2138
|
-
* @returns <
|
|
2111
|
+
* @returns <any> Return the avatar URL of the user if the user is reputable, false otherwise
|
|
2139
2112
|
*/
|
|
2140
2113
|
const githubReputation = async (userLogin, minimumAmountOfFollowing, minimumAmountOfFollowers, minimumAmountOfPublicRepos) => {
|
|
2141
2114
|
if (!process.env.GITHUB_ACCESS_TOKEN)
|
|
2142
2115
|
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.");
|
|
2143
|
-
const following = await
|
|
2144
|
-
const repos = await getNumberOfPublicReposGitHub(userLogin);
|
|
2145
|
-
const followers = await getNumberOfFollowersGitHub(userLogin);
|
|
2116
|
+
const { following, followers, publicRepos, avatarUrl } = await getGitHubStats(userLogin);
|
|
2146
2117
|
if (following < minimumAmountOfFollowing ||
|
|
2147
|
-
|
|
2118
|
+
publicRepos < minimumAmountOfPublicRepos ||
|
|
2148
2119
|
followers < minimumAmountOfFollowers)
|
|
2149
|
-
return
|
|
2150
|
-
|
|
2120
|
+
return {
|
|
2121
|
+
reputable: false,
|
|
2122
|
+
avatarUrl: ""
|
|
2123
|
+
};
|
|
2124
|
+
return {
|
|
2125
|
+
reputable: true,
|
|
2126
|
+
avatarUrl: avatarUrl
|
|
2127
|
+
};
|
|
2151
2128
|
};
|
|
2152
2129
|
|
|
2153
2130
|
/**
|
|
@@ -2355,8 +2332,13 @@ const vmDependenciesAndCacheArtifactsCommand = (zKeyPath, potPath, snsTopic, reg
|
|
|
2355
2332
|
// eslint-disable-next-line no-template-curly-in-string
|
|
2356
2333
|
"touch ${MARKER_FILE}",
|
|
2357
2334
|
"sudo yum update -y",
|
|
2358
|
-
"curl -
|
|
2359
|
-
"
|
|
2335
|
+
"curl -O https://nodejs.org/dist/v16.13.0/node-v16.13.0-linux-x64.tar.xz",
|
|
2336
|
+
"tar -xf node-v16.13.0-linux-x64.tar.xz",
|
|
2337
|
+
"mv node-v16.13.0-linux-x64 nodejs",
|
|
2338
|
+
"sudo mv nodejs /opt/",
|
|
2339
|
+
"echo 'export NODEJS_HOME=/opt/nodejs' >> /etc/profile",
|
|
2340
|
+
"echo 'export PATH=$NODEJS_HOME/bin:$PATH' >> /etc/profile",
|
|
2341
|
+
"source /etc/profile",
|
|
2360
2342
|
"npm install -g snarkjs",
|
|
2361
2343
|
`aws s3 cp s3://${zKeyPath} /var/tmp/genesisZkey.zkey`,
|
|
2362
2344
|
`aws s3 cp s3://${potPath} /var/tmp/pot.ptau`,
|
|
@@ -2375,6 +2357,7 @@ const vmDependenciesAndCacheArtifactsCommand = (zKeyPath, potPath, snsTopic, reg
|
|
|
2375
2357
|
* @returns Array<string> - the list of commands for contribution verification.
|
|
2376
2358
|
*/
|
|
2377
2359
|
const vmContributionVerificationCommand = (bucketName, lastZkeyStoragePath, verificationTranscriptStoragePathAndFilename) => [
|
|
2360
|
+
`source /etc/profile`,
|
|
2378
2361
|
`aws s3 cp s3://${bucketName}/${lastZkeyStoragePath} /var/tmp/lastZKey.zkey > /var/tmp/log.txt`,
|
|
2379
2362
|
`snarkjs zkvi /var/tmp/genesisZkey.zkey /var/tmp/pot.ptau /var/tmp/lastZKey.zkey > /var/tmp/verification_transcript.log`,
|
|
2380
2363
|
`aws s3 cp /var/tmp/verification_transcript.log s3://${bucketName}/${verificationTranscriptStoragePathAndFilename} &>/dev/null`,
|