Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add IPFS signature to polls and votes #24

Merged
merged 3 commits into from
Apr 23, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ yarn-error.log*
.vscode

.idea
.cosine
60 changes: 48 additions & 12 deletions components/choices/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@ const express = require("express");
const dbo = require("../../db/conn");
const {
getInputFromSigPayload,
getTimestampFromPayloadBytes,
getIPFSProofFromPayload,
getUserTotalVotingPowerAtReferenceBlock,
} = require("../../utils");
const { default: BigNumber } = require("bignumber.js");
const { getPkhfromPk } = require("@taquito/utils");
const { uploadToIPFS } = require("../../services/ipfs.service");

// This help convert the id from string to ObjectId for the _id.
const ObjectId = require("mongodb").ObjectId;
Expand All @@ -33,13 +36,16 @@ const getChoiceById = async (req, response) => {
};

const updateChoiceById = async (req, response) => {
const { payloadBytes, publicKey } = req.body;
const { payloadBytes, publicKey, signature } = req.body;

let j = 0;
let i = 0;

try {
const values = getInputFromSigPayload(payloadBytes);

const payloadDate = getTimestampFromPayloadBytes(payloadBytes);

let db_connect = dbo.getDb("Lite");

const pollID = values[0].pollID;
Expand Down Expand Up @@ -105,7 +111,40 @@ const updateChoiceById = async (req, response) => {
if (total.eq(0)) {
throw new Error("No balance at proposal level");
}
const isVoted = await db_connect
Man-Jain marked this conversation as resolved.
Show resolved Hide resolved
.collection('Choices')
.find({
pollID: poll._id,
walletAddresses: { $elemMatch: { address: address } },
})
.toArray();

if (isVoted.length > 0) {
const oldVote = await db_connect.collection("Choices").findOne({
_id: ObjectId(isVoted[0].walletAddresses[0].choiceId),
});

const oldSignaturePayload = oldVote.walletAddresses[0].payloadBytes;
if (oldSignaturePayload) {
const oldSignatureDate =
getTimestampFromPayloadBytes(oldSignaturePayload);

if (payloadDate <= oldSignatureDate) {
throw new Error("Invalid Signature");
}
}
}

const cidLink = await uploadToIPFS(
getIPFSProofFromPayload(payloadBytes, signature)
);
if (!cidLink) {
throw new Error(
"Could not upload proof to IPFS, Vote was not registered. Please try again later"
);
}

// TODO: Optimize this Promise.all
await Promise.all(
values.map(async (value) => {
const { choiceId } = value;
Expand All @@ -114,19 +153,15 @@ const updateChoiceById = async (req, response) => {
address,
balanceAtReferenceBlock: total.toString(),
choiceId,
payloadBytes,
signature,
};

walletVote.cidLink = cidLink;

const choice = await db_connect
.collection("Choices")
.findOne({ _id: ObjectId(choiceId) });

const isVoted = await db_connect
.collection("Choices")
.find({
pollID: poll._id,
walletAddresses: { $elemMatch: { address: address } },
})
.toArray();
if (isVoted.length > 0) {
if (poll.votingStrategy === 0) {
const mongoClient = dbo.getClient();
Expand All @@ -137,9 +172,6 @@ const updateChoiceById = async (req, response) => {
walletAddresses: walletVote,
},
};
const oldVote = await db_connect.collection("Choices").findOne({
_id: ObjectId(isVoted[0].walletAddresses[0].choiceId),
});

let remove = {
$pull: {
Expand All @@ -152,6 +184,9 @@ const updateChoiceById = async (req, response) => {
try {
await session.withTransaction(async () => {
const coll1 = db_connect.collection("Choices");
// const coll2 = db_connect.collection("Polls");


// Important:: You must pass the session to the operations
await coll1.updateOne(
{ _id: ObjectId(oldVote._id) },
Expand Down Expand Up @@ -257,6 +292,7 @@ const updateChoiceById = async (req, response) => {
}
};

// Get the user's choice
const choicesByUser = async (req, response) => {
const { id } = req.params.id;

Expand Down
30 changes: 27 additions & 3 deletions components/polls/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ const {
getCurrentBlock,
getTotalSupplyAtCurrentBlock,
getUserTotalVotingPowerAtReferenceBlock,
getIPFSProofFromPayload,
} = require("../../utils");

const { uploadToIPFS } = require("../../services/ipfs.service");

const ObjectId = require("mongodb").ObjectId;

const getPollById = async (req, response) => {
Expand Down Expand Up @@ -49,7 +52,7 @@ const getPollsById = async (req, response) => {
};

const addPoll = async (req, response) => {
const { payloadBytes, publicKey } = req.body;
const { payloadBytes, publicKey, signature } = req.body;

try {
const values = getInputFromSigPayload(payloadBytes);
Expand Down Expand Up @@ -141,11 +144,29 @@ const addPoll = async (req, response) => {
_id: ObjectId(),
};
});

const choicesPoll = choicesData.map((element) => {
return element._id;
});

const pollExists = await db_connect
.collection("Polls")
.findOne({ payloadBytes });

if (pollExists) {
throw new Error("Invalid Signature, Poll already exists");
}

const cidLink = await uploadToIPFS(
Man-Jain marked this conversation as resolved.
Show resolved Hide resolved
getIPFSProofFromPayload(payloadBytes, signature)
);
if (!cidLink) {
throw new Error(
"Could not upload proof to IPFS, Vote was not registered. Please try again later"
);
}



let PollData = {
name,
description,
Expand All @@ -159,7 +180,10 @@ const addPoll = async (req, response) => {
choices: choicesPoll,
author,
votingStrategy,
isXTZ
isXTZ,
payloadBytes,
signature,
cidLink
};

let data = {
Expand Down
3 changes: 2 additions & 1 deletion config.env.example
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
ATLAS_URI=#YOUR_MONGODB_URI
PORT=#YOUR_NONDEFAULT_APP_PORT
PORT=#YOUR_NONDEFAULT_APP_PORT
NFT_STORAGE_KEY=XXXXXX #TokenFrom Nft.Storage
10 changes: 10 additions & 0 deletions config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
require("dotenv").config({ path: "./config.env" });

const AppConfig = {
ServerPort: process.env.PORT || 5000,
IPFS: {
NFT_STORAGE_TOKEN: process.env.NFT_STORAGE_KEY,
}
}

module.exports = AppConfig
Loading