Merkle Tree Implementation in JS with keccak256
I coded some Merkle Tree implementations in JavaScript with keccak256. This code takes JSON Objects from the local JSON File that called output.json. It has this type of objects:
{
"key": "{\"address\":\"0xCA1b1d94C8aDbeD62dB06af2933820098d397D12\",\"type\":\"index\"}",
"value": "{\"index\":0}"
}
And my code creates the merkle tree from these key-value pairs, selects one of them randomly, finds its index on the tree, hashes it, and tries to concatenate and hash it with its sibling. However, no matter how hard I try to concatenate and hash the same hashes, I never get the same hashes.
Here is the my JS code:
const fs = require('fs');
const keccak256 = require('keccak256');
const json = JSON.parse(fs.readFileSync('output.json', { encoding: 'utf8' }));
let indexArray = [];
function main() {
const tree = json.map((item) => {
return {
key: item.key.toString(),
value: item.value.toString(),
};
});
searchObject = tree[Math.floor(Math.random() * tree.length)]
let current = JSON.stringify(searchObject);
let iter = 0;
//creating leafs
for (let i = 0; i < tree.length; i++) {
let element = tree[i];
tree[i] = keccak256(JSON.stringify(element));
indexArray.push(tree[i]);
}
//logging
for (let i = 0; i < tree.length; i++) {
//tree[i] = tree[i].toString('hex');
console.log(`${iter}. layer'ın ${i}. elemanı: ${tree[i].toString('hex')}`);
}
iter++;
while (tree.length > 1) {
//create merkle tree
for (let i = 0; i < tree.length - 1; i++) {
process.stdout.write(`${tree[i].toString('hex')} and ${tree[i+1].toString('hex')} concatenated and hashed, and the result is this output:`);
tree[i] = keccak256(tree[i] + tree[i+1]);
process.stdout.write(`${tree[i].toString('hex')}\n`);
tree.splice(i+1, 1);
}
//logging
for (let i = 0; i < tree.length; i++) {
indexArray.push(tree[i]);
console.log(`${iter}. layer'ın ${i}. elemanı: ${tree[i].toString('hex')}`);
}
iter++;
}
console.log(`Merkle root is: ${tree[0].toString('hex')}\n`);
indexArray.reverse();
for (let i = 0; i < indexArray.length; i++) {
console.log(`${ i }. eleman: ${indexArray[i].toString('hex')}`);
}
console.log(`\n\nBeginning search...`);
let dex = null;
for (let i = 0; i < indexArray.length; i++) {
if ( keccak256(current).toString('hex') === indexArray[i].toString('hex')) {
console.log(`\n${searchObject.key + searchObject.value} and its hash ${keccak256(current).toString('hex')} is found at ${i}. index`);
dex = i;
break;
}
}
let hash = null;
if (dex % 2 == 0) {
hash = keccak256( indexArray[dex-1] + current );
console.log(`\n`);
console.log(`${keccak256(current).toString('hex')} and its sibling is at ${dex-1} index which is ${indexArray[dex-1].toString('hex')} hashed together and the result is ${hash.toString('hex')}`);
dex = Math.floor((dex-1)/2);
}
else {
hash = keccak256( current + indexArray[dex+1] );
console.log(`\n`);
console.log(`${keccak256(current).toString('hex')} and its sibling is at ${dex+1} index which is ${indexArray[dex+1].toString('hex')} hashed together and the result is ${hash.toString('hex')}`);
dex = Math.floor((dex-1)/2);
}
if (hash === indexArray[dex]) {
console.log(`\nProof is valid!`);
} else {
console.log(`\nProof is not valid!`);
}
}
main();