diff --git a/benchmarks/checkpointing.js b/benchmarks/checkpointing.js deleted file mode 100644 index 644fb82..0000000 --- a/benchmarks/checkpointing.js +++ /dev/null @@ -1,52 +0,0 @@ -var iterations = 500 -var samples = 20 - -var async = require('async') -var crypto = require('crypto') -var Trie = require('../index.js') -var i - -function iterTest (numOfIter, cb) { - var vals = [] - var keys = [] - - for (i = 0; i <= numOfIter; i++) { - vals.push(crypto.pseudoRandomBytes(32)) - keys.push(crypto.pseudoRandomBytes(32)) - } - - var hrstart = process.hrtime() - var numOfOps = 0 - var trie = new Trie() - - for (i = 0; i < numOfIter; i++) { - trie.put(vals[i], keys[i], function () { - trie.checkpoint() - trie.get('test', function () { - numOfOps++ - if (numOfOps === numOfIter) { - var hrend = process.hrtime(hrstart) - cb(hrend) - } - }) - }) - } -} - -i = 0 -var avg = [0, 0] - -async.whilst(function () { - i++ - return i <= samples -}, function (done) { - iterTest(iterations, function (hrend) { - avg[0] += hrend[0] - avg[1] += hrend[1] - - console.info('Execution time (hr): %ds %dms', hrend[0], hrend[1] / 1000000) - done() - }) -}, function () { - console.info('Average Execution time (hr): %ds %dms', avg[0] / samples, avg[1] / 1000000 / samples) -}) diff --git a/benchmarks/checkpointing.ts b/benchmarks/checkpointing.ts new file mode 100644 index 0000000..39c8b41 --- /dev/null +++ b/benchmarks/checkpointing.ts @@ -0,0 +1,60 @@ +import * as async from 'async' +import * as crypto from 'crypto' +const Trie = require('../dist/index.js').CheckpointTrie + +let iterations = 500 +let samples = 20 +let i = 0 + +function iterTest(numOfIter: number, cb: Function) { + let vals = [] as any + let keys = [] as any + + for (i = 0; i <= numOfIter; i++) { + vals.push(crypto.pseudoRandomBytes(32)) + keys.push(crypto.pseudoRandomBytes(32)) + } + + let hrstart = process.hrtime() + let numOfOps = 0 + let trie = new Trie() + + for (i = 0; i < numOfIter; i++) { + trie.put(vals[i], keys[i], function () { + trie.checkpoint() + trie.get(Buffer.from('test'), function () { + numOfOps++ + if (numOfOps === numOfIter) { + const hrend = process.hrtime(hrstart) + cb(hrend) + } + }) + }) + } +} + +i = 0 +let avg = [0, 0] + +async.whilst( + function () { + i++ + return i <= samples + }, + function (done) { + iterTest(iterations, function (hrend: Array) { + avg[0] += hrend[0] + avg[1] += hrend[1] + + console.info('Execution time (hr): %ds %dms', hrend[0], hrend[1] / 1000000) + done() + }) + }, + function () { + console.info( + 'Average Execution time (hr): %ds %dms', + avg[0] / samples, + avg[1] / 1000000 / samples, + ) + }, +) diff --git a/benchmarks/index.ts b/benchmarks/index.ts new file mode 100644 index 0000000..e9424c7 --- /dev/null +++ b/benchmarks/index.ts @@ -0,0 +1,2 @@ +require('./checkpointing') +require('./random') diff --git a/benchmarks/random.js b/benchmarks/random.ts similarity index 75% rename from benchmarks/random.js rename to benchmarks/random.ts index 071a994..7c3f749 100644 --- a/benchmarks/random.js +++ b/benchmarks/random.ts @@ -1,15 +1,15 @@ // https://github.com/ethereum/wiki/wiki/Benchmarks 'use strict' -const Trie = require('../') -const ethUtil = require('ethereumjs-util') -const async = require('async') +import * as async from 'async' +import * as ethUtil from 'ethereumjs-util' +const Trie = require('../dist/index.js').BaseTrie const ROUNDS = 1000 const SYMMETRIC = true const ERA_SIZE = 1000 let trie = new Trie() -let seed = new Buffer(32).fill(0) +let seed = Buffer.alloc(32).fill(0) let testName = 'rounds ' + ROUNDS + ' ' + ERA_SIZE + ' ' + SYMMETRIC ? 'sys' : 'rand' console.time(testName) @@ -17,7 +17,7 @@ run(() => { console.timeEnd(testName) }) -function run (cb) { +function run(cb: any) { let i = 0 async.whilst( () => { @@ -33,12 +33,13 @@ function run (cb) { trie.put(seed, val, genRoot) } - function genRoot () { + function genRoot() { if (i % ERA_SIZE === 0) { seed = trie.root } done() } - }, cb + }, + cb, ) } diff --git a/docs/classes/_basetrie_.trie.md b/docs/classes/_basetrie_.trie.md index 78cddf7..997ac8a 100644 --- a/docs/classes/_basetrie_.trie.md +++ b/docs/classes/_basetrie_.trie.md @@ -391,7 +391,7 @@ ___ ### del -▸ **del**(`key`: Buffer, `cb`: Function): *void* +▸ **del**(`key`: Buffer, `cb`: ErrorCallback): *void* *Defined in [baseTrie.ts:183](https://github.com/ethereumjs/merkle-patricia-tree/blob/master/src/baseTrie.ts#L183)* @@ -406,7 +406,7 @@ deletes a value given a `key` Name | Type | ------ | ------ | `key` | Buffer | -`cb` | Function | +`cb` | ErrorCallback | **Returns:** *void* @@ -459,7 +459,7 @@ ___ ### get -▸ **get**(`key`: Buffer, `cb`: Function): *void* +▸ **get**(`key`: Buffer, `cb`: BufferCallback): *void* *Defined in [baseTrie.ts:125](https://github.com/ethereumjs/merkle-patricia-tree/blob/master/src/baseTrie.ts#L125)* @@ -474,7 +474,7 @@ Gets a value given a `key` Name | Type | Description | ------ | ------ | ------ | `key` | Buffer | the key to search for | -`cb` | Function | A callback `Function` which is given the arguments `err` - for errors that may have occured and `value` - the found value in a `Buffer` or if no value was found `null` | +`cb` | BufferCallback | A callback `Function` which is given the arguments `err` - for errors that may have occured and `value` - the found value in a `Buffer` or if no value was found `null` | **Returns:** *void* @@ -482,7 +482,7 @@ ___ ### getRaw -▸ **getRaw**(`key`: Buffer, `cb`: Function): *void* +▸ **getRaw**(`key`: Buffer, `cb`: BufferCallback): *void* *Defined in [baseTrie.ts:208](https://github.com/ethereumjs/merkle-patricia-tree/blob/master/src/baseTrie.ts#L208)* @@ -495,7 +495,7 @@ Retrieves a value directly from key/value db. Name | Type | ------ | ------ | `key` | Buffer | -`cb` | Function | +`cb` | BufferCallback | **Returns:** *void* @@ -584,7 +584,7 @@ ___ ### `Static` prove -▸ **prove**(`trie`: [Trie](_basetrie_.trie.md), `key`: Buffer, `cb`: Function): *void* +▸ **prove**(`trie`: [Trie](_basetrie_.trie.md), `key`: Buffer, `cb`: ProveCallback): *void* *Defined in [baseTrie.ts:70](https://github.com/ethereumjs/merkle-patricia-tree/blob/master/src/baseTrie.ts#L70)* @@ -594,7 +594,7 @@ Name | Type | ------ | ------ | `trie` | [Trie](_basetrie_.trie.md) | `key` | Buffer | -`cb` | Function | +`cb` | ProveCallback | **Returns:** *void* @@ -602,7 +602,7 @@ ___ ### `Static` verifyProof -▸ **verifyProof**(`rootHash`: Buffer, `key`: Buffer, `proofNodes`: Buffer[], `cb`: Function): *void* +▸ **verifyProof**(`rootHash`: Buffer, `key`: Buffer, `proofNodes`: Buffer[], `cb`: BufferCallback): *void* *Defined in [baseTrie.ts:85](https://github.com/ethereumjs/merkle-patricia-tree/blob/master/src/baseTrie.ts#L85)* @@ -613,6 +613,6 @@ Name | Type | `rootHash` | Buffer | `key` | Buffer | `proofNodes` | Buffer[] | -`cb` | Function | +`cb` | BufferCallback | **Returns:** *void* diff --git a/docs/classes/_checkpointtrie_.checkpointtrie.md b/docs/classes/_checkpointtrie_.checkpointtrie.md index 93bb5aa..8aa1c02 100644 --- a/docs/classes/_checkpointtrie_.checkpointtrie.md +++ b/docs/classes/_checkpointtrie_.checkpointtrie.md @@ -189,7 +189,7 @@ ___ ▸ **_createScratchReadStream**(`scratch`: ScratchDB): *ScratchReadStream‹›* -*Defined in [checkpointTrie.ts:154](https://github.com/ethereumjs/merkle-patricia-tree/blob/master/src/checkpointTrie.ts#L154)* +*Defined in [checkpointTrie.ts:152](https://github.com/ethereumjs/merkle-patricia-tree/blob/master/src/checkpointTrie.ts#L152)* Returns a `ScratchReadStream` based on the state updates since checkpoint. @@ -301,7 +301,7 @@ ___ *Overrides [Trie](_basetrie_.trie.md).[_formatNode](_basetrie_.trie.md#_formatnode)* -*Defined in [checkpointTrie.ts:163](https://github.com/ethereumjs/merkle-patricia-tree/blob/master/src/checkpointTrie.ts#L163)* +*Defined in [checkpointTrie.ts:161](https://github.com/ethereumjs/merkle-patricia-tree/blob/master/src/checkpointTrie.ts#L161)* **Parameters:** @@ -563,7 +563,7 @@ ___ ### del -▸ **del**(`key`: Buffer, `cb`: Function): *void* +▸ **del**(`key`: Buffer, `cb`: ErrorCallback): *void* *Inherited from [Trie](_basetrie_.trie.md).[del](_basetrie_.trie.md#del)* @@ -580,7 +580,7 @@ deletes a value given a `key` Name | Type | ------ | ------ | `key` | Buffer | -`cb` | Function | +`cb` | ErrorCallback | **Returns:** *void* @@ -637,7 +637,7 @@ ___ ### get -▸ **get**(`key`: Buffer, `cb`: Function): *void* +▸ **get**(`key`: Buffer, `cb`: BufferCallback): *void* *Inherited from [Trie](_basetrie_.trie.md).[get](_basetrie_.trie.md#get)* @@ -654,7 +654,7 @@ Gets a value given a `key` Name | Type | Description | ------ | ------ | ------ | `key` | Buffer | the key to search for | -`cb` | Function | A callback `Function` which is given the arguments `err` - for errors that may have occured and `value` - the found value in a `Buffer` or if no value was found `null` | +`cb` | BufferCallback | A callback `Function` which is given the arguments `err` - for errors that may have occured and `value` - the found value in a `Buffer` or if no value was found `null` | **Returns:** *void* @@ -662,7 +662,7 @@ ___ ### getRaw -▸ **getRaw**(`key`: Buffer, `cb`: Function): *void* +▸ **getRaw**(`key`: Buffer, `cb`: BufferCallback): *void* *Inherited from [Trie](_basetrie_.trie.md).[getRaw](_basetrie_.trie.md#getraw)* @@ -677,7 +677,7 @@ Retrieves a value directly from key/value db. Name | Type | ------ | ------ | `key` | Buffer | -`cb` | Function | +`cb` | BufferCallback | **Returns:** *void* @@ -794,7 +794,7 @@ ___ ### `Static` prove -▸ **prove**(`trie`: [Trie](_basetrie_.trie.md), `key`: Buffer, `cb`: Function): *void* +▸ **prove**(`trie`: [Trie](_basetrie_.trie.md), `key`: Buffer, `cb`: ProveCallback): *void* *Inherited from [Trie](_basetrie_.trie.md).[prove](_basetrie_.trie.md#static-prove)* @@ -806,7 +806,7 @@ Name | Type | ------ | ------ | `trie` | [Trie](_basetrie_.trie.md) | `key` | Buffer | -`cb` | Function | +`cb` | ProveCallback | **Returns:** *void* @@ -814,7 +814,7 @@ ___ ### `Static` verifyProof -▸ **verifyProof**(`rootHash`: Buffer, `key`: Buffer, `proofNodes`: Buffer[], `cb`: Function): *void* +▸ **verifyProof**(`rootHash`: Buffer, `key`: Buffer, `proofNodes`: Buffer[], `cb`: BufferCallback): *void* *Inherited from [Trie](_basetrie_.trie.md).[verifyProof](_basetrie_.trie.md#static-verifyproof)* @@ -827,6 +827,6 @@ Name | Type | `rootHash` | Buffer | `key` | Buffer | `proofNodes` | Buffer[] | -`cb` | Function | +`cb` | BufferCallback | **Returns:** *void* diff --git a/docs/classes/_secure_.securetrie.md b/docs/classes/_secure_.securetrie.md index 6e48425..680f127 100644 --- a/docs/classes/_secure_.securetrie.md +++ b/docs/classes/_secure_.securetrie.md @@ -205,7 +205,7 @@ ___ *Inherited from [CheckpointTrie](_checkpointtrie_.checkpointtrie.md).[_createScratchReadStream](_checkpointtrie_.checkpointtrie.md#private-_createscratchreadstream)* -*Defined in [checkpointTrie.ts:154](https://github.com/ethereumjs/merkle-patricia-tree/blob/master/src/checkpointTrie.ts#L154)* +*Defined in [checkpointTrie.ts:152](https://github.com/ethereumjs/merkle-patricia-tree/blob/master/src/checkpointTrie.ts#L152)* Returns a `ScratchReadStream` based on the state updates since checkpoint. @@ -323,7 +323,7 @@ ___ *Overrides [Trie](_basetrie_.trie.md).[_formatNode](_basetrie_.trie.md#_formatnode)* -*Defined in [checkpointTrie.ts:163](https://github.com/ethereumjs/merkle-patricia-tree/blob/master/src/checkpointTrie.ts#L163)* +*Defined in [checkpointTrie.ts:161](https://github.com/ethereumjs/merkle-patricia-tree/blob/master/src/checkpointTrie.ts#L161)* **Parameters:** @@ -647,7 +647,7 @@ ___ ### get -▸ **get**(`key`: Buffer, `cb`: Function): *void* +▸ **get**(`key`: Buffer, `cb`: BufferCallback): *void* *Overrides [Trie](_basetrie_.trie.md).[get](_basetrie_.trie.md#get)* @@ -658,7 +658,7 @@ ___ Name | Type | ------ | ------ | `key` | Buffer | -`cb` | Function | +`cb` | BufferCallback | **Returns:** *void* @@ -666,7 +666,7 @@ ___ ### getRaw -▸ **getRaw**(`key`: Buffer, `cb`: Function): *void* +▸ **getRaw**(`key`: Buffer, `cb`: BufferCallback): *void* *Inherited from [Trie](_basetrie_.trie.md).[getRaw](_basetrie_.trie.md#getraw)* @@ -681,7 +681,7 @@ Retrieves a value directly from key/value db. Name | Type | ------ | ------ | `key` | Buffer | -`cb` | Function | +`cb` | BufferCallback | **Returns:** *void* @@ -799,7 +799,7 @@ ___ ### `Static` prove -▸ **prove**(`trie`: [SecureTrie](_secure_.securetrie.md), `key`: Buffer, `cb`: Function): *void* +▸ **prove**(`trie`: [SecureTrie](_secure_.securetrie.md), `key`: Buffer, `cb`: ProveCallback): *void* *Overrides [Trie](_basetrie_.trie.md).[prove](_basetrie_.trie.md#static-prove)* @@ -811,7 +811,7 @@ Name | Type | ------ | ------ | `trie` | [SecureTrie](_secure_.securetrie.md) | `key` | Buffer | -`cb` | Function | +`cb` | ProveCallback | **Returns:** *void* @@ -819,7 +819,7 @@ ___ ### `Static` verifyProof -▸ **verifyProof**(`rootHash`: Buffer, `key`: Buffer, `proof`: Buffer[], `cb`: Function): *void* +▸ **verifyProof**(`rootHash`: Buffer, `key`: Buffer, `proof`: Buffer[], `cb`: BufferCallback): *void* *Overrides [Trie](_basetrie_.trie.md).[verifyProof](_basetrie_.trie.md#static-verifyproof)* @@ -832,6 +832,6 @@ Name | Type | `rootHash` | Buffer | `key` | Buffer | `proof` | Buffer[] | -`cb` | Function | +`cb` | BufferCallback | **Returns:** *void* diff --git a/karma.conf.js b/karma.conf.js index a46e6cb..d872533 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -1,16 +1,22 @@ -module.exports = function(config) { +module.exports = function (config) { config.set({ - browserDisconnectTimeout: 100000, - browserNoActivityTimeout: 100000, - frameworks: ['browserify', 'tap'], - plugins: ['karma-browserify', 'karma-tap', 'karma-chrome-launcher', 'karma-firefox-launcher'], - files: ['./test/*.js'], + frameworks: ['karma-typescript', 'tap'], + files: ['src/**/*.ts', 'test/**/*.ts'], preprocessors: { - './dist/**/*.js': ['browserify'], - './test/**/*.js': ['browserify'], + '**/*.ts': ['karma-typescript'], + }, + plugins: ['karma-typescript', 'karma-tap', 'karma-chrome-launcher', 'karma-firefox-launcher'], + karmaTypescriptConfig: { + bundlerOptions: { + entrypoints: /\.spec\.ts$/, + }, }, colors: true, browsers: ['FirefoxHeadless', 'ChromeHeadless'], singleRun: true, + concurrency: Infinity, + // Fail after timeout + browserDisconnectTimeout: 100000, + browserNoActivityTimeout: 100000, }) } diff --git a/package.json b/package.json index 89f4a42..42d18c7 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "dist/**/*" ], "scripts": { + "benchmarks": "npm run build && ts-node benchmarks/index.ts", "build": "ethereumjs-config-build", "prepublishOnly": "npm run test && npm run build", "coverage": "nyc --reporter=lcov npm run test:node", @@ -22,7 +23,7 @@ "tsc": "ethereumjs-config-tsc", "test": "npm run test:node && npm run test:browser", "test:browser": "npm run build && karma start karma.conf.js", - "test:node": "npm run build && tape test/*.js | tap-prettify -" + "test:node": "npm run build && tape -r ts-node/register test/*.ts | tap-prettify -" }, "husky": { "hooks": { @@ -48,6 +49,7 @@ ], "license": "MPL-2.0", "dependencies": { + "@types/async": "^3.0.8", "async": "^2.6.1", "ethereumjs-util": "^6.1.0", "level-mem": "^3.0.1", @@ -63,21 +65,23 @@ "@ethereumjs/config-tslint": "^1.1.1", "@types/bn.js": "^4.11.5", "@types/levelup": "^3.1.1", + "@types/tape": "^4.2.34", "browserify": "^16.5.0", "husky": "^4.2.3", "karma": "^4.4.1", - "karma-browserify": "^7.0.0", "karma-chrome-launcher": "^3.1.0", "karma-firefox-launcher": "^1.3.0", "karma-tap": "^4.2.0", + "karma-typescript": "^5.0.1", "nyc": "^15.0.0", "prettier": "^2.0.2", "tap-prettify": "^0.0.2", - "tape": "^4.13.0", + "tape": "^4.13.2", + "ts-node": "^8.8.1", "tslint": "^5.18.0", "typedoc": "next", "typedoc-plugin-markdown": "^2.2.16", - "typescript": "^3.5.3", + "typescript": "^3.7.5", "typestrict": "^1.0.2" }, "contributors": [ diff --git a/src/baseTrie.ts b/src/baseTrie.ts index abaab5e..1937afd 100644 --- a/src/baseTrie.ts +++ b/src/baseTrie.ts @@ -5,7 +5,7 @@ import { TrieReadStream as ReadStream } from './readStream' import { PrioritizedTaskExecutor } from './prioritizedTaskExecutor' import { callTogether } from './util/async' import { stringToNibbles, matchingNibbleLength, doKeysMatch } from './util/nibbles' -import { ErrorCallback } from './types' +import { BufferCallback, ProveCallback, ErrorCallback } from './types' import { TrieNode, decodeNode, @@ -62,12 +62,12 @@ export class Trie { } } - proofTrie.db.batch(opStack, (e?: Error) => { - cb(e, proofTrie) + proofTrie.db.batch(opStack, (err) => { + cb(err, proofTrie) }) } - static prove(trie: Trie, key: Buffer, cb: Function) { + static prove(trie: Trie, key: Buffer, cb: ProveCallback) { trie.findPath(key, function ( err: Error, node: TrieNode, @@ -82,13 +82,13 @@ export class Trie { }) } - static verifyProof(rootHash: Buffer, key: Buffer, proofNodes: Buffer[], cb: Function) { + static verifyProof(rootHash: Buffer, key: Buffer, proofNodes: Buffer[], cb: BufferCallback) { let proofTrie = new Trie(null, rootHash) Trie.fromProof( proofNodes, (error: Error, proofTrie: Trie) => { if (error) cb(new Error('Invalid proof nodes given'), null) - proofTrie.get(key, (e: Error, r: Buffer | null) => { + proofTrie.get(key, (e, r) => { return cb(e, r) }) }, @@ -122,7 +122,7 @@ export class Trie { * @param {Buffer} key - the key to search for * @param {Function} cb A callback `Function` which is given the arguments `err` - for errors that may have occured and `value` - the found value in a `Buffer` or if no value was found `null` */ - get(key: Buffer, cb: Function) { + get(key: Buffer, cb: BufferCallback) { key = ethUtil.toBuffer(key) this.findPath(key, (err: Error, node: TrieNode, remainder: number[], stack: TrieNode[]) => { @@ -180,7 +180,7 @@ export class Trie { * @param {Buffer} key * @param {Function} callback the callback `Function` */ - del(key: Buffer, cb: Function) { + del(key: Buffer, cb: ErrorCallback) { key = ethUtil.toBuffer(key) cb = callTogether(cb, this.sem.leave) @@ -205,7 +205,7 @@ export class Trie { * Retrieves a value directly from key/value db. * @deprecated */ - getRaw(key: Buffer, cb: Function) { + getRaw(key: Buffer, cb: BufferCallback) { this.db.get(key, cb) } @@ -231,8 +231,8 @@ export class Trie { if (isRawNode(node)) { cb(null, decodeRawNode(node as Buffer[])) } else { - this.db.get(node as Buffer, (err: Error, value: Buffer | null) => { - let node = null + this.db.get(node as Buffer, (err, value) => { + let node = null as any if (value) { node = decodeNode(value) } else { diff --git a/src/db.ts b/src/db.ts index a5db3ab..52c55cd 100644 --- a/src/db.ts +++ b/src/db.ts @@ -1,5 +1,5 @@ import { LevelUp } from 'levelup' -import { ErrorCallback } from './types' +import { ErrorCallback, BufferCallback } from './types' const level = require('level-mem') export const ENCODING_OPTS = { keyEncoding: 'binary', valueEncoding: 'binary' } @@ -38,7 +38,7 @@ export class DB { * `err` - for errors that may have occured * and `value` - the found value in a `Buffer` or if no value was found `null`. */ - get(key: Buffer, cb: Function) { + get(key: Buffer, cb: BufferCallback) { if (!Buffer.isBuffer(key)) throw new Error('Invalid input: expected buffer') this._leveldb.get(key, ENCODING_OPTS, (err?: Error, v?: Buffer) => { diff --git a/src/scratch.ts b/src/scratch.ts index 15efee4..3ba4697 100644 --- a/src/scratch.ts +++ b/src/scratch.ts @@ -1,5 +1,6 @@ import { DB, ENCODING_OPTS } from './db' import { asyncFirstSeries } from './util/async' +import { BufferCallback } from './types' /** * An in-memory wrap over `DB` with an upstream DB @@ -19,7 +20,7 @@ export class ScratchDB extends DB { * Similar to `DB.get`, but first searches in-memory * scratch DB, if key not found, searches upstream DB. */ - get(key: Buffer, cb: Function) { + get(key: Buffer, cb: BufferCallback) { const getDBs = this._upstream._leveldb ? [this._leveldb, this._upstream._leveldb] : [this._leveldb] diff --git a/src/secure.ts b/src/secure.ts index bda35a8..1eff0c2 100644 --- a/src/secure.ts +++ b/src/secure.ts @@ -1,6 +1,6 @@ import { keccak256 } from 'ethereumjs-util' import { CheckpointTrie } from './checkpointTrie' -import { ErrorCallback } from './types' +import { BufferCallback, ProveCallback, ErrorCallback } from './types' /** * You can create a secure Trie where the keys are automatically hashed @@ -15,12 +15,12 @@ export class SecureTrie extends CheckpointTrie { super(...args) } - static prove(trie: SecureTrie, key: Buffer, cb: Function) { + static prove(trie: SecureTrie, key: Buffer, cb: ProveCallback) { const hash = keccak256(key) super.prove(trie, hash, cb) } - static verifyProof(rootHash: Buffer, key: Buffer, proof: Buffer[], cb: Function) { + static verifyProof(rootHash: Buffer, key: Buffer, proof: Buffer[], cb: BufferCallback) { const hash = keccak256(key) super.verifyProof(rootHash, hash, proof, cb) } @@ -31,7 +31,7 @@ export class SecureTrie extends CheckpointTrie { return new SecureTrie(db._leveldb, this.root) } - get(key: Buffer, cb: Function) { + get(key: Buffer, cb: BufferCallback) { const hash = keccak256(key) super.get(hash, cb) } diff --git a/src/types.ts b/src/types.ts index 9a0dd91..354c379 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1 +1,3 @@ -export type ErrorCallback = (err?: Error) => void +export type BufferCallback = (err?: Error | null, value?: Buffer | null) => void +export type ProveCallback = (err?: Error | null, proof?: Buffer[] | null) => void +export type ErrorCallback = (err?: Error | null) => void diff --git a/src/util/nibbles.ts b/src/util/nibbles.ts index 33c20d3..3f1778d 100644 --- a/src/util/nibbles.ts +++ b/src/util/nibbles.ts @@ -5,8 +5,8 @@ * @private */ export function stringToNibbles(key: Buffer): number[] { - const bkey = new Buffer(key) - let nibbles = [] + const bkey = Buffer.from(key) + let nibbles = [] as any for (let i = 0; i < bkey.length; i++) { let q = i * 2 @@ -25,7 +25,7 @@ export function stringToNibbles(key: Buffer): number[] { * @private */ export function nibblesToBuffer(arr: number[]): Buffer { - let buf = new Buffer(arr.length / 2) + let buf = Buffer.alloc(arr.length / 2) for (let i = 0; i < buf.length; i++) { let q = i * 2 buf[i] = (arr[q] << 4) + arr[++q] diff --git a/test/checkpoint.js b/test/checkpoint.spec.ts similarity index 51% rename from test/checkpoint.js rename to test/checkpoint.spec.ts index 6020f94..eb7ad6f 100644 --- a/test/checkpoint.js +++ b/test/checkpoint.spec.ts @@ -1,98 +1,103 @@ -const tape = require('tape') +import * as tape from 'tape' const Trie = require('../dist/checkpointTrie').CheckpointTrie +import { CheckpointTrie } from '../dist/checkpointTrie' -tape('testing checkpoints', function(tester) { - let trie, preRoot, postRoot, trieCopy +tape('testing checkpoints', function (tester) { const it = tester.test - it('setup', function(t) { + let trie: CheckpointTrie + let trieCopy: CheckpointTrie + let preRoot: String + let postRoot: String + + it('setup', function (t) { trie = new Trie() - trie.put(Buffer.from('do'), Buffer.from('verb'), function() { - trie.put(Buffer.from('doge'), Buffer.from('coin'), function() { + trie.put(Buffer.from('do'), Buffer.from('verb'), function () { + trie.put(Buffer.from('doge'), Buffer.from('coin'), function () { preRoot = trie.root.toString('hex') t.end() }) }) }) - it('should copy trie and get value before checkpoint', function(t) { + it('should copy trie and get value before checkpoint', function (t) { trieCopy = trie.copy() t.equal(trieCopy.root.toString('hex'), preRoot) - trieCopy.get(Buffer.from('do'), function(err, res) { + trieCopy.get(Buffer.from('do'), function (err, res) { t.error(err) - t.ok(Buffer.from('verb').equals(res)) + t.ok(Buffer.from('verb').equals(Buffer.from(res!))) t.end() }) }) - it('should create a checkpoint', function(t) { + it('should create a checkpoint', function (t) { trie.checkpoint() t.end() }) - it('should save to the cache', function(t) { - trie.put(Buffer.from('test'), Buffer.from('something'), function() { - trie.put(Buffer.from('love'), Buffer.from('emotion'), function() { + it('should save to the cache', function (t) { + trie.put(Buffer.from('test'), Buffer.from('something'), function () { + trie.put(Buffer.from('love'), Buffer.from('emotion'), function () { postRoot = trie.root.toString('hex') t.end() }) }) }) - it('should get values from before checkpoint', function(t) { - trie.get(Buffer.from('doge'), function(err, res) { + it('should get values from before checkpoint', function (t) { + trie.get(Buffer.from('doge'), function (err, res) { t.error(err) - t.ok(Buffer.from('coin').equals(res)) + t.ok(Buffer.from('coin').equals(Buffer.from(res!))) t.end() }) }) - it('should get values from cache', function(t) { - trie.get(Buffer.from('love'), function(err, res) { + it('should get values from cache', function (t) { + trie.get(Buffer.from('love'), function (err, res) { t.error(err) - t.ok(Buffer.from('emotion').equals(res)) + t.ok(Buffer.from('emotion').equals(Buffer.from(res!))) t.end() }) }) - it('should copy trie and get upstream and cache values after checkpoint', function(t) { + it('should copy trie and get upstream and cache values after checkpoint', function (t) { trieCopy = trie.copy() t.equal(trieCopy.root.toString('hex'), postRoot) t.equal(trieCopy._checkpoints.length, 1) t.ok(trieCopy.isCheckpoint) - trieCopy.get(Buffer.from('do'), function(err, res) { + trieCopy.get(Buffer.from('do'), function (err, res) { t.error(err) - t.ok(Buffer.from('verb').equals(res)) - trieCopy.get(Buffer.from('love'), function(err, res) { + t.ok(Buffer.from('verb').equals(Buffer.from(res!))) + trieCopy.get(Buffer.from('love'), function (err, res) { t.error(err) - t.ok(Buffer.from('emotion').equals(res)) + t.ok(Buffer.from('emotion').equals(Buffer.from(res!))) t.end() }) }) }) - it('should revert to the orginal root', function(t) { + it('should revert to the orginal root', function (t) { t.equal(trie.isCheckpoint, true) - trie.revert(function() { + trie.revert(function () { t.equal(trie.root.toString('hex'), preRoot) t.equal(trie.isCheckpoint, false) t.end() }) }) - it('should not get values from cache after revert', function(t) { - trie.get(Buffer.from('love'), function(err, res) { + it('should not get values from cache after revert', function (t) { + trie.get(Buffer.from('love'), function (err, res) { t.error(err) t.notOk(res) t.end() }) }) - it('should commit a checkpoint', function(t) { + it('should commit a checkpoint', function (t) { trie.checkpoint() - trie.put(Buffer.from('test'), Buffer.from('something'), function() { - trie.put(Buffer.from('love'), Buffer.from('emotion'), function() { - trie.commit(function() { + trie.put(Buffer.from('test'), Buffer.from('something'), function () { + trie.put(Buffer.from('love'), Buffer.from('emotion'), function () { + trie.commit(function () { t.equal(trie.isCheckpoint, false) t.equal(trie.root.toString('hex'), postRoot) t.end() @@ -101,23 +106,23 @@ tape('testing checkpoints', function(tester) { }) }) - it('should get new values after commit', function(t) { - trie.get(Buffer.from('love'), function(err, res) { + it('should get new values after commit', function (t) { + trie.get(Buffer.from('love'), function (err, res) { t.error(err) - t.ok(Buffer.from('emotion').equals(res)) + t.ok(Buffer.from('emotion').equals(Buffer.from(res!))) t.end() }) }) - it('should commit a nested checkpoint', function(t) { + it('should commit a nested checkpoint', function (t) { trie.checkpoint() - var root - trie.put(Buffer.from('test'), Buffer.from('something else'), function() { + let root: Buffer + trie.put(Buffer.from('test'), Buffer.from('something else'), function () { root = trie.root trie.checkpoint() - trie.put(Buffer.from('the feels'), Buffer.from('emotion'), function() { - trie.revert() - trie.commit(function() { + trie.put(Buffer.from('the feels'), Buffer.from('emotion'), function () { + trie.revert(() => {}) + trie.commit(function () { t.equal(trie.isCheckpoint, false) t.equal(trie.root.toString('hex'), root.toString('hex')) t.end() diff --git a/test/db.js b/test/db.spec.ts similarity index 75% rename from test/db.js rename to test/db.spec.ts index b7096ff..13014d2 100644 --- a/test/db.js +++ b/test/db.spec.ts @@ -1,8 +1,9 @@ -const tape = require('tape') +import * as tape from 'tape' const DB = require('../dist/db').DB +import { DB as IDB, BatchDBOp } from '../dist/db' tape('DB basic functionality', (t) => { - const db = new DB() + const db = new DB() as IDB const k = Buffer.from('foo') const v = Buffer.from('bar') @@ -11,7 +12,7 @@ tape('DB basic functionality', (t) => { db.put(k, v, () => { db.get(k, (err, res) => { st.error(err) - st.ok(v.equals(res)) + st.ok(v.equals(res!)) st.end() }) }) @@ -30,12 +31,15 @@ tape('DB basic functionality', (t) => { t.test('batch ops', (st) => { const k2 = Buffer.from('bar') const v2 = Buffer.from('baz') - const ops = [{ type: 'put', key: k, value: v }, { type: 'put', key: k2, value: v2 }] + const ops = [ + { type: 'put', key: k, value: v }, + { type: 'put', key: k2, value: v2 }, + ] as BatchDBOp[] db.batch(ops, (err) => { st.error(err) db.get(k2, (err, res) => { st.error(err) - st.ok(v2.equals(res)) + st.ok(v2.equals(res!)) st.end() }) }) diff --git a/test/encodeing.js b/test/encoding.spec.ts similarity index 52% rename from test/encodeing.js rename to test/encoding.spec.ts index 3bcb8e9..e82923e 100644 --- a/test/encodeing.js +++ b/test/encoding.spec.ts @@ -1,12 +1,12 @@ +import * as tape from 'tape' const Trie = require('../dist/index').CheckpointTrie -const tape = require('tape') const trie = new Trie() const trie2 = new Trie() const hex = 'FF44A3B3' -tape('encoding hexprefixes ', function(t) { - trie.put(new Buffer(hex, 'hex'), Buffer.from('test'), function() { - trie2.put('0x' + hex, Buffer.from('test'), function() { +tape('encoding hexprefixes', function (t) { + trie.put(Buffer.from(hex, 'hex'), Buffer.from('test'), function () { + trie2.put('0x' + hex, Buffer.from('test'), function () { t.equal(trie.root.toString('hex'), trie2.root.toString('hex')) t.end() }) diff --git a/test/failingRefactorTests.js b/test/failingRefactorTests.js deleted file mode 100644 index d5c1f30..0000000 --- a/test/failingRefactorTests.js +++ /dev/null @@ -1,69 +0,0 @@ -const async = require('async') -const tape = require('tape') - -const Trie = require('../dist/secure').SecureTrie -const trie = new Trie() -const a = new Buffer('f8448080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0a155280bc3c09fd31b0adebbdd4ef3d5128172c0d2008be964dc9e10e0f0fedf', 'hex') -const ak = new Buffer('095e7baea6a6c7c4c2dfeb977efac326af552d87', 'hex') - -const b = new Buffer('f844802ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0db94dc4aab9b6a1a11956906ea34f3252f394576aece12199b23b269bb2738ab', 'hex') -const bk = new Buffer('945304eb96065b2a98b57a48a06ae28d285a71b5', 'hex') - -const c = new Buffer('f84c80880de0b6b3a7640000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470', 'hex') -const ck = new Buffer('a94f5374fce5edbc8e2a8697c15331677e6ebf0b', 'hex') - // checkpoint - // checkpoint - // commit -const d = new Buffer('f8488084535500b1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0a155280bc3c09fd31b0adebbdd4ef3d5128172c0d2008be964dc9e10e0f0fedf', 'hex') -const dk = new Buffer('095e7baea6a6c7c4c2dfeb977efac326af552d87', 'hex') - -const e = new Buffer('f8478083010851a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0db94dc4aab9b6a1a11956906ea34f3252f394576aece12199b23b269bb2738ab', 'hex') -const ek = new Buffer('945304eb96065b2a98b57a48a06ae28d285a71b5', 'hex') - -const f = new Buffer('f84c01880de0b6b3540df72ca056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470', 'hex') -const fk = new Buffer('a94f5374fce5edbc8e2a8697c15331677e6ebf0b', 'hex') - -// commit -const g = new Buffer('f8488084535500b1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0a155280bc3c09fd31b0adebbdd4ef3d5128172c0d2008be964dc9e10e0f0fedf', 'hex') -const gk = new Buffer('095e7baea6a6c7c4c2dfeb977efac326af552d87', 'hex') - -tape('secure tests shouldnt crash ', function (t) { - async.series([ - - function (done) { - console.log('done') - trie.put(ak, a, done) - }, - function (done) { - trie.put(bk, b, done) - }, - function (done) { - trie.put(ck, c, done) - }, - function (done) { - trie.checkpoint() - trie.checkpoint() - done() - }, - function (done) { - trie.commit(done) - }, - function (done) { - trie.put(dk, d, done) - }, - function (done) { - trie.put(ek, e, done) - }, - function (done) { - trie.put(fk, f, done) - }, - function (done) { - trie.commit(done) - }, - function (done) { - trie.put(gk, g, done) - } - ], function () { - t.end() - }) -}) diff --git a/test/failingRefactorTests.spec.ts b/test/failingRefactorTests.spec.ts new file mode 100644 index 0000000..d02ecd2 --- /dev/null +++ b/test/failingRefactorTests.spec.ts @@ -0,0 +1,92 @@ +import * as tape from 'tape' +import * as async from 'async' +const Trie = require('../dist/secure').SecureTrie + +const trie = new Trie() +const a = Buffer.from( + 'f8448080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0a155280bc3c09fd31b0adebbdd4ef3d5128172c0d2008be964dc9e10e0f0fedf', + 'hex', +) +const ak = Buffer.from('095e7baea6a6c7c4c2dfeb977efac326af552d87', 'hex') + +const b = Buffer.from( + 'f844802ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0db94dc4aab9b6a1a11956906ea34f3252f394576aece12199b23b269bb2738ab', + 'hex', +) +const bk = Buffer.from('945304eb96065b2a98b57a48a06ae28d285a71b5', 'hex') + +const c = Buffer.from( + 'f84c80880de0b6b3a7640000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470', + 'hex', +) +const ck = Buffer.from('a94f5374fce5edbc8e2a8697c15331677e6ebf0b', 'hex') +// checkpoint +// checkpoint +// commit +const d = Buffer.from( + 'f8488084535500b1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0a155280bc3c09fd31b0adebbdd4ef3d5128172c0d2008be964dc9e10e0f0fedf', + 'hex', +) +const dk = Buffer.from('095e7baea6a6c7c4c2dfeb977efac326af552d87', 'hex') + +const e = Buffer.from( + 'f8478083010851a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0db94dc4aab9b6a1a11956906ea34f3252f394576aece12199b23b269bb2738ab', + 'hex', +) +const ek = Buffer.from('945304eb96065b2a98b57a48a06ae28d285a71b5', 'hex') + +const f = Buffer.from( + 'f84c01880de0b6b3540df72ca056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470', + 'hex', +) +const fk = Buffer.from('a94f5374fce5edbc8e2a8697c15331677e6ebf0b', 'hex') + +// commit +const g = Buffer.from( + 'f8488084535500b1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0a155280bc3c09fd31b0adebbdd4ef3d5128172c0d2008be964dc9e10e0f0fedf', + 'hex', +) +const gk = Buffer.from('095e7baea6a6c7c4c2dfeb977efac326af552d87', 'hex') + +tape('secure tests shouldnt crash ', function (t) { + async.series( + [ + function (done) { + console.log('done') + trie.put(ak, a, done) + }, + function (done) { + trie.put(bk, b, done) + }, + function (done) { + trie.put(ck, c, done) + }, + function (done) { + trie.checkpoint() + trie.checkpoint() + done() + }, + function (done) { + trie.commit(done) + }, + function (done) { + trie.put(dk, d, done) + }, + function (done) { + trie.put(ek, e, done) + }, + function (done) { + trie.put(fk, f, done) + }, + function (done) { + trie.commit(done) + }, + function (done) { + trie.put(gk, g, done) + }, + ], + function () { + t.end() + }, + ) +}) diff --git a/test/fixture/hex_encoded_securetrie_test.json b/test/fixtures/hex_encoded_securetrie_test.json similarity index 100% rename from test/fixture/hex_encoded_securetrie_test.json rename to test/fixtures/hex_encoded_securetrie_test.json diff --git a/test/fixture/trieanyorder.json b/test/fixtures/trieanyorder.json similarity index 100% rename from test/fixture/trieanyorder.json rename to test/fixtures/trieanyorder.json diff --git a/test/fixture/trieanyorder_secureTrie.json b/test/fixtures/trieanyorder_secureTrie.json similarity index 100% rename from test/fixture/trieanyorder_secureTrie.json rename to test/fixtures/trieanyorder_secureTrie.json diff --git a/test/fixture/trietest.json b/test/fixtures/trietest.json similarity index 100% rename from test/fixture/trietest.json rename to test/fixtures/trietest.json diff --git a/test/fixture/trietest_secureTrie.json b/test/fixtures/trietest_secureTrie.json similarity index 100% rename from test/fixture/trietest_secureTrie.json rename to test/fixtures/trietest_secureTrie.json diff --git a/test/fixture/trietestnextprev.json b/test/fixtures/trietestnextprev.json similarity index 100% rename from test/fixture/trietestnextprev.json rename to test/fixtures/trietestnextprev.json diff --git a/test/index.js b/test/index.js deleted file mode 100644 index 37e5338..0000000 --- a/test/index.js +++ /dev/null @@ -1,304 +0,0 @@ -const Trie = require('../dist/index').CheckpointTrie -const async = require('async') -const rlp = require('rlp') -const tape = require('tape') -const ethUtil = require('ethereumjs-util') - -tape('simple save and retrive', function(tester) { - var it = tester.test - - it('should not crash if given a non-existant root', function(t) { - var root = new Buffer('3f4399b08efe68945c1cf90ffe85bbe3ce978959da753f9e649f034015b8817d', 'hex') - var trie = new Trie(null, root) - - trie.get(Buffer.from('test'), function(err, value) { - t.equal(value, null) - t.notEqual(err, null) - t.end() - }) - }) - var trie = new Trie() - - it('save a value', function(t) { - trie.put(Buffer.from('test'), Buffer.from('one'), t.end) - }) - - it('should get a value', function(t) { - trie.get(Buffer.from('test'), function(err, value) { - t.equal(value.toString(), 'one') - t.end(err) - }) - }) - - it('should update a value', function(t) { - trie.put(Buffer.from('test'), Buffer.from('two'), function() { - trie.get(Buffer.from('test'), function(err, value) { - t.equal(value.toString(), 'two') - t.end(err) - }) - }) - }) - - it('should delete a value', function(t) { - trie.del(Buffer.from('test'), function(stack) { - trie.get(Buffer.from('test'), function(err, value) { - t.notok(value) - t.end(err) - }) - }) - }) - - it('should recreate a value', function(t) { - trie.put(new Buffer('test'), new Buffer('one'), t.end) - }) - - it('should get updated a value', function(t) { - trie.get(Buffer.from('test'), function(err, value) { - t.equal(value.toString(), 'one') - t.end(err) - }) - }) - - it('should create a branch here', function(t) { - trie.put(new Buffer('doge'), new Buffer('coin'), function() { - t.equal( - 'de8a34a8c1d558682eae1528b47523a483dd8685d6db14b291451a66066bf0fc', - trie.root.toString('hex'), - ) - t.end() - }) - }) - - it('should get a value that is in a branch', function(t) { - trie.get(new Buffer('doge'), function(err, value) { - t.equal(value.toString(), 'coin') - t.end(err) - }) - }) - - it('should delete from a branch', function(t) { - trie.del(Buffer.from('doge'), function(err1, stack) { - trie.get(Buffer.from('doge'), function(err2, value) { - t.equal(value, null) - t.end(err1 || err2) - }) - }) - }) -}) - -tape('storing longer values', function(tester) { - var it = tester.test - var trie = new Trie() - var longString = 'this will be a really really really long value' - var longStringRoot = 'b173e2db29e79c78963cff5196f8a983fbe0171388972106b114ef7f5c24dfa3' - - it('should store a longer string', function(t) { - trie.put(new Buffer('done'), new Buffer(longString), function(err1, value) { - trie.put(new Buffer('doge'), new Buffer('coin'), function(err2, value) { - t.equal(longStringRoot, trie.root.toString('hex')) - t.end(err1 || err2) - }) - }) - }) - - it('should retreive a longer value', function(t) { - trie.get(new Buffer('done'), function(err, value) { - t.equal(value.toString(), longString) - t.end(err) - }) - }) - - it('should when being modiefied delete the old value', function(t) { - trie.put(new Buffer('done'), new Buffer('test'), t.end) - }) -}) - -tape('testing Extentions and branches', function(tester) { - var trie = new Trie() - var it = tester.test - - it('should store a value', function(t) { - trie.put(new Buffer('doge'), new Buffer('coin'), t.end) - }) - - it('should create extention to store this value', function(t) { - trie.put(new Buffer('do'), new Buffer('verb'), function() { - t.equal( - 'f803dfcb7e8f1afd45e88eedb4699a7138d6c07b71243d9ae9bff720c99925f9', - trie.root.toString('hex'), - ) - t.end() - }) - }) - - it('should store this value under the extention ', function(t) { - trie.put(new Buffer('done'), new Buffer('finished'), function() { - t.equal( - '409cff4d820b394ed3fb1cd4497bdd19ffa68d30ae34157337a7043c94a3e8cb', - trie.root.toString('hex'), - ) - t.end() - }) - }) -}) - -tape('testing Extentions and branches - reverse', function(tester) { - var it = tester.test - var trie = new Trie() - - it('should create extention to store this value', function(t) { - trie.put(new Buffer('do'), new Buffer('verb'), t.end) - }) - - it('should store a value', function(t) { - trie.put(new Buffer('doge'), new Buffer('coin'), t.end) - }) - - it('should store this value under the extention ', function(t) { - trie.put(new Buffer('done'), new Buffer('finished'), function() { - t.equal( - '409cff4d820b394ed3fb1cd4497bdd19ffa68d30ae34157337a7043c94a3e8cb', - trie.root.toString('hex'), - ) - t.end() - }) - }) -}) - -tape('testing deletions cases', function(tester) { - var it = tester.test - var trie = new Trie() - - it('should delete from a branch->branch-branch', function(t) { - async.parallel( - [ - async.apply(trie.put.bind(trie), new Buffer([11, 11, 11]), Buffer.from('first')), - async.apply( - trie.put.bind(trie), - new Buffer([12, 22, 22]), - Buffer.from('create the first branch'), - ), - async.apply( - trie.put.bind(trie), - new Buffer([12, 34, 44]), - Buffer.from('create the last branch'), - ), - ], - function() { - trie.del(new Buffer([12, 22, 22]), function() { - trie.get(new Buffer([12, 22, 22]), function(err, val) { - t.equal(null, val) - trie = new Trie() - t.end(err) - }) - }) - }, - ) - }) - - it('should delete from a branch->branch-extention', function(t) { - async.parallel( - [ - async.apply(trie.put.bind(trie), new Buffer([11, 11, 11]), Buffer.from('first')), - async.apply( - trie.put.bind(trie), - new Buffer([12, 22, 22]), - Buffer.from('create the first branch'), - ), - async.apply( - trie.put.bind(trie), - new Buffer([12, 33, 33]), - Buffer.from('create the middle branch'), - ), - async.apply( - trie.put.bind(trie), - new Buffer([12, 33, 44]), - Buffer.from('create the last branch'), - ), - ], - function() { - trie.del(new Buffer([12, 22, 22]), function() { - trie.get(new Buffer([12, 22, 22]), function(err, val) { - t.equal(null, val) - t.end(err) - }) - }) - }, - ) - }) - - it('should delete from a extention->branch-extention', function(t) { - trie.put(new Buffer([11, 11, 11]), Buffer.from('first'), function() { - // create the top branch - trie.put(new Buffer([12, 22, 22]), Buffer.from('create the first branch'), function() { - // crete the middle branch - trie.put(new Buffer([12, 33, 33]), Buffer.from('create the middle branch'), function() { - trie.put(new Buffer([12, 33, 44]), Buffer.from('create the last branch'), function() { - // delete the middle branch - trie.del(new Buffer([11, 11, 11]), function() { - trie.get(new Buffer([11, 11, 11]), function(err, val) { - t.equal(null, val) - t.end(err) - }) - }) - }) - }) - }) - }) - }) - - it('should delete from a extention->branch-branch', function(t) { - trie.put(new Buffer([11, 11, 11]), Buffer.from('first'), function() { - // create the top branch - trie.put(new Buffer([12, 22, 22]), Buffer.from('create the first branch'), function() { - // crete the middle branch - trie.put(new Buffer([12, 33, 33]), Buffer.from('create the middle branch'), function() { - trie.put(new Buffer([12, 34, 44]), Buffer.from('create the last branch'), function() { - // delete the middle branch - trie.del(new Buffer([11, 11, 11]), function() { - trie.get(new Buffer([11, 11, 11]), function(err, val) { - t.equal(null, val) - t.end(err) - }) - }) - }) - }) - }) - }) - }) -}) - -tape('it should create the genesis state root from ethereum', function(tester) { - var it = tester.test - var trie4 = new Trie() - var g = new Buffer('8a40bfaa73256b60764c1bf40675a99083efb075', 'hex') - var j = new Buffer('e6716f9544a56c530d868e4bfbacb172315bdead', 'hex') - var v = new Buffer('1e12515ce3e0f817a4ddef9ca55788a1d66bd2df', 'hex') - var a = new Buffer('1a26338f0d905e295fccb71fa9ea849ffa12aaf4', 'hex') - var stateRoot = new Buffer(32) - - stateRoot.fill(0) - var startAmount = new Buffer(26) - startAmount.fill(0) - startAmount[0] = 1 - var account = [startAmount, 0, stateRoot, ethUtil.keccak256()] - var rlpAccount = rlp.encode(account) - var cppRlp = - 'f85e9a010000000000000000000000000000000000000000000000000080a00000000000000000000000000000000000000000000000000000000000000000a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470' - - var genesisStateRoot = '2f4399b08efe68945c1cf90ffe85bbe3ce978959da753f9e649f034015b8817d' - tester.equal(cppRlp, rlpAccount.toString('hex')) - - it('shall match the root', function(t) { - trie4.put(g, rlpAccount, function() { - trie4.put(j, rlpAccount, function() { - trie4.put(v, rlpAccount, function() { - trie4.put(a, rlpAccount, function() { - t.equal(trie4.root.toString('hex'), genesisStateRoot) - t.end() - }) - }) - }) - }) - }) -}) diff --git a/test/index.spec.ts b/test/index.spec.ts new file mode 100644 index 0000000..e30ed11 --- /dev/null +++ b/test/index.spec.ts @@ -0,0 +1,309 @@ +import * as tape from 'tape' +import * as async from 'async' +import * as rlp from 'rlp' +import * as ethUtil from 'ethereumjs-util' +const Trie = require('../dist/index').CheckpointTrie +import { CheckpointTrie } from '../dist/checkpointTrie' + +tape('simple save and retrive', function (tester) { + var it = tester.test + + it('should not crash if given a non-existant root', function (t) { + var root = Buffer.from( + '3f4399b08efe68945c1cf90ffe85bbe3ce978959da753f9e649f034015b8817d', + 'hex', + ) + var trie = new Trie(null, root) as CheckpointTrie + + trie.get(Buffer.from('test'), function (err, value) { + t.equal(value, null) + t.notEqual(err, null) + t.end() + }) + }) + + var trie = new Trie() as CheckpointTrie + + it('save a value', function (t) { + trie.put(Buffer.from('test'), Buffer.from('one'), t.end) + }) + + it('should get a value', function (t) { + trie.get(Buffer.from('test'), function (err, value) { + t.equal(value!.toString(), 'one') + t.end(err) + }) + }) + + it('should update a value', function (t) { + trie.put(Buffer.from('test'), Buffer.from('two'), function () { + trie.get(Buffer.from('test'), function (err, value) { + t.equal(value!.toString(), 'two') + t.end(err) + }) + }) + }) + + it('should delete a value', function (t) { + trie.del(Buffer.from('test'), function (err) { + trie.get(Buffer.from('test'), function (err, value) { + t.notok(value) + t.end(err) + }) + }) + }) + + it('should recreate a value', function (t) { + trie.put(Buffer.from('test'), Buffer.from('one'), t.end) + }) + + it('should get updated a value', function (t) { + trie.get(Buffer.from('test'), function (err, value) { + t.equal(value!.toString(), 'one') + t.end(err) + }) + }) + + it('should create a branch here', function (t) { + trie.put(Buffer.from('doge'), Buffer.from('coin'), function () { + t.equal( + 'de8a34a8c1d558682eae1528b47523a483dd8685d6db14b291451a66066bf0fc', + trie.root.toString('hex'), + ) + t.end() + }) + }) + + it('should get a value that is in a branch', function (t) { + trie.get(Buffer.from('doge'), function (err, value) { + t.equal(value!.toString(), 'coin') + t.end(err) + }) + }) + + it('should delete from a branch', function (t) { + trie.del(Buffer.from('doge'), function (err1) { + trie.get(Buffer.from('doge'), function (err2, value) { + t.equal(value, null) + t.end(err1 || err2) + }) + }) + }) +}) + +tape('storing longer values', function (tester) { + var it = tester.test + var trie = new Trie() as CheckpointTrie + var longString = 'this will be a really really really long value' + var longStringRoot = 'b173e2db29e79c78963cff5196f8a983fbe0171388972106b114ef7f5c24dfa3' + + it('should store a longer string', function (t) { + trie.put(Buffer.from('done'), Buffer.from(longString), function (err1) { + trie.put(Buffer.from('doge'), Buffer.from('coin'), function (err2) { + t.equal(longStringRoot, trie.root.toString('hex')) + t.end(err1 || err2) + }) + }) + }) + + it('should retreive a longer value', function (t) { + trie.get(Buffer.from('done'), function (err, value) { + t.equal(value!.toString(), longString) + t.end(err) + }) + }) + + it('should when being modiefied delete the old value', function (t) { + trie.put(Buffer.from('done'), Buffer.from('test'), t.end) + }) +}) + +tape('testing Extentions and branches', function (tester) { + var trie = new Trie() as CheckpointTrie + var it = tester.test + + it('should store a value', function (t) { + trie.put(Buffer.from('doge'), Buffer.from('coin'), t.end) + }) + + it('should create extention to store this value', function (t) { + trie.put(Buffer.from('do'), Buffer.from('verb'), function () { + t.equal( + 'f803dfcb7e8f1afd45e88eedb4699a7138d6c07b71243d9ae9bff720c99925f9', + trie.root.toString('hex'), + ) + t.end() + }) + }) + + it('should store this value under the extention ', function (t) { + trie.put(Buffer.from('done'), Buffer.from('finished'), function () { + t.equal( + '409cff4d820b394ed3fb1cd4497bdd19ffa68d30ae34157337a7043c94a3e8cb', + trie.root.toString('hex'), + ) + t.end() + }) + }) +}) + +tape('testing Extentions and branches - reverse', function (tester) { + var it = tester.test + var trie = new Trie() as CheckpointTrie + + it('should create extention to store this value', function (t) { + trie.put(Buffer.from('do'), Buffer.from('verb'), t.end) + }) + + it('should store a value', function (t) { + trie.put(Buffer.from('doge'), Buffer.from('coin'), t.end) + }) + + it('should store this value under the extention ', function (t) { + trie.put(Buffer.from('done'), Buffer.from('finished'), function () { + t.equal( + '409cff4d820b394ed3fb1cd4497bdd19ffa68d30ae34157337a7043c94a3e8cb', + trie.root.toString('hex'), + ) + t.end() + }) + }) +}) + +tape('testing deletions cases', function (tester) { + var it = tester.test + var trie = new Trie() as CheckpointTrie + + it('should delete from a branch->branch-branch', function (t) { + async.parallel( + [ + async.apply(trie.put.bind(trie), Buffer.from([11, 11, 11]), Buffer.from('first')), + async.apply( + trie.put.bind(trie), + Buffer.from([12, 22, 22]), + Buffer.from('create the first branch'), + ), + async.apply( + trie.put.bind(trie), + Buffer.from([12, 34, 44]), + Buffer.from('create the last branch'), + ), + ], + function () { + trie.del(Buffer.from([12, 22, 22]), function () { + trie.get(Buffer.from([12, 22, 22]), function (err, val) { + t.equal(null, val) + trie = new Trie() as CheckpointTrie + t.end(err) + }) + }) + }, + ) + }) + + it('should delete from a branch->branch-extention', function (t) { + async.parallel( + [ + async.apply(trie.put.bind(trie), Buffer.from([11, 11, 11]), Buffer.from('first')), + async.apply( + trie.put.bind(trie), + Buffer.from([12, 22, 22]), + Buffer.from('create the first branch'), + ), + async.apply( + trie.put.bind(trie), + Buffer.from([12, 33, 33]), + Buffer.from('create the middle branch'), + ), + async.apply( + trie.put.bind(trie), + Buffer.from([12, 33, 44]), + Buffer.from('create the last branch'), + ), + ], + function () { + trie.del(Buffer.from([12, 22, 22]), function () { + trie.get(Buffer.from([12, 22, 22]), function (err, val) { + t.equal(null, val) + t.end(err) + }) + }) + }, + ) + }) + + it('should delete from a extention->branch-extention', function (t) { + trie.put(Buffer.from([11, 11, 11]), Buffer.from('first'), function () { + // create the top branch + trie.put(Buffer.from([12, 22, 22]), Buffer.from('create the first branch'), function () { + // crete the middle branch + trie.put(Buffer.from([12, 33, 33]), Buffer.from('create the middle branch'), function () { + trie.put(Buffer.from([12, 33, 44]), Buffer.from('create the last branch'), function () { + // delete the middle branch + trie.del(Buffer.from([11, 11, 11]), function () { + trie.get(Buffer.from([11, 11, 11]), function (err, val) { + t.equal(null, val) + t.end(err) + }) + }) + }) + }) + }) + }) + }) + + it('should delete from a extention->branch-branch', function (t) { + trie.put(Buffer.from([11, 11, 11]), Buffer.from('first'), function () { + // create the top branch + trie.put(Buffer.from([12, 22, 22]), Buffer.from('create the first branch'), function () { + // crete the middle branch + trie.put(Buffer.from([12, 33, 33]), Buffer.from('create the middle branch'), function () { + trie.put(Buffer.from([12, 34, 44]), Buffer.from('create the last branch'), function () { + // delete the middle branch + trie.del(Buffer.from([11, 11, 11]), function () { + trie.get(Buffer.from([11, 11, 11]), function (err, val) { + t.equal(null, val) + t.end(err) + }) + }) + }) + }) + }) + }) + }) +}) + +tape('it should create the genesis state root from ethereum', function (tester) { + var it = tester.test + var trie4 = new Trie() as CheckpointTrie + var g = Buffer.from('8a40bfaa73256b60764c1bf40675a99083efb075', 'hex') + var j = Buffer.from('e6716f9544a56c530d868e4bfbacb172315bdead', 'hex') + var v = Buffer.from('1e12515ce3e0f817a4ddef9ca55788a1d66bd2df', 'hex') + var a = Buffer.from('1a26338f0d905e295fccb71fa9ea849ffa12aaf4', 'hex') + var stateRoot = Buffer.alloc(32) + + stateRoot.fill(0) + var startAmount = Buffer.alloc(26) + startAmount.fill(0) + startAmount[0] = 1 + var account = [startAmount, 0, stateRoot, ethUtil.KECCAK256_NULL] + var rlpAccount = rlp.encode(account) + var cppRlp = + 'f85e9a010000000000000000000000000000000000000000000000000080a00000000000000000000000000000000000000000000000000000000000000000a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470' + + var genesisStateRoot = '2f4399b08efe68945c1cf90ffe85bbe3ce978959da753f9e649f034015b8817d' + tester.equal(cppRlp, rlpAccount.toString('hex')) + + it('shall match the root', function (t) { + trie4.put(g, rlpAccount, function () { + trie4.put(j, rlpAccount, function () { + trie4.put(v, rlpAccount, function () { + trie4.put(a, rlpAccount, function () { + t.equal(trie4.root.toString('hex'), genesisStateRoot) + t.end() + }) + }) + }) + }) + }) +}) diff --git a/test/offical.js b/test/offical.spec.ts similarity index 61% rename from test/offical.js rename to test/offical.spec.ts index 2514826..67b677f 100644 --- a/test/offical.js +++ b/test/offical.spec.ts @@ -1,33 +1,33 @@ +import * as tape from 'tape' +import * as async from 'async' const Trie = require('../dist/index').CheckpointTrie -const async = require('async') -const tape = require('tape') -tape('offical tests', function(t) { - const jsonTests = require('./fixture/trietest.json').tests +tape('offical tests', function (t) { + const jsonTests = require('./fixtures/trietest.json').tests const testNames = Object.keys(jsonTests) let trie = new Trie() async.eachSeries( testNames, - function(i, done) { + function (i, done) { let inputs = jsonTests[i].in let expect = jsonTests[i].root async.eachSeries( inputs, - function(input, done) { - for (i = 0; i < 2; i++) { + function (input: any, done) { + for (let i = 0; i < 2; i++) { if (input[i] && input[i].slice(0, 2) === '0x') { - input[i] = new Buffer(input[i].slice(2), 'hex') + input[i] = Buffer.from(input[i].slice(2), 'hex') } else if (input[i] && typeof input[i] === 'string') { input[i] = Buffer.from(input[i]) } } - trie.put(new Buffer(input[0]), input[1], function() { + trie.put(Buffer.from(input[0]), input[1], function () { done() }) }, - function() { + function () { t.equal('0x' + trie.root.toString('hex'), expect) trie = new Trie() done() @@ -38,34 +38,34 @@ tape('offical tests', function(t) { ) }) -tape('offical tests any order', function(t) { - const jsonTests = require('./fixture/trieanyorder.json').tests +tape('offical tests any order', function (t) { + const jsonTests = require('./fixtures/trieanyorder.json').tests var testNames = Object.keys(jsonTests) var trie = new Trie() async.eachSeries( testNames, - function(i, done) { + function (i, done) { var test = jsonTests[i] var keys = Object.keys(test.in) async.eachSeries( keys, - function(key, done) { + function (key: any, done) { var val = test.in[key] if (key.slice(0, 2) === '0x') { - key = new Buffer(key.slice(2), 'hex') + key = Buffer.from(key.slice(2), 'hex') } if (val && val.slice(0, 2) === '0x') { - val = new Buffer(val.slice(2), 'hex') + val = Buffer.from(val.slice(2), 'hex') } - trie.put(new Buffer(key), new Buffer(val), function() { + trie.put(Buffer.from(key), Buffer.from(val), function () { done() }) }, - function() { + function () { t.equal('0x' + trie.root.toString('hex'), test.root) trie = new Trie() done() diff --git a/test/prioritizedTaskExecutor.js b/test/prioritizedTaskExecutor.spec.ts similarity index 70% rename from test/prioritizedTaskExecutor.js rename to test/prioritizedTaskExecutor.spec.ts index 88b1488..99b7b03 100644 --- a/test/prioritizedTaskExecutor.js +++ b/test/prioritizedTaskExecutor.spec.ts @@ -1,19 +1,19 @@ +import * as tape from 'tape' const PrioritizedTaskExecutor = require('../dist/prioritizedTaskExecutor').PrioritizedTaskExecutor -const tape = require('tape') const taskExecutor = new PrioritizedTaskExecutor(2) tape('prioritized task executor test', function (t) { var tasks = [1, 2, 3, 4] - var callbacks = [] - var executionOrder = [] + var callbacks = [] as any + var executionOrder = [] as any tasks.forEach(function (task) { - taskExecutor.execute(task, function (cb) { + taskExecutor.execute(task, function (cb: Function) { executionOrder.push(task) callbacks.push(cb) }) }) - callbacks.forEach(function (callback) { + callbacks.forEach(function (callback: Function) { callback() }) diff --git a/test/proof.js b/test/proof.spec.ts similarity index 52% rename from test/proof.js rename to test/proof.spec.ts index 7cd6a28..e19afcb 100644 --- a/test/proof.js +++ b/test/proof.spec.ts @@ -1,52 +1,59 @@ +import * as tape from 'tape' +import * as async from 'async' const Trie = require('../dist/index').CheckpointTrie -const async = require('async') -const tape = require('tape') +import { CheckpointTrie } from '../dist/checkpointTrie' -tape('simple merkle proofs generation and verification', function(tester) { +tape('simple merkle proofs generation and verification', function (tester) { var it = tester.test - it('create a merkle proof and verify it', function(t) { - var trie = new Trie() + it('create a merkle proof and verify it', function (t) { + var trie = new Trie() as CheckpointTrie async.series( [ - function(cb) { + function (cb) { trie.put( Buffer.from('key1aa'), Buffer.from('0123456789012345678901234567890123456789xx'), cb, ) }, - function(cb) { + function (cb) { trie.put(Buffer.from('key2bb'), Buffer.from('aval2'), cb) }, - function(cb) { + function (cb) { trie.put(Buffer.from('key3cc'), Buffer.from('aval3'), cb) }, - function(cb) { - Trie.prove(trie, Buffer.from('key2bb'), function(err, prove) { + function (cb) { + CheckpointTrie.prove(trie, Buffer.from('key2bb'), function (err, prove) { if (err) return cb(err) - Trie.verifyProof(trie.root, Buffer.from('key2bb'), prove, function(err, val) { + CheckpointTrie.verifyProof(trie.root, Buffer.from('key2bb'), prove!, function ( + err, + val, + ) { if (err) return cb(err) - t.equal(val.toString('utf8'), 'aval2') + t.equal(val!.toString('utf8'), 'aval2') cb() }) }) }, - function(cb) { - Trie.prove(trie, Buffer.from('key1aa'), function(err, prove) { + function (cb) { + CheckpointTrie.prove(trie, Buffer.from('key1aa'), function (err, prove) { if (err) return cb(err) - Trie.verifyProof(trie.root, Buffer.from('key1aa'), prove, function(err, val) { + CheckpointTrie.verifyProof(trie.root, Buffer.from('key1aa'), prove!, function ( + err, + val, + ) { if (err) return cb(err) - t.equal(val.toString('utf8'), '0123456789012345678901234567890123456789xx') + t.equal(val!.toString('utf8'), '0123456789012345678901234567890123456789xx') cb() }) }) }, - function(cb) { - Trie.prove(trie, Buffer.from('key2bb'), function(err, prove) { + function (cb) { + CheckpointTrie.prove(trie, Buffer.from('key2bb'), function (err, prove) { t.equal(err, null, 'Path to key2 should create valid proof of absence') if (err) return cb(err) - Trie.verifyProof(trie.root, Buffer.from('key2'), prove, function(err, val) { + CheckpointTrie.verifyProof(trie.root, Buffer.from('key2'), prove!, function (err, val) { // In this case, the proof _happens_ to contain enough nodes to prove `key2` because // traversing into `key22` would touch all the same nodes as traversing into `key2` t.equal(val, null, 'Expected value at a random key to be null') @@ -55,38 +62,41 @@ tape('simple merkle proofs generation and verification', function(tester) { }) }) }, - function(cb) { + function (cb) { let myKey = Buffer.from('anyrandomkey') - Trie.prove(trie, myKey, function(err, prove) { + CheckpointTrie.prove(trie, myKey, function (err, prove) { if (err) return cb(err) - Trie.verifyProof(trie.root, myKey, prove, function(err, val) { + CheckpointTrie.verifyProof(trie.root, myKey, prove!, function (err, val) { t.equal(val, null, 'Expected value to be null') - t.equal(err, null, err) + t.equal(err, null, err ? err.toString() : undefined) cb() }) }) }, - function(cb) { + function (cb) { let myKey = Buffer.from('anothergarbagekey') // should generate a valid proof of null - Trie.prove(trie, myKey, function(err, prove) { + CheckpointTrie.prove(trie, myKey, function (err, prove) { if (err) return cb(err) - prove.push(Buffer.from('123456')) // extra nodes are just ignored - Trie.verifyProof(trie.root, myKey, prove, function(err, val) { + prove!.push(Buffer.from('123456')) // extra nodes are just ignored + CheckpointTrie.verifyProof(trie.root, myKey, prove!, function (err, val) { t.equal(val, null, 'Expected value to be null') - t.equal(err, null, err) + t.equal(err, null, err ? err.toString() : undefined) cb() }) }) }, - function(cb) { + function (cb) { trie.put(Buffer.from('another'), Buffer.from('3498h4riuhgwe'), cb) }, - function(cb) { + function (cb) { // to throw an error we need to request proof for one key - Trie.prove(trie, Buffer.from('another'), function(err, prove) { + CheckpointTrie.prove(trie, Buffer.from('another'), function (err, prove) { if (err) return cb(err) // and try to use that proof on another key - Trie.verifyProof(trie.root, Buffer.from('key1aa'), prove, function(err, val) { + CheckpointTrie.verifyProof(trie.root, Buffer.from('key1aa'), prove!, function ( + err, + val, + ) { t.equal(val, null, 'Expected value: to be null ') // this proof would be insignificant to prove `key1aa` t.notEqual(err, null, 'Expected error: Missing node in DB') @@ -96,180 +106,186 @@ tape('simple merkle proofs generation and verification', function(tester) { }) }, ], - function(err) { + function (err) { t.end(err) }, ) }) - it('create a merkle proof and verify it with a single long key', function(t) { + it('create a merkle proof and verify it with a single long key', function (t) { var trie = new Trie() async.series( [ - function(cb) { + function (cb) { trie.put( Buffer.from('key1aa'), Buffer.from('0123456789012345678901234567890123456789xx'), cb, ) }, - function(cb) { - Trie.prove(trie, Buffer.from('key1aa'), function(err, prove) { + function (cb) { + CheckpointTrie.prove(trie, Buffer.from('key1aa'), function (err, prove) { if (err) return cb(err) - Trie.verifyProof(trie.root, Buffer.from('key1aa'), prove, function(err, val) { + CheckpointTrie.verifyProof(trie.root, Buffer.from('key1aa'), prove!, function ( + err, + val, + ) { if (err) return cb(err) - t.equal(val.toString('utf8'), '0123456789012345678901234567890123456789xx') + t.equal(val!.toString('utf8'), '0123456789012345678901234567890123456789xx') cb() }) }) }, ], - function(err) { + function (err) { t.end(err) }, ) }) - it('create a merkle proof and verify it with a single short key', function(t) { + it('create a merkle proof and verify it with a single short key', function (t) { var trie = new Trie() async.series( [ - function(cb) { + function (cb) { trie.put(Buffer.from('key1aa'), Buffer.from('01234'), cb) }, - function(cb) { - Trie.prove(trie, Buffer.from('key1aa'), function(err, prove) { + function (cb) { + CheckpointTrie.prove(trie, Buffer.from('key1aa'), function (err, prove) { if (err) return cb(err) - Trie.verifyProof(trie.root, Buffer.from('key1aa'), prove, function(err, val) { + CheckpointTrie.verifyProof(trie.root, Buffer.from('key1aa'), prove!, function ( + err, + val, + ) { if (err) return cb(err) - t.equal(val.toString('utf8'), '01234') + t.equal(val!.toString('utf8'), '01234') cb() }) }) }, ], - function(err) { + function (err) { t.end(err) }, ) }) - it('create a merkle proof and verify it with keys in the middle', function(t) { + it('create a merkle proof and verify it with keys in the middle', function (t) { var trie = new Trie() async.series( [ - function(cb) { + function (cb) { trie.put( Buffer.from('key1aa'), Buffer.from('0123456789012345678901234567890123456789xxx'), cb, ) }, - function(cb) { + function (cb) { trie.put( Buffer.from('key1'), Buffer.from('0123456789012345678901234567890123456789Very_Long'), cb, ) }, - function(cb) { + function (cb) { trie.put(Buffer.from('key2bb'), Buffer.from('aval3'), cb) }, - function(cb) { + function (cb) { trie.put(Buffer.from('key2'), Buffer.from('short'), cb) }, - function(cb) { + function (cb) { trie.put(Buffer.from('key3cc'), Buffer.from('aval3'), cb) }, - function(cb) { + function (cb) { trie.put(Buffer.from('key3'), Buffer.from('1234567890123456789012345678901'), cb) }, - function(cb) { - Trie.prove(trie, 'key1', function(err, prove) { + function (cb) { + CheckpointTrie.prove(trie, Buffer.from('key1'), function (err, prove) { if (err) return cb(err) - Trie.verifyProof(trie.root, Buffer.from('key1'), prove, function(err, val) { + CheckpointTrie.verifyProof(trie.root, Buffer.from('key1'), prove!, function (err, val) { if (err) return cb(err) - t.equal(val.toString('utf8'), '0123456789012345678901234567890123456789Very_Long') + t.equal(val!.toString('utf8'), '0123456789012345678901234567890123456789Very_Long') cb() }) }) }, - function(cb) { - Trie.prove(trie, 'key2', function(err, prove) { + function (cb) { + CheckpointTrie.prove(trie, Buffer.from('key2'), function (err, prove) { if (err) return cb(err) - Trie.verifyProof(trie.root, Buffer.from('key2'), prove, function(err, val) { + CheckpointTrie.verifyProof(trie.root, Buffer.from('key2'), prove!, function (err, val) { if (err) return cb(err) - t.equal(val.toString('utf8'), 'short') + t.equal(val!.toString('utf8'), 'short') cb() }) }) }, - function(cb) { - Trie.prove(trie, 'key3', function(err, prove) { + function (cb) { + CheckpointTrie.prove(trie, Buffer.from('key3'), function (err, prove) { if (err) return cb(err) - Trie.verifyProof(trie.root, Buffer.from('key3'), prove, function(err, val) { + CheckpointTrie.verifyProof(trie.root, Buffer.from('key3'), prove!, function (err, val) { if (err) return cb(err) - t.equal(val.toString('utf8'), '1234567890123456789012345678901') + t.equal(val!.toString('utf8'), '1234567890123456789012345678901') cb() }) }) }, ], - function(err) { + function (err) { t.end(err) }, ) }) - it('should succeed with a simple embedded extension-branch', function(t) { + it('should succeed with a simple embedded extension-branch', function (t) { var trie = new Trie() async.series( [ - cb => { + (cb) => { trie.put(Buffer.from('a'), Buffer.from('a'), cb) }, - cb => { + (cb) => { trie.put(Buffer.from('b'), Buffer.from('b'), cb) }, - cb => { + (cb) => { trie.put(Buffer.from('c'), Buffer.from('c'), cb) }, - cb => { - Trie.prove(trie, Buffer.from('a'), function(err, prove) { + (cb) => { + CheckpointTrie.prove(trie, Buffer.from('a'), function (err, prove) { if (err) return cb(err) - Trie.verifyProof(trie.root, Buffer.from('a'), prove, function(err, val) { + CheckpointTrie.verifyProof(trie.root, Buffer.from('a'), prove!, function (err, val) { if (err) return cb(err) - t.equal(val.toString('utf8'), 'a') + t.equal(val!.toString('utf8'), 'a') cb() }) }) }, - cb => { - Trie.prove(trie, Buffer.from('b'), function(err, prove) { + (cb) => { + CheckpointTrie.prove(trie, Buffer.from('b'), function (err, prove) { if (err) return cb(err) - Trie.verifyProof(trie.root, Buffer.from('b'), prove, function(err, val) { + CheckpointTrie.verifyProof(trie.root, Buffer.from('b'), prove!, function (err, val) { if (err) return cb(err) - t.equal(val.toString('utf8'), 'b') + t.equal(val!.toString('utf8'), 'b') cb() }) }) }, - cb => { - Trie.prove(trie, Buffer.from('c'), function(err, prove) { + (cb) => { + CheckpointTrie.prove(trie, Buffer.from('c'), function (err, prove) { if (err) return cb(err) - Trie.verifyProof(trie.root, Buffer.from('c'), prove, function(err, val) { + CheckpointTrie.verifyProof(trie.root, Buffer.from('c'), prove!, function (err, val) { if (err) return cb(err) - t.equal(val.toString('utf8'), 'c') + t.equal(val!.toString('utf8'), 'c') cb() }) }) }, ], - function(err) { + function (err) { t.end(err) }, ) diff --git a/test/scratch.js b/test/scratch.spec.ts similarity index 77% rename from test/scratch.js rename to test/scratch.spec.ts index 9bd6905..4a9a3e7 100644 --- a/test/scratch.js +++ b/test/scratch.spec.ts @@ -1,10 +1,12 @@ -const tape = require('tape') +import * as tape from 'tape' const ScratchDB = require('../dist/scratch').ScratchDB const DB = require('../dist/db').DB +import { DB as IDB } from '../dist/db' +import { ScratchDB as IScratchDB } from '../dist/scratch' tape('ScratchDB', (t) => { - const upstream = new DB() - const scratch = new ScratchDB(upstream) + const upstream = new DB() as IDB + const scratch = new ScratchDB(upstream) as IScratchDB const k = Buffer.from('foo') const v = Buffer.from('bar') @@ -23,7 +25,7 @@ tape('ScratchDB', (t) => { scratch.put(k, v, () => { scratch.get(k, (err, res) => { st.error(err) - st.ok(v.equals(res)) + st.ok(v.equals(res!)) st.end() }) }) @@ -41,7 +43,7 @@ tape('ScratchDB', (t) => { upstream.put(k2, v2, () => { upstream.get(k2, (err, res) => { st.error(err) - st.ok(v2.equals(res)) + st.ok(v2.equals(res!)) st.end() }) }) @@ -50,7 +52,7 @@ tape('ScratchDB', (t) => { t.test('scratch should get value from upstream', (st) => { scratch.get(k2, (err, res) => { st.error(err) - st.ok(v2.equals(res)) + st.ok(v2.equals(res!)) st.end() }) }) diff --git a/test/secure.js b/test/secure.js deleted file mode 100644 index 4417008..0000000 --- a/test/secure.js +++ /dev/null @@ -1,105 +0,0 @@ -const Trie = require('../dist/secure').SecureTrie -const async = require('async') -const tape = require('tape') - -tape('SecureTrie', function(t) { - const trie = new Trie() - const k = Buffer.from('foo') - const v = Buffer.from('bar') - - t.test('put and get value', function(st) { - trie.put(k, v, function() { - trie.get(k, function(err, res) { - st.error(err) - st.ok(v.equals(res)) - st.end() - }) - }) - }) - - t.test('copy trie', function(st) { - const t = trie.copy() - t.get(k, function(err, res) { - st.error(err) - st.ok(v.equals(res)) - st.end() - }) - }) -}) - -tape('SecureTrie proof', function(t) { - t.test('create a merkle proof and verify it with a single short key', function(st) { - const trie = new Trie() - - async.series( - [ - function(cb) { - trie.put(Buffer.from('key1aa'), Buffer.from('01234'), cb) - }, - function(cb) { - Trie.prove(trie, Buffer.from('key1aa'), function(err, prove) { - if (err) return cb(err) - Trie.verifyProof(trie.root, Buffer.from('key1aa'), prove, function(err, val) { - if (err) return cb(err) - st.equal(val.toString('utf8'), '01234') - cb() - }) - }) - }, - ], - function(err) { - st.end(err) - }, - ) - }) -}) - -tape('secure tests', function(it) { - let trie = new Trie() - const jsonTests = require('./fixture/trietest_secureTrie.json').tests - - it.test('empty values', function(t) { - async.eachSeries( - jsonTests.emptyValues.in, - function(row, cb) { - trie.put(Buffer.from(row[0]), row[1] ? Buffer.from(row[1]) : null, cb) - }, - function(err) { - t.equal('0x' + trie.root.toString('hex'), jsonTests.emptyValues.root) - t.end(err) - }, - ) - }) - - it.test('branchingTests', function(t) { - trie = new Trie() - async.eachSeries( - jsonTests.branchingTests.in, - function(row, cb) { - trie.put(Buffer.from(row[0]), row[1] ? Buffer.from(row[1]) : null, cb) - }, - function() { - t.equal('0x' + trie.root.toString('hex'), jsonTests.branchingTests.root) - t.end() - }, - ) - }) - - it.test('jeff', function(t) { - async.eachSeries( - jsonTests.jeff.in, - function(row, cb) { - var val = row[1] - if (val) { - val = new Buffer(row[1].slice(2), 'hex') - } - - trie.put(new Buffer(row[0].slice(2), 'hex'), val, cb) - }, - function() { - t.equal('0x' + trie.root.toString('hex'), jsonTests.jeff.root.toString('hex')) - t.end() - }, - ) - }) -}) diff --git a/test/secure.spec.ts b/test/secure.spec.ts new file mode 100644 index 0000000..128e870 --- /dev/null +++ b/test/secure.spec.ts @@ -0,0 +1,114 @@ +import * as tape from 'tape' +import * as async from 'async' +const Trie = require('../dist/secure').SecureTrie +import { SecureTrie } from '../dist/secure' + +tape('SecureTrie', function (t) { + const trie = new Trie() as SecureTrie + const k = Buffer.from('foo') + const v = Buffer.from('bar') + + t.test('put and get value', function (st) { + trie.put(k, v, function () { + trie.get(k, function (err, res) { + st.error(err) + st.ok(v.equals(res!)) + st.end() + }) + }) + }) + + t.test('copy trie', function (st) { + const t = trie.copy() + t.get(k, function (err, res) { + st.error(err) + st.ok(v.equals(res!)) + st.end() + }) + }) +}) + +tape('SecureTrie proof', function (t) { + t.test('create a merkle proof and verify it with a single short key', function (st) { + const trie = new Trie() + + async.series( + [ + function (cb) { + trie.put(Buffer.from('key1aa'), Buffer.from('01234'), cb) + }, + function (cb) { + SecureTrie.prove(trie, Buffer.from('key1aa'), function (err, prove) { + if (err) return cb(err) + SecureTrie.verifyProof(trie.root, Buffer.from('key1aa'), prove!, function (err, val) { + if (err) return cb(err) + st.equal(val!.toString('utf8'), '01234') + cb() + }) + }) + }, + ], + function (err) { + st.end(err) + }, + ) + }) +}) + +tape('secure tests', function (it) { + let trie = new Trie() as SecureTrie + const jsonTests = require('./fixtures/trietest_secureTrie.json').tests + + it.test('empty values', function (t) { + async.eachSeries( + jsonTests.emptyValues.in, + function (row: any, cb) { + trie.put( + Buffer.from(row[0]), + row[1] ? Buffer.from(row[1]) : ((null as unknown) as Buffer), + cb, + ) + }, + function (err) { + t.equal('0x' + trie.root.toString('hex'), jsonTests.emptyValues.root) + t.end(err) + }, + ) + }) + + it.test('branchingTests', function (t) { + trie = new Trie() + async.eachSeries( + jsonTests.branchingTests.in, + function (row: any, cb) { + trie.put( + Buffer.from(row[0]), + row[1] ? Buffer.from(row[1]) : ((null as unknown) as Buffer), + cb, + ) + }, + function () { + t.equal('0x' + trie.root.toString('hex'), jsonTests.branchingTests.root) + t.end() + }, + ) + }) + + it.test('jeff', function (t) { + async.eachSeries( + jsonTests.jeff.in, + function (row: any, cb) { + var val = row[1] + if (val) { + val = Buffer.from(row[1].slice(2), 'hex') + } + + trie.put(Buffer.from(row[0].slice(2), 'hex'), val, cb) + }, + function () { + t.equal('0x' + trie.root.toString('hex'), jsonTests.jeff.root.toString('hex')) + t.end() + }, + ) + }) +}) diff --git a/test/streams.js b/test/streams.spec.ts similarity index 81% rename from test/streams.js rename to test/streams.spec.ts index dfb0d5d..23aa9dc 100644 --- a/test/streams.js +++ b/test/streams.spec.ts @@ -1,9 +1,11 @@ +import * as tape from 'tape' const Trie = require('../dist/index').CheckpointTrie -const describe = require('tape') +import { CheckpointTrie } from '../dist/checkpointTrie' +import { BatchDBOp } from '../dist/db' -describe('kv stream test', function(tester) { +tape('kv stream test', function (tester) { var it = tester.test - var trie = new Trie() + var trie = new Trie() as CheckpointTrie var init = [ { type: 'del', @@ -89,26 +91,28 @@ describe('kv stream test', function(tester) { key: Buffer.from('occupssation'), value: Buffer.from('Clown'), }, - ] + ] as BatchDBOp[] - var valObj = {} - init.forEach(function(i) { - if (i.type === 'put') valObj[i.key] = i.value + var valObj = {} as any + init.forEach(function (i) { + if (i.type === 'put') { + valObj[String(i.key)] = i.value + } }) - it('should populate trie', function(t) { - trie.batch(init, function() { + it('should populate trie', function (t) { + trie.batch(init, function () { t.end() }) }) - it('should fetch all of the nodes', function(t) { + it('should fetch all of the nodes', function (t) { var stream = trie.createReadStream() - stream.on('data', function(d) { + stream.on('data', function (d: any) { t.equal(valObj[d.key.toString()].toString(), d.value.toString()) delete valObj[d.key.toString()] }) - stream.on('end', function() { + stream.on('end', function () { var keys = Object.keys(valObj) t.equal(keys.length, 0) t.end() @@ -116,7 +120,7 @@ describe('kv stream test', function(tester) { }) }) -describe('db stream test', function(tester) { +tape('db stream test', function (tester) { var it = tester.test var trie = new Trie() var init = [ @@ -158,21 +162,21 @@ describe('db stream test', function(tester) { e64329dadee2fb8a113b4c88cfe973aeaa9b523d4dc8510b84ca23f9d5bfbd90: true, c916d458bfb5f27603c5bd93b00f022266712514a59cde749f19220daffc743f: true, '2386bfb0de9cf93902a110f5ab07b917ffc0b9ea599cb7f4f8bb6fd1123c866c': true, - } + } as any - it('should populate trie', function(t) { + it('should populate trie', function (t) { trie.checkpoint() trie.batch(init, t.end) }) - it('should only fetch nodes in the current trie', function(t) { + it('should only fetch nodes in the current trie', function (t) { var stream = trie._createScratchReadStream() - stream.on('data', function(d) { + stream.on('data', function (d: any) { var key = d.key.toString('hex') t.ok(!!expectedNodes[key]) delete expectedNodes[key] }) - stream.on('end', function() { + stream.on('end', function () { t.equal(Object.keys(expectedNodes).length, 0) t.end() }) diff --git a/tsconfig.json b/tsconfig.json index 68b5c24..4782753 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,4 +1,4 @@ { "extends": "@ethereumjs/config-tsc", - "include": ["src/**/*.ts"] + "include": ["src/**/*.ts"], }