From fbb250028132cd9d32ce947a3f5a0781f0f1b899 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Mon, 3 Jul 2017 14:40:31 -0700 Subject: [PATCH] layout: aggressive asserts. --- lib/blockchain/layout-browser.js | 46 +++++++++++++++-------- lib/blockchain/layout.js | 56 ++++++++++++++++++++-------- lib/mempool/layout-browser.js | 7 +++- lib/mempool/layout.js | 5 +++ lib/utils/util.js | 4 ++ lib/wallet/layout-browser.js | 27 ++++++++++++++ lib/wallet/layout.js | 63 ++++++++++++++++++++++++++++++++ 7 files changed, 176 insertions(+), 32 deletions(-) diff --git a/lib/blockchain/layout-browser.js b/lib/blockchain/layout-browser.js index d5eb315e..03b3fd49 100644 --- a/lib/blockchain/layout-browser.js +++ b/lib/blockchain/layout-browser.js @@ -6,6 +6,7 @@ 'use strict'; +const assert = require('assert'); const util = require('../utils/util'); const pad8 = util.pad8; const pad32 = util.pad32; @@ -46,44 +47,58 @@ const layout = { return 'v' + pad8(bit) + hex(hash); }, vv: function vv(key) { + assert(typeof key === 'string'); + assert(key.length === 36); return [+key.slice(1, 4), key.slice(4, 36)]; }, - T: function T(address, hash) { - address = hex(address); + T: function T(addr, hash) { + addr = hex(addr); - if (address.length === 64) - return 'W' + address + hex(hash); + if (addr.length === 64) + return 'W' + addr + hex(hash); - return 'T' + address + hex(hash); + assert(addr.length === 40); + return 'T' + addr + hex(hash); }, - C: function C(address, hash, index) { - address = hex(address); + C: function C(addr, hash, index) { + addr = hex(addr); - if (address.length === 64) - return 'X' + address + hex(hash) + pad32(index); + if (addr.length === 64) + return 'X' + addr + hex(hash) + pad32(index); - return 'C' + address + hex(hash) + pad32(index); + assert(addr.length === 40); + return 'C' + addr + hex(hash) + pad32(index); }, pp: function aa(key) { + assert(typeof key === 'string'); + assert(key.length === 65); return key.slice(1, 65); }, Cc: function Cc(key) { let hash, index; + assert(typeof key === 'string'); + if (key.length === 139) { hash = key.slice(65, 129); index = +key.slice(129); - } else { + } else if (key.length === 115) { hash = key.slice(41, 105); index = +key.slice(105); + } else { + assert(false); } return [hash, index]; }, Tt: function Tt(key) { - return key.length === 129 - ? key.slice(64) - : key.slice(41); + assert(typeof key === 'string'); + + if (key.length === 129) + return key.slice(64); + + assert(key.length === 105); + return key.slice(41); } }; @@ -92,8 +107,9 @@ const layout = { */ function hex(hash) { - if (typeof hash !== 'string') + if (Buffer.isBuffer(hash)) hash = hash.toString('hex'); + assert(typeof hash === 'string'); return hash; } diff --git a/lib/blockchain/layout.js b/lib/blockchain/layout.js index e0c667e0..7ea8c5c8 100644 --- a/lib/blockchain/layout.js +++ b/lib/blockchain/layout.js @@ -6,6 +6,8 @@ 'use strict'; +const assert = require('assert'); + /* * Database Layout: * R -> tip hash @@ -61,78 +63,97 @@ const layout = { }, v: function v(bit, hash) { let key = Buffer.allocUnsafe(1 + 1 + 32); + assert(typeof bit === 'number'); key[0] = 0x76; key[1] = bit; write(key, hash, 2); return key; }, vv: function vv(key) { + assert(Buffer.isBuffer(key)); + assert(key.length === 34); return [key[1], key.toString('hex', 2, 34)]; }, - T: function T(address, hash) { - let len = address.length; + T: function T(addr, hash) { + let len = addr.length; let key; - if (typeof address === 'string') + if (typeof addr === 'string') len /= 2; if (len === 32) { key = Buffer.allocUnsafe(65); key[0] = 0xab; // W + T - write(key, address, 1); + write(key, addr, 1); write(key, hash, 33); - } else { + } else if (len === 20) { key = Buffer.allocUnsafe(53); key[0] = 0x54; // T - write(key, address, 1); + write(key, addr, 1); write(key, hash, 21); + } else { + assert(false); } return key; }, - C: function C(address, hash, index) { - let len = address.length; + C: function C(addr, hash, index) { + let len = addr.length; let key; - if (typeof address === 'string') + assert(typeof index === 'number'); + + if (typeof addr === 'string') len /= 2; if (len === 32) { key = Buffer.allocUnsafe(69); key[0] = 0x9a; // W + C - write(key, address, 1); + write(key, addr, 1); write(key, hash, 33); key.writeUInt32BE(index, 65, true); - } else { + } else if (len === 20) { key = Buffer.allocUnsafe(57); key[0] = 0x43; // C - write(key, address, 1); + write(key, addr, 1); write(key, hash, 21); key.writeUInt32BE(index, 53, true); + } else { + assert(false); } return key; }, pp: function aa(key) { + assert(Buffer.isBuffer(key)); + assert(key.length === 33); return key.toString('hex', 1, 33); }, Cc: function Cc(key) { let hash, index; + assert(Buffer.isBuffer(key)); + if (key.length === 69) { hash = key.toString('hex', 33, 65); index = key.readUInt32BE(65, 0); - } else { + } else if (key.length === 57) { hash = key.toString('hex', 21, 53); index = key.readUInt32BE(53, 0); + } else { + assert(false); } return [hash, index]; }, Tt: function Tt(key) { - return key.length === 65 - ? key.toString('hex', 33, 65) - : key.toString('hex', 21, 53); + assert(Buffer.isBuffer(key)); + + if (key.length === 65) + return key.toString('hex', 33, 65); + + assert(key.length === 53); + return key.toString('hex', 21, 53); } }; @@ -143,6 +164,7 @@ const layout = { function write(data, str, off) { if (Buffer.isBuffer(str)) return str.copy(data, off); + assert(typeof str === 'string'); data.write(str, off, 'hex'); } @@ -155,6 +177,7 @@ function pair(prefix, hash) { function ipair(prefix, num) { let key = Buffer.allocUnsafe(5); + assert(typeof num === 'number'); key[0] = prefix; key.writeUInt32BE(num, 1, true); return key; @@ -162,6 +185,7 @@ function ipair(prefix, num) { function bpair(prefix, hash, index) { let key = Buffer.allocUnsafe(37); + assert(typeof index === 'number'); key[0] = prefix; write(key, hash, 1); key.writeUInt32BE(index, 33, true); diff --git a/lib/mempool/layout-browser.js b/lib/mempool/layout-browser.js index e4833ea5..b7da4bb4 100644 --- a/lib/mempool/layout-browser.js +++ b/lib/mempool/layout-browser.js @@ -6,6 +6,8 @@ 'use strict'; +const assert = require('assert'); + const layout = { binary: false, R: 'R', @@ -15,6 +17,8 @@ const layout = { return 'e' + hex(hash); }, ee: function ee(key) { + assert(typeof key === 'string'); + assert(key.length === 65); return key.slice(1, 65); } }; @@ -24,8 +28,9 @@ const layout = { */ function hex(hash) { - if (typeof hash !== 'string') + if (Buffer.isBuffer(hash)) hash = hash.toString('hex'); + assert(typeof hash === 'string'); return hash; } diff --git a/lib/mempool/layout.js b/lib/mempool/layout.js index ae4c26fd..3fac1d64 100644 --- a/lib/mempool/layout.js +++ b/lib/mempool/layout.js @@ -6,6 +6,8 @@ 'use strict'; +const assert = require('assert'); + /* * Database Layout: * R -> tip hash @@ -25,6 +27,8 @@ const layout = { return key; }, ee: function ee(key) { + assert(Buffer.isBuffer(key)); + assert(key.length === 33); return key.toString('hex', 1, 33); } }; @@ -36,6 +40,7 @@ const layout = { function write(data, str, off) { if (Buffer.isBuffer(str)) return str.copy(data, off); + assert(typeof str === 'string'); data.write(str, off, 'hex'); } diff --git a/lib/utils/util.js b/lib/utils/util.js index 72f9ecf0..8bb2f8a2 100644 --- a/lib/utils/util.js +++ b/lib/utils/util.js @@ -540,6 +540,7 @@ util.indexOf = function indexOf(items, data) { */ util.pad8 = function pad8(num) { + assert(typeof num === 'number'); assert(num >= 0); num = num + ''; switch (num.length) { @@ -561,6 +562,7 @@ util.pad8 = function pad8(num) { */ util.pad32 = function pad32(num) { + assert(typeof num === 'number'); assert(num >= 0); num = num + ''; switch (num.length) { @@ -597,6 +599,7 @@ util.pad32 = function pad32(num) { */ util.hex8 = function hex8(num) { + assert(typeof num === 'number'); assert(num >= 0); num = num.toString(16); switch (num.length) { @@ -617,6 +620,7 @@ util.hex8 = function hex8(num) { */ util.hex32 = function hex32(num) { + assert(typeof num === 'number'); assert(num >= 0); num = num.toString(16); switch (num.length) { diff --git a/lib/wallet/layout-browser.js b/lib/wallet/layout-browser.js index 9b0e14ac..e1617bf9 100644 --- a/lib/wallet/layout-browser.js +++ b/lib/wallet/layout-browser.js @@ -6,6 +6,7 @@ 'use strict'; +const assert = require('assert'); const util = require('../utils/util'); const pad32 = util.pad32; const layouts = exports; @@ -13,42 +14,53 @@ const layouts = exports; layouts.walletdb = { binary: false, p: function p(hash) { + assert(typeof hash === 'string'); return 'p' + hash; }, pp: function pp(key) { + assert(typeof key === 'string'); return key.slice(1); }, P: function P(wid, hash) { + assert(typeof hash === 'string'); return 'p' + pad32(wid) + hash; }, Pp: function Pp(key) { + assert(typeof key === 'string'); return key.slice(11); }, r: function r(wid, index, hash) { + assert(typeof hash === 'string'); return 'r' + pad32(wid) + pad32(index) + hash; }, rr: function rr(key) { + assert(typeof key === 'string'); return key.slice(21); }, w: function w(wid) { return 'w' + pad32(wid); }, ww: function ww(key) { + assert(typeof key === 'string'); return +key.slice(1); }, l: function l(id) { + assert(typeof id === 'string'); return 'l' + id; }, ll: function ll(key) { + assert(typeof key === 'string'); return key.slice(1); }, a: function a(wid, index) { return 'a' + pad32(wid) + pad32(index); }, i: function i(wid, name) { + assert(typeof name === 'string'); return 'i' + pad32(wid) + name; }, ii: function ii(key) { + assert(typeof key === 'string'); return [+key.slice(1, 11), key.slice(11)]; }, n: function n(wid, index) { @@ -62,9 +74,11 @@ layouts.walletdb = { return 'b' + pad32(height); }, bb: function bb(key) { + assert(typeof key === 'string'); return +key.slice(1); }, o: function o(hash, index) { + assert(typeof hash === 'string'); return 'o' + hash + pad32(index); }, oo: function oo(key) { @@ -75,44 +89,56 @@ layouts.walletdb = { layouts.txdb = { binary: false, prefix: function prefix(wid, key) { + assert(typeof key === 'string'); return 't' + pad32(wid) + key; }, pre: function prefix(key) { + assert(typeof key === 'string'); return +key.slice(1, 11); }, R: 'R', hi: function hi(ch, hash, index) { + assert(typeof hash === 'string'); return ch + hash + pad32(index); }, hii: function hii(key) { + assert(typeof key === 'string'); key = key.slice(12); return [key.slice(0, 64), +key.slice(64)]; }, ih: function ih(ch, index, hash) { + assert(typeof hash === 'string'); return ch + pad32(index) + hash; }, ihh: function ihh(key) { + assert(typeof key === 'string'); key = key.slice(12); return [+key.slice(0, 10), key.slice(10)]; }, iih: function iih(ch, index, num, hash) { + assert(typeof hash === 'string'); return ch + pad32(index) + pad32(num) + hash; }, iihh: function iihh(key) { + assert(typeof key === 'string'); key = key.slice(12); return [+key.slice(0, 10), +key.slice(10, 20), key.slice(20)]; }, ihi: function ihi(ch, index, hash, num) { + assert(typeof hash === 'string'); return ch + pad32(index) + hash + pad32(num); }, ihii: function ihii(key) { + assert(typeof key === 'string'); key = key.slice(12); return [+key.slice(0, 10), key.slice(10, 74), +key.slice(74)]; }, ha: function ha(ch, hash) { + assert(typeof hash === 'string'); return ch + hash; }, haa: function haa(key) { + assert(typeof key === 'string'); key = key.slice(12); return key; }, @@ -201,6 +227,7 @@ layouts.txdb = { return 'b' + pad32(height); }, bb: function bb(key) { + assert(typeof key === 'string'); key = key.slice(12); return +key.slice(0); } diff --git a/lib/wallet/layout.js b/lib/wallet/layout.js index fb07f95b..6aaa8329 100644 --- a/lib/wallet/layout.js +++ b/lib/wallet/layout.js @@ -6,6 +6,7 @@ 'use strict'; +const assert = require('assert'); const layouts = exports; /* @@ -29,25 +30,35 @@ layouts.walletdb = { binary: true, p: function p(hash) { let key = Buffer.allocUnsafe(1 + (hash.length / 2)); + assert(typeof hash === 'string'); key[0] = 0x70; key.write(hash, 1, 'hex'); return key; }, pp: function pp(key) { + assert(Buffer.isBuffer(key)); + assert(key.length >= 21); return key.toString('hex', 1); }, P: function P(wid, hash) { let key = Buffer.allocUnsafe(1 + 4 + (hash.length / 2)); + assert(typeof wid === 'number'); + assert(typeof hash === 'string'); key[0] = 0x50; key.writeUInt32BE(wid, 1, true); key.write(hash, 5, 'hex'); return key; }, Pp: function Pp(key) { + assert(Buffer.isBuffer(key)); + assert(key.length >= 25); return key.toString('hex', 5); }, r: function r(wid, index, hash) { let key = Buffer.allocUnsafe(1 + 4 + 4 + (hash.length / 2)); + assert(typeof wid === 'number'); + assert(typeof index === 'number'); + assert(typeof hash === 'string'); key[0] = 0x72; key.writeUInt32BE(wid, 1, true); key.writeUInt32BE(index, 5, true); @@ -55,30 +66,40 @@ layouts.walletdb = { return key; }, rr: function rr(key) { + assert(Buffer.isBuffer(key)); + assert(key.length >= 29); return key.toString('hex', 9); }, w: function w(wid) { let key = Buffer.allocUnsafe(5); + assert(typeof wid === 'number'); key[0] = 0x77; key.writeUInt32BE(wid, 1, true); return key; }, ww: function ww(key) { + assert(Buffer.isBuffer(key)); + assert(key.length === 5); return key.readUInt32BE(1, true); }, l: function l(id) { let len = Buffer.byteLength(id, 'ascii'); let key = Buffer.allocUnsafe(1 + len); + assert(typeof id === 'string'); key[0] = 0x6c; if (len > 0) key.write(id, 1, 'ascii'); return key; }, ll: function ll(key) { + assert(Buffer.isBuffer(key)); + assert(key.length >= 1); return key.toString('ascii', 1); }, a: function a(wid, index) { let key = Buffer.allocUnsafe(9); + assert(typeof wid === 'number'); + assert(typeof index === 'number'); key[0] = 0x61; key.writeUInt32BE(wid, 1, true); key.writeUInt32BE(index, 5, true); @@ -87,6 +108,8 @@ layouts.walletdb = { i: function i(wid, name) { let len = Buffer.byteLength(name, 'ascii'); let key = Buffer.allocUnsafe(5 + len); + assert(typeof wid === 'number'); + assert(typeof name === 'string'); key[0] = 0x69; key.writeUInt32BE(wid, 1, true); if (len > 0) @@ -94,10 +117,14 @@ layouts.walletdb = { return key; }, ii: function ii(key) { + assert(Buffer.isBuffer(key)); + assert(key.length >= 5); return [key.readUInt32BE(1, true), key.toString('ascii', 5)]; }, n: function n(wid, index) { let key = Buffer.allocUnsafe(9); + assert(typeof wid === 'number'); + assert(typeof index === 'number'); key[0] = 0x6e; key.writeUInt32BE(wid, 1, true); key.writeUInt32BE(index, 5, true); @@ -106,27 +133,35 @@ layouts.walletdb = { R: Buffer.from([0x52]), h: function h(height) { let key = Buffer.allocUnsafe(5); + assert(typeof height === 'number'); key[0] = 0x68; key.writeUInt32BE(height, 1, true); return key; }, b: function b(height) { let key = Buffer.allocUnsafe(5); + assert(typeof height === 'number'); key[0] = 0x62; key.writeUInt32BE(height, 1, true); return key; }, bb: function bb(key) { + assert(Buffer.isBuffer(key)); + assert(key.length === 5); return key.readUInt32BE(1, true); }, o: function o(hash, index) { let key = Buffer.allocUnsafe(37); + assert(typeof hash === 'string'); + assert(typeof index === 'number'); key[0] = 0x6f; key.write(hash, 1, 'hex'); key.writeUInt32BE(index, 33, true); return key; }, oo: function oo(key) { + assert(Buffer.isBuffer(key)); + assert(key.length === 37); return [key.toString('hex', 1, 33), key.readUInt32BE(33, true)]; } }; @@ -153,39 +188,54 @@ layouts.txdb = { binary: true, prefix: function prefix(wid, key) { let out = Buffer.allocUnsafe(5 + key.length); + assert(typeof wid === 'number'); + assert(Buffer.isBuffer(key)); out[0] = 0x74; out.writeUInt32BE(wid, 1); key.copy(out, 5); return out; }, pre: function prefix(key) { + assert(Buffer.isBuffer(key)); + assert(key.length >= 5); return key.readUInt32BE(1, true); }, R: Buffer.from([0x52]), hi: function hi(ch, hash, index) { let key = Buffer.allocUnsafe(37); + assert(typeof hash === 'string'); + assert(typeof index === 'number'); key[0] = ch; key.write(hash, 1, 'hex'); key.writeUInt32BE(index, 33, true); return key; }, hii: function hii(key) { + assert(Buffer.isBuffer(key)); + assert(key.length - 5 === 37); key = key.slice(6); return [key.toString('hex', 0, 32), key.readUInt32BE(32, true)]; }, ih: function ih(ch, index, hash) { let key = Buffer.allocUnsafe(37); + assert(typeof index === 'number'); + assert(typeof hash === 'string'); key[0] = ch; key.writeUInt32BE(index, 1, true); key.write(hash, 5, 'hex'); return key; }, ihh: function ihh(key) { + assert(Buffer.isBuffer(key)); + assert(key.length - 5 === 37); key = key.slice(6); return [key.readUInt32BE(0, true), key.toString('hex', 4, 36)]; }, iih: function iih(ch, index, num, hash) { let key = Buffer.allocUnsafe(41); + assert(typeof index === 'number'); + assert(typeof num === 'number'); + assert(typeof hash === 'string'); key[0] = ch; key.writeUInt32BE(index, 1, true); key.writeUInt32BE(num, 5, true); @@ -193,6 +243,8 @@ layouts.txdb = { return key; }, iihh: function iihh(key) { + assert(Buffer.isBuffer(key)); + assert(key.length - 5 === 41); key = key.slice(6); return [ key.readUInt32BE(0, true), @@ -202,6 +254,9 @@ layouts.txdb = { }, ihi: function ihi(ch, index, hash, num) { let key = Buffer.allocUnsafe(41); + assert(typeof index === 'number'); + assert(typeof hash === 'string'); + assert(typeof num === 'number'); key[0] = ch; key.writeUInt32BE(index, 1, true); key.write(hash, 5, 'hex'); @@ -209,6 +264,8 @@ layouts.txdb = { return key; }, ihii: function ihii(key) { + assert(Buffer.isBuffer(key)); + assert(key.length - 5 === 41); key = key.slice(6); return [ key.readUInt32BE(0, true), @@ -218,11 +275,14 @@ layouts.txdb = { }, ha: function ha(ch, hash) { let key = Buffer.allocUnsafe(33); + assert(typeof hash === 'string'); key[0] = ch; key.write(hash, 1, 'hex'); return key; }, haa: function haa(key) { + assert(Buffer.isBuffer(key)); + assert(key.length - 5 === 33); key = key.slice(6); return key.toString('hex', 0); }, @@ -303,11 +363,14 @@ layouts.txdb = { }, b: function b(height) { let key = Buffer.allocUnsafe(5); + assert(typeof height === 'number'); key[0] = 0x62; key.writeUInt32BE(height, 1, true); return key; }, bb: function bb(key) { + assert(Buffer.isBuffer(key)); + assert(key.length - 5 === 5); key = key.slice(6); return key.readUInt32BE(0, true); }