@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/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/services.ts
CHANGED
|
@@ -22,7 +22,7 @@ export const getFirestoreDatabase = (app: FirebaseApp): Firestore => getFirestor
|
|
|
22
22
|
* @param app <FirebaseApp> - the Firebase application.
|
|
23
23
|
* @returns <Functions> - the Cloud Functions associated to the application.
|
|
24
24
|
*/
|
|
25
|
-
export const getFirebaseFunctions = (app: FirebaseApp): Functions => getFunctions(app,
|
|
25
|
+
export const getFirebaseFunctions = (app: FirebaseApp): Functions => getFunctions(app, "europe-west1")
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
28
|
* Retrieve the configuration variables for the AWS services (S3, EC2).
|
package/src/helpers/storage.ts
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
temporaryStoreCurrentContributionMultiPartUploadId,
|
|
14
14
|
temporaryStoreCurrentContributionUploadedChunkData
|
|
15
15
|
} from "./functions"
|
|
16
|
+
import { GenericBar } from "cli-progress"
|
|
16
17
|
|
|
17
18
|
/**
|
|
18
19
|
* Return the bucket name based on ceremony prefix.
|
|
@@ -80,6 +81,7 @@ export const getChunksAndPreSignedUrls = async (
|
|
|
80
81
|
* @param cloudFunctions <Functions> - the Firebase Cloud Functions service instance.
|
|
81
82
|
* @param ceremonyId <string> - the unique identifier of the ceremony.
|
|
82
83
|
* @param alreadyUploadedChunks Array<ETagWithPartNumber> - the temporary information about the already uploaded chunks.
|
|
84
|
+
* @param logger <GenericBar> - an optional logger to show progress.
|
|
83
85
|
* @returns <Promise<Array<ETagWithPartNumber>>> - the completed (uploaded) chunks information.
|
|
84
86
|
*/
|
|
85
87
|
export const uploadParts = async (
|
|
@@ -87,11 +89,15 @@ export const uploadParts = async (
|
|
|
87
89
|
contentType: string | false,
|
|
88
90
|
cloudFunctions?: Functions,
|
|
89
91
|
ceremonyId?: string,
|
|
90
|
-
alreadyUploadedChunks?: Array<ETagWithPartNumber
|
|
92
|
+
alreadyUploadedChunks?: Array<ETagWithPartNumber>,
|
|
93
|
+
logger?: GenericBar
|
|
91
94
|
): Promise<Array<ETagWithPartNumber>> => {
|
|
92
95
|
// Keep track of uploaded chunks.
|
|
93
96
|
const uploadedChunks: Array<ETagWithPartNumber> = alreadyUploadedChunks || []
|
|
94
97
|
|
|
98
|
+
// if we were passed a logger, start it
|
|
99
|
+
if (logger) logger.start(chunksWithUrls.length, 0)
|
|
100
|
+
|
|
95
101
|
// Loop through remaining chunks.
|
|
96
102
|
for (let i = alreadyUploadedChunks ? alreadyUploadedChunks.length : 0; i < chunksWithUrls.length; i += 1) {
|
|
97
103
|
// Consume the pre-signed url to upload the chunk.
|
|
@@ -128,6 +134,9 @@ export const uploadParts = async (
|
|
|
128
134
|
// nb. this must be done only when contributing (not finalizing).
|
|
129
135
|
if (!!ceremonyId && !!cloudFunctions)
|
|
130
136
|
await temporaryStoreCurrentContributionUploadedChunkData(cloudFunctions, ceremonyId, chunk)
|
|
137
|
+
|
|
138
|
+
// increment the count on the logger
|
|
139
|
+
if (logger) logger.increment()
|
|
131
140
|
}
|
|
132
141
|
|
|
133
142
|
return uploadedChunks
|
|
@@ -150,6 +159,7 @@ export const uploadParts = async (
|
|
|
150
159
|
* @param configStreamChunkSize <number> - size of each chunk into which the artifact is going to be splitted (nb. will be converted in MB).
|
|
151
160
|
* @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).
|
|
152
161
|
* @param [temporaryDataToResumeMultiPartUpload] <TemporaryParticipantContributionData> - the temporary information necessary to resume an already started multi-part upload.
|
|
162
|
+
* @param logger <GenericBar> - an optional logger to show progress.
|
|
153
163
|
*/
|
|
154
164
|
export const multiPartUpload = async (
|
|
155
165
|
cloudFunctions: Functions,
|
|
@@ -158,7 +168,8 @@ export const multiPartUpload = async (
|
|
|
158
168
|
localFilePath: string,
|
|
159
169
|
configStreamChunkSize: number,
|
|
160
170
|
ceremonyId?: string,
|
|
161
|
-
temporaryDataToResumeMultiPartUpload?: TemporaryParticipantContributionData
|
|
171
|
+
temporaryDataToResumeMultiPartUpload?: TemporaryParticipantContributionData,
|
|
172
|
+
logger?: GenericBar
|
|
162
173
|
) => {
|
|
163
174
|
// The unique identifier of the multi-part upload.
|
|
164
175
|
let multiPartUploadId: string = ""
|
|
@@ -198,7 +209,8 @@ export const multiPartUpload = async (
|
|
|
198
209
|
mime.lookup(localFilePath), // content-type.
|
|
199
210
|
cloudFunctions,
|
|
200
211
|
ceremonyId,
|
|
201
|
-
alreadyUploadedChunks
|
|
212
|
+
alreadyUploadedChunks,
|
|
213
|
+
logger
|
|
202
214
|
)
|
|
203
215
|
|
|
204
216
|
// Step (3).
|
package/src/helpers/utils.ts
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
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
|
|
6
|
-
import {
|
|
7
|
-
CircuitMetadata,
|
|
8
|
-
Contribution,
|
|
9
|
-
CircuitDocument,
|
|
5
|
+
import fetch from "@adobe/node-fetch-retry"
|
|
6
|
+
import {
|
|
7
|
+
CircuitMetadata,
|
|
8
|
+
Contribution,
|
|
9
|
+
CircuitDocument,
|
|
10
10
|
CircuitInputData,
|
|
11
|
-
ContributionValidity,
|
|
12
|
-
FirebaseDocumentInfo,
|
|
13
|
-
SetupCeremonyData,
|
|
11
|
+
ContributionValidity,
|
|
12
|
+
FirebaseDocumentInfo,
|
|
13
|
+
SetupCeremonyData,
|
|
14
14
|
CeremonySetupTemplate,
|
|
15
|
-
CeremonySetupTemplateCircuitArtifacts
|
|
15
|
+
CeremonySetupTemplateCircuitArtifacts
|
|
16
16
|
} from "../types/index"
|
|
17
17
|
import { finalContributionIndex, genesisZkeyIndex, potFilenameTemplate } from "./constants"
|
|
18
18
|
import {
|
|
@@ -22,14 +22,14 @@ import {
|
|
|
22
22
|
getContributionsCollectionPath
|
|
23
23
|
} from "./database"
|
|
24
24
|
import { CeremonyTimeoutType } from "../types/enums"
|
|
25
|
-
import {
|
|
26
|
-
getPotStorageFilePath,
|
|
27
|
-
getR1csStorageFilePath,
|
|
28
|
-
getWasmStorageFilePath,
|
|
25
|
+
import {
|
|
26
|
+
getPotStorageFilePath,
|
|
27
|
+
getR1csStorageFilePath,
|
|
28
|
+
getWasmStorageFilePath,
|
|
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
|
/**
|
|
@@ -41,23 +41,29 @@ import { promisify } from "util"
|
|
|
41
41
|
*/
|
|
42
42
|
export const parseCeremonyFile = async (path: string, cleanup: boolean = false): Promise<SetupCeremonyData> => {
|
|
43
43
|
// check that the path exists
|
|
44
|
-
if (!fs.existsSync(path))
|
|
45
|
-
|
|
44
|
+
if (!fs.existsSync(path))
|
|
45
|
+
throw new Error(
|
|
46
|
+
"The provided path to the configuration file does not exist. Please provide an absolute path and try again."
|
|
47
|
+
)
|
|
48
|
+
|
|
46
49
|
try {
|
|
47
50
|
// read the data
|
|
48
51
|
const data: CeremonySetupTemplate = JSON.parse(fs.readFileSync(path).toString())
|
|
49
52
|
|
|
50
53
|
// verify that the data is correct
|
|
51
|
-
if (
|
|
54
|
+
if (
|
|
55
|
+
data["timeoutMechanismType"] !== CeremonyTimeoutType.DYNAMIC &&
|
|
56
|
+
data["timeoutMechanismType"] !== CeremonyTimeoutType.FIXED
|
|
57
|
+
)
|
|
52
58
|
throw new Error("Invalid timeout type. Please choose between DYNAMIC and FIXED.")
|
|
53
|
-
|
|
59
|
+
|
|
54
60
|
// validate that we have at least 1 circuit input data
|
|
55
|
-
if (!data.circuits || data.circuits.length === 0)
|
|
61
|
+
if (!data.circuits || data.circuits.length === 0)
|
|
56
62
|
throw new Error("You need to provide the data for at least 1 circuit.")
|
|
57
63
|
|
|
58
64
|
// validate that the end date is in the future
|
|
59
|
-
let endDate: Date
|
|
60
|
-
let startDate: Date
|
|
65
|
+
let endDate: Date
|
|
66
|
+
let startDate: Date
|
|
61
67
|
try {
|
|
62
68
|
endDate = new Date(data.endDate)
|
|
63
69
|
startDate = new Date(data.startDate)
|
|
@@ -66,12 +72,12 @@ export const parseCeremonyFile = async (path: string, cleanup: boolean = false):
|
|
|
66
72
|
}
|
|
67
73
|
|
|
68
74
|
if (endDate <= startDate) throw new Error("The end date should be greater than the start date.")
|
|
69
|
-
|
|
75
|
+
|
|
70
76
|
const currentDate = new Date()
|
|
71
77
|
|
|
72
|
-
if (endDate <= currentDate || startDate <= currentDate)
|
|
78
|
+
if (endDate <= currentDate || startDate <= currentDate)
|
|
73
79
|
throw new Error("The start and end dates should be in the future.")
|
|
74
|
-
|
|
80
|
+
|
|
75
81
|
// validate penalty
|
|
76
82
|
if (data.penalty <= 0) throw new Error("The penalty should be greater than zero.")
|
|
77
83
|
|
|
@@ -87,58 +93,49 @@ export const parseCeremonyFile = async (path: string, cleanup: boolean = false):
|
|
|
87
93
|
circuitArtifacts.push({
|
|
88
94
|
artifacts: artifacts
|
|
89
95
|
})
|
|
90
|
-
const r1csPath = artifacts.r1csStoragePath
|
|
91
|
-
const wasmPath = artifacts.wasmStoragePath
|
|
92
96
|
|
|
93
97
|
// where we storing the r1cs downloaded
|
|
94
98
|
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
|
-
}
|
|
99
|
+
// where we storing the wasm downloaded
|
|
100
|
+
const localWasmPath = `./${circuitData.name}.wasm`
|
|
118
101
|
|
|
119
102
|
// 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
103
|
const streamPipeline = promisify(pipeline)
|
|
123
104
|
|
|
124
|
-
|
|
125
|
-
|
|
105
|
+
// Make the call.
|
|
106
|
+
const responseR1CS = await fetch(artifacts.r1csStoragePath)
|
|
107
|
+
|
|
108
|
+
// Handle errors.
|
|
109
|
+
if (!responseR1CS.ok && responseR1CS.status !== 200)
|
|
110
|
+
throw new Error(
|
|
111
|
+
`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.`
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
await streamPipeline(responseR1CS.body!, createWriteStream(localR1csPath))
|
|
115
|
+
// Write the file locally
|
|
126
116
|
|
|
127
|
-
if (response.Body instanceof Readable)
|
|
128
|
-
await streamPipeline(response.Body, fs.createWriteStream(localR1csPath))
|
|
129
|
-
|
|
130
117
|
// extract the metadata from the r1cs
|
|
131
118
|
const metadata = getR1CSInfo(localR1csPath)
|
|
132
119
|
|
|
120
|
+
// download wasm too to ensure it's available
|
|
121
|
+
const responseWASM = await fetch(artifacts.wasmStoragePath)
|
|
122
|
+
if (!responseWASM.ok && responseWASM.status !== 200)
|
|
123
|
+
throw new Error(
|
|
124
|
+
`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.`
|
|
125
|
+
)
|
|
126
|
+
await streamPipeline(responseWASM.body!, createWriteStream(localWasmPath))
|
|
127
|
+
|
|
133
128
|
// validate that the circuit hash and template links are valid
|
|
134
129
|
const template = circuitData.template
|
|
135
130
|
|
|
136
131
|
const URLMatch = template.source.match(urlPattern)
|
|
137
|
-
if (!URLMatch || URLMatch.length === 0 || URLMatch.length > 1)
|
|
132
|
+
if (!URLMatch || URLMatch.length === 0 || URLMatch.length > 1)
|
|
133
|
+
throw new Error("You should provide the URL to the circuits templates on GitHub.")
|
|
138
134
|
|
|
139
135
|
const hashMatch = template.commitHash.match(commitHashPattern)
|
|
140
|
-
if (!hashMatch || hashMatch.length === 0 || hashMatch.length > 1)
|
|
141
|
-
|
|
136
|
+
if (!hashMatch || hashMatch.length === 0 || hashMatch.length > 1)
|
|
137
|
+
throw new Error("You should provide a valid commit hash of the circuit templates.")
|
|
138
|
+
|
|
142
139
|
// calculate the hash of the r1cs file
|
|
143
140
|
const r1csBlake2bHash = await blake512FromPath(localR1csPath)
|
|
144
141
|
|
|
@@ -151,12 +148,12 @@ export const parseCeremonyFile = async (path: string, cleanup: boolean = false):
|
|
|
151
148
|
const smallestPowersOfTauCompleteFilenameForCircuit = `${potFilenameTemplate}${doubleDigitsPowers}.ptau`
|
|
152
149
|
const firstZkeyCompleteFilename = `${circuitPrefix}_${genesisZkeyIndex}.zkey`
|
|
153
150
|
|
|
154
|
-
// storage paths
|
|
151
|
+
// storage paths
|
|
155
152
|
const r1csStorageFilePath = getR1csStorageFilePath(circuitPrefix, r1csCompleteFilename)
|
|
156
153
|
const wasmStorageFilePath = getWasmStorageFilePath(circuitPrefix, wasmCompleteFilename)
|
|
157
154
|
const potStorageFilePath = getPotStorageFilePath(smallestPowersOfTauCompleteFilenameForCircuit)
|
|
158
155
|
const zkeyStorageFilePath = getZkeyStorageFilePath(circuitPrefix, firstZkeyCompleteFilename)
|
|
159
|
-
|
|
156
|
+
|
|
160
157
|
const files: any = {
|
|
161
158
|
potFilename: smallestPowersOfTauCompleteFilenameForCircuit,
|
|
162
159
|
r1csFilename: r1csCompleteFilename,
|
|
@@ -169,14 +166,15 @@ export const parseCeremonyFile = async (path: string, cleanup: boolean = false):
|
|
|
169
166
|
r1csBlake2bHash: r1csBlake2bHash
|
|
170
167
|
}
|
|
171
168
|
|
|
172
|
-
// validate that the compiler hash is a valid hash
|
|
169
|
+
// validate that the compiler hash is a valid hash
|
|
173
170
|
const compiler = circuitData.compiler
|
|
174
171
|
const compilerHashMatch = compiler.commitHash.match(commitHashPattern)
|
|
175
|
-
if (!compilerHashMatch || compilerHashMatch.length === 0 || compilerHashMatch.length > 1)
|
|
172
|
+
if (!compilerHashMatch || compilerHashMatch.length === 0 || compilerHashMatch.length > 1)
|
|
173
|
+
throw new Error("You should provide a valid commit hash of the circuit compiler.")
|
|
176
174
|
|
|
177
175
|
// validate that the verification options are valid
|
|
178
176
|
const verification = circuitData.verification
|
|
179
|
-
if (verification.cfOrVm !== "CF" && verification.cfOrVm !== "VM")
|
|
177
|
+
if (verification.cfOrVm !== "CF" && verification.cfOrVm !== "VM")
|
|
180
178
|
throw new Error("Please enter a valid verification mechanism: either CF or VM")
|
|
181
179
|
|
|
182
180
|
// @todo VM parameters verification
|
|
@@ -189,8 +187,7 @@ export const parseCeremonyFile = async (path: string, cleanup: boolean = false):
|
|
|
189
187
|
let circuit: CircuitDocument | CircuitInputData = {} as CircuitDocument | CircuitInputData
|
|
190
188
|
|
|
191
189
|
if (data.timeoutMechanismType === CeremonyTimeoutType.DYNAMIC) {
|
|
192
|
-
if (circuitData.dynamicThreshold <= 0)
|
|
193
|
-
throw new Error("The dynamic threshold should be > 0.")
|
|
190
|
+
if (circuitData.dynamicThreshold <= 0) throw new Error("The dynamic threshold should be > 0.")
|
|
194
191
|
dynamicThreshold = circuitData.dynamicThreshold
|
|
195
192
|
|
|
196
193
|
// the Circuit data for the ceremony setup
|
|
@@ -198,7 +195,7 @@ export const parseCeremonyFile = async (path: string, cleanup: boolean = false):
|
|
|
198
195
|
name: circuitData.name,
|
|
199
196
|
description: circuitData.description,
|
|
200
197
|
prefix: circuitPrefix,
|
|
201
|
-
sequencePosition: i+1,
|
|
198
|
+
sequencePosition: i + 1,
|
|
202
199
|
metadata: metadata,
|
|
203
200
|
files: files,
|
|
204
201
|
template: template,
|
|
@@ -209,23 +206,20 @@ export const parseCeremonyFile = async (path: string, cleanup: boolean = false):
|
|
|
209
206
|
contributionComputation: 0,
|
|
210
207
|
fullContribution: 0,
|
|
211
208
|
verifyCloudFunction: 0
|
|
212
|
-
}
|
|
213
|
-
|
|
209
|
+
}
|
|
214
210
|
}
|
|
215
211
|
}
|
|
216
212
|
|
|
217
213
|
if (data.timeoutMechanismType === CeremonyTimeoutType.FIXED) {
|
|
218
|
-
if (circuitData.fixedTimeWindow <= 0)
|
|
219
|
-
throw new Error("The fixed time window threshold should be > 0.")
|
|
214
|
+
if (circuitData.fixedTimeWindow <= 0) throw new Error("The fixed time window threshold should be > 0.")
|
|
220
215
|
fixedTimeWindow = circuitData.fixedTimeWindow
|
|
221
216
|
|
|
222
|
-
|
|
223
217
|
// the Circuit data for the ceremony setup
|
|
224
218
|
circuit = {
|
|
225
219
|
name: circuitData.name,
|
|
226
220
|
description: circuitData.description,
|
|
227
221
|
prefix: circuitPrefix,
|
|
228
|
-
sequencePosition: i+1,
|
|
222
|
+
sequencePosition: i + 1,
|
|
229
223
|
metadata: metadata,
|
|
230
224
|
files: files,
|
|
231
225
|
template: template,
|
|
@@ -236,16 +230,15 @@ export const parseCeremonyFile = async (path: string, cleanup: boolean = false):
|
|
|
236
230
|
contributionComputation: 0,
|
|
237
231
|
fullContribution: 0,
|
|
238
232
|
verifyCloudFunction: 0
|
|
239
|
-
}
|
|
240
|
-
|
|
233
|
+
}
|
|
241
234
|
}
|
|
242
235
|
}
|
|
243
236
|
|
|
244
|
-
|
|
245
237
|
circuits.push(circuit)
|
|
246
238
|
|
|
247
|
-
// remove the local r1cs
|
|
239
|
+
// remove the local r1cs and wasm downloads (if used for verifying the config only vs setup)
|
|
248
240
|
if (cleanup) fs.unlinkSync(localR1csPath)
|
|
241
|
+
fs.unlinkSync(localWasmPath)
|
|
249
242
|
}
|
|
250
243
|
|
|
251
244
|
const setupData: SetupCeremonyData = {
|
|
@@ -263,7 +256,6 @@ export const parseCeremonyFile = async (path: string, cleanup: boolean = false):
|
|
|
263
256
|
}
|
|
264
257
|
|
|
265
258
|
return setupData
|
|
266
|
-
|
|
267
259
|
} catch (error: any) {
|
|
268
260
|
throw new Error(`Error while parsing up the ceremony setup file. ${error.message}`)
|
|
269
261
|
}
|
|
@@ -457,9 +449,11 @@ export const getPublicAttestationPreambleForContributor = (
|
|
|
457
449
|
ceremonyName: string,
|
|
458
450
|
isFinalizing: boolean
|
|
459
451
|
) =>
|
|
460
|
-
`Hey, I'm ${contributorIdentifier} and I have ${
|
|
461
|
-
|
|
462
|
-
|
|
452
|
+
`Hey, I'm ${contributorIdentifier} and I have ${isFinalizing ? "finalized" : "contributed to"} the ${ceremonyName}${
|
|
453
|
+
ceremonyName.toLowerCase().includes("trusted setup") || ceremonyName.toLowerCase().includes("ceremony")
|
|
454
|
+
? "."
|
|
455
|
+
: " MPC Phase2 Trusted Setup ceremony."
|
|
456
|
+
}\nThe following are my contribution signatures:`
|
|
463
457
|
|
|
464
458
|
/**
|
|
465
459
|
* Check and prepare public attestation for the contributor made only of its valid contributions.
|
|
@@ -740,4 +734,4 @@ export const getR1CSInfo = (localR1CSFilePath: string): CircuitMetadata => {
|
|
|
740
734
|
* @param in <number> - the input number to be converted.
|
|
741
735
|
* @returns <string> - the two digits stringified number derived from the conversion.
|
|
742
736
|
*/
|
|
743
|
-
export const convertToDoubleDigits = (amount: number): string => (amount < 10 ? `0${amount}` : amount.toString())
|
|
737
|
+
export const convertToDoubleDigits = (amount: number): string => (amount < 10 ? `0${amount}` : amount.toString())
|
package/src/helpers/vm.ts
CHANGED
|
@@ -82,7 +82,7 @@ export const vmDependenciesAndCacheArtifactsCommand = (
|
|
|
82
82
|
zKeyPath: string,
|
|
83
83
|
potPath: string,
|
|
84
84
|
snsTopic: string,
|
|
85
|
-
region: string
|
|
85
|
+
region: string
|
|
86
86
|
): Array<string> => [
|
|
87
87
|
"#!/bin/bash",
|
|
88
88
|
'MARKER_FILE="/var/run/my_script_ran"',
|
|
@@ -93,8 +93,13 @@ export const vmDependenciesAndCacheArtifactsCommand = (
|
|
|
93
93
|
// eslint-disable-next-line no-template-curly-in-string
|
|
94
94
|
"touch ${MARKER_FILE}",
|
|
95
95
|
"sudo yum update -y",
|
|
96
|
-
"curl -
|
|
97
|
-
"
|
|
96
|
+
"curl -O https://nodejs.org/dist/v16.13.0/node-v16.13.0-linux-x64.tar.xz",
|
|
97
|
+
"tar -xf node-v16.13.0-linux-x64.tar.xz",
|
|
98
|
+
"mv node-v16.13.0-linux-x64 nodejs",
|
|
99
|
+
"sudo mv nodejs /opt/",
|
|
100
|
+
"echo 'export NODEJS_HOME=/opt/nodejs' >> /etc/profile",
|
|
101
|
+
"echo 'export PATH=$NODEJS_HOME/bin:$PATH' >> /etc/profile",
|
|
102
|
+
"source /etc/profile",
|
|
98
103
|
"npm install -g snarkjs",
|
|
99
104
|
`aws s3 cp s3://${zKeyPath} /var/tmp/genesisZkey.zkey`,
|
|
100
105
|
`aws s3 cp s3://${potPath} /var/tmp/pot.ptau`,
|
|
@@ -118,6 +123,7 @@ export const vmContributionVerificationCommand = (
|
|
|
118
123
|
lastZkeyStoragePath: string,
|
|
119
124
|
verificationTranscriptStoragePathAndFilename: string
|
|
120
125
|
): Array<string> => [
|
|
126
|
+
`source /etc/profile`,
|
|
121
127
|
`aws s3 cp s3://${bucketName}/${lastZkeyStoragePath} /var/tmp/lastZKey.zkey > /var/tmp/log.txt`,
|
|
122
128
|
`snarkjs zkvi /var/tmp/genesisZkey.zkey /var/tmp/pot.ptau /var/tmp/lastZKey.zkey > /var/tmp/verification_transcript.log`,
|
|
123
129
|
`aws s3 cp /var/tmp/verification_transcript.log s3://${bucketName}/${verificationTranscriptStoragePathAndFilename} &>/dev/null`,
|
package/src/index.ts
CHANGED
|
@@ -87,7 +87,7 @@ export {
|
|
|
87
87
|
verifyContribution,
|
|
88
88
|
checkAndPrepareCoordinatorForFinalization,
|
|
89
89
|
finalizeCircuit,
|
|
90
|
-
finalizeCeremony
|
|
90
|
+
finalizeCeremony
|
|
91
91
|
} from "./helpers/functions"
|
|
92
92
|
export { toHex, blake512FromPath, computeSHA256ToHex, compareHashes } from "./helpers/crypto"
|
|
93
93
|
export {
|
|
@@ -159,4 +159,4 @@ export {
|
|
|
159
159
|
createEC2Client,
|
|
160
160
|
vmContributionVerificationCommand,
|
|
161
161
|
retrieveCommandStatus
|
|
162
|
-
} from "./helpers/vm"
|
|
162
|
+
} from "./helpers/vm"
|
package/src/types/index.ts
CHANGED
|
@@ -620,7 +620,6 @@ export type SetupCeremonyData = {
|
|
|
620
620
|
circuitArtifacts: Array<CeremonySetupTemplateCircuitArtifacts>
|
|
621
621
|
}
|
|
622
622
|
|
|
623
|
-
|
|
624
623
|
export type CeremonySetupTemplateCircuitArtifacts = {
|
|
625
624
|
artifacts: {
|
|
626
625
|
bucket: string
|
|
@@ -640,11 +639,16 @@ export type CeremonySetupTemplateCircuitName = {
|
|
|
640
639
|
}
|
|
641
640
|
|
|
642
641
|
export type CeremonySetupTemplate = {
|
|
643
|
-
title: string
|
|
642
|
+
title: string
|
|
644
643
|
description: string
|
|
645
644
|
startDate: string
|
|
646
645
|
endDate: string
|
|
647
646
|
timeoutMechanismType: CeremonyTimeoutType
|
|
648
|
-
penalty: number
|
|
649
|
-
circuits: Array<
|
|
650
|
-
|
|
647
|
+
penalty: number
|
|
648
|
+
circuits: Array<
|
|
649
|
+
CircuitDocument &
|
|
650
|
+
CeremonySetupTemplateCircuitArtifacts &
|
|
651
|
+
CeremonySetupTemplateCircuitTimeout &
|
|
652
|
+
CeremonySetupTemplateCircuitName
|
|
653
|
+
>
|
|
654
|
+
}
|