UNPKG

nmmr

Version:

Merkle Mountain Ranges as used on the Nostr protocol

100 lines (84 loc) 2.96 kB
This is a [fork](https://github.com/HerodotusDev/merkle-mountain-ranges) from Herodotus Dev Ltd's merkle-mountain-ranges npm package altered to fit Nostr protocol ecosystem ### Installing the package ```sh $> npm i nmmr ``` ### Usage ```js import NMMR from 'nmmr' // Append data as bytes then save chunks to nostr event const t = new TextEncoder() const nmmr = new NMMR() await nmmr.append(t.encode('a')) await nmmr.append(t.encode('b')) const expectedRoot = nmmr.getRoot() const chunks = [] for await (const chunk of nmmr.getChunks()) { // chunk = { contentBytes, index, total, proof } chunks.push(chunk) await createAndPublishNostrEvent(chunk) } // Later verify some chunk is really part of the whole const chunk = chunks[0] NMMR.verifyProof({ ...chunk, root: expectedRoot }) // Or derive the root when it is supplied by another signed object. const root = NMMR.calculateRoot({ contentBytes: chunk.contentBytes, index: chunk.index, total: chunk.total, proof: chunk.proof }) ``` Version 2 hashes each leaf as `sha256(uint(nodeIndex) || sha256(contentBytes))`. Proofs are a compact `Uint8Array` containing 32-byte sibling hashes followed by the other MMR peaks. The target leaf and root are not repeated in the proof. #### Manually Using the Merkle Mountain Range Note: Prefer using the above default export. ```js import { InMemoryMMR } from 'nmmr' const mmr = new InMemoryMMR() const leaves = 11 // Total node size will be 19 for (let idx = 0; idx < leaves; ++idx) { await mmr.append((idx + 1).toString()) // Leaf number starts at 1 in this implementation. } /* Height 3 15 / \ / \ / \ / \ 2 7 14 / \ / \ 1 3 6 10 13 18 / \ / \ / \ / \ / \ 0 1 2 4 5 8 9 11 12 16 17 19 */ // Generating a proof for leaf no.9 (16th node in the inclusion diagram above) const proof = mmr.getProof(9) console.log('Inclusion proof of leaf no.9', proof) // Verifying the proof (throws on failure, pass on success) mmr.verifyProof(proof) console.log('Valid proof!') // Inclusion proof of leaf no.9 { // index: 9, // value: '6', // peaks: [ 15, 18, 19 ], // peaksHashes: [ // '0x7811cf3bd6a5f019f9c345900f760694309d019be0766007388665145c431b3', // '0x5ad94a9ad7f469929d8e513ddb87e8758bddc928b06dede8c9e248630ed48f9', // '0x197f42d06f2cf19f82d475673f16350416f2c9180d77bea8a3bcc29d27b7325' // ], // siblingHashes: [ // '0x3531a94afdc03b1ee109786fdddaf23a7864c8f18ddff9d552b5dfb50ac66a', // '0x41132c938a98be60612de7aed9daa905f91c8390f731c7fde8fb8bd59bbe4c3', // '0x4a1fead9ecdd90793ba10b7da6e8a30d655843296f148f147a89cb3e978528' // ], // lastVisitedNodeIdx: 15 // } // Valid proof! ``` ## License [GNU GPLv3](https://github.com/HerodotusDev/merkle-mountain-ranges/blob/main/LICENSE)