@devtion/backend 0.0.0-2319823 → 0.0.0-2cb7418
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/src/functions/index.js +252 -5
- package/dist/src/functions/index.mjs +252 -7
- package/dist/types/functions/bandada.d.ts +4 -0
- package/dist/types/functions/bandada.d.ts.map +1 -0
- package/dist/types/functions/index.d.ts +2 -0
- package/dist/types/functions/index.d.ts.map +1 -1
- package/dist/types/functions/siwe.d.ts +4 -0
- package/dist/types/functions/siwe.d.ts.map +1 -0
- package/dist/types/lib/errors.d.ts +1 -1
- package/dist/types/lib/services.d.ts +7 -0
- package/dist/types/lib/services.d.ts.map +1 -1
- package/dist/types/types/index.d.ts +56 -0
- package/dist/types/types/index.d.ts.map +1 -1
- package/package.json +4 -3
- package/src/functions/bandada.ts +155 -0
- package/src/functions/ceremony.ts +1 -1
- package/src/functions/index.ts +2 -0
- package/src/functions/siwe.ts +77 -0
- package/src/functions/user.ts +2 -2
- package/src/lib/errors.ts +1 -1
- package/src/lib/services.ts +36 -0
- package/src/types/declarations.d.ts +1 -0
- package/src/types/index.ts +60 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module @p0tion/backend
|
|
3
|
-
* @version 1.1
|
|
3
|
+
* @version 1.2.1
|
|
4
4
|
* @file MPC Phase 2 backend for Firebase services management
|
|
5
5
|
* @copyright Ethereum Foundation 2022
|
|
6
6
|
* @license MIT
|
|
@@ -27,10 +27,13 @@ var path = require('path');
|
|
|
27
27
|
var os = require('os');
|
|
28
28
|
var clientSsm = require('@aws-sdk/client-ssm');
|
|
29
29
|
var clientEc2 = require('@aws-sdk/client-ec2');
|
|
30
|
+
var ethers = require('ethers');
|
|
30
31
|
var functionsV1 = require('firebase-functions/v1');
|
|
31
32
|
var functionsV2 = require('firebase-functions/v2');
|
|
32
33
|
var timerNode = require('timer-node');
|
|
33
34
|
var snarkjs = require('snarkjs');
|
|
35
|
+
var apiSdk = require('@bandada/api-sdk');
|
|
36
|
+
var auth = require('firebase-admin/auth');
|
|
34
37
|
|
|
35
38
|
function _interopNamespaceDefault(e) {
|
|
36
39
|
var n = Object.create(null);
|
|
@@ -72,7 +75,7 @@ var LogLevel;
|
|
|
72
75
|
* @notice the set of Firebase Functions status codes. The codes are the same at the
|
|
73
76
|
* ones exposed by {@link https://github.com/grpc/grpc/blob/master/doc/statuscodes.md | gRPC}.
|
|
74
77
|
* @param errorCode <FunctionsErrorCode> - the set of possible error codes.
|
|
75
|
-
* @param message <string> - the error
|
|
78
|
+
* @param message <string> - the error message.
|
|
76
79
|
* @param [details] <string> - the details of the error (optional).
|
|
77
80
|
* @returns <HttpsError>
|
|
78
81
|
*/
|
|
@@ -164,6 +167,8 @@ const COMMON_ERRORS = {
|
|
|
164
167
|
CM_INVALID_COMMAND_EXECUTION: makeError("unknown", "There was an error while executing the command on the VM", "Please, contact the coordinator if the error persists.")
|
|
165
168
|
};
|
|
166
169
|
|
|
170
|
+
dotenv.config();
|
|
171
|
+
let provider;
|
|
167
172
|
/**
|
|
168
173
|
* Return a configured and connected instance of the AWS S3 client.
|
|
169
174
|
* @dev this method check and utilize the environment variables to configure the connection
|
|
@@ -186,6 +191,36 @@ const getS3Client = async () => {
|
|
|
186
191
|
region: process.env.AWS_REGION
|
|
187
192
|
});
|
|
188
193
|
};
|
|
194
|
+
/**
|
|
195
|
+
* Returns a Prvider, connected via a configured JSON URL or else
|
|
196
|
+
* the ethers.js default provider, using configured API keys.
|
|
197
|
+
* @returns <ethers.providers.Provider> An Eth node provider
|
|
198
|
+
*/
|
|
199
|
+
const setEthProvider = () => {
|
|
200
|
+
if (provider)
|
|
201
|
+
return provider;
|
|
202
|
+
console.log(`setting new provider`);
|
|
203
|
+
// Use JSON URL if defined
|
|
204
|
+
// if ((hardhat as any).ethers) {
|
|
205
|
+
// console.log(`using hardhat.ethers provider`)
|
|
206
|
+
// provider = (hardhat as any).ethers.provider
|
|
207
|
+
// } else
|
|
208
|
+
if (process.env.ETH_PROVIDER_JSON_URL) {
|
|
209
|
+
console.log(`JSON URL provider at ${process.env.ETH_PROVIDER_JSON_URL}`);
|
|
210
|
+
provider = new ethers.providers.JsonRpcProvider({
|
|
211
|
+
url: process.env.ETH_PROVIDER_JSON_URL,
|
|
212
|
+
skipFetchSetup: true
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
// Otherwise, connect the default provider with ALchemy, Infura, or both
|
|
217
|
+
provider = ethers.providers.getDefaultProvider("homestead", {
|
|
218
|
+
alchemy: process.env.ETH_PROVIDER_ALCHEMY_API_KEY,
|
|
219
|
+
infura: process.env.ETH_PROVIDER_INFURA_API_KEY
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
return provider;
|
|
223
|
+
};
|
|
189
224
|
|
|
190
225
|
dotenv.config();
|
|
191
226
|
/**
|
|
@@ -556,7 +591,7 @@ const registerAuthUser = functions__namespace
|
|
|
556
591
|
email === process.env.CUSTOM_CLAIMS_COORDINATOR_EMAIL_ADDRESS_OR_DOMAIN)) {
|
|
557
592
|
const auth = admin.auth();
|
|
558
593
|
// if provider == github.com let's use our functions to check the user's reputation
|
|
559
|
-
if (user.providerData[0].providerId === "github.com") {
|
|
594
|
+
if (user.providerData.length > 0 && user.providerData[0].providerId === "github.com") {
|
|
560
595
|
const vars = getGitHubVariables();
|
|
561
596
|
// this return true or false
|
|
562
597
|
try {
|
|
@@ -588,7 +623,7 @@ const registerAuthUser = functions__namespace
|
|
|
588
623
|
encodedDisplayName,
|
|
589
624
|
// Metadata.
|
|
590
625
|
creationTime,
|
|
591
|
-
lastSignInTime,
|
|
626
|
+
lastSignInTime: lastSignInTime || creationTime,
|
|
592
627
|
// Optional.
|
|
593
628
|
email: email || "",
|
|
594
629
|
emailVerified: emailVerified || false,
|
|
@@ -842,7 +877,7 @@ const finalizeCeremony = functions__namespace
|
|
|
842
877
|
// Get ceremony circuits.
|
|
843
878
|
const circuits = await getCeremonyCircuits(ceremonyId);
|
|
844
879
|
// Get final contribution for each circuit.
|
|
845
|
-
// nb. the `getFinalContributionDocument` checks the
|
|
880
|
+
// nb. the `getFinalContributionDocument` checks the existence of the final contribution document (if not present, throws).
|
|
846
881
|
// Therefore, we just need to call the method without taking any data to verify the pre-condition of having already computed
|
|
847
882
|
// the final contributions for each ceremony circuit.
|
|
848
883
|
for await (const circuit of circuits)
|
|
@@ -2407,6 +2442,216 @@ const completeMultiPartUpload = functions__namespace
|
|
|
2407
2442
|
}
|
|
2408
2443
|
});
|
|
2409
2444
|
|
|
2445
|
+
const VKEY_DATA = {
|
|
2446
|
+
protocol: "groth16",
|
|
2447
|
+
curve: "bn128",
|
|
2448
|
+
nPublic: 3,
|
|
2449
|
+
vk_alpha_1: [
|
|
2450
|
+
"20491192805390485299153009773594534940189261866228447918068658471970481763042",
|
|
2451
|
+
"9383485363053290200918347156157836566562967994039712273449902621266178545958",
|
|
2452
|
+
"1"
|
|
2453
|
+
],
|
|
2454
|
+
vk_beta_2: [
|
|
2455
|
+
[
|
|
2456
|
+
"6375614351688725206403948262868962793625744043794305715222011528459656738731",
|
|
2457
|
+
"4252822878758300859123897981450591353533073413197771768651442665752259397132"
|
|
2458
|
+
],
|
|
2459
|
+
[
|
|
2460
|
+
"10505242626370262277552901082094356697409835680220590971873171140371331206856",
|
|
2461
|
+
"21847035105528745403288232691147584728191162732299865338377159692350059136679"
|
|
2462
|
+
],
|
|
2463
|
+
["1", "0"]
|
|
2464
|
+
],
|
|
2465
|
+
vk_gamma_2: [
|
|
2466
|
+
[
|
|
2467
|
+
"10857046999023057135944570762232829481370756359578518086990519993285655852781",
|
|
2468
|
+
"11559732032986387107991004021392285783925812861821192530917403151452391805634"
|
|
2469
|
+
],
|
|
2470
|
+
[
|
|
2471
|
+
"8495653923123431417604973247489272438418190587263600148770280649306958101930",
|
|
2472
|
+
"4082367875863433681332203403145435568316851327593401208105741076214120093531"
|
|
2473
|
+
],
|
|
2474
|
+
["1", "0"]
|
|
2475
|
+
],
|
|
2476
|
+
vk_delta_2: [
|
|
2477
|
+
[
|
|
2478
|
+
"3697618915467790705869942236922063775466274665053173890632463796679068973252",
|
|
2479
|
+
"14948341351907992175709156460547989243732741534604949238422596319735704165658"
|
|
2480
|
+
],
|
|
2481
|
+
[
|
|
2482
|
+
"3028459181652799888716942141752307629938889957960373621898607910203491239368",
|
|
2483
|
+
"11380736494786911280692284374675752681598754560757720296073023058533044108340"
|
|
2484
|
+
],
|
|
2485
|
+
["1", "0"]
|
|
2486
|
+
],
|
|
2487
|
+
vk_alphabeta_12: [
|
|
2488
|
+
[
|
|
2489
|
+
[
|
|
2490
|
+
"2029413683389138792403550203267699914886160938906632433982220835551125967885",
|
|
2491
|
+
"21072700047562757817161031222997517981543347628379360635925549008442030252106"
|
|
2492
|
+
],
|
|
2493
|
+
[
|
|
2494
|
+
"5940354580057074848093997050200682056184807770593307860589430076672439820312",
|
|
2495
|
+
"12156638873931618554171829126792193045421052652279363021382169897324752428276"
|
|
2496
|
+
],
|
|
2497
|
+
[
|
|
2498
|
+
"7898200236362823042373859371574133993780991612861777490112507062703164551277",
|
|
2499
|
+
"7074218545237549455313236346927434013100842096812539264420499035217050630853"
|
|
2500
|
+
]
|
|
2501
|
+
],
|
|
2502
|
+
[
|
|
2503
|
+
[
|
|
2504
|
+
"7077479683546002997211712695946002074877511277312570035766170199895071832130",
|
|
2505
|
+
"10093483419865920389913245021038182291233451549023025229112148274109565435465"
|
|
2506
|
+
],
|
|
2507
|
+
[
|
|
2508
|
+
"4595479056700221319381530156280926371456704509942304414423590385166031118820",
|
|
2509
|
+
"19831328484489333784475432780421641293929726139240675179672856274388269393268"
|
|
2510
|
+
],
|
|
2511
|
+
[
|
|
2512
|
+
"11934129596455521040620786944827826205713621633706285934057045369193958244500",
|
|
2513
|
+
"8037395052364110730298837004334506829870972346962140206007064471173334027475"
|
|
2514
|
+
]
|
|
2515
|
+
]
|
|
2516
|
+
],
|
|
2517
|
+
IC: [
|
|
2518
|
+
[
|
|
2519
|
+
"12951059800758687233303204819298121944551181861362200875212570257618182506154",
|
|
2520
|
+
"5751958719396509176593242305268064754837298673622815112953832050159760501392",
|
|
2521
|
+
"1"
|
|
2522
|
+
],
|
|
2523
|
+
[
|
|
2524
|
+
"9561588427935871983444704959674198910445823619407211599507208879011862515257",
|
|
2525
|
+
"14576201570478094842467636169770180675293504492823217349086195663150934064643",
|
|
2526
|
+
"1"
|
|
2527
|
+
],
|
|
2528
|
+
[
|
|
2529
|
+
"4811967233483727873912563574622036989372099129165459921963463310078093941559",
|
|
2530
|
+
"1874883809855039536107616044787862082553628089593740724610117059083415551067",
|
|
2531
|
+
"1"
|
|
2532
|
+
],
|
|
2533
|
+
[
|
|
2534
|
+
"12252730267779308452229639835051322390696643456253768618882001876621526827161",
|
|
2535
|
+
"7899194018737016222260328309937800777948677569409898603827268776967707173231",
|
|
2536
|
+
"1"
|
|
2537
|
+
]
|
|
2538
|
+
]
|
|
2539
|
+
};
|
|
2540
|
+
dotenv.config();
|
|
2541
|
+
const { BANDADA_API_URL, BANDADA_GROUP_ID } = process.env;
|
|
2542
|
+
const bandadaApi = new apiSdk.ApiSdk(BANDADA_API_URL);
|
|
2543
|
+
const bandadaValidateProof = functions__namespace
|
|
2544
|
+
.region("europe-west1")
|
|
2545
|
+
.runWith({
|
|
2546
|
+
memory: "512MB"
|
|
2547
|
+
})
|
|
2548
|
+
.https.onCall(async (data) => {
|
|
2549
|
+
if (!BANDADA_GROUP_ID)
|
|
2550
|
+
throw new Error("BANDADA_GROUP_ID is not defined in .env");
|
|
2551
|
+
const { proof, publicSignals } = data;
|
|
2552
|
+
const isCorrect = snarkjs.groth16.verify(VKEY_DATA, publicSignals, proof);
|
|
2553
|
+
if (!isCorrect)
|
|
2554
|
+
return {
|
|
2555
|
+
valid: false,
|
|
2556
|
+
message: "Invalid proof",
|
|
2557
|
+
token: ""
|
|
2558
|
+
};
|
|
2559
|
+
const commitment = data.publicSignals[1];
|
|
2560
|
+
const isMember = await bandadaApi.isGroupMember(BANDADA_GROUP_ID, commitment);
|
|
2561
|
+
if (!isMember)
|
|
2562
|
+
return {
|
|
2563
|
+
valid: false,
|
|
2564
|
+
message: "Not a member of the group",
|
|
2565
|
+
token: ""
|
|
2566
|
+
};
|
|
2567
|
+
const auth$1 = auth.getAuth();
|
|
2568
|
+
try {
|
|
2569
|
+
await admin.auth().createUser({
|
|
2570
|
+
uid: commitment
|
|
2571
|
+
});
|
|
2572
|
+
}
|
|
2573
|
+
catch (error) {
|
|
2574
|
+
// if user already exist then just pass
|
|
2575
|
+
if (error.code !== "auth/uid-already-exists") {
|
|
2576
|
+
throw new Error(error);
|
|
2577
|
+
}
|
|
2578
|
+
}
|
|
2579
|
+
const token = await auth$1.createCustomToken(commitment);
|
|
2580
|
+
return {
|
|
2581
|
+
valid: true,
|
|
2582
|
+
message: "Valid proof and group member",
|
|
2583
|
+
token
|
|
2584
|
+
};
|
|
2585
|
+
});
|
|
2586
|
+
|
|
2587
|
+
dotenv.config();
|
|
2588
|
+
const checkNonceOfSIWEAddress = functions__namespace
|
|
2589
|
+
.region("europe-west1")
|
|
2590
|
+
.runWith({ memory: "1GB" })
|
|
2591
|
+
.https.onCall(async (data) => {
|
|
2592
|
+
try {
|
|
2593
|
+
const { auth0Token } = data;
|
|
2594
|
+
const result = (await fetch(`${process.env.AUTH0_APPLICATION_URL}/userinfo`, {
|
|
2595
|
+
method: "GET",
|
|
2596
|
+
headers: {
|
|
2597
|
+
"content-type": "application/json",
|
|
2598
|
+
authorization: `Bearer ${auth0Token}`
|
|
2599
|
+
}
|
|
2600
|
+
}).then((_res) => _res.json()));
|
|
2601
|
+
if (!result.sub) {
|
|
2602
|
+
return {
|
|
2603
|
+
valid: false,
|
|
2604
|
+
message: "No user detected. Please check device flow token"
|
|
2605
|
+
};
|
|
2606
|
+
}
|
|
2607
|
+
const auth$1 = auth.getAuth();
|
|
2608
|
+
// check nonce
|
|
2609
|
+
const parts = result.sub.split("|");
|
|
2610
|
+
const address = decodeURIComponent(parts[2]).split(":")[2];
|
|
2611
|
+
const minimumNonce = Number(process.env.ETH_MINIMUM_NONCE);
|
|
2612
|
+
const nonceBlockHeight = "latest"; // process.env.ETH_NONCE_BLOCK_HEIGHT
|
|
2613
|
+
// look up nonce for address @block
|
|
2614
|
+
let nonceOk = true;
|
|
2615
|
+
if (minimumNonce > 0) {
|
|
2616
|
+
const provider = setEthProvider();
|
|
2617
|
+
console.log(`got provider - block # ${await provider.getBlockNumber()}`);
|
|
2618
|
+
const nonce = await provider.getTransactionCount(address, nonceBlockHeight);
|
|
2619
|
+
console.log(`nonce ${nonce}`);
|
|
2620
|
+
nonceOk = nonce >= minimumNonce;
|
|
2621
|
+
}
|
|
2622
|
+
console.log(`checking nonce ${nonceOk}`);
|
|
2623
|
+
if (!nonceOk) {
|
|
2624
|
+
return {
|
|
2625
|
+
valid: false,
|
|
2626
|
+
message: "Eth address does not meet the nonce requirements"
|
|
2627
|
+
};
|
|
2628
|
+
}
|
|
2629
|
+
try {
|
|
2630
|
+
await admin.auth().createUser({
|
|
2631
|
+
displayName: address,
|
|
2632
|
+
uid: address
|
|
2633
|
+
});
|
|
2634
|
+
}
|
|
2635
|
+
catch (error) {
|
|
2636
|
+
// if user already exist then just pass
|
|
2637
|
+
if (error.code !== "auth/uid-already-exists") {
|
|
2638
|
+
throw new Error(error);
|
|
2639
|
+
}
|
|
2640
|
+
}
|
|
2641
|
+
const token = await auth$1.createCustomToken(address);
|
|
2642
|
+
return {
|
|
2643
|
+
valid: true,
|
|
2644
|
+
token
|
|
2645
|
+
};
|
|
2646
|
+
}
|
|
2647
|
+
catch (error) {
|
|
2648
|
+
return {
|
|
2649
|
+
valid: false,
|
|
2650
|
+
message: `Something went wrong ${error}`
|
|
2651
|
+
};
|
|
2652
|
+
}
|
|
2653
|
+
});
|
|
2654
|
+
|
|
2410
2655
|
dotenv.config();
|
|
2411
2656
|
/**
|
|
2412
2657
|
* Check and remove the current contributor if it doesn't complete the contribution on the specified amount of time.
|
|
@@ -2608,9 +2853,11 @@ const resumeContributionAfterTimeoutExpiration = functions__namespace
|
|
|
2608
2853
|
|
|
2609
2854
|
admin.initializeApp();
|
|
2610
2855
|
|
|
2856
|
+
exports.bandadaValidateProof = bandadaValidateProof;
|
|
2611
2857
|
exports.checkAndPrepareCoordinatorForFinalization = checkAndPrepareCoordinatorForFinalization;
|
|
2612
2858
|
exports.checkAndRemoveBlockingContributor = checkAndRemoveBlockingContributor;
|
|
2613
2859
|
exports.checkIfObjectExist = checkIfObjectExist;
|
|
2860
|
+
exports.checkNonceOfSIWEAddress = checkNonceOfSIWEAddress;
|
|
2614
2861
|
exports.checkParticipantForCeremony = checkParticipantForCeremony;
|
|
2615
2862
|
exports.completeMultiPartUpload = completeMultiPartUpload;
|
|
2616
2863
|
exports.coordinateCeremonyParticipant = coordinateCeremonyParticipant;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module @p0tion/backend
|
|
3
|
-
* @version 1.1
|
|
3
|
+
* @version 1.2.1
|
|
4
4
|
* @file MPC Phase 2 backend for Firebase services management
|
|
5
5
|
* @copyright Ethereum Foundation 2022
|
|
6
6
|
* @license MIT
|
|
@@ -25,10 +25,13 @@ import path from 'path';
|
|
|
25
25
|
import os from 'os';
|
|
26
26
|
import { SSMClient, CommandInvocationStatus } from '@aws-sdk/client-ssm';
|
|
27
27
|
import { EC2Client } from '@aws-sdk/client-ec2';
|
|
28
|
+
import ethers from 'ethers';
|
|
28
29
|
import * as functionsV1 from 'firebase-functions/v1';
|
|
29
30
|
import * as functionsV2 from 'firebase-functions/v2';
|
|
30
31
|
import { Timer } from 'timer-node';
|
|
31
|
-
import { zKey } from 'snarkjs';
|
|
32
|
+
import { zKey, groth16 } from 'snarkjs';
|
|
33
|
+
import { ApiSdk } from '@bandada/api-sdk';
|
|
34
|
+
import { getAuth } from 'firebase-admin/auth';
|
|
32
35
|
|
|
33
36
|
/**
|
|
34
37
|
* Log levels.
|
|
@@ -49,7 +52,7 @@ var LogLevel;
|
|
|
49
52
|
* @notice the set of Firebase Functions status codes. The codes are the same at the
|
|
50
53
|
* ones exposed by {@link https://github.com/grpc/grpc/blob/master/doc/statuscodes.md | gRPC}.
|
|
51
54
|
* @param errorCode <FunctionsErrorCode> - the set of possible error codes.
|
|
52
|
-
* @param message <string> - the error
|
|
55
|
+
* @param message <string> - the error message.
|
|
53
56
|
* @param [details] <string> - the details of the error (optional).
|
|
54
57
|
* @returns <HttpsError>
|
|
55
58
|
*/
|
|
@@ -141,6 +144,8 @@ const COMMON_ERRORS = {
|
|
|
141
144
|
CM_INVALID_COMMAND_EXECUTION: makeError("unknown", "There was an error while executing the command on the VM", "Please, contact the coordinator if the error persists.")
|
|
142
145
|
};
|
|
143
146
|
|
|
147
|
+
dotenv.config();
|
|
148
|
+
let provider;
|
|
144
149
|
/**
|
|
145
150
|
* Return a configured and connected instance of the AWS S3 client.
|
|
146
151
|
* @dev this method check and utilize the environment variables to configure the connection
|
|
@@ -163,6 +168,36 @@ const getS3Client = async () => {
|
|
|
163
168
|
region: process.env.AWS_REGION
|
|
164
169
|
});
|
|
165
170
|
};
|
|
171
|
+
/**
|
|
172
|
+
* Returns a Prvider, connected via a configured JSON URL or else
|
|
173
|
+
* the ethers.js default provider, using configured API keys.
|
|
174
|
+
* @returns <ethers.providers.Provider> An Eth node provider
|
|
175
|
+
*/
|
|
176
|
+
const setEthProvider = () => {
|
|
177
|
+
if (provider)
|
|
178
|
+
return provider;
|
|
179
|
+
console.log(`setting new provider`);
|
|
180
|
+
// Use JSON URL if defined
|
|
181
|
+
// if ((hardhat as any).ethers) {
|
|
182
|
+
// console.log(`using hardhat.ethers provider`)
|
|
183
|
+
// provider = (hardhat as any).ethers.provider
|
|
184
|
+
// } else
|
|
185
|
+
if (process.env.ETH_PROVIDER_JSON_URL) {
|
|
186
|
+
console.log(`JSON URL provider at ${process.env.ETH_PROVIDER_JSON_URL}`);
|
|
187
|
+
provider = new ethers.providers.JsonRpcProvider({
|
|
188
|
+
url: process.env.ETH_PROVIDER_JSON_URL,
|
|
189
|
+
skipFetchSetup: true
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
// Otherwise, connect the default provider with ALchemy, Infura, or both
|
|
194
|
+
provider = ethers.providers.getDefaultProvider("homestead", {
|
|
195
|
+
alchemy: process.env.ETH_PROVIDER_ALCHEMY_API_KEY,
|
|
196
|
+
infura: process.env.ETH_PROVIDER_INFURA_API_KEY
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
return provider;
|
|
200
|
+
};
|
|
166
201
|
|
|
167
202
|
dotenv.config();
|
|
168
203
|
/**
|
|
@@ -533,7 +568,7 @@ const registerAuthUser = functions
|
|
|
533
568
|
email === process.env.CUSTOM_CLAIMS_COORDINATOR_EMAIL_ADDRESS_OR_DOMAIN)) {
|
|
534
569
|
const auth = admin.auth();
|
|
535
570
|
// if provider == github.com let's use our functions to check the user's reputation
|
|
536
|
-
if (user.providerData[0].providerId === "github.com") {
|
|
571
|
+
if (user.providerData.length > 0 && user.providerData[0].providerId === "github.com") {
|
|
537
572
|
const vars = getGitHubVariables();
|
|
538
573
|
// this return true or false
|
|
539
574
|
try {
|
|
@@ -565,7 +600,7 @@ const registerAuthUser = functions
|
|
|
565
600
|
encodedDisplayName,
|
|
566
601
|
// Metadata.
|
|
567
602
|
creationTime,
|
|
568
|
-
lastSignInTime,
|
|
603
|
+
lastSignInTime: lastSignInTime || creationTime,
|
|
569
604
|
// Optional.
|
|
570
605
|
email: email || "",
|
|
571
606
|
emailVerified: emailVerified || false,
|
|
@@ -819,7 +854,7 @@ const finalizeCeremony = functions
|
|
|
819
854
|
// Get ceremony circuits.
|
|
820
855
|
const circuits = await getCeremonyCircuits(ceremonyId);
|
|
821
856
|
// Get final contribution for each circuit.
|
|
822
|
-
// nb. the `getFinalContributionDocument` checks the
|
|
857
|
+
// nb. the `getFinalContributionDocument` checks the existence of the final contribution document (if not present, throws).
|
|
823
858
|
// Therefore, we just need to call the method without taking any data to verify the pre-condition of having already computed
|
|
824
859
|
// the final contributions for each ceremony circuit.
|
|
825
860
|
for await (const circuit of circuits)
|
|
@@ -2384,6 +2419,216 @@ const completeMultiPartUpload = functions
|
|
|
2384
2419
|
}
|
|
2385
2420
|
});
|
|
2386
2421
|
|
|
2422
|
+
const VKEY_DATA = {
|
|
2423
|
+
protocol: "groth16",
|
|
2424
|
+
curve: "bn128",
|
|
2425
|
+
nPublic: 3,
|
|
2426
|
+
vk_alpha_1: [
|
|
2427
|
+
"20491192805390485299153009773594534940189261866228447918068658471970481763042",
|
|
2428
|
+
"9383485363053290200918347156157836566562967994039712273449902621266178545958",
|
|
2429
|
+
"1"
|
|
2430
|
+
],
|
|
2431
|
+
vk_beta_2: [
|
|
2432
|
+
[
|
|
2433
|
+
"6375614351688725206403948262868962793625744043794305715222011528459656738731",
|
|
2434
|
+
"4252822878758300859123897981450591353533073413197771768651442665752259397132"
|
|
2435
|
+
],
|
|
2436
|
+
[
|
|
2437
|
+
"10505242626370262277552901082094356697409835680220590971873171140371331206856",
|
|
2438
|
+
"21847035105528745403288232691147584728191162732299865338377159692350059136679"
|
|
2439
|
+
],
|
|
2440
|
+
["1", "0"]
|
|
2441
|
+
],
|
|
2442
|
+
vk_gamma_2: [
|
|
2443
|
+
[
|
|
2444
|
+
"10857046999023057135944570762232829481370756359578518086990519993285655852781",
|
|
2445
|
+
"11559732032986387107991004021392285783925812861821192530917403151452391805634"
|
|
2446
|
+
],
|
|
2447
|
+
[
|
|
2448
|
+
"8495653923123431417604973247489272438418190587263600148770280649306958101930",
|
|
2449
|
+
"4082367875863433681332203403145435568316851327593401208105741076214120093531"
|
|
2450
|
+
],
|
|
2451
|
+
["1", "0"]
|
|
2452
|
+
],
|
|
2453
|
+
vk_delta_2: [
|
|
2454
|
+
[
|
|
2455
|
+
"3697618915467790705869942236922063775466274665053173890632463796679068973252",
|
|
2456
|
+
"14948341351907992175709156460547989243732741534604949238422596319735704165658"
|
|
2457
|
+
],
|
|
2458
|
+
[
|
|
2459
|
+
"3028459181652799888716942141752307629938889957960373621898607910203491239368",
|
|
2460
|
+
"11380736494786911280692284374675752681598754560757720296073023058533044108340"
|
|
2461
|
+
],
|
|
2462
|
+
["1", "0"]
|
|
2463
|
+
],
|
|
2464
|
+
vk_alphabeta_12: [
|
|
2465
|
+
[
|
|
2466
|
+
[
|
|
2467
|
+
"2029413683389138792403550203267699914886160938906632433982220835551125967885",
|
|
2468
|
+
"21072700047562757817161031222997517981543347628379360635925549008442030252106"
|
|
2469
|
+
],
|
|
2470
|
+
[
|
|
2471
|
+
"5940354580057074848093997050200682056184807770593307860589430076672439820312",
|
|
2472
|
+
"12156638873931618554171829126792193045421052652279363021382169897324752428276"
|
|
2473
|
+
],
|
|
2474
|
+
[
|
|
2475
|
+
"7898200236362823042373859371574133993780991612861777490112507062703164551277",
|
|
2476
|
+
"7074218545237549455313236346927434013100842096812539264420499035217050630853"
|
|
2477
|
+
]
|
|
2478
|
+
],
|
|
2479
|
+
[
|
|
2480
|
+
[
|
|
2481
|
+
"7077479683546002997211712695946002074877511277312570035766170199895071832130",
|
|
2482
|
+
"10093483419865920389913245021038182291233451549023025229112148274109565435465"
|
|
2483
|
+
],
|
|
2484
|
+
[
|
|
2485
|
+
"4595479056700221319381530156280926371456704509942304414423590385166031118820",
|
|
2486
|
+
"19831328484489333784475432780421641293929726139240675179672856274388269393268"
|
|
2487
|
+
],
|
|
2488
|
+
[
|
|
2489
|
+
"11934129596455521040620786944827826205713621633706285934057045369193958244500",
|
|
2490
|
+
"8037395052364110730298837004334506829870972346962140206007064471173334027475"
|
|
2491
|
+
]
|
|
2492
|
+
]
|
|
2493
|
+
],
|
|
2494
|
+
IC: [
|
|
2495
|
+
[
|
|
2496
|
+
"12951059800758687233303204819298121944551181861362200875212570257618182506154",
|
|
2497
|
+
"5751958719396509176593242305268064754837298673622815112953832050159760501392",
|
|
2498
|
+
"1"
|
|
2499
|
+
],
|
|
2500
|
+
[
|
|
2501
|
+
"9561588427935871983444704959674198910445823619407211599507208879011862515257",
|
|
2502
|
+
"14576201570478094842467636169770180675293504492823217349086195663150934064643",
|
|
2503
|
+
"1"
|
|
2504
|
+
],
|
|
2505
|
+
[
|
|
2506
|
+
"4811967233483727873912563574622036989372099129165459921963463310078093941559",
|
|
2507
|
+
"1874883809855039536107616044787862082553628089593740724610117059083415551067",
|
|
2508
|
+
"1"
|
|
2509
|
+
],
|
|
2510
|
+
[
|
|
2511
|
+
"12252730267779308452229639835051322390696643456253768618882001876621526827161",
|
|
2512
|
+
"7899194018737016222260328309937800777948677569409898603827268776967707173231",
|
|
2513
|
+
"1"
|
|
2514
|
+
]
|
|
2515
|
+
]
|
|
2516
|
+
};
|
|
2517
|
+
dotenv.config();
|
|
2518
|
+
const { BANDADA_API_URL, BANDADA_GROUP_ID } = process.env;
|
|
2519
|
+
const bandadaApi = new ApiSdk(BANDADA_API_URL);
|
|
2520
|
+
const bandadaValidateProof = functions
|
|
2521
|
+
.region("europe-west1")
|
|
2522
|
+
.runWith({
|
|
2523
|
+
memory: "512MB"
|
|
2524
|
+
})
|
|
2525
|
+
.https.onCall(async (data) => {
|
|
2526
|
+
if (!BANDADA_GROUP_ID)
|
|
2527
|
+
throw new Error("BANDADA_GROUP_ID is not defined in .env");
|
|
2528
|
+
const { proof, publicSignals } = data;
|
|
2529
|
+
const isCorrect = groth16.verify(VKEY_DATA, publicSignals, proof);
|
|
2530
|
+
if (!isCorrect)
|
|
2531
|
+
return {
|
|
2532
|
+
valid: false,
|
|
2533
|
+
message: "Invalid proof",
|
|
2534
|
+
token: ""
|
|
2535
|
+
};
|
|
2536
|
+
const commitment = data.publicSignals[1];
|
|
2537
|
+
const isMember = await bandadaApi.isGroupMember(BANDADA_GROUP_ID, commitment);
|
|
2538
|
+
if (!isMember)
|
|
2539
|
+
return {
|
|
2540
|
+
valid: false,
|
|
2541
|
+
message: "Not a member of the group",
|
|
2542
|
+
token: ""
|
|
2543
|
+
};
|
|
2544
|
+
const auth = getAuth();
|
|
2545
|
+
try {
|
|
2546
|
+
await admin.auth().createUser({
|
|
2547
|
+
uid: commitment
|
|
2548
|
+
});
|
|
2549
|
+
}
|
|
2550
|
+
catch (error) {
|
|
2551
|
+
// if user already exist then just pass
|
|
2552
|
+
if (error.code !== "auth/uid-already-exists") {
|
|
2553
|
+
throw new Error(error);
|
|
2554
|
+
}
|
|
2555
|
+
}
|
|
2556
|
+
const token = await auth.createCustomToken(commitment);
|
|
2557
|
+
return {
|
|
2558
|
+
valid: true,
|
|
2559
|
+
message: "Valid proof and group member",
|
|
2560
|
+
token
|
|
2561
|
+
};
|
|
2562
|
+
});
|
|
2563
|
+
|
|
2564
|
+
dotenv.config();
|
|
2565
|
+
const checkNonceOfSIWEAddress = functions
|
|
2566
|
+
.region("europe-west1")
|
|
2567
|
+
.runWith({ memory: "1GB" })
|
|
2568
|
+
.https.onCall(async (data) => {
|
|
2569
|
+
try {
|
|
2570
|
+
const { auth0Token } = data;
|
|
2571
|
+
const result = (await fetch(`${process.env.AUTH0_APPLICATION_URL}/userinfo`, {
|
|
2572
|
+
method: "GET",
|
|
2573
|
+
headers: {
|
|
2574
|
+
"content-type": "application/json",
|
|
2575
|
+
authorization: `Bearer ${auth0Token}`
|
|
2576
|
+
}
|
|
2577
|
+
}).then((_res) => _res.json()));
|
|
2578
|
+
if (!result.sub) {
|
|
2579
|
+
return {
|
|
2580
|
+
valid: false,
|
|
2581
|
+
message: "No user detected. Please check device flow token"
|
|
2582
|
+
};
|
|
2583
|
+
}
|
|
2584
|
+
const auth = getAuth();
|
|
2585
|
+
// check nonce
|
|
2586
|
+
const parts = result.sub.split("|");
|
|
2587
|
+
const address = decodeURIComponent(parts[2]).split(":")[2];
|
|
2588
|
+
const minimumNonce = Number(process.env.ETH_MINIMUM_NONCE);
|
|
2589
|
+
const nonceBlockHeight = "latest"; // process.env.ETH_NONCE_BLOCK_HEIGHT
|
|
2590
|
+
// look up nonce for address @block
|
|
2591
|
+
let nonceOk = true;
|
|
2592
|
+
if (minimumNonce > 0) {
|
|
2593
|
+
const provider = setEthProvider();
|
|
2594
|
+
console.log(`got provider - block # ${await provider.getBlockNumber()}`);
|
|
2595
|
+
const nonce = await provider.getTransactionCount(address, nonceBlockHeight);
|
|
2596
|
+
console.log(`nonce ${nonce}`);
|
|
2597
|
+
nonceOk = nonce >= minimumNonce;
|
|
2598
|
+
}
|
|
2599
|
+
console.log(`checking nonce ${nonceOk}`);
|
|
2600
|
+
if (!nonceOk) {
|
|
2601
|
+
return {
|
|
2602
|
+
valid: false,
|
|
2603
|
+
message: "Eth address does not meet the nonce requirements"
|
|
2604
|
+
};
|
|
2605
|
+
}
|
|
2606
|
+
try {
|
|
2607
|
+
await admin.auth().createUser({
|
|
2608
|
+
displayName: address,
|
|
2609
|
+
uid: address
|
|
2610
|
+
});
|
|
2611
|
+
}
|
|
2612
|
+
catch (error) {
|
|
2613
|
+
// if user already exist then just pass
|
|
2614
|
+
if (error.code !== "auth/uid-already-exists") {
|
|
2615
|
+
throw new Error(error);
|
|
2616
|
+
}
|
|
2617
|
+
}
|
|
2618
|
+
const token = await auth.createCustomToken(address);
|
|
2619
|
+
return {
|
|
2620
|
+
valid: true,
|
|
2621
|
+
token
|
|
2622
|
+
};
|
|
2623
|
+
}
|
|
2624
|
+
catch (error) {
|
|
2625
|
+
return {
|
|
2626
|
+
valid: false,
|
|
2627
|
+
message: `Something went wrong ${error}`
|
|
2628
|
+
};
|
|
2629
|
+
}
|
|
2630
|
+
});
|
|
2631
|
+
|
|
2387
2632
|
dotenv.config();
|
|
2388
2633
|
/**
|
|
2389
2634
|
* Check and remove the current contributor if it doesn't complete the contribution on the specified amount of time.
|
|
@@ -2585,4 +2830,4 @@ const resumeContributionAfterTimeoutExpiration = functions
|
|
|
2585
2830
|
|
|
2586
2831
|
admin.initializeApp();
|
|
2587
2832
|
|
|
2588
|
-
export { checkAndPrepareCoordinatorForFinalization, checkAndRemoveBlockingContributor, checkIfObjectExist, checkParticipantForCeremony, completeMultiPartUpload, coordinateCeremonyParticipant, createBucket, finalizeCeremony, finalizeCircuit, generateGetObjectPreSignedUrl, generatePreSignedUrlsParts, initEmptyWaitingQueueForCircuit, permanentlyStoreCurrentContributionTimeAndHash, processSignUpWithCustomClaims, progressToNextCircuitForContribution, progressToNextContributionStep, refreshParticipantAfterContributionVerification, registerAuthUser, resumeContributionAfterTimeoutExpiration, setupCeremony, startCeremony, startMultiPartUpload, stopCeremony, temporaryStoreCurrentContributionMultiPartUploadId, temporaryStoreCurrentContributionUploadedChunkData, verifycontribution };
|
|
2833
|
+
export { bandadaValidateProof, checkAndPrepareCoordinatorForFinalization, checkAndRemoveBlockingContributor, checkIfObjectExist, checkNonceOfSIWEAddress, checkParticipantForCeremony, completeMultiPartUpload, coordinateCeremonyParticipant, createBucket, finalizeCeremony, finalizeCircuit, generateGetObjectPreSignedUrl, generatePreSignedUrlsParts, initEmptyWaitingQueueForCircuit, permanentlyStoreCurrentContributionTimeAndHash, processSignUpWithCustomClaims, progressToNextCircuitForContribution, progressToNextContributionStep, refreshParticipantAfterContributionVerification, registerAuthUser, resumeContributionAfterTimeoutExpiration, setupCeremony, startCeremony, startMultiPartUpload, stopCeremony, temporaryStoreCurrentContributionMultiPartUploadId, temporaryStoreCurrentContributionUploadedChunkData, verifycontribution };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bandada.d.ts","sourceRoot":"","sources":["../../../src/functions/bandada.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,SAAS,MAAM,oBAAoB,CAAA;AA6G/C,eAAO,MAAM,oBAAoB,mDA0C3B,CAAA;AAEN,eAAe,oBAAoB,CAAA"}
|
|
@@ -3,5 +3,7 @@ export { startCeremony, stopCeremony, setupCeremony, initEmptyWaitingQueueForCir
|
|
|
3
3
|
export { checkParticipantForCeremony, progressToNextContributionStep, permanentlyStoreCurrentContributionTimeAndHash, temporaryStoreCurrentContributionMultiPartUploadId, temporaryStoreCurrentContributionUploadedChunkData, progressToNextCircuitForContribution, checkAndPrepareCoordinatorForFinalization } from "./participant";
|
|
4
4
|
export { coordinateCeremonyParticipant, verifycontribution, refreshParticipantAfterContributionVerification, finalizeCircuit } from "./circuit";
|
|
5
5
|
export { createBucket, checkIfObjectExist, generateGetObjectPreSignedUrl, startMultiPartUpload, generatePreSignedUrlsParts, completeMultiPartUpload } from "./storage";
|
|
6
|
+
export { bandadaValidateProof } from "./bandada";
|
|
7
|
+
export { checkNonceOfSIWEAddress } from "./siwe";
|
|
6
8
|
export { checkAndRemoveBlockingContributor, resumeContributionAfterTimeoutExpiration } from "./timeout";
|
|
7
9
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/functions/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,6BAA6B,EAAE,MAAM,QAAQ,CAAA;AACxE,OAAO,EACH,aAAa,EACb,YAAY,EACZ,aAAa,EACb,+BAA+B,EAC/B,gBAAgB,EACnB,MAAM,YAAY,CAAA;AACnB,OAAO,EACH,2BAA2B,EAC3B,8BAA8B,EAC9B,8CAA8C,EAC9C,kDAAkD,EAClD,kDAAkD,EAClD,oCAAoC,EACpC,yCAAyC,EAC5C,MAAM,eAAe,CAAA;AACtB,OAAO,EACH,6BAA6B,EAC7B,kBAAkB,EAClB,+CAA+C,EAC/C,eAAe,EAClB,MAAM,WAAW,CAAA;AAClB,OAAO,EACH,YAAY,EACZ,kBAAkB,EAClB,6BAA6B,EAC7B,oBAAoB,EACpB,0BAA0B,EAC1B,uBAAuB,EAC1B,MAAM,WAAW,CAAA;AAClB,OAAO,EAAE,iCAAiC,EAAE,wCAAwC,EAAE,MAAM,WAAW,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/functions/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,6BAA6B,EAAE,MAAM,QAAQ,CAAA;AACxE,OAAO,EACH,aAAa,EACb,YAAY,EACZ,aAAa,EACb,+BAA+B,EAC/B,gBAAgB,EACnB,MAAM,YAAY,CAAA;AACnB,OAAO,EACH,2BAA2B,EAC3B,8BAA8B,EAC9B,8CAA8C,EAC9C,kDAAkD,EAClD,kDAAkD,EAClD,oCAAoC,EACpC,yCAAyC,EAC5C,MAAM,eAAe,CAAA;AACtB,OAAO,EACH,6BAA6B,EAC7B,kBAAkB,EAClB,+CAA+C,EAC/C,eAAe,EAClB,MAAM,WAAW,CAAA;AAClB,OAAO,EACH,YAAY,EACZ,kBAAkB,EAClB,6BAA6B,EAC7B,oBAAoB,EACpB,0BAA0B,EAC1B,uBAAuB,EAC1B,MAAM,WAAW,CAAA;AAClB,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAA;AAChD,OAAO,EAAE,uBAAuB,EAAE,MAAM,QAAQ,CAAA;AAChD,OAAO,EAAE,iCAAiC,EAAE,wCAAwC,EAAE,MAAM,WAAW,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"siwe.d.ts","sourceRoot":"","sources":["../../../src/functions/siwe.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,SAAS,MAAM,oBAAoB,CAAA;AAQ/C,eAAO,MAAM,uBAAuB,mDAgE9B,CAAA;AAEN,eAAe,uBAAuB,CAAA"}
|
|
@@ -6,7 +6,7 @@ import { LogLevel } from "../types/enums";
|
|
|
6
6
|
* @notice the set of Firebase Functions status codes. The codes are the same at the
|
|
7
7
|
* ones exposed by {@link https://github.com/grpc/grpc/blob/master/doc/statuscodes.md | gRPC}.
|
|
8
8
|
* @param errorCode <FunctionsErrorCode> - the set of possible error codes.
|
|
9
|
-
* @param message <string> - the error
|
|
9
|
+
* @param message <string> - the error message.
|
|
10
10
|
* @param [details] <string> - the details of the error (optional).
|
|
11
11
|
* @returns <HttpsError>
|
|
12
12
|
*/
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import ethers from "ethers";
|
|
1
2
|
import { S3Client } from "@aws-sdk/client-s3";
|
|
2
3
|
/**
|
|
3
4
|
* Return a configured and connected instance of the AWS S3 client.
|
|
@@ -6,4 +7,10 @@ import { S3Client } from "@aws-sdk/client-s3";
|
|
|
6
7
|
* @returns <Promise<S3Client>> - the instance of the connected S3 Client instance.
|
|
7
8
|
*/
|
|
8
9
|
export declare const getS3Client: () => Promise<S3Client>;
|
|
10
|
+
/**
|
|
11
|
+
* Returns a Prvider, connected via a configured JSON URL or else
|
|
12
|
+
* the ethers.js default provider, using configured API keys.
|
|
13
|
+
* @returns <ethers.providers.Provider> An Eth node provider
|
|
14
|
+
*/
|
|
15
|
+
export declare const setEthProvider: () => ethers.providers.Provider;
|
|
9
16
|
//# sourceMappingURL=services.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"services.d.ts","sourceRoot":"","sources":["../../../src/lib/services.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"services.d.ts","sourceRoot":"","sources":["../../../src/lib/services.ts"],"names":[],"mappings":"AACA,OAAO,MAAM,MAAM,QAAQ,CAAA;AAC3B,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAM7C;;;;;GAKG;AACH,eAAO,MAAM,WAAW,QAAa,QAAQ,QAAQ,CAkBpD,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,cAAc,QAAO,OAAO,SAAS,CAAC,QAwBlD,CAAA"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CeremonyInputData, CircuitDocument, ETagWithPartNumber } from "@devtion/actions";
|
|
2
|
+
import type { Groth16Proof, PublicSignals } from "snarkjs";
|
|
2
3
|
/**
|
|
3
4
|
* Group all the necessary data needed for running the `setupCeremony` cloud function.
|
|
4
5
|
* @typedef {Object} SetupCeremonyData
|
|
@@ -127,4 +128,59 @@ export type FinalizeCircuitData = {
|
|
|
127
128
|
bucketName: string;
|
|
128
129
|
beacon: string;
|
|
129
130
|
};
|
|
131
|
+
/**
|
|
132
|
+
* Group all the necessary data needed for running the `bandadaValidateProof` cloud function.
|
|
133
|
+
* @typedef {Object} BandadaValidateProof
|
|
134
|
+
* @property {string} merkleTreeRoot - the merkle tree root of the group.
|
|
135
|
+
* @property {string} nullifierHash - the nullifier hash of the member.
|
|
136
|
+
* @property {string} externalNullifier - the external nullifier of the member.
|
|
137
|
+
* @property {PackedProof} proof - the packed proof generated on the client.
|
|
138
|
+
*/
|
|
139
|
+
export type BandadaValidateProof = {
|
|
140
|
+
proof: Groth16Proof;
|
|
141
|
+
publicSignals: PublicSignals;
|
|
142
|
+
};
|
|
143
|
+
/**
|
|
144
|
+
* Define the return object of the function that verifies the Bandada membership and proof.
|
|
145
|
+
* @typedef {Object} VerifiedBandadaResponse
|
|
146
|
+
* @property {boolean} valid - true if the proof is valid and the user is a member of the group; otherwise false.
|
|
147
|
+
* @property {string} message - a message describing the result of the verification.
|
|
148
|
+
* @property {string} token - the custom access token.
|
|
149
|
+
*/
|
|
150
|
+
export type VerifiedBandadaResponse = {
|
|
151
|
+
valid: boolean;
|
|
152
|
+
message: string;
|
|
153
|
+
token: string;
|
|
154
|
+
};
|
|
155
|
+
/**
|
|
156
|
+
* Define the check nonce object for the cloud function
|
|
157
|
+
* @typedef {Object} CheckNonceOfSIWEAddressRequest
|
|
158
|
+
* @property {string} auth0Token - token from the device flow authentication
|
|
159
|
+
*/
|
|
160
|
+
export type CheckNonceOfSIWEAddressRequest = {
|
|
161
|
+
auth0Token: string;
|
|
162
|
+
};
|
|
163
|
+
/**
|
|
164
|
+
* Define the check nonce response object of the cloud function
|
|
165
|
+
* @typedef {Object} CheckNonceOfSIWEAddressResponse
|
|
166
|
+
* @property {boolean} valid - if the checking result was valid or not
|
|
167
|
+
* @property {string} message - informative message
|
|
168
|
+
* @property {string} token - token to sign in
|
|
169
|
+
*/
|
|
170
|
+
export type CheckNonceOfSIWEAddressResponse = {
|
|
171
|
+
valid: boolean;
|
|
172
|
+
message?: string;
|
|
173
|
+
token?: string;
|
|
174
|
+
};
|
|
175
|
+
/**
|
|
176
|
+
* Define the response from auth0 /userinfo endpoint
|
|
177
|
+
*
|
|
178
|
+
*/
|
|
179
|
+
export type Auth0UserInfo = {
|
|
180
|
+
sub: string;
|
|
181
|
+
nickname: string;
|
|
182
|
+
name: string;
|
|
183
|
+
picture: string;
|
|
184
|
+
updated_at: string;
|
|
185
|
+
};
|
|
130
186
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AACxF,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAE1D;;;;;;GAMG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC5B,iBAAiB,EAAE,iBAAiB,CAAA;IACpC,cAAc,EAAE,MAAM,CAAA;IACtB,QAAQ,EAAE,KAAK,CAAC,eAAe,CAAC,CAAA;CACnC,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC3B,UAAU,EAAE,MAAM,CAAA;CACrB,CAAA;AAED;;;;;GAKG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACjC,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;CACpB,CAAA;AAED;;;;;;GAMG;AACH,MAAM,MAAM,wBAAwB,GAAG,sBAAsB,GAAG;IAC5D,UAAU,CAAC,EAAE,MAAM,CAAA;CACtB,CAAA;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,8BAA8B,GAAG,sBAAsB,GAAG;IAClE,QAAQ,EAAE,MAAM,CAAA;IAChB,aAAa,EAAE,MAAM,CAAA;IACrB,UAAU,CAAC,EAAE,MAAM,CAAA;CACtB,CAAA;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,2BAA2B,GAAG,sBAAsB,GAAG;IAC/D,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,KAAK,CAAC,kBAAkB,CAAC,CAAA;IAChC,UAAU,CAAC,EAAE,MAAM,CAAA;CACtB,CAAA;AAED;;;;;;GAMG;AACH,MAAM,MAAM,8CAA8C,GAAG;IACzD,UAAU,EAAE,MAAM,CAAA;IAClB,2BAA2B,EAAE,MAAM,CAAA;IACnC,gBAAgB,EAAE,MAAM,CAAA;CAC3B,CAAA;AAED;;;;;GAKG;AACH,MAAM,MAAM,kDAAkD,GAAG;IAC7D,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;CACnB,CAAA;AAED;;;;;GAKG;AACH,MAAM,MAAM,kDAAkD,GAAG;IAC7D,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,kBAAkB,CAAA;CAC5B,CAAA;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACjC,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,kCAAkC,EAAE,MAAM,CAAA;CAC7C,CAAA;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAC9B,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,MAAM,CAAA;CACjB,CAAA;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,oBAAoB,GAAG;IAC/B,KAAK,EAAE,YAAY,CAAA;IACnB,aAAa,EAAE,aAAa,CAAA;CAC/B,CAAA;AAED;;;;;;GAMG;AACH,MAAM,MAAM,uBAAuB,GAAG;IAClC,KAAK,EAAE,OAAO,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,CAAA;CAChB,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,8BAA8B,GAAG;IACzC,UAAU,EAAE,MAAM,CAAA;CACrB,CAAA;AAED;;;;;;GAMG;AACH,MAAM,MAAM,+BAA+B,GAAG;IAC1C,KAAK,EAAE,OAAO,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;CACjB,CAAA;AACD;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG;IACxB,GAAG,EAAE,MAAM,CAAA;IACX,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;CACrB,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devtion/backend",
|
|
3
|
-
"version": "0.0.0-
|
|
3
|
+
"version": "0.0.0-2cb7418",
|
|
4
4
|
"description": "MPC Phase 2 backend for Firebase services management",
|
|
5
5
|
"repository": "git@github.com:privacy-scaling-explorations/p0tion.git",
|
|
6
6
|
"homepage": "https://github.com/privacy-scaling-explorations/p0tion",
|
|
@@ -67,6 +67,7 @@
|
|
|
67
67
|
"@aws-sdk/client-ssm": "^3.357.0",
|
|
68
68
|
"@aws-sdk/middleware-endpoint": "^3.329.0",
|
|
69
69
|
"@aws-sdk/s3-request-presigner": "^3.329.0",
|
|
70
|
+
"@bandada/api-sdk": "^1.0.0-beta.1",
|
|
70
71
|
"@devtion/actions": "latest",
|
|
71
72
|
"blakejs": "^1.2.1",
|
|
72
73
|
"dotenv": "^16.0.3",
|
|
@@ -76,7 +77,7 @@
|
|
|
76
77
|
"html-entities": "^2.3.3",
|
|
77
78
|
"rimraf": "^5.0.0",
|
|
78
79
|
"rollup": "^3.21.6",
|
|
79
|
-
"snarkjs": "
|
|
80
|
+
"snarkjs": "0.7.3",
|
|
80
81
|
"solc": "^0.8.19",
|
|
81
82
|
"timer-node": "^5.0.7",
|
|
82
83
|
"uuid": "^9.0.0",
|
|
@@ -85,5 +86,5 @@
|
|
|
85
86
|
"publishConfig": {
|
|
86
87
|
"access": "public"
|
|
87
88
|
},
|
|
88
|
-
"gitHead": "
|
|
89
|
+
"gitHead": "ab9fdd5025661b41824cda16265a674d2ca8e2bf"
|
|
89
90
|
}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import dotenv from "dotenv"
|
|
2
|
+
import * as functions from "firebase-functions"
|
|
3
|
+
import { ApiSdk } from "@bandada/api-sdk"
|
|
4
|
+
import { groth16 } from "snarkjs"
|
|
5
|
+
import { getAuth } from "firebase-admin/auth"
|
|
6
|
+
import admin from "firebase-admin"
|
|
7
|
+
import { BandadaValidateProof, VerifiedBandadaResponse } from "../types/index"
|
|
8
|
+
|
|
9
|
+
const VKEY_DATA = {
|
|
10
|
+
protocol: "groth16",
|
|
11
|
+
curve: "bn128",
|
|
12
|
+
nPublic: 3,
|
|
13
|
+
vk_alpha_1: [
|
|
14
|
+
"20491192805390485299153009773594534940189261866228447918068658471970481763042",
|
|
15
|
+
"9383485363053290200918347156157836566562967994039712273449902621266178545958",
|
|
16
|
+
"1"
|
|
17
|
+
],
|
|
18
|
+
vk_beta_2: [
|
|
19
|
+
[
|
|
20
|
+
"6375614351688725206403948262868962793625744043794305715222011528459656738731",
|
|
21
|
+
"4252822878758300859123897981450591353533073413197771768651442665752259397132"
|
|
22
|
+
],
|
|
23
|
+
[
|
|
24
|
+
"10505242626370262277552901082094356697409835680220590971873171140371331206856",
|
|
25
|
+
"21847035105528745403288232691147584728191162732299865338377159692350059136679"
|
|
26
|
+
],
|
|
27
|
+
["1", "0"]
|
|
28
|
+
],
|
|
29
|
+
vk_gamma_2: [
|
|
30
|
+
[
|
|
31
|
+
"10857046999023057135944570762232829481370756359578518086990519993285655852781",
|
|
32
|
+
"11559732032986387107991004021392285783925812861821192530917403151452391805634"
|
|
33
|
+
],
|
|
34
|
+
[
|
|
35
|
+
"8495653923123431417604973247489272438418190587263600148770280649306958101930",
|
|
36
|
+
"4082367875863433681332203403145435568316851327593401208105741076214120093531"
|
|
37
|
+
],
|
|
38
|
+
["1", "0"]
|
|
39
|
+
],
|
|
40
|
+
vk_delta_2: [
|
|
41
|
+
[
|
|
42
|
+
"3697618915467790705869942236922063775466274665053173890632463796679068973252",
|
|
43
|
+
"14948341351907992175709156460547989243732741534604949238422596319735704165658"
|
|
44
|
+
],
|
|
45
|
+
[
|
|
46
|
+
"3028459181652799888716942141752307629938889957960373621898607910203491239368",
|
|
47
|
+
"11380736494786911280692284374675752681598754560757720296073023058533044108340"
|
|
48
|
+
],
|
|
49
|
+
["1", "0"]
|
|
50
|
+
],
|
|
51
|
+
vk_alphabeta_12: [
|
|
52
|
+
[
|
|
53
|
+
[
|
|
54
|
+
"2029413683389138792403550203267699914886160938906632433982220835551125967885",
|
|
55
|
+
"21072700047562757817161031222997517981543347628379360635925549008442030252106"
|
|
56
|
+
],
|
|
57
|
+
[
|
|
58
|
+
"5940354580057074848093997050200682056184807770593307860589430076672439820312",
|
|
59
|
+
"12156638873931618554171829126792193045421052652279363021382169897324752428276"
|
|
60
|
+
],
|
|
61
|
+
[
|
|
62
|
+
"7898200236362823042373859371574133993780991612861777490112507062703164551277",
|
|
63
|
+
"7074218545237549455313236346927434013100842096812539264420499035217050630853"
|
|
64
|
+
]
|
|
65
|
+
],
|
|
66
|
+
[
|
|
67
|
+
[
|
|
68
|
+
"7077479683546002997211712695946002074877511277312570035766170199895071832130",
|
|
69
|
+
"10093483419865920389913245021038182291233451549023025229112148274109565435465"
|
|
70
|
+
],
|
|
71
|
+
[
|
|
72
|
+
"4595479056700221319381530156280926371456704509942304414423590385166031118820",
|
|
73
|
+
"19831328484489333784475432780421641293929726139240675179672856274388269393268"
|
|
74
|
+
],
|
|
75
|
+
[
|
|
76
|
+
"11934129596455521040620786944827826205713621633706285934057045369193958244500",
|
|
77
|
+
"8037395052364110730298837004334506829870972346962140206007064471173334027475"
|
|
78
|
+
]
|
|
79
|
+
]
|
|
80
|
+
],
|
|
81
|
+
IC: [
|
|
82
|
+
[
|
|
83
|
+
"12951059800758687233303204819298121944551181861362200875212570257618182506154",
|
|
84
|
+
"5751958719396509176593242305268064754837298673622815112953832050159760501392",
|
|
85
|
+
"1"
|
|
86
|
+
],
|
|
87
|
+
[
|
|
88
|
+
"9561588427935871983444704959674198910445823619407211599507208879011862515257",
|
|
89
|
+
"14576201570478094842467636169770180675293504492823217349086195663150934064643",
|
|
90
|
+
"1"
|
|
91
|
+
],
|
|
92
|
+
[
|
|
93
|
+
"4811967233483727873912563574622036989372099129165459921963463310078093941559",
|
|
94
|
+
"1874883809855039536107616044787862082553628089593740724610117059083415551067",
|
|
95
|
+
"1"
|
|
96
|
+
],
|
|
97
|
+
[
|
|
98
|
+
"12252730267779308452229639835051322390696643456253768618882001876621526827161",
|
|
99
|
+
"7899194018737016222260328309937800777948677569409898603827268776967707173231",
|
|
100
|
+
"1"
|
|
101
|
+
]
|
|
102
|
+
]
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
dotenv.config()
|
|
106
|
+
|
|
107
|
+
const { BANDADA_API_URL, BANDADA_GROUP_ID } = process.env
|
|
108
|
+
|
|
109
|
+
const bandadaApi = new ApiSdk(BANDADA_API_URL)
|
|
110
|
+
|
|
111
|
+
export const bandadaValidateProof = functions
|
|
112
|
+
.region("europe-west1")
|
|
113
|
+
.runWith({
|
|
114
|
+
memory: "512MB"
|
|
115
|
+
})
|
|
116
|
+
.https.onCall(async (data: BandadaValidateProof): Promise<VerifiedBandadaResponse> => {
|
|
117
|
+
if (!BANDADA_GROUP_ID) throw new Error("BANDADA_GROUP_ID is not defined in .env")
|
|
118
|
+
|
|
119
|
+
const { proof, publicSignals } = data
|
|
120
|
+
const isCorrect = groth16.verify(VKEY_DATA, publicSignals, proof)
|
|
121
|
+
if (!isCorrect)
|
|
122
|
+
return {
|
|
123
|
+
valid: false,
|
|
124
|
+
message: "Invalid proof",
|
|
125
|
+
token: ""
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const commitment = data.publicSignals[1]
|
|
129
|
+
const isMember = await bandadaApi.isGroupMember(BANDADA_GROUP_ID, commitment)
|
|
130
|
+
if (!isMember)
|
|
131
|
+
return {
|
|
132
|
+
valid: false,
|
|
133
|
+
message: "Not a member of the group",
|
|
134
|
+
token: ""
|
|
135
|
+
}
|
|
136
|
+
const auth = getAuth()
|
|
137
|
+
try {
|
|
138
|
+
await admin.auth().createUser({
|
|
139
|
+
uid: commitment
|
|
140
|
+
})
|
|
141
|
+
} catch (error: any) {
|
|
142
|
+
// if user already exist then just pass
|
|
143
|
+
if (error.code !== "auth/uid-already-exists") {
|
|
144
|
+
throw new Error(error)
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
const token = await auth.createCustomToken(commitment)
|
|
148
|
+
return {
|
|
149
|
+
valid: true,
|
|
150
|
+
message: "Valid proof and group member",
|
|
151
|
+
token
|
|
152
|
+
}
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
export default bandadaValidateProof
|
|
@@ -298,7 +298,7 @@ export const finalizeCeremony = functions
|
|
|
298
298
|
const circuits = await getCeremonyCircuits(ceremonyId)
|
|
299
299
|
|
|
300
300
|
// Get final contribution for each circuit.
|
|
301
|
-
// nb. the `getFinalContributionDocument` checks the
|
|
301
|
+
// nb. the `getFinalContributionDocument` checks the existence of the final contribution document (if not present, throws).
|
|
302
302
|
// Therefore, we just need to call the method without taking any data to verify the pre-condition of having already computed
|
|
303
303
|
// the final contributions for each ceremony circuit.
|
|
304
304
|
for await (const circuit of circuits) await getFinalContribution(ceremonyId, circuit.id)
|
package/src/functions/index.ts
CHANGED
|
@@ -31,6 +31,8 @@ export {
|
|
|
31
31
|
generatePreSignedUrlsParts,
|
|
32
32
|
completeMultiPartUpload
|
|
33
33
|
} from "./storage"
|
|
34
|
+
export { bandadaValidateProof } from "./bandada"
|
|
35
|
+
export { checkNonceOfSIWEAddress } from "./siwe"
|
|
34
36
|
export { checkAndRemoveBlockingContributor, resumeContributionAfterTimeoutExpiration } from "./timeout"
|
|
35
37
|
|
|
36
38
|
admin.initializeApp()
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import dotenv from "dotenv"
|
|
2
|
+
import fetch from "@adobe/node-fetch-retry"
|
|
3
|
+
import * as functions from "firebase-functions"
|
|
4
|
+
import { getAuth } from "firebase-admin/auth"
|
|
5
|
+
import admin from "firebase-admin"
|
|
6
|
+
import { Auth0UserInfo, CheckNonceOfSIWEAddressRequest, CheckNonceOfSIWEAddressResponse } from "../types"
|
|
7
|
+
import { setEthProvider } from "../lib/services"
|
|
8
|
+
|
|
9
|
+
dotenv.config()
|
|
10
|
+
|
|
11
|
+
export const checkNonceOfSIWEAddress = functions
|
|
12
|
+
.region("europe-west1")
|
|
13
|
+
.runWith({ memory: "1GB" })
|
|
14
|
+
.https.onCall(async (data: CheckNonceOfSIWEAddressRequest): Promise<CheckNonceOfSIWEAddressResponse> => {
|
|
15
|
+
try {
|
|
16
|
+
const { auth0Token } = data
|
|
17
|
+
const result = (await fetch(`${process.env.AUTH0_APPLICATION_URL}/userinfo`, {
|
|
18
|
+
method: "GET",
|
|
19
|
+
headers: {
|
|
20
|
+
"content-type": "application/json",
|
|
21
|
+
authorization: `Bearer ${auth0Token}`
|
|
22
|
+
}
|
|
23
|
+
}).then((_res) => _res.json())) as Auth0UserInfo
|
|
24
|
+
if (!result.sub) {
|
|
25
|
+
return {
|
|
26
|
+
valid: false,
|
|
27
|
+
message: "No user detected. Please check device flow token"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
const auth = getAuth()
|
|
31
|
+
// check nonce
|
|
32
|
+
const parts = result.sub.split("|")
|
|
33
|
+
const address = decodeURIComponent(parts[2]).split(":")[2]
|
|
34
|
+
|
|
35
|
+
const minimumNonce = Number(process.env.ETH_MINIMUM_NONCE)
|
|
36
|
+
const nonceBlockHeight = "latest" // process.env.ETH_NONCE_BLOCK_HEIGHT
|
|
37
|
+
// look up nonce for address @block
|
|
38
|
+
let nonceOk = true
|
|
39
|
+
if (minimumNonce > 0) {
|
|
40
|
+
const provider = setEthProvider()
|
|
41
|
+
console.log(`got provider - block # ${await provider.getBlockNumber()}`)
|
|
42
|
+
const nonce = await provider.getTransactionCount(address, nonceBlockHeight)
|
|
43
|
+
console.log(`nonce ${nonce}`)
|
|
44
|
+
nonceOk = nonce >= minimumNonce
|
|
45
|
+
}
|
|
46
|
+
console.log(`checking nonce ${nonceOk}`)
|
|
47
|
+
if (!nonceOk) {
|
|
48
|
+
return {
|
|
49
|
+
valid: false,
|
|
50
|
+
message: "Eth address does not meet the nonce requirements"
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
await admin.auth().createUser({
|
|
55
|
+
displayName: address,
|
|
56
|
+
uid: address
|
|
57
|
+
})
|
|
58
|
+
} catch (error: any) {
|
|
59
|
+
// if user already exist then just pass
|
|
60
|
+
if (error.code !== "auth/uid-already-exists") {
|
|
61
|
+
throw new Error(error)
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const token = await auth.createCustomToken(address)
|
|
65
|
+
return {
|
|
66
|
+
valid: true,
|
|
67
|
+
token
|
|
68
|
+
}
|
|
69
|
+
} catch (error) {
|
|
70
|
+
return {
|
|
71
|
+
valid: false,
|
|
72
|
+
message: `Something went wrong ${error}`
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
export default checkNonceOfSIWEAddress
|
package/src/functions/user.ts
CHANGED
|
@@ -55,7 +55,7 @@ export const registerAuthUser = functions
|
|
|
55
55
|
) {
|
|
56
56
|
const auth = admin.auth()
|
|
57
57
|
// if provider == github.com let's use our functions to check the user's reputation
|
|
58
|
-
if (user.providerData[0].providerId === "github.com") {
|
|
58
|
+
if (user.providerData.length > 0 && user.providerData[0].providerId === "github.com") {
|
|
59
59
|
const vars = getGitHubVariables()
|
|
60
60
|
|
|
61
61
|
// this return true or false
|
|
@@ -112,7 +112,7 @@ export const registerAuthUser = functions
|
|
|
112
112
|
encodedDisplayName,
|
|
113
113
|
// Metadata.
|
|
114
114
|
creationTime,
|
|
115
|
-
lastSignInTime,
|
|
115
|
+
lastSignInTime: lastSignInTime || creationTime,
|
|
116
116
|
// Optional.
|
|
117
117
|
email: email || "",
|
|
118
118
|
emailVerified: emailVerified || false,
|
package/src/lib/errors.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { LogLevel } from "../types/enums"
|
|
|
7
7
|
* @notice the set of Firebase Functions status codes. The codes are the same at the
|
|
8
8
|
* ones exposed by {@link https://github.com/grpc/grpc/blob/master/doc/statuscodes.md | gRPC}.
|
|
9
9
|
* @param errorCode <FunctionsErrorCode> - the set of possible error codes.
|
|
10
|
-
* @param message <string> - the error
|
|
10
|
+
* @param message <string> - the error message.
|
|
11
11
|
* @param [details] <string> - the details of the error (optional).
|
|
12
12
|
* @returns <HttpsError>
|
|
13
13
|
*/
|
package/src/lib/services.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
|
+
import dotenv from "dotenv"
|
|
2
|
+
import ethers from "ethers"
|
|
1
3
|
import { S3Client } from "@aws-sdk/client-s3"
|
|
2
4
|
import { COMMON_ERRORS, logAndThrowError } from "./errors"
|
|
3
5
|
|
|
6
|
+
dotenv.config()
|
|
7
|
+
let provider: ethers.providers.Provider
|
|
8
|
+
|
|
4
9
|
/**
|
|
5
10
|
* Return a configured and connected instance of the AWS S3 client.
|
|
6
11
|
* @dev this method check and utilize the environment variables to configure the connection
|
|
@@ -26,3 +31,34 @@ export const getS3Client = async (): Promise<S3Client> => {
|
|
|
26
31
|
region: process.env.AWS_REGION!
|
|
27
32
|
})
|
|
28
33
|
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Returns a Prvider, connected via a configured JSON URL or else
|
|
37
|
+
* the ethers.js default provider, using configured API keys.
|
|
38
|
+
* @returns <ethers.providers.Provider> An Eth node provider
|
|
39
|
+
*/
|
|
40
|
+
export const setEthProvider = (): ethers.providers.Provider => {
|
|
41
|
+
if (provider) return provider
|
|
42
|
+
console.log(`setting new provider`)
|
|
43
|
+
|
|
44
|
+
// Use JSON URL if defined
|
|
45
|
+
// if ((hardhat as any).ethers) {
|
|
46
|
+
// console.log(`using hardhat.ethers provider`)
|
|
47
|
+
// provider = (hardhat as any).ethers.provider
|
|
48
|
+
// } else
|
|
49
|
+
if (process.env.ETH_PROVIDER_JSON_URL) {
|
|
50
|
+
console.log(`JSON URL provider at ${process.env.ETH_PROVIDER_JSON_URL}`)
|
|
51
|
+
provider = new ethers.providers.JsonRpcProvider({
|
|
52
|
+
url: process.env.ETH_PROVIDER_JSON_URL,
|
|
53
|
+
skipFetchSetup: true
|
|
54
|
+
})
|
|
55
|
+
} else {
|
|
56
|
+
// Otherwise, connect the default provider with ALchemy, Infura, or both
|
|
57
|
+
provider = ethers.providers.getDefaultProvider("homestead", {
|
|
58
|
+
alchemy: process.env.ETH_PROVIDER_ALCHEMY_API_KEY!,
|
|
59
|
+
infura: process.env.ETH_PROVIDER_INFURA_API_KEY!
|
|
60
|
+
})
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return provider
|
|
64
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
declare module "@bandada/api-sdk"
|
package/src/types/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CeremonyInputData, CircuitDocument, ETagWithPartNumber } from "@devtion/actions"
|
|
2
|
+
import type { Groth16Proof, PublicSignals } from "snarkjs"
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Group all the necessary data needed for running the `setupCeremony` cloud function.
|
|
@@ -138,3 +139,62 @@ export type FinalizeCircuitData = {
|
|
|
138
139
|
bucketName: string
|
|
139
140
|
beacon: string
|
|
140
141
|
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Group all the necessary data needed for running the `bandadaValidateProof` cloud function.
|
|
145
|
+
* @typedef {Object} BandadaValidateProof
|
|
146
|
+
* @property {string} merkleTreeRoot - the merkle tree root of the group.
|
|
147
|
+
* @property {string} nullifierHash - the nullifier hash of the member.
|
|
148
|
+
* @property {string} externalNullifier - the external nullifier of the member.
|
|
149
|
+
* @property {PackedProof} proof - the packed proof generated on the client.
|
|
150
|
+
*/
|
|
151
|
+
export type BandadaValidateProof = {
|
|
152
|
+
proof: Groth16Proof
|
|
153
|
+
publicSignals: PublicSignals
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Define the return object of the function that verifies the Bandada membership and proof.
|
|
158
|
+
* @typedef {Object} VerifiedBandadaResponse
|
|
159
|
+
* @property {boolean} valid - true if the proof is valid and the user is a member of the group; otherwise false.
|
|
160
|
+
* @property {string} message - a message describing the result of the verification.
|
|
161
|
+
* @property {string} token - the custom access token.
|
|
162
|
+
*/
|
|
163
|
+
export type VerifiedBandadaResponse = {
|
|
164
|
+
valid: boolean
|
|
165
|
+
message: string
|
|
166
|
+
token: string
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Define the check nonce object for the cloud function
|
|
171
|
+
* @typedef {Object} CheckNonceOfSIWEAddressRequest
|
|
172
|
+
* @property {string} auth0Token - token from the device flow authentication
|
|
173
|
+
*/
|
|
174
|
+
export type CheckNonceOfSIWEAddressRequest = {
|
|
175
|
+
auth0Token: string
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Define the check nonce response object of the cloud function
|
|
180
|
+
* @typedef {Object} CheckNonceOfSIWEAddressResponse
|
|
181
|
+
* @property {boolean} valid - if the checking result was valid or not
|
|
182
|
+
* @property {string} message - informative message
|
|
183
|
+
* @property {string} token - token to sign in
|
|
184
|
+
*/
|
|
185
|
+
export type CheckNonceOfSIWEAddressResponse = {
|
|
186
|
+
valid: boolean
|
|
187
|
+
message?: string
|
|
188
|
+
token?: string
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Define the response from auth0 /userinfo endpoint
|
|
192
|
+
*
|
|
193
|
+
*/
|
|
194
|
+
export type Auth0UserInfo = {
|
|
195
|
+
sub: string
|
|
196
|
+
nickname: string
|
|
197
|
+
name: string
|
|
198
|
+
picture: string
|
|
199
|
+
updated_at: string
|
|
200
|
+
}
|