Last active
July 24, 2023 13:55
-
-
Save eddmann/0af11a2436202cd994ecf73f70d49674 to your computer and use it in GitHub Desktop.
Bitcoin Internals: How Blocks use Merkle Trees in JavaScript
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const fetchLatestBlock = () => | |
fetch(`https://blockchain.info/q/latesthash?cors=true`) | |
.then(r => r.text()); | |
const fetchMerkleRootAndTransactions = block => | |
fetch(`https://blockchain.info/rawblock/${block}?cors=true`) | |
.then(r => r.json()) | |
.then(d => [d.mrkl_root, d.tx.map(t => t.hash)]); | |
const toBytes = hex => | |
hex.match(/../g).reduce((acc, hex) => [...acc, parseInt(hex, 16)], []); | |
const toHex = bytes => | |
bytes.reduce((acc, bytes) => acc + bytes.toString(16).padStart(2, '0'), ''); | |
const toPairs = arr => | |
Array.from(Array(Math.ceil(arr.length / 2)), (_, i) => arr.slice(i * 2, i * 2 + 2)); | |
const hashPair = (a, b = a) => { | |
const bytes = toBytes(`${b}${a}`).reverse(); | |
const hashed = sha256.array(sha256.array(bytes)); | |
return toHex(hashed.reverse()); | |
}; | |
const merkleRoot = txs => | |
txs.length === 1 ? txs[0] : merkleRoot(toPairs(txs).reduce((tree, pair) => [...tree, hashPair(...pair)], [])); | |
fetchLatestBlock() | |
.then(fetchMerkleRootAndTransactions) | |
.then(([root, txs]) => { | |
const isValid = merkleRoot(txs) === root; | |
console.log(isValid); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I wrote a typescript + nodejs variant. Not concise at all. Just for practice.
https://gist.github.com/changtimwu/a40002009c4d8ca960fa0ad403731fd0