![Oracle Drags Its Feet in the JavaScript Trademark Dispute](https://cdn.sanity.io/images/cgdhsj6q/production/919c3b22c24f93884c548d60cbb338e819ff2435-1024x1024.webp?w=400&fit=max&auto=format)
Security News
Oracle Drags Its Feet in the JavaScript Trademark Dispute
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.
@accumulators/merkle-mountain-range
Advanced tools
A TypeScript implementation of Merkle Mountain Ranges
MMR is a structure that allows appending and proving efficiently. Time complexity of both operations is O(log tree_size).
import MemoryStore from "@accumulators/memory";
import { KeccakHasher } from "@accumulators/hashers";
import Mmr from "@accumulators/merkle-mountain-range";
const store = new MemoryStore();
const hasher = new KeccakHasher();
const mmr = new Mmr(store, hasher);
await mmr.append("1");
await mmr.append("2");
await mmr.append("3");
const { elementIndex } = await mmr.append("4");
await mmr.append("5");
const proof = await mmr.getProof(elementIndex);
console.log(await mmr.verifyProof(proof, "4")); // true
constructor(store: Store, hasher: Hasher, mmrId?: string)
Creates a new MMR with a given hasher
instance and stores its value in provided store
.
All the values in store
have keys prefixes with mmrId
. If you want to recreate an existing MMR, you need to provide the same mmrId
as the original MMR. In case you want to create a new MMR, you can omit mmrId
and it will be generated automatically. mmrId
can be later accessed using the property (e.g. myMmr.mmrId
).
append(value: string)
Appends a new value to the MMR. Returns the promise of AppendResult
.
interface AppendResult {
leavesCount: number; // number of leaves in the mmr after append
elementsCount: number; // number of all nodes in the mmr after append
elementIndex: number; // index in the mmr of the appended element
rootHash: string; // root hash of the mmr after append
}
For instance after appending 6th element ot the MMR, the result would be:
{
leavesCount: 6,
elementsCount: 10,
elementIndex: 9,
rootHash: "0x..."
}
getProof(elementIndex: number, options?: ProofOptions)
Returns information that is needed to verify the proof of the element with a given elementIndex
.
interface Proof {
elementIndex: number; // index in the mmr of requested element (same as in function argument)
elementHash: number; // hash of the requested element
siblingHashes: string[]; // hashes of all siblings on the path from requested element to the peak
peaksHashes: string[]; // hashes of all peaks
elementsCount: number; // number of all nodes in the mmr
}
interface ProofOptions {
elementsCount?: number; // You can provide elementsCount if you know its value, so it doesn't have to be fetched from the store
formattingOpts?: {
proof: FormattingOptions;
peaks: FormattingOptions;
};
}
formattingOpts.proof
apply to siblingHashes
and formattingOpts.peaks
apply to peaksHashes
.
verifyProof(proof: Proof, elementValue: string, options?: ProofOptions)
Verifies if a certain element in the MMR has a given value. Returns true
if the proof is valid, false
otherwise.
getProofs(elementsIds: number[], options?: ProofOptions)
Same as getProof
but for multiple elements. Returns an array of Proof
. Store is accessed for all proofs at once, so it's more efficient than calling getProof
multiple times.
verifyProofs(proofs: Proof[], elementsValues: string[], options?: ProofOptions)
Same as verifyProof
but for multiple elements. Returns an array of booleans. Store is accessed for all proofs at once, so it's more efficient than calling verifyProof
multiple times.
getPeaks(options?: PeaksOptions)
Returns an array of hashes of all peaks in the MMR. The return type is promise of string[]
.
interface PeaksOptions {
elementsCount?: number; // You can provide elementsCount if you know its value, so it doesn't have to be fetched from the store
formattingOpts?: FormattingOptions;
}
bagThePeaks(elementsCount?: number)
Bags all peaks in the MMR and returns the final hash of type promise of string
.
You can provide elementsCount
if you know its value, so it doesn't have to be fetched from the store.
calculateRootHash(bag: string, leafCount: number)
Calculates the root hash of the MMR based on the hash returned from bagThePeaks
function and the size of the MMR. Returns the promise of string
.
retrievePeaksHashes(peaksIdxs: number[], formattingOptions?: FormattingOptions)
Returns promise of an array of hashes of peaks with given indexes. If formattingOptions
are provided, the array will be formatted according to them.
clear()
Clears all the MMR data from the store.
All helper functions are static.
mapLeafIndexToElementIndex(leafIndex: number)
Converts leaf index (0-based) to element index.
Table of first few values:
leafIndex | elementIndex |
---|---|
0 | 1 |
1 | 2 |
2 | 4 |
3 | 5 |
4 | 8 |
mapElementIndexToLeafIndex(elementIndex: number)
Converts element index to leaf index (0-based). If the element is not a leaf, it will throw an error.
In some cases you may want peaks and siblings arrays to have a constant size between all requests. In that case you can set formatting options and provide nullValue
that will be added at the end of an array if it's shorter than outputSize
. If the array is longer than outputSize
, it will throw an error.
interface FormattingOptions {
outputSize: number; // size of the output array
nullValue: string; // value with which the array will be filled
}
For example this code
const mmr = new Mmr(store, hasher);
await mmr.append("0x1");
await mmr.append("0x2");
await mmr.append("0x3");
const formattingOptions = {
nullValue: `0x0`,
outputSize: 4,
};
const options = {
formattingOpts: {
peaks: formattingOptions,
proof: formattingOptions,
},
};
const proof = await mmr.getProof(2, options);
console.log(proof.peaksHashes);
without formatting options would return
["0xe90b7bce...", "0x3"]
but with formatting options it will return
["0xe90b7bce...", "0x3", "0x0", "0x0"]
(0xe90b7bce...
is just a hash("0x1", "0x2")
)
4.2.3 (2023-10-06)
Note: Version bump only for package accumulators
FAQs
A TypeScript implementation of Merkle Mountain Ranges
The npm package @accumulators/merkle-mountain-range receives a total of 10 weekly downloads. As such, @accumulators/merkle-mountain-range popularity was classified as not popular.
We found that @accumulators/merkle-mountain-range demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.
Security News
The Linux Foundation is warning open source developers that compliance with global sanctions is mandatory, highlighting legal risks and restrictions on contributions.
Security News
Maven Central now validates Sigstore signatures, making it easier for developers to verify the provenance of Java packages.