diff --git a/packages/buidler/contracts/Signchain.sol b/packages/buidler/contracts/Signchain.sol index 474ecdf..a6200c8 100644 --- a/packages/buidler/contracts/Signchain.sol +++ b/packages/buidler/contracts/Signchain.sol @@ -54,4 +54,14 @@ contract Signchain is DocumentRegistry, SigningModule { } + function saveNotarizeDoc(bytes32 documentHash, address notary) public payable{ + require(msg.value == notaryFee, "Invalid Notary Fee"); + notarizedDocs[documentHash] = Notarize(notary, msg.value, false); + } + + function notarizeDoc(bytes32 documentHash) public { + notarizedDocs[documentHash].notarized = true; + payable(address(msg.sender)).transfer(notarizedDocs[documentHash].notaryFee); + emit DocumentNatarized(documentHash, now, msg.sender); + } } diff --git a/packages/react-app/src/App.jsx b/packages/react-app/src/App.jsx index 3948614..88bc656 100644 --- a/packages/react-app/src/App.jsx +++ b/packages/react-app/src/App.jsx @@ -85,7 +85,7 @@ function App() { loadWeb3Modal(); } if(address){ - init(address).then(data => console.log(idx)) + //init(address).then(data => console.log(idx)) } }, [loadWeb3Modal, address]); diff --git a/packages/react-app/src/components/Documents.js b/packages/react-app/src/components/Documents.js index e8a2742..5ef8fc4 100644 --- a/packages/react-app/src/components/Documents.js +++ b/packages/react-app/src/components/Documents.js @@ -2,7 +2,7 @@ import React, { useEffect, useState } from "react"; import { Button, Icon, Loader, Table, Modal, Step } from "semantic-ui-react"; import { Badge } from "antd"; -import {authorizeUser, getAllUsers, getAllFile, downloadFiles} from "../lib/threadDb"; +import {authorizeUser, getAllUsers, getAllFile, downloadFiles, attachSignature, notarizeDoc} from "../lib/threadDb"; const index = require("../lib/e2ee"); @@ -52,7 +52,7 @@ export default function Documents(props) { const getAllDoc = async (client) => { setLoading(true); const userInfo = JSON.parse(loggedUser) - const doc = await getAllFile(client,userInfo.publicKey, props.tx, props.writeContracts, props.address) + const doc = await getAllFile(client,userInfo.publicKey, props.address, props.tx, props.writeContracts) if (doc.length > 0) { setDocs(doc); } @@ -62,18 +62,17 @@ export default function Documents(props) { const downloadFile = (name, key, location) => { setDownloading(name); console.log("docment:",location) - downloadFiles(name, key, userInfo.email, location, password) + downloadFiles(name, key, userInfo.address, location, password) .then(result => {setDownloading(null)}); }; - const signDocument = async docHash => { - const result = await index.attachSignature(docHash, props.tx, props.writeContracts, - props.userProvider.getSigner()); + const signDocument = async (docHash, docId) => { + const result = await attachSignature(docId, props.userProvider.getSigner(), caller, docHash, dbClient); }; - const notarizeDocument = async docHash => { - const result = await index.notarizeDoc(docHash, props.tx, props.writeContracts, - props.userProvider.getSigner()); + const notarizeDocument = async (docId, docHash) => { + const result = await notarizeDoc(docId, docHash, props.tx, props.writeContracts, props.userProvider.getSigner(), + caller, dbClient); }; return ( @@ -111,7 +110,7 @@ export default function Documents(props) { - {new Date(value.timestamp).toDateString()} + {value.timestamp} {" "} @@ -129,12 +128,14 @@ export default function Documents(props) { {value.notary === caller.address && !value.notarySigned ? ( - ) : !value.partySigned ? ( - diff --git a/packages/react-app/src/components/Stepper/Steps.js b/packages/react-app/src/components/Stepper/Steps.js index 6f33764..8609e57 100644 --- a/packages/react-app/src/components/Stepper/Steps.js +++ b/packages/react-app/src/components/Stepper/Steps.js @@ -139,17 +139,15 @@ const stepper = props => { allParties.push(caller); registerDoc( allParties, - fileInfo.fileHash, - fileInfo.cipherKey, + fileInfo, title, - fileInfo.fileKey, - fileInfo.fileName, setSubmitting, signer, docNotary, dbClient, + caller, props.tx, - props.writeContracts, + props.writeContracts ); }} className="button" diff --git a/packages/react-app/src/components/database/Database.js b/packages/react-app/src/components/database/Database.js index a694970..f4b540f 100644 --- a/packages/react-app/src/components/database/Database.js +++ b/packages/react-app/src/components/database/Database.js @@ -24,10 +24,15 @@ export default function Database(){ address: { type: 'string'}, publicKey: { type: 'string'}, userType: { type: 'number'}, - documentId: { + nonce: {type:'number'}, + documentInfo: { type:'array', items: { - type: 'string' + type: 'object', + properties: { + documentId: {type:'string'}, + signatureId: {type:'string'} + } } } }, @@ -39,6 +44,7 @@ export default function Database(){ type: 'object', properties: { _id: {type:'string'}, + title: {type:'string'}, documentHash : {type: 'string'}, fileLocation: {type: 'string'}, fileName: {type: 'string'}, @@ -47,14 +53,39 @@ export default function Database(){ items :{ type: 'object', properties:{ - email: {type: 'string'}, - key: {type:'string'} + address: {type: 'string'}, + cipherKey: {type:'string'} } } } }, } + const signatureDetails = { + $schema: 'http://json-schema.org/draft-07/schema#', + title: 'SignatureDetails', + type: 'object', + properties: { + _id: {type:'string'}, + signers:{ + type:'array', + items: {type:'string'} + }, + signature: { + type: 'array', + items: { + type:'object', + properties:{ + signer: {type:'string'}, //user address + signatureDigest: {type: 'string'}, + timeStamp: {type: 'string'}, + nonce: {type: 'number'} + } + }, + } + } + } + const setThreadDb = async ()=>{ const userAuth = await createUserAuth(keyInfo.key,keyInfo.secret) const privateKey = await PrivateKey.fromRandom() @@ -84,6 +115,7 @@ export default function Database(){ console.log("Creating tables!!!") const result1 = await dbClient.newCollection(threadID, {name:'RegisterUser', schema: registrationSchema}) const result2 = await dbClient.newCollection(threadID, {name:'Document', schema: documentSchema}) + await dbClient.newCollection(threadID, {name:'SignatureDetails', schema: signatureDetails}) console.log("Tables created!!:") setThreadID(threadID) } diff --git a/packages/react-app/src/lib/e2ee.js b/packages/react-app/src/lib/e2ee.js index bf9df3c..bc91166 100644 --- a/packages/react-app/src/lib/e2ee.js +++ b/packages/react-app/src/lib/e2ee.js @@ -388,7 +388,7 @@ export const uploadDoc = async function(file, password, setSubmitting, storageTy setSubmitting(false) setFileInfo({ cipherKey: cipherKey, - fileKey: fileKey, + fileLocation: fileKey, fileHash: fileHash, fileName: file.name, fileFormat: fileFormat diff --git a/packages/react-app/src/lib/threadDb.js b/packages/react-app/src/lib/threadDb.js index 8421098..c4d77e7 100644 --- a/packages/react-app/src/lib/threadDb.js +++ b/packages/react-app/src/lib/threadDb.js @@ -1,5 +1,3 @@ -import {getNotaryInfo} from "./e2ee"; - const e2e = require('./e2e-encrypt.js') const e2ee = require('./e2ee.js') const fileDownload = require('js-file-download') @@ -12,8 +10,8 @@ const keyInfo = { secret:'bcm7zjaxlipajgsm6qd6big7lv52cihf2whbbaji' } -const threadDbId = [1, 85, 96, 42, 105, 247, 113, 107, 30, 172, 138, 152, 79, 105, 200, 155, 166, 203, 19, - 199, 98, 41, 139, 71, 6, 103, 216, 114, 197, 198, 186, 245, 57, 72] +const threadDbId = [1, 85, 125, 191, 215, 114, 237, 51, 20, 250, 73, 167, 140, 79, 44, 163, 178, 32, + 196, 123, 8, 91, 204, 186, 30, 22, 91, 219, 60, 220, 108, 199, 131, 224] export const authorizeUser = async (password)=>{ try { @@ -43,7 +41,8 @@ export const registerNewUser = async function(did, name, email, privateKey, user address: address, publicKey: publicKey.toString("hex"), userType: userType, - documentId: ["-1"] + nonce: 0, + documentInfo: [{_id:"-1"}] } const status = await dbClient.create(threadId, 'RegisterUser', [data]) console.log("User registration status:",status) @@ -87,6 +86,7 @@ export const getAllUsers = async function(dbClient,loggedUser){ email: result.email, key: result.publicKey, userType: result.userType, + nonce: result.nonce } if (loggedUser === result.publicKey) { caller =value @@ -104,15 +104,15 @@ export const getAllUsers = async function(dbClient,loggedUser){ } } -export const registerDoc = async function(party, fileHash, cipherKey, title, fileLocation, fileName, - setSubmitting, signer, notary, dbClient, tx, writeContracts){ +export const registerDoc = async function(party, fileInfo, title, setSubmitting, signer, notary, dbClient, caller, + tx, writeContracts ){ let encryptedKeys=[] let userAddress=[] - + const { fileHash, fileLocation, fileName, cipherKey } = fileInfo setSubmitting(true) console.log("Party:",party) - const signature = await signDocument(fileHash, tx, writeContracts , signer) + const signature = await signDocument(fileHash, signer, caller.nonce) console.log("sign:",signature) for (let i=0;i { - console.log("Document signed!!!!") - setSubmitting(false) - }) - + setSubmitting(false) } -const signDocument = async function (fileHash, tx, writeContracts , signer){ - const selfAddress = await signer.getAddress() - console.log("Self:",selfAddress) - const replayNonce = await tx(writeContracts.Signchain.replayNonce(selfAddress)) - console.log("Nonce:",replayNonce) +const signDocument = async function (fileHash, signer, replayNonce){ const params = [ ["bytes32", "uint"], [fileHash, replayNonce] @@ -182,22 +196,61 @@ const signDocument = async function (fileHash, tx, writeContracts , signer){ return [replayNonce, await signer.signMessage(ethers.utils.arrayify(paramsHash))] } +export const attachSignature = async function(documentId, signer, caller, fileHash, dbClient){ + const query = new Where('address').eq(caller.address) + const threadId = ThreadID.fromBytes(threadDbId) + const user = await dbClient.find(threadId, 'RegisterUser', query) + const signatureId = user[0].documentInfo.filter((value)=>value.documentId===documentId) + const signature = await signDocument(fileHash, signer, caller.nonce) + //verify signature contract call + const signStatus = await dbClient.findByID(threadId, 'SignatureDetails', signatureId[0].signatureId) + const date = new Date() + signStatus.signature.push({ + signer: caller.address, + signatureDigest: signature[1], + timestamp: date.toDateString(), + nonce: signature[0] + }) + await dbClient.save(threadId,'SignatureDetails',[signStatus]) + console.log("Updated signature!!") + + user[0].nonce = user[0].nonce+1 + await dbClient.save(threadId,'RegisterUser',[user[0]]) + console.log("Updated Nonce!!:") + return true +} + +export const notarizeDoc = async function(docId, fileHash, tx, writeContracts , signer, caller, dbClient){ + const signature = await attachSignature(docId, signer, caller, fileHash, dbClient) + console.log("Signature added!!") + const result = await tx(writeContracts.Signchain.notarizeDoc(fileHash)) + console.log("Result:", result) + return true +} + +export const getNotaryInfo = async function(fileHash, tx, writeContracts) { + return await tx(writeContracts.Signchain.notarizedDocs(fileHash)) +} -export const getAllFile = async function(dbClient, loggedUserKey, tx, writeContracts,address){ +export const getAllFile = async function(dbClient, loggedUserKey,address,tx, writeContracts){ const threadId = ThreadID.fromBytes(threadDbId) const query = new Where('publicKey').eq(loggedUserKey) const users = await dbClient.find(threadId, 'RegisterUser', query) let result = [] let documents =[] - for (let i=0;i item[0]===address.toString()) + if (signDetails.signers.length !== signDetails.signature.length){ + const array = signDetails.signature.filter((item) => item.signer === address.toString()) + console.log("Array:",i," :",signDetails, ": address: ",address) if (array.length===1){ partySigned = true } @@ -207,15 +260,15 @@ export const getAllFile = async function(dbClient, loggedUserKey, tx, writeContr partySigned = true } let value = { + docId: document._id, hash: hash, documentLocation:document.fileLocation, key: document.key, - title: signDetails.title, - timestamp: parseInt(signDetails.timestamp) * 1000, + title: document.title, + timestamp: signDetails.signature[0].timestamp, signStatus: signStatus, signers: signDetails.signers, - signatures: signDetails.signatures, - owner: signDetails.owner, + signatures: signDetails.signature, partySigned: partySigned, notary: notaryInfo.notaryAddress, notarySigned: notaryInfo.notarized @@ -229,12 +282,11 @@ export const downloadFiles = async function (name, key, loggedUser,documentLocat let cipherKey = null for (let i=0;i