Skip to content

Instantly share code, notes, and snippets.

@ccoincash
Last active November 28, 2020 12:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ccoincash/40ffe1a0f17c336ca7f05b7d9f6a08ca to your computer and use it in GitHub Desktop.
Save ccoincash/40ffe1a0f17c336ca7f05b7d9f6a08ca to your computer and use it in GitHub Desktop.
merkle tree implementation
contract MerkleTree {
// TODO second preimage attack
static function calculateMerkleRoot(bytes leaf, bytes merklePath) : bytes {
int i = 0;
int merklePathLength = len(merklePath) / 33;
require(merklePathLength <= 5);
bytes merkleValue = leaf;
loop (5) {
if (i < merklePathLength) {
int left = unpack(merklePath[i * 33 + 32 : i * 33 + 33]);
if (left == 2) {
merkleValue = sha256(merkleValue);
}
else if (left) {
merkleValue = sha256(merkleValue + merklePath[i * 33 : i * 33 + 32]);
} else {
merkleValue = sha256(merklePath[i * 33 : i * 33 + 32] + merkleValue);
}
i = i + 1;
}
}
return merkleValue;
}
static function verifyLeaf(bytes leaf, bytes merklePath, bytes merkleRoot) : bool {
bytes merkleValue = MerkleTree.calculateMerkleRoot(leaf, merklePath);
return merkleValue == merkleRoot;
}
static function verifyTwoLeafPath(
bytes leafA,
bytes leafAMerklePath,
bytes leafB,
bytes leafBMerklePath,
bytes mergeMerklePath,
bool leafAIsLeft,
bytes merkleRoot) : bool {
bytes leafARoot = MerkleTree.calculateMerkleRoot(leafA, leafAMerklePath);
bytes leafBRoot = MerkleTree.calculateMerkleRoot(leafB, leafBMerklePath);
bytes mergeNode = b'';
if (leafAIsLeft) {
mergeNode = sha256(leafARoot + leafBRoot);
}
else {
mergeNode = sha256(leafBRoot + leafARoot);
}
return MerkleTree.verifyLeaf(mergeNode, mergeMerklePath, merkleRoot);
}
static function calculateTwoLeafMerkleRoot(
bytes leafA,
bytes leafAMerklePath,
bytes leafB,
bytes leafBMerklePath,
bytes mergeMerklePath,
bool leafAIsLeft): bytes {
bytes leafARoot = MerkleTree.calculateMerkleRoot(leafA, leafAMerklePath);
bytes leafBRoot = MerkleTree.calculateMerkleRoot(leafB, leafBMerklePath);
bytes mergeNode = b'';
if (leafAIsLeft) {
mergeNode = sha256(leafARoot + leafBRoot);
}
else {
mergeNode = sha256(leafBRoot + leafARoot);
}
return MerkleTree.calculateMerkleRoot(mergeNode, mergeMerklePath);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment