Add static verify method
This commit is contained in:
parent
c9517a5005
commit
49ee00c1c0
|
@ -170,7 +170,7 @@ Class reprensenting a Merkle Tree
|
||||||
|
|
||||||
### constructor
|
### constructor
|
||||||
|
|
||||||
\+ **new MerkleTree**(`leaves`: any[], `hashAlgorithm`: any, `options`: [Options](#options)): *[MerkleTree](_index_.merkletree.md)*
|
\+ **new MerkleTree**(`leaves`: any[], `hashFn`: any, `options`: [Options](#options)): *[MerkleTree](_index_.merkletree.md)*
|
||||||
|
|
||||||
**`desc`** Constructs a Merkle Tree.
|
**`desc`** Constructs a Merkle Tree.
|
||||||
All nodes and leaves are stored as Buffers.
|
All nodes and leaves are stored as Buffers.
|
||||||
|
@ -196,7 +196,7 @@ const tree = new MerkleTree(leaves, sha256)
|
||||||
Name | Type | Default | Description |
|
Name | Type | Default | Description |
|
||||||
------ | ------ | ------ | ------ |
|
------ | ------ | ------ | ------ |
|
||||||
`leaves` | any[] | - | Array of hashed leaves. Each leaf must be a Buffer. |
|
`leaves` | any[] | - | Array of hashed leaves. Each leaf must be a Buffer. |
|
||||||
`hashAlgorithm` | any | SHA256 | Algorithm used for hashing leaves and nodes |
|
`hashFn` | any | SHA256 | Hash function to use for hashing leaves and nodes |
|
||||||
`options` | [Options](#options) | {} | Additional options |
|
`options` | [Options](#options) | {} | Additional options |
|
||||||
|
|
||||||
**Returns:** *[MerkleTree](_index_.merkletree.md)*
|
**Returns:** *[MerkleTree](_index_.merkletree.md)*
|
||||||
|
@ -973,7 +973,7 @@ ___
|
||||||
|
|
||||||
• **hashLeaves**? : *boolean*
|
• **hashLeaves**? : *boolean*
|
||||||
|
|
||||||
If set to `true`, the leaves will hashed using the set hashing algorithms.
|
If set to `true`, the leaves will hashed using the set hashing functions.
|
||||||
|
|
||||||
___
|
___
|
||||||
|
|
||||||
|
@ -1025,7 +1025,7 @@ npm test
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
As is, this implemenation is vulnerable to a [second pre-image attack](https://en.wikipedia.org/wiki/Merkle_tree#Second_preimage_attack). Use a difference hashing algorithm function for leaves and nodes, so that `H(x) != H'(x)`.
|
As is, this implemenation is vulnerable to a [second pre-image attack](https://en.wikipedia.org/wiki/Merkle_tree#Second_preimage_attack). Use a difference hashing function for leaves and nodes, so that `H(x) != H'(x)`.
|
||||||
|
|
||||||
Also, as is, this implementation is vulnerable to a forgery attack for an unbalanced tree, where the last leaf node can be duplicated to create an artificial balanced tree, resulting in the same Merkle root hash. Do not accept unbalanced tree to prevent this.
|
Also, as is, this implementation is vulnerable to a forgery attack for an unbalanced tree, where the last leaf node can be duplicated to create an artificial balanced tree, resulting in the same Merkle root hash. Do not accept unbalanced tree to prevent this.
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ var tree
|
||||||
function compute () {
|
function compute () {
|
||||||
const value = getInputValue()
|
const value = getInputValue()
|
||||||
const leaves = parseInput(value)
|
const leaves = parseInput(value)
|
||||||
const hash = getHashFn()
|
const hashFn = getHashFn()
|
||||||
const fillDefaultHash = getDefaultFillHashInput()
|
const fillDefaultHash = getDefaultFillHashInput()
|
||||||
const _options = Object.assign({}, options, {
|
const _options = Object.assign({}, options, {
|
||||||
fillDefaultHash: options.fillDefaultHash ? fillDefaultHash : undefined
|
fillDefaultHash: options.fillDefaultHash ? fillDefaultHash : undefined
|
||||||
|
@ -50,7 +50,7 @@ function compute () {
|
||||||
console.log('input leaves:', leaves)
|
console.log('input leaves:', leaves)
|
||||||
console.log('hash:', getHashType())
|
console.log('hash:', getHashType())
|
||||||
console.log('options:', _options)
|
console.log('options:', _options)
|
||||||
tree = new window.MerkleTree(leaves, hash, _options)
|
tree = new window.MerkleTree(leaves, hashFn, _options)
|
||||||
const hexRoot = tree.getHexRoot()
|
const hexRoot = tree.getHexRoot()
|
||||||
const hexLeaves = tree.getHexLeaves()
|
const hexLeaves = tree.getHexLeaves()
|
||||||
const hexLayers = tree.getHexLayers()
|
const hexLayers = tree.getHexLayers()
|
||||||
|
@ -111,13 +111,11 @@ function setVerified (verified) {
|
||||||
|
|
||||||
function verify () {
|
function verify () {
|
||||||
setVerified('')
|
setVerified('')
|
||||||
if (!tree) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const proof = getVerifyProof()
|
const proof = getVerifyProof()
|
||||||
const leaf = getVerifyLeaf()
|
const leaf = getVerifyLeaf()
|
||||||
const root = getVerifyRoot()
|
const root = getVerifyRoot()
|
||||||
const verified = tree.verify(proof, leaf, root)
|
const hashFn = getHashFn()
|
||||||
|
const verified = window.MerkleTree.verify(proof, leaf, root, hashFn, options)
|
||||||
setVerified(`${verified}`)
|
setVerified(`${verified}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "merkletreejs",
|
"name": "merkletreejs",
|
||||||
"version": "0.2.21",
|
"version": "0.2.22",
|
||||||
"description": "Construct Merkle Trees and verify proofs",
|
"description": "Construct Merkle Trees and verify proofs",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
|
|
|
@ -48,7 +48,7 @@ export class MerkleTree extends Base {
|
||||||
* All nodes and leaves are stored as Buffers.
|
* All nodes and leaves are stored as Buffers.
|
||||||
* Lonely leaf nodes are promoted to the next level up without being hashed again.
|
* Lonely leaf nodes are promoted to the next level up without being hashed again.
|
||||||
* @param {Buffer[]} leaves - Array of hashed leaves. Each leaf must be a Buffer.
|
* @param {Buffer[]} leaves - Array of hashed leaves. Each leaf must be a Buffer.
|
||||||
* @param {Function} hashFunction - Algorithm used for hashing leaves and nodes
|
* @param {Function} hashFunction - Hash function to use for hashing leaves and nodes
|
||||||
* @param {Object} options - Additional options
|
* @param {Object} options - Additional options
|
||||||
* @example
|
* @example
|
||||||
*```js
|
*```js
|
||||||
|
@ -376,6 +376,9 @@ export class MerkleTree extends Base {
|
||||||
*```
|
*```
|
||||||
*/
|
*/
|
||||||
getProof (leaf: Buffer | string, index?: number):any[] {
|
getProof (leaf: Buffer | string, index?: number):any[] {
|
||||||
|
if (typeof leaf === 'undefined') {
|
||||||
|
throw new Error('leaf is required')
|
||||||
|
}
|
||||||
leaf = this.bufferify(leaf)
|
leaf = this.bufferify(leaf)
|
||||||
const proof = []
|
const proof = []
|
||||||
|
|
||||||
|
@ -892,6 +895,27 @@ export class MerkleTree extends Base {
|
||||||
return objs[0]
|
return objs[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* verify
|
||||||
|
* @desc Returns true if the proof path (array of hashes) can connect the target node
|
||||||
|
* to the Merkle root.
|
||||||
|
* @param {Object[]} proof - Array of proof objects that should connect
|
||||||
|
* target node to Merkle root.
|
||||||
|
* @param {Buffer} targetNode - Target node Buffer
|
||||||
|
* @param {Buffer} root - Merkle root Buffer
|
||||||
|
* @param {Function} hashFunction - Hash function for hashing leaves and nodes
|
||||||
|
* @param {Object} options - Additional options
|
||||||
|
* @return {Boolean}
|
||||||
|
* @example
|
||||||
|
*```js
|
||||||
|
*const verified = MerkleTree.verify(proof, leaf, root, sha256, options)
|
||||||
|
*```
|
||||||
|
*/
|
||||||
|
static verify (proof: any[], targetNode: Buffer | string, root: Buffer | string, hashFn = SHA256, options: Options = {}):boolean {
|
||||||
|
const tree = new MerkleTree([], hashFn, options)
|
||||||
|
return tree.verify(proof, targetNode, root)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* getMultiProof
|
* getMultiProof
|
||||||
* @desc Returns the multiproof for given tree indices.
|
* @desc Returns the multiproof for given tree indices.
|
||||||
|
|
|
@ -88,6 +88,21 @@ test('sha256 with sort pairs option', t => {
|
||||||
t.equal(tree.getRoot().toString('hex'), root)
|
t.equal(tree.getRoot().toString('hex'), root)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('sha256 - static verify', t => {
|
||||||
|
t.plan(2)
|
||||||
|
|
||||||
|
const leaves = ['a', 'b', 'c'].map(x => sha256(Buffer.from(x)))
|
||||||
|
const tree = new MerkleTree(leaves, sha256)
|
||||||
|
const leaf = sha256(Buffer.from('a'))
|
||||||
|
const badLeaf = sha256(Buffer.from('o'))
|
||||||
|
const proof = tree.getProof(leaf)
|
||||||
|
const badProof = tree.getProof(badLeaf)
|
||||||
|
const root = tree.getRoot()
|
||||||
|
|
||||||
|
t.equal(MerkleTree.verify(proof, leaf, root, sha256), true)
|
||||||
|
t.equal(MerkleTree.verify(badProof, leaf, root, sha256), false)
|
||||||
|
})
|
||||||
|
|
||||||
test('sha256 verify with positional hex proof and no pairSort', t => {
|
test('sha256 verify with positional hex proof and no pairSort', t => {
|
||||||
t.plan(1)
|
t.plan(1)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue