sort leaves option
This commit is contained in:
parent
d84aa0e8a9
commit
882236e603
52
README.md
52
README.md
|
@ -91,7 +91,7 @@ Output
|
|||
|
||||
## Documentation
|
||||
|
||||
<!-- :%s// -->
|
||||
<!-- :%s/// -->
|
||||
<!-- :%s/\[Options\]()/\[Options\](#options) -->
|
||||
|
||||
## Class
|
||||
|
@ -116,7 +116,8 @@ Class reprensenting a Merkle Tree
|
|||
* [isBitcoinTree](#isbitcointree)
|
||||
* [layers](#layers)
|
||||
* [leaves](#leaves)
|
||||
* [sort](#sort)
|
||||
* [sortLeaves](#sortleaves)
|
||||
* [sortPairs](#sortpairs)
|
||||
|
||||
### Methods
|
||||
|
||||
|
@ -133,13 +134,15 @@ Class reprensenting a Merkle Tree
|
|||
* [bufferify](#bufferify)
|
||||
* [print](#print-1)
|
||||
|
||||
---
|
||||
|
||||
## Constructors
|
||||
|
||||
<a id="constructor"></a>
|
||||
|
||||
### constructor
|
||||
|
||||
⊕ **new MerkleTree**(leaves: *`any`*, hashAlgorithm: *`any`*, options?: *[Options](#options)
|
||||
⊕ **new MerkleTree**(leaves: *`any`*, hashAlgorithm: *`any`*, options?: *[Options]()
|
||||
|
||||
*__desc__*: Constructs a Merkle Tree. All nodes and leaves are stored as Buffers. Lonely leaf nodes are promoted to the next level up without being hashed again.
|
||||
|
||||
|
@ -164,10 +167,12 @@ const tree = new MerkleTree(leaves, sha256)
|
|||
| ------ | ------ | ------ | ------ |
|
||||
| leaves | `any` | - | Array of hashed leaves. Each leaf must be a Buffer. |
|
||||
| hashAlgorithm | `any` | - | Algorithm used for hashing leaves and nodes |
|
||||
| `Default value` options | [Options](#options) | {} as any | Additional options |
|
||||
| `Default value` options | [Options]() | {} as any | Additional options |
|
||||
|
||||
**Returns:** [MerkleTree]()
|
||||
|
||||
___
|
||||
|
||||
## Properties
|
||||
|
||||
<a id="duplicateodd"></a>
|
||||
|
@ -223,11 +228,18 @@ ___
|
|||
**● leaves**: *`any`[]*
|
||||
|
||||
___
|
||||
<a id="sort"></a>
|
||||
<a id="sortleaves"></a>
|
||||
|
||||
### sort
|
||||
### sortLeaves
|
||||
|
||||
**● sort**: *`boolean`*
|
||||
**● sortLeaves**: *`boolean`*
|
||||
|
||||
___
|
||||
<a id="sortpairs"></a>
|
||||
|
||||
### sortPairs
|
||||
|
||||
**● sortPairs**: *`boolean`*
|
||||
|
||||
___
|
||||
|
||||
|
@ -432,6 +444,16 @@ ___
|
|||
|
||||
## Options
|
||||
|
||||
### Properties
|
||||
|
||||
* [duplicateOdd](#duplicateodd)
|
||||
* [hashLeaves](#hashleaves)
|
||||
* [isBitcoinTree](#isbitcointree)
|
||||
* [sortLeaves](#sortleaves)
|
||||
* [sortPairs](#sortpairs)
|
||||
|
||||
---
|
||||
|
||||
## Properties
|
||||
|
||||
<a id="duplicateodd"></a>
|
||||
|
@ -461,14 +483,22 @@ ___
|
|||
If set to `true`, constructs the Merkle Tree using the [Bitcoin Merkle Tree implementation](http://www.righto.com/2014/02/bitcoin-mining-hard-way-algorithms.html). Enable it when you need to replicate Bitcoin constructed Merkle Trees. In Bitcoin Merkle Trees, single nodes are combined with themselves, and each output hash is hashed again.
|
||||
|
||||
___
|
||||
<a id="sort"></a>
|
||||
<a id="sortleaves"></a>
|
||||
|
||||
### sort
|
||||
### sortLeaves
|
||||
|
||||
**● sort**: *`boolean`*
|
||||
**● sortLeaves**: *`boolean`*
|
||||
|
||||
If set to `true`, the leaves and hashing pairs will be sorted.
|
||||
If set to `true`, the leaves will be sorted.
|
||||
|
||||
___
|
||||
<a id="sortpairs"></a>
|
||||
|
||||
### sortPairs
|
||||
|
||||
**● sortPairs**: *`boolean`*
|
||||
|
||||
If set to `true`, the hashing pairs will be sorted.
|
||||
|
||||
## Test
|
||||
|
||||
|
|
|
@ -5,8 +5,10 @@ interface Options {
|
|||
hashLeaves: boolean;
|
||||
/** If set to `true`, constructs the Merkle Tree using the [Bitcoin Merkle Tree implementation](http://www.righto.com/2014/02/bitcoin-mining-hard-way-algorithms.html). Enable it when you need to replicate Bitcoin constructed Merkle Trees. In Bitcoin Merkle Trees, single nodes are combined with themselves, and each output hash is hashed again. */
|
||||
isBitcoinTree: boolean;
|
||||
/** If set to `true`, the leaves and hashing pairs will be sorted. */
|
||||
sort: boolean;
|
||||
/** If set to `true`, the leaves will be sorted. */
|
||||
sortLeaves: boolean;
|
||||
/** If set to `true`, the hashing pairs will be sorted. */
|
||||
sortPairs: boolean;
|
||||
}
|
||||
/**
|
||||
* Class reprensenting a Merkle Tree
|
||||
|
@ -19,7 +21,8 @@ export declare class MerkleTree {
|
|||
isBitcoinTree: boolean;
|
||||
leaves: any[];
|
||||
layers: any[];
|
||||
sort: boolean;
|
||||
sortLeaves: boolean;
|
||||
sortPairs: boolean;
|
||||
/**
|
||||
* @desc Constructs a Merkle Tree.
|
||||
* All nodes and leaves are stored as Buffers.
|
||||
|
|
|
@ -34,13 +34,17 @@ var MerkleTree = /** @class */ (function () {
|
|||
if (options === void 0) { options = {}; }
|
||||
this.isBitcoinTree = !!options.isBitcoinTree;
|
||||
this.hashLeaves = !!options.hashLeaves;
|
||||
this.sort = !!options.sort;
|
||||
this.sortLeaves = !!options.sortLeaves;
|
||||
this.sortPairs = !!options.sortPairs;
|
||||
this.duplicateOdd = !!options.duplicateOdd;
|
||||
this.hashAlgo = bufferifyFn(hashAlgorithm);
|
||||
if (this.hashLeaves) {
|
||||
leaves = leaves.map(this.hashAlgo);
|
||||
}
|
||||
this.leaves = leaves.map(bufferify);
|
||||
if (this.sortLeaves) {
|
||||
this.leaves = this.leaves.sort(Buffer.compare);
|
||||
}
|
||||
this.layers = [this.leaves];
|
||||
this.createHashes(this.leaves);
|
||||
}
|
||||
|
@ -74,20 +78,17 @@ var MerkleTree = /** @class */ (function () {
|
|||
var left = nodes[i];
|
||||
var right = i + 1 == nodes.length ? left : nodes[i + 1];
|
||||
var data = null;
|
||||
var combined = null;
|
||||
if (this.isBitcoinTree) {
|
||||
var combined = [reverse(left), reverse(right)];
|
||||
if (this.sort) {
|
||||
combined.sort(Buffer.compare);
|
||||
}
|
||||
data = Buffer.concat(combined);
|
||||
combined = [reverse(left), reverse(right)];
|
||||
}
|
||||
else {
|
||||
var combined = [left, right];
|
||||
if (this.sort) {
|
||||
combined = [left, right];
|
||||
}
|
||||
if (this.sortPairs) {
|
||||
combined.sort(Buffer.compare);
|
||||
}
|
||||
data = Buffer.concat(combined);
|
||||
}
|
||||
var hash = this.hashAlgo(data);
|
||||
// double hash if bitcoin tree
|
||||
if (this.isBitcoinTree) {
|
||||
|
|
31
index.ts
31
index.ts
|
@ -9,8 +9,10 @@ interface Options {
|
|||
hashLeaves: boolean
|
||||
/** If set to `true`, constructs the Merkle Tree using the [Bitcoin Merkle Tree implementation](http://www.righto.com/2014/02/bitcoin-mining-hard-way-algorithms.html). Enable it when you need to replicate Bitcoin constructed Merkle Trees. In Bitcoin Merkle Trees, single nodes are combined with themselves, and each output hash is hashed again. */
|
||||
isBitcoinTree: boolean
|
||||
/** If set to `true`, the leaves and hashing pairs will be sorted. */
|
||||
sort: boolean
|
||||
/** If set to `true`, the leaves will be sorted. */
|
||||
sortLeaves: boolean
|
||||
/** If set to `true`, the hashing pairs will be sorted. */
|
||||
sortPairs: boolean
|
||||
}
|
||||
|
||||
|
||||
|
@ -25,7 +27,8 @@ export class MerkleTree {
|
|||
isBitcoinTree: boolean
|
||||
leaves: any[]
|
||||
layers: any[]
|
||||
sort: boolean
|
||||
sortLeaves: boolean
|
||||
sortPairs: boolean
|
||||
|
||||
/**
|
||||
* @desc Constructs a Merkle Tree.
|
||||
|
@ -52,7 +55,8 @@ export class MerkleTree {
|
|||
constructor(leaves, hashAlgorithm, options:Options={} as any) {
|
||||
this.isBitcoinTree = !!options.isBitcoinTree
|
||||
this.hashLeaves = !!options.hashLeaves
|
||||
this.sort = !!options.sort
|
||||
this.sortLeaves = !!options.sortLeaves
|
||||
this.sortPairs = !!options.sortPairs
|
||||
this.duplicateOdd = !!options.duplicateOdd
|
||||
this.hashAlgo = bufferifyFn(hashAlgorithm)
|
||||
if (this.hashLeaves) {
|
||||
|
@ -60,6 +64,10 @@ export class MerkleTree {
|
|||
}
|
||||
|
||||
this.leaves = leaves.map(bufferify)
|
||||
if (this.sortLeaves) {
|
||||
this.leaves = this.leaves.sort(Buffer.compare)
|
||||
}
|
||||
|
||||
this.layers = [this.leaves]
|
||||
this.createHashes(this.leaves)
|
||||
}
|
||||
|
@ -101,22 +109,19 @@ export class MerkleTree {
|
|||
const left = nodes[i]
|
||||
const right = i + 1 == nodes.length ? left : nodes[i + 1];
|
||||
let data = null
|
||||
let combined = null
|
||||
|
||||
if (this.isBitcoinTree) {
|
||||
let combined = [reverse(left), reverse(right)]
|
||||
if (this.sort) {
|
||||
combined.sort(Buffer.compare)
|
||||
}
|
||||
|
||||
data = Buffer.concat(combined)
|
||||
combined = [reverse(left), reverse(right)]
|
||||
} else {
|
||||
let combined = [left, right]
|
||||
if (this.sort) {
|
||||
combined = [left, right]
|
||||
}
|
||||
|
||||
if (this.sortPairs) {
|
||||
combined.sort(Buffer.compare)
|
||||
}
|
||||
|
||||
data = Buffer.concat(combined)
|
||||
}
|
||||
|
||||
let hash = this.hashAlgo(data)
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "merkletreejs",
|
||||
"version": "0.1.0",
|
||||
"version": "0.1.1",
|
||||
"description": "Construct Merkle Trees and verify proofs",
|
||||
"main": "dist/index.js",
|
||||
"types": "typings/merkletreejs/*",
|
||||
|
|
|
@ -39,21 +39,31 @@ test('crypto-js - sha256', t => {
|
|||
t.equal(tree.getRoot().toString('hex'), root)
|
||||
})
|
||||
|
||||
test('sha256 with sort option', t => {
|
||||
test('sha256 with sort pairs option', t => {
|
||||
t.plan(1)
|
||||
|
||||
const leaves = ['a', 'b', 'c', 'd', 'e', 'f'].map(x => sha256(x))
|
||||
const tree = new MerkleTree(leaves, sha256, {sort: true})
|
||||
const tree = new MerkleTree(leaves, sha256, {sortPairs: true})
|
||||
const root = 'a30ba95a1a5dc397fe45ea20105363b08d682b864a28f4940419a29349a28325'
|
||||
|
||||
t.equal(tree.getRoot().toString('hex'), root)
|
||||
})
|
||||
|
||||
test('sha256 with sha256 leaves and sort option and duplicate odd option', t => {
|
||||
test('sha3 with sort leaves and sort pairs option', t => {
|
||||
t.plan(1)
|
||||
|
||||
const leaves = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'].map(x => sha3(x))
|
||||
const tree = new MerkleTree(leaves, sha3, {sortLeaves: true, sortPairs: true})
|
||||
const root = '60219f87561939610b484575e45c6e81156a53b86d7cd16640d930d14f21758e'
|
||||
|
||||
t.equal(tree.getRoot().toString('hex'), root)
|
||||
})
|
||||
|
||||
test('sha256 with sha256 leaves and sort pairs option and duplicate odd option', t => {
|
||||
t.plan(1)
|
||||
|
||||
const leaves = ['a', 'b', 'c', 'd', 'e', 'f'].map(x => sha256(x))
|
||||
const tree = new MerkleTree(leaves, sha256, {sort: true, duplicateOdd: true})
|
||||
const tree = new MerkleTree(leaves, sha256, {sortPairs: true, duplicateOdd: true})
|
||||
const root = 'a5260b2a7ec31584e5d5689a5628c2b3d949e2397334fd71c107478e5f887eaf'
|
||||
|
||||
t.equal(tree.getRoot().toString('hex'), root)
|
||||
|
|
Loading…
Reference in New Issue