diff --git a/client/index.js b/client/index.js index 28980e4..b81cfae 100644 --- a/client/index.js +++ b/client/index.js @@ -5,13 +5,27 @@ const MerkleTree = require('../utils/MerkleTree'); const serverUrl = 'http://localhost:1225'; async function main() { - // TODO: how do we prove to the server we're on the nice list? + // TODO: how do we prove to the server we're on the nice list? + const tree = new MerkleTree(niceList); - const { data: gift } = await axios.post(`${serverUrl}/gift`, { - // TODO: add request body parameters here! - }); + const name = "Ephyrian"; // Example name to prove - console.log({ gift }); + const index = niceList.findIndex(n => n === name); + + const proof = tree.getProof(index); + + const root = tree.getRoot(); /* Only for demonstration, not to be sent */ + + + const { data: gift } = await axios.post(`${serverUrl}/gift`, { + // TODO: add request body parameters here! + name: name, + proof: proof, + root: root /* This could be for additional verification */ + }); + + console.log("Sending to server:", { name, proof }); + console.log({ gift }); } main(); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 70a452c..29fc2e4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,22 +6,11 @@ "": { "name": "holiday-gift-list", "dependencies": { - "@faker-js/faker": "^7.6.0", "axios": "^1.2.0", - "body-parser": "^1.20.1", "ethereum-cryptography": "^1.1.2", "express": "^4.18.2" } }, - "node_modules/@faker-js/faker": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-7.6.0.tgz", - "integrity": "sha512-XK6BTq1NDMo9Xqw/YkYyGjSsg44fbNwYRx7QK2CuoQgyy+f1rrTDHoExVM5PsyXCtfl2vs2vVJ0MN0yN6LppRw==", - "engines": { - "node": ">=14.0.0", - "npm": ">=6.0.0" - } - }, "node_modules/@noble/hashes": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.1.2.tgz", @@ -785,11 +774,6 @@ } }, "dependencies": { - "@faker-js/faker": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-7.6.0.tgz", - "integrity": "sha512-XK6BTq1NDMo9Xqw/YkYyGjSsg44fbNwYRx7QK2CuoQgyy+f1rrTDHoExVM5PsyXCtfl2vs2vVJ0MN0yN6LppRw==" - }, "@noble/hashes": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.1.2.tgz", diff --git a/server/index.js b/server/index.js index cc302ca..88071fe 100644 --- a/server/index.js +++ b/server/index.js @@ -1,5 +1,6 @@ const express = require('express'); -const verifyProof = require('../utils/verifyProof'); +const { verifyProof, concat } = require('../utils/verifyProof'); +const { keccak256 } = require('ethereum-cryptography/keccak'); const port = 1225; @@ -7,15 +8,20 @@ const app = express(); app.use(express.json()); // TODO: hardcode a merkle root here representing the whole nice list -// paste the hex string in here, without the 0x prefix -const MERKLE_ROOT = ''; +// (paste the hex string in here, without the 0x prefix) +const MERKLE_ROOT = '4cdf89e56895bbcabd3551d431b8ba74239d026cfac7af5fcb1c15934a4eaf34'; app.post('/gift', (req, res) => { // grab the parameters from the front-end here - const body = req.body; + const { name, proof } = req.body; + const leaf = keccak256(Buffer.from(name)).toString('hex'); // Assuming names are stored as simple hex strings in the tree + + console.log("Received proof for:", name, " with proof:", proof); // TODO: prove that a name is in the list - const isInTheList = false; + const isInTheList = verifyProof(proof, leaf, MERKLE_ROOT, concat); + console.log("Verification result:", isInTheList); + if(isInTheList) { res.send("You got a toy robot!"); } @@ -24,6 +30,7 @@ app.post('/gift', (req, res) => { } }); + app.listen(port, () => { console.log(`Listening on port ${port}!`); -}); +}); \ No newline at end of file diff --git a/utils/MerkleTree.js b/utils/MerkleTree.js index 7997952..ccc9c2b 100644 --- a/utils/MerkleTree.js +++ b/utils/MerkleTree.js @@ -67,4 +67,4 @@ class MerkleTree { } } -module.exports = MerkleTree; +module.exports = MerkleTree; \ No newline at end of file diff --git a/utils/example.js b/utils/example.js deleted file mode 100644 index 7dcf6ff..0000000 --- a/utils/example.js +++ /dev/null @@ -1,19 +0,0 @@ -const MerkleTree = require('./MerkleTree'); -const niceList = require('./niceList'); -const verifyProof = require('./verifyProof'); - -// create the merkle tree for the whole nice list -const merkleTree = new MerkleTree(niceList); - -// get the root -const root = merkleTree.getRoot(); - -// find the proof that norman block is in the list -const name = 'Norman Block'; -const index = niceList.findIndex(n => n === name); -const proof = merkleTree.getProof(index); - -// verify proof against the Merkle Root -console.log( verifyProof(proof, name, root) ); // true, Norman Block is in the list! - -// TRY IT OUT: what happens if you try a name not in the list, or a fake proof? \ No newline at end of file diff --git a/utils/niceList.json b/utils/niceList.json index b2f5d29..40fc2b0 100644 --- a/utils/niceList.json +++ b/utils/niceList.json @@ -998,5 +998,10 @@ "Everett Bergnaum DVM", "Mr. Marty Fahey", "Joel Raynor", - "Edmond Carroll PhD" -] + "Edmond Carroll PhD", + "Homer J. Simpson", + "Peter Griffin", + "Stan Smith", + "Cleveland Brown", + "Ephyrian" +] \ No newline at end of file diff --git a/utils/verifyProof.js b/utils/verifyProof.js index f5f5cb1..27db437 100644 --- a/utils/verifyProof.js +++ b/utils/verifyProof.js @@ -1,23 +1,41 @@ const { keccak256 } = require('ethereum-cryptography/keccak'); -const { hexToBytes, bytesToHex } = require('ethereum-cryptography/utils'); +const { bytesToHex } = require('ethereum-cryptography/utils'); const concat = (left, right) => keccak256(Buffer.concat([left, right])); function verifyProof(proof, leaf, root) { - proof = proof.map(({data, left}) => ({ - left, data: hexToBytes(data) + + proof = proof.map(({data, left}) => ({ + left, data: Buffer.from(data, 'hex') })); + let data = keccak256(Buffer.from(leaf)); + console.log("Initial hash from leaf:", bytesToHex(data)); for (let i = 0; i < proof.length; i++) { - if (proof[i].left) { - data = concat(proof[i].data, data); - } else { - data = concat(data, proof[i].data); - } + + console.log(`Step ${i}, applying data: ${bytesToHex(proof[i].data)}, left: ${proof[i].left}`); + + data = proof[i].left ? concat(proof[i].data, data) : concat(data, proof[i].data); + console.log(`Hash after step ${i}:`, bytesToHex(data)); } - return bytesToHex(data) === root; + const finalComputedRoot = bytesToHex(data); + + console.log("Computed root:", bytesToHex(data)); + console.log("Expected root:", root); + + return finalComputedRoot === root; } -module.exports = verifyProof; +module.exports = { verifyProof, concat }; + + + + + + + + + +