test/specs/generic/utils/merkle/MerklePath.spec.js
describe('MerklePath', () => {
const values = [
BufferUtils.fromAscii('0'),
BufferUtils.fromAscii('1'),
BufferUtils.fromAscii('2'),
BufferUtils.fromAscii('3'),
BufferUtils.fromAscii('4'),
BufferUtils.fromAscii('5'),
BufferUtils.fromAscii('6')
];
it('correctly computes an empty proof', () => {
const root = MerkleTree.computeRoot([]);
const proof = MerklePath.compute([], values[0]);
expect(proof.nodes.length).toBe(0);
expect(root.equals(proof.computeRoot(values[0]))).toBe(false);
});
it('correctly computes a simple proof', () => {
const v4 = values.slice(0, 4);
/*
* (X) should be the nodes included in the proof.
* *X* marks the values to be proven.
* h6
* / \
* h4 (h5)
* / \ / \
* (h0) h1 h2 h3
* | | | |
* v0 *v1* v2 v3
*/
const root = MerkleTree.computeRoot(v4);
const proof = MerklePath.compute(v4, values[1]);
expect(proof.nodes.length).toBe(2);
expect(root.equals(proof.computeRoot(values[1]))).toBe(true);
});
it('correctly computes more complex proofs', () => {
/*
* h4
* / \
* h3 (h2)
* / \ |
* (h0) h1 v2
* | |
* v0 *v1*
*/
const v3 = values.slice(0, 3);
let root = MerkleTree.computeRoot(v3);
let proof = MerklePath.compute(v3, values[1]);
expect(proof.nodes.length).toBe(2, 'scenario 1');
expect(root.equals(proof.computeRoot(values[1]))).toBe(true, 'scenario 1');
/*
* h4
* / \
* (h3) h2
* / \ |
* h0 h1 *v2*
* | |
* v0 v1
*/
proof = MerklePath.compute(v3, values[2]);
expect(proof.nodes.length).toBe(1, 'scenario 2');
expect(root.equals(proof.computeRoot(values[2]))).toBe(true, 'scenario 2');
/*
* h6
* / \
* (h4) h5
* / \ / \
* h0 h1 (h2) h3
* / \ / \ / \ |
* v0 v1 v2 v3 v4 v5 *v6*
*/
const v7 = values;
root = MerkleTree.computeRoot(v7);
proof = MerklePath.compute(v7, values[6]);
expect(proof.nodes.length).toBe(2, 'scenario 3');
expect(root.equals(proof.computeRoot(values[6]))).toBe(true, 'scenario 3');
/*
* h6
* / \
* h4 (h5)
* / \ / \
* (h0) h1 h2 h3
* / \ / \ / \ |
* v0 v1 *v2* (v3) v4 v5 v6
*/
proof = MerklePath.compute(v7, values[2]);
expect(proof.nodes.length).toBe(3, 'scenario 4');
expect(root.equals(proof.computeRoot(values[2]))).toBe(true, 'scenario 4');
/*
* h6
* / \
* (h4) h5
* / \ / \
* h0 h1 h2 (h3)
* / \ / \ / \ |
* v0 v1 v2 v3 (v4) *v5* v6
*/
proof = MerklePath.compute(v7, values[5]);
expect(proof.nodes.length).toBe(3, 'scenario 5');
expect(root.equals(proof.computeRoot(values[5]))).toBe(true, 'scenario 5');
});
it('correctly serializes and unserializes proof', () => {
const proof = MerklePath.compute(values, values[6]);
const serialization = proof.serialize();
expect(serialization.byteLength).toBe(proof.serializedSize);
const proof2 = MerklePath.unserialize(serialization);
expect(proof.equals(proof)).toBe(true);
expect(proof.equals(proof2)).toBe(true);
});
});