refactoring protocol interface

This commit is contained in:
2023-06-30 17:48:36 -04:00
parent 43478d481b
commit 0d476075ca
21 changed files with 432 additions and 113 deletions

38
PLAN.md
View File

@@ -1,46 +1,36 @@
# ZK-Chat v2
## Topic
* Should we rewrite ZK-chat?
* current ZK Chat is not maintainable
* We could use zkitterd-zkchat
* We could write it from scratch
## Requirements
### Login
* Cryptkeeper
## Credential Storage
* Localstorage
* Start with this, its easy, but not super secure
* Cryptkeeper?
* Sismo?
* Zupass?
* Walletconnect/metamask?
### Groups
## Group Creation
* Admin (me) can make groups
* by invite code
* Permission to add 1 identity commitment
* Gated Rooms (that you can watch, but can't participate in)
* Gated Room Ideas (that you can watch, but can't participate in)
* Steam Games!
* ZK Stamps!
*
* Events!
* Devconnect
### Types of Rooms:
### Types of Rooms/Groups
| Type | Read | Write | Encrypted | Centralized | RLN Protected |
| ------- | ------------- | ------------------------------- | ------------------- | ----------- | ------------- |
| Public | Y | via link/code for all rooms | N | Y | Y |
| Gated | Y | via link/code for specific room | N | Y | Y |
| ------- | ------------- | ------------------------------- | ------------------- | ----------- | ------------- |
| Public? | Y | via link/code for all rooms | N | Y | Y |
| Private | via link/code | via link/code for specific room | N | Y | Y |
| Secure | via link/code | via link/code for specific room | Y (shared password) | Y | Y |
| DM-P2P | via link/code | via link/code for specific room | Y (shared password) | N (p2p) | ? |
### Chat
* Public group chat
* Private group chat
* by invite link
* if idcommitment is in group
* DMs (private group chat, but encrypted)
* Start with Gated Rooms
## Open Questions
* P2P v Centralized?

View File

@@ -15,8 +15,8 @@ const isDark = usePreferredDark();
export default defineComponent({
setup() {
const state = useGlobalState()
fetchServers()
const state = useGlobalState()
return { state }
},
})

View File

@@ -3,10 +3,11 @@
<nav class="navbar fixed-top navbar-dark bg-dark navbar-expand-lg">
<div class="container-fluid d-flex align-content-between">
<div class="d-flex">
<a class="navbar-brand" href="#">Discreetly</a>
<a class="navbar-brand d-none d-md-block" href="#">Discreetly</a>
<div class="collapse navbar-collapse" id="navbarText">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<a class="navbar-brand d-block d-md-none" href="#">Discreetly</a>
<li class="nav-item">
<NuxtLink to="/" class="nav-link">Home</NuxtLink>
</li>
@@ -21,7 +22,7 @@
</div>
<div class="navbar-brand" id="server-title">{{ serverName }}</div>
<div>
<div class="navbar-text">© 2023 Privacy and Scaling Explorations</div>
<div class="navbar-text d-none d-md-block">© 2023 Privacy and Scaling Explorations</div>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarText"
aria-controls="navbarText" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>

View File

@@ -1,5 +1,8 @@
<template>
<div class="chat-room">
<h3>{{ room.name }}</h3>
</div>
<div class="chat-messages">
<div class="chat-message" v-for="(message, index) in messages" :key="index">
<p>
@@ -14,7 +17,7 @@
<script lang="ts">
import { ref, onMounted, watch } from 'vue'
import { RoomI, MessageI } from '../../../interfaces/src/main'
import { RoomI, MessageI } from '../../../protocol-interfaces/src/main'
import io from 'socket.io-client'
import { RLNFullProof } from 'rlnjs'

View File

@@ -7,9 +7,9 @@
</template>
<script setup lang="ts">
import { RoomI } from '../../../interfaces/src/main'
import { RoomGroupI } from '../../../protocol-interfaces/src/main'
defineProps<{
rooms: RoomI[]
rooms: RoomGroupI[]
switchRoom: (roomId: bigint) => void
}>()
</script>

View File

@@ -13,11 +13,11 @@
<script setup lang="ts">
import { getSelectedRoom, getSelectedServer, setSelectedRoom } from '../../store'
import { ref } from 'vue'
import { RoomI } from '../../../interfaces/src/main'
import { ServerI } from 'interfaces/interfaces'
import { RoomI, RoomGroupI, ServerI } from '../../../protocol-interfaces/src/main'
const server: Ref<ServerI> = ref(getSelectedServer())
const room: Ref<RoomI> = ref(getSelectedRoom())
const roomGroups: Ref<RoomGroupI[]> = ref(server.value.roomGroups)
const roomSocketEndpoint = ref(server.value.messageHandlerSocket)
function switchRoom(new_room: RoomI["id"]) {
@@ -28,6 +28,8 @@ function switchRoom(new_room: RoomI["id"]) {
</script>
<script lang="ts">
export default {
data() {
return {

View File

@@ -1,15 +1,8 @@
import { RoomI } from '../../protocol-interfaces/src/main';
import { RoomI, ServerI } from '../../protocol-interfaces/src/main';
export interface SettingsI {
selectedServer: number;
servers: ServerI[];
}
export interface ServerI {
name: string;
serverInfoEndpoint: string;
messageHandlerSocket: string;
serverData: { rooms: RoomI[]; selectedRoom?: RoomI['id'] };
selectedServer: number;
selectedRoom: RoomI['id'];
}
export interface RoomsProviderI {

View File

@@ -1,7 +1,7 @@
<template>
<div class="d-flex flex-column align-content-between">
<AppHeader />
<main class="align-items-center align-self-stretch">
<main class="container-fluid align-items-center align-self-stretch">
<slot />
</main>
</div>

View File

@@ -9,7 +9,6 @@ import { useGlobalState } from '../store'
export default defineComponent({
async setup() {
const state = useGlobalState()
console.log(state.value.settings)
return { state }
},
})

View File

@@ -1,7 +1,7 @@
import { defineStore } from 'pinia';
import { SettingsI, ServerI } from '../interfaces/interfaces';
import { RoomI } from '../../protocol-interfaces/src/main';
import { MembershipI, RoomGroupI, RoomI, ServerI } from '../../protocol-interfaces/src/main';
import { createGlobalState, useStorage } from '@vueuse/core';
import { SettingsI } from 'interfaces/interfaces';
const STORE_NAME = 'root';
@@ -10,14 +10,26 @@ const defaultServers: ServerI[] = [
name: 'Discreetly',
serverInfoEndpoint: 'localhost:3001',
messageHandlerSocket: 'localhost:3002',
serverData: { rooms: [], selectedRoom: 0n }
roomGroups: [
{
name: 'client_defaults',
rooms: [
{
id: 0n,
name: 'Loading...',
membership: [0n, 1n, 2n] as MembershipI
}
]
}
]
}
];
// TODO: Need to write a settings class
const getDefaultSettings = (): SettingsI => ({
selectedServer: 0,
servers: defaultServers
servers: defaultServers,
selectedRoom: 0n
});
export const useGlobalState = createGlobalState(() => {
@@ -38,50 +50,53 @@ export function getSelectedServer(): ServerI {
return defaultServers[0];
}
export function getRooms(): RoomI[] {
export function getRooms(): RoomGroupI[] | undefined {
const settings = useGlobalState().value.settings;
return settings.servers[settings.selectedServer].serverData.rooms;
return settings.servers[settings.selectedServer].roomGroups;
}
export function getSelectedRoom(): RoomI {
const settings = useGlobalState().value.settings;
const selectedRoom = settings.servers[settings.selectedServer].serverData.selectedRoom;
console.log(settings);
const selectedRoom = settings.selectedRoom;
if (selectedRoom) {
return settings.servers[settings.selectedServer].serverData.rooms.find(
(element) => element.id === selectedRoom
) as RoomI;
} else {
return settings.servers[settings.selectedServer].serverData.rooms[0];
settings.servers[settings.selectedServer].roomGroups.forEach((RoomGroup) => {
RoomGroup.rooms.forEach((room) => {
if (room.id === selectedRoom) {
return room;
}
});
});
}
return settings.servers[settings.selectedServer].roomGroups[0].rooms[0];
}
export function setSelectedRoom(room: RoomI['id']) {
const settings = useGlobalState().value.settings;
settings.servers[settings.selectedServer].serverData.selectedRoom = room;
settings.selectedRoom = room;
}
export async function fetchRooms(): Promise<RoomI[]> {
export async function fetchRooms(): Promise<RoomGroupI[]> {
const settings = useGlobalState().value.settings;
const server = settings.servers[settings.selectedServer];
const endpoint = 'http://' + server.serverInfoEndpoint + '/rooms';
const response = await useFetch(endpoint);
console.log(response);
const data: RoomI[] = (await response.data.value) as RoomI[];
server.serverData.rooms = data as RoomI[];
return server.serverData.rooms;
const data: RoomGroupI[] = (await response.data.value) as RoomGroupI[];
server.roomGroups = data as RoomGroupI[];
return server.roomGroups;
}
export async function fetchServers(): Promise<ServerI[]> {
export async function fetchServers(): Promise<void> {
const servers = useGlobalState().value.settings.servers;
servers.forEach(async (server: ServerI, index: number) => {
const endpoint = 'http://' + server.serverInfoEndpoint + '/';
try {
const response = await useFetch(endpoint);
console.log(response);
servers[index].serverData = response.data.value as ServerI['serverData'];
servers[index] = response.data.value as ServerI;
} catch (error) {
console.log(error);
}
});
return servers;
}

View File

@@ -0,0 +1,10 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RoomType = void 0;
var RoomType;
(function (RoomType) {
RoomType["PUBLIC"] = "public";
RoomType["GATED"] = "gated";
RoomType["PRIVATE"] = "private";
RoomType["SECURE"] = "secure";
})(RoomType || (exports.RoomType = RoomType = {}));

View File

@@ -33,16 +33,24 @@ export interface SystemMessageI {
}
export interface RoomI {
id: RLNFullProof['rlnIdentifier']; // RLN Identifier
id: RLNFullProof['rlnIdentifier'] | string; // RLN Identifier
name: string; // Readable name
rateLimit?: number; // Messages per minute
membership?: MembershipI; // List of Identity Commitments, or a contract address for an RLN contract
type?: RoomType; // Public or private
messageHandlerSocket?: number; // Port for websocket connections
}
export interface RoomGroupI {
name: string;
rooms: RoomI[];
}
export interface ServerI {
name: string;
version?: string;
serverInfoEndpoint: string;
messageHandlerSocket?: string; // Default port for websocket connections
publicMembership?: MembershipI;
rooms: RoomI[];
wsPort?: number;
roomGroups: RoomGroupI[];
}

View File

@@ -0,0 +1,49 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.serverConfig = exports.rooms = void 0;
var poseidon2_1 = require("poseidon-lite/poseidon2");
require("dotenv/config");
var serverID = 999n;
console.log(process.env.serverID);
try {
serverID = process.env.serverID ? process.env.serverID : 999n;
}
catch (error) {
console.error('Error reading serverID from .env file!');
}
var room_1 = (0, poseidon2_1.poseidon2)([serverID, 1n]);
var room_2 = (0, poseidon2_1.poseidon2)([serverID, 2n]);
var room_3 = (0, poseidon2_1.poseidon2)([serverID, 3n]);
var room_4 = (0, poseidon2_1.poseidon2)([serverID, 4n]);
var fake_user_1 = (0, poseidon2_1.poseidon2)([0n, 1n]);
var fake_user_2 = (0, poseidon2_1.poseidon2)([0n, 2n]);
var fake_user_3 = (0, poseidon2_1.poseidon2)([0n, 3n]);
var fake_user_4 = (0, poseidon2_1.poseidon2)([0n, 4n]);
var fake_user_5 = (0, poseidon2_1.poseidon2)([0n, 5n]);
exports.rooms = [
{
id: room_1,
name: 'General',
membership: [fake_user_1, fake_user_2]
},
{
id: room_2,
name: 'Event 1',
membership: [fake_user_1, fake_user_3, fake_user_5]
},
{
id: room_3,
name: 'Club 1',
membership: [fake_user_2, fake_user_3, fake_user_4]
},
{
id: room_4,
name: 'Test 1',
membership: [fake_user_4, fake_user_5]
}
];
exports.serverConfig = {
version: '0.0.1',
rooms: exports.rooms,
wsPort: 3001
};

View File

@@ -1,16 +1,16 @@
import { MembershipI, RoomI, ServerI } from '../../protocol-interfaces/src/main';
import { MembershipI, RoomGroupI, ServerI } from '../../protocol-interfaces/src/main';
import { poseidon2 } from 'poseidon-lite/poseidon2';
import 'dotenv/config';
let serverID = 999n;
console.log(process.env.serverID);
let serverID = 999n;
try {
serverID = process.env.serverID ? (process.env.serverID as unknown as bigint) : 999n;
} catch (error) {
console.error('Error reading serverID from .env file!');
}
console.log('SERVERID:', serverID);
const room_1 = poseidon2([serverID, 1n]);
const room_2 = poseidon2([serverID, 2n]);
@@ -23,31 +23,43 @@ const fake_user_3 = poseidon2([0n, 3n]);
const fake_user_4 = poseidon2([0n, 4n]);
const fake_user_5 = poseidon2([0n, 5n]);
export const rooms: RoomI[] = [
export const rooms: RoomGroupI[] = [
{
id: room_1,
name: 'General',
membership: [fake_user_1, fake_user_2] as MembershipI
name: 'Default',
rooms: [
{
id: room_1,
name: 'General',
membership: [fake_user_1, fake_user_2, fake_user_5] as MembershipI
}
]
},
{
id: room_2,
name: 'Event 1',
membership: [fake_user_1, fake_user_3, fake_user_5] as MembershipI
name: 'Games',
rooms: [
{
id: room_3,
name: 'Gunfire Reborn',
membership: [fake_user_2, fake_user_3, fake_user_4] as MembershipI
}
]
},
{
id: room_3,
name: 'Club 1',
membership: [fake_user_2, fake_user_3, fake_user_4] as MembershipI
},
{
id: room_4,
name: 'Test 1',
membership: [fake_user_4, fake_user_5] as MembershipI
name: 'Events',
rooms: [
{
id: room_2,
name: 'DevConnect 2023',
membership: [fake_user_1, fake_user_3, fake_user_5] as MembershipI
}
]
}
];
export const serverConfig: ServerI = {
name: 'Discreetly',
serverInfoEndpoint: 'localhost:3001',
messageHandlerSocket: 'localhost:3002',
version: '0.0.1',
rooms: rooms,
wsPort: 3001
roomGroups: rooms
};

View File

@@ -6,7 +6,7 @@
"scripts": {
"build": "tsc",
"start": "node dist/server/src/server.js",
"watch": "tsc --watch",
"watch": "tsc --watch ./src/server.ts --outDir ./dist/",
"serve": "nodemon -q dist/server/src/server.js",
"dev": "concurrently \"npm run watch\" \"npm run serve\""
},
@@ -27,4 +27,4 @@
"concurrently": "^8.2.0",
"nodemon": "^2.0.22"
}
}
}

View File

@@ -0,0 +1,74 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var express = require("express");
var http_1 = require("http");
var socket_io_1 = require("socket.io");
var cors = require("cors");
// import { createClient } from 'redis';
// import initializeClaimCodeManager from './inviteCodes';
var rooms_1 = require("../mockData/rooms");
var verifier_1 = require("./verifier");
// Deal with bigints in JSON
BigInt.prototype.toJSON = function () {
return this.toString();
};
// HTTP is to get info from the server about configuration, rooms, etc
var http_port = 3001;
// Socket is to communicate chat room messages back and forth
var socket_port = 3002;
var app = express();
var socket_server = new http_1.Server(app);
var io = new socket_io_1.Server(socket_server, {
cors: {
origin: '*'
}
});
// Redis
// const redisClient = createClient();
// redisClient.on('error', (err) => console.log('Redis Client Error', err));
// await redisClient.connect();
// const ccm = await initializeClaimCodeManager(redisClient);
io.on('connection', function (socket) {
console.debug('a user connected');
socket.on('messageFromClient', function (msg) {
console.log('VALIDATING MESSAGE ' + msg);
var valid = (0, verifier_1.default)(msg);
if (!valid) {
console.log('INVALID MESSAGE');
return;
}
io.emit('messageToClient', msg);
});
socket.on('disconnect', function () {
console.log('user disconnected');
});
});
app.use(cors({
origin: '*'
}));
app.get('/', function (req, res) {
console.log('fetching server info');
res.json(rooms_1.serverConfig);
});
app.get('/rooms', function (req, res) {
console.log('fetching rooms');
res.json(rooms_1.rooms);
});
// app.post('/join', (req, res) => {
// req.on('data', (data) => {
// if (ccm.claimCode(data.claimCode)) {
// res.status(200).send('OK');
// }
// });
// });
app.listen(http_port, function () {
console.log("Http Server is running at http://localhost:".concat(http_port));
});
socket_server.listen(socket_port, function () {
console.log("Socket Server is running at http://localhost:".concat(socket_port));
});
// // Disconnect from redis on exit
// process.on('SIGINT', () => {
// console.log('disconnecting redis');
// redisClient.disconnect().then(process.exit());
// });

View File

@@ -2,8 +2,8 @@ import * as express from 'express';
import { Server } from 'http';
import { Server as SocketIOServer, Socket } from 'socket.io';
import * as cors from 'cors';
import { createClient } from 'redis';
import initializeClaimCodeManager from './inviteCodes';
// import { createClient } from 'redis';
// import initializeClaimCodeManager from './inviteCodes';
import { serverConfig, rooms } from '../mockData/rooms';
import { MessageI } from '../../protocol-interfaces/src/main';
import verifyProof from './verifier';
@@ -29,11 +29,11 @@ const io = new SocketIOServer(socket_server, {
// Redis
const redisClient = createClient();
redisClient.on('error', (err) => console.log('Redis Client Error', err));
await redisClient.connect();
// const redisClient = createClient();
// redisClient.on('error', (err) => console.log('Redis Client Error', err));
// await redisClient.connect();
const ccm = await initializeClaimCodeManager(redisClient);
// const ccm = await initializeClaimCodeManager(redisClient);
io.on('connection', (socket: Socket) => {
console.debug('a user connected');
@@ -69,13 +69,13 @@ app.get('/rooms', (req, res) => {
res.json(rooms);
});
app.post('/join', (req, res) => {
req.on('data', (data) => {
if (ccm.claimCode(data.claimCode)) {
res.status(200).send('OK');
}
});
});
// app.post('/join', (req, res) => {
// req.on('data', (data) => {
// if (ccm.claimCode(data.claimCode)) {
// res.status(200).send('OK');
// }
// });
// });
app.listen(http_port, () => {
console.log(`Http Server is running at http://localhost:${http_port}`);
@@ -85,8 +85,8 @@ socket_server.listen(socket_port, () => {
console.log(`Socket Server is running at http://localhost:${socket_port}`);
});
// Disconnect from redis on exit
process.on('SIGINT', () => {
console.log('disconnecting redis');
redisClient.disconnect().then(process.exit());
});
// // Disconnect from redis on exit
// process.on('SIGINT', () => {
// console.log('disconnecting redis');
// redisClient.disconnect().then(process.exit());
// });

View File

@@ -0,0 +1,56 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
var rlnjs_1 = require("rlnjs");
var vkey_1 = require("../vkey");
var poseidon1_1 = require("poseidon-lite/poseidon1");
var v = new rlnjs_1.RLNVerifier(vkey_1.default);
function verifyProof(msg) {
return __awaiter(this, void 0, void 0, function () {
var rlnIdentifier, msgHash;
return __generator(this, function (_a) {
rlnIdentifier = BigInt(msg.room);
msgHash = (0, poseidon1_1.poseidon1)([BigInt(msg.message)]);
if (msgHash !== msg.proof.snarkProof.publicSignals.x) {
return [2 /*return*/, false];
}
return [2 /*return*/, v.verifyProof(rlnIdentifier, msg.proof)];
});
});
}
exports.default = verifyProof;

113
packages/server/vkey.js Normal file
View File

@@ -0,0 +1,113 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var vkey = {
protocol: 'groth16',
curve: 'bn128',
nPublic: 6,
vk_alpha_1: [
'20491192805390485299153009773594534940189261866228447918068658471970481763042',
'9383485363053290200918347156157836566562967994039712273449902621266178545958',
'1'
],
vk_beta_2: [
[
'6375614351688725206403948262868962793625744043794305715222011528459656738731',
'4252822878758300859123897981450591353533073413197771768651442665752259397132'
],
[
'10505242626370262277552901082094356697409835680220590971873171140371331206856',
'21847035105528745403288232691147584728191162732299865338377159692350059136679'
],
['1', '0']
],
vk_gamma_2: [
[
'10857046999023057135944570762232829481370756359578518086990519993285655852781',
'11559732032986387107991004021392285783925812861821192530917403151452391805634'
],
[
'8495653923123431417604973247489272438418190587263600148770280649306958101930',
'4082367875863433681332203403145435568316851327593401208105741076214120093531'
],
['1', '0']
],
vk_delta_2: [
[
'15843492564726493141206137545151112430025849862599515978867263397998469229435',
'2641620088579599196632429938637192954942125142987513582409483595468154705252'
],
[
'15253737609999317848814269759926613543448600884487473171254509409515750175717',
'5271356778587753254754924912815340007170603638024344160250381896827480645043'
],
['1', '0']
],
vk_alphabeta_12: [
[
[
'2029413683389138792403550203267699914886160938906632433982220835551125967885',
'21072700047562757817161031222997517981543347628379360635925549008442030252106'
],
[
'5940354580057074848093997050200682056184807770593307860589430076672439820312',
'12156638873931618554171829126792193045421052652279363021382169897324752428276'
],
[
'7898200236362823042373859371574133993780991612861777490112507062703164551277',
'7074218545237549455313236346927434013100842096812539264420499035217050630853'
]
],
[
[
'7077479683546002997211712695946002074877511277312570035766170199895071832130',
'10093483419865920389913245021038182291233451549023025229112148274109565435465'
],
[
'4595479056700221319381530156280926371456704509942304414423590385166031118820',
'19831328484489333784475432780421641293929726139240675179672856274388269393268'
],
[
'11934129596455521040620786944827826205713621633706285934057045369193958244500',
'8037395052364110730298837004334506829870972346962140206007064471173334027475'
]
]
],
IC: [
[
'8031258441513870069218926350614535264375964850237573994722576082762376130120',
'10856498242370539938488350327252922752003577472410177605193208995032874394673',
'1'
],
[
'6483252634275925296767139694699053893443836312825029906678314981076912443786',
'16200022412659747824780247185834575217619738528738428671945007014456517089372',
'1'
],
[
'7826131472601844425468162165824594247304650569207551767375062083390202086552',
'2402384756959723717021967545289751015365966591283482074295616436041168540089',
'1'
],
[
'20962113991123244313787181712543056653777929662474801940683684948379034271478',
'10027415109369829970480667053393212645687990826409423031435115025507048005668',
'1'
],
[
'8432217673912769193496764557897133928865280459035798630016076595324914715282',
'20140501773370324201599509349598154319266316748526834245336285321298662406811',
'1'
],
[
'8639415035468784196192154580377416064832122309444291133088330742211195696933',
'15649905236006734960923326584432471368516604758914831046395015521642928125044',
'1'
],
[
'18517720151730935158822308288483895851104724976532389037453836090081541714567',
'6657134491916402491200160156155595678121894405383483866631617566354129332784',
'1'
]
]
};
exports.default = vkey;

View File

@@ -1,6 +0,0 @@
{
"extends": "./packages/frontend/.nuxt/tsconfig.json",
"compilerOptions": {
"resolveJsonModule": true
}
}