Skip to content

Commit

Permalink
Merge pull request #19 from influenceth/merkle
Browse files Browse the repository at this point in the history
Added merkle library
  • Loading branch information
clexmond authored Sep 29, 2022
2 parents c40eebc + 388a045 commit f696af7
Show file tree
Hide file tree
Showing 4 changed files with 596 additions and 8 deletions.
4 changes: 3 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ const CREW_CLASS_DESCRIPTIONS = [
'If there is a problem, an engineer will find an answer. Whether it is buildings, ships, or processes, engineers are thrilled to be the one to solve the puzzle.',
'On the surface it appears that miners value their strength over their brains, but like their quarry, the reality lies underneath: they are highly skilled and erudite in their area of expertise.',
'Predicting the ebb and flow of the market is about more than just the raw data, it is about anticipating the needs and desires of humanity- this is what merchants strive to understand.',
'Motivated by a desire to expand human knowledge, scientists learn from the past, while keeping their gaze steadily on the future.'
'Motivated by a desire to expand human knowledge, scientists learn from the past, while keeping their gaze steadily on the future.'
];
const CREW_TITLES = [
'Communications Officer', 'Teaching Assistant', 'Librarian', 'Nurse', 'Public Safety Officer', 'Warehouse Worker',
Expand Down Expand Up @@ -623,6 +623,7 @@ const starknetContracts = require('./contracts_starknet.json');
* Other utils
*/
const Address = require('./lib/address');
const Merkle = require('./lib/merkle');

module.exports = {
MASTER_SEED,
Expand Down Expand Up @@ -665,6 +666,7 @@ module.exports = {
toCrewItem,
toCrewTrait,
Address,
Merkle,
KeplerianOrbit,
contracts: ethereumContracts, // (for backward compatibility)
ethereumContracts,
Expand Down
107 changes: 107 additions & 0 deletions lib/merkle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
const { hash } = require('starknet');

const pedersenHash = (a, b) => {
let aSorted = BigInt(a);
let bSorted = BigInt(b);

if (aSorted > bSorted) {
aSorted = BigInt(b);
bSorted = BigInt(a);
}

return BigInt(hash.pedersen([ aSorted, bSorted ]));
};

// Generates merkle root from values list each pair of values must be in sorted order
const generateMerkleRoot = (values) => {
if (values.length === 1) return values[0];
if (values.length % 2 !== 0) values.push(0);

const nextLevel = getNextLevel(values)
return generateMerkleRoot(nextLevel);
};

// Generates merkle proof from an index of the value list each pair of values must be in sorted order
const generateMerkleProof = (values, index) => {
return generateProofHelper(values, index, []);
};

// Checks the validity of a merkle proof the last element of the proof should be the root
const verifyMerkleProof = (leaf, proof) => {
const root = proof.pop();
let curr = BigInt(leaf);

for (const proofElem of proof) {
curr = pedersenHash(curr, proofElem);
}

return curr === root;
};

const getNextLevel = (level) => {
const nextLevel = [];

for (let i = 0; i < level.length; i += 2) {
const node = pedersenHash(level[i], level[i + 1]);
nextLevel.push(node);
}

return nextLevel;
};

const generateProofHelper = (level, index, proof) => {
if (level.length === 1) return proof;
if (level.length % 2 !== 0) level.push(0n);

const nextLevel = getNextLevel(level);
let indexParent = 0

for (let i = 0; i < level.length; i++) {
if (i === index) {
indexParent = Math.floor(i / 2);

if (i % 2 === 0) {
proof.push(BigInt(level[index + 1]));
} else {
proof.push(BigInt(level[index - 1]));
}
}
}

return generateProofHelper(nextLevel, indexParent, proof);
};

const generateMerkleProofFromTree = (tree, index) => {
return generateProofFromTreeHelper(tree, index, 0, []);
};

const generateProofFromTreeHelper = (tree, index, currentLevel, proof) => {
const level = tree[currentLevel];
if (level.length === 1) return proof;
if (level.length % 2 !== 0) level.push(0n);

currentLevel++;
const nextLevel = tree[currentLevel];
let indexParent = 0

for (let i = 0; i < level.length; i++) {
if (i === index) {
indexParent = Math.floor(i / 2);

if (i % 2 === 0) {
proof.push(BigInt(level[index + 1]));
} else {
proof.push(BigInt(level[index - 1]));
}
}
}

return generateProofFromTreeHelper(tree, indexParent, currentLevel, proof);
};

module.exports = {
generateMerkleRoot,
generateMerkleProof,
verifyMerkleProof,
generateMerkleProofFromTree
};
Loading

0 comments on commit f696af7

Please sign in to comment.