From 49e4aa4158a73417061e811b1c920fdb89558312 Mon Sep 17 00:00:00 2001 From: Kagami Hiiragi Date: Mon, 16 Feb 2015 19:47:19 +0300 Subject: [PATCH] Add object.validate API --- lib/structs.js | 53 +++++++++++++++++++++++++++++++++++++++++++++----- tests/unit.js | 19 +++++++++++++++++- 2 files changed, 66 insertions(+), 6 deletions(-) diff --git a/lib/structs.js b/lib/structs.js index 6ce66bb..5c240ce 100644 --- a/lib/structs.js +++ b/lib/structs.js @@ -316,12 +316,13 @@ var object = exports.object = { * @param {Object=} opts - Decoding options * @param {boolean} opts.allowExpired - Allow expired objects * @param {boolean} opts.skipPow - Do not validate object POW - * @return {DecodeResult} - * [Decoded `object` structure.]{@link module:bitmessage/structs.object.DecodeResult} + * @return {DecodeResult} [Decoded `object` structure.]{@link + * module:bitmessage/structs.object.DecodeResult} + * @throws {Error} Invalid object */ decode: function(buf, opts) { var decoded = message.decode(buf); - assert(decoded.command === "object", "Bad command"); + assert(decoded.command === "object", "Given message is not an object"); return object.decodePayload(decoded.payload, opts); }, @@ -331,11 +332,15 @@ var object = exports.object = { */ decodePayload: function(buf, opts) { opts = opts || {}; + // 8 + 8 + 4 + (1+) + (1+) assert(buf.length >= 22, "object message payload is too small"); assert(buf.length <= 262144, "object message payload is too big"); - var nonce = new Buffer(8); - buf.copy(nonce, 0, 0, 8); + var nonce; + if (!opts._validate) { + nonce = new Buffer(8); + buf.copy(nonce, 0, 0, 8); + } // TTL. var expiresTime = util.readTimestamp64BE(buf.slice(8, 16)); @@ -358,6 +363,9 @@ var object = exports.object = { var decodedVersion = var_int.decode(buf.slice(20)); var decodedStream = var_int.decode(decodedVersion.rest); var headerLength = 20 + decodedVersion.length + decodedStream.length; + + if (opts._validate) { return; } + var objectPayload = new Buffer(decodedStream.rest.length); decodedStream.rest.copy(objectPayload); @@ -372,6 +380,41 @@ var object = exports.object = { }; }, + /** + * Check whether given `object` message is valid. + * @param {Buffer} buf - Message + * @param {Object=} opts - Any of [object.decode]{@link + * module:bitmessage/structs.object.decode} options + * @return {?Error} Return an error with description if object is + * invalid. + */ + validate: function(buf, opts) { + var decoded; + try { + decoded = message.decode(buf); + } catch(e) { + return e; + } + if (decoded.command !== "object") { + return new Error("Given message is not an object"); + } + return object.validatePayload(decoded.payload, opts); + }, + + /** + * Check whether `object` message payload is valid. + * The same as [validate]{@link + * module:bitmessage/structs.object.validate}. + */ + validatePayload: function(buf, opts) { + opts = objectAssign({}, opts, {_validate: true}); + try { + object.decodePayload(buf, opts); + } catch(e) { + return e; + } + }, + /** * Encode `object` message. * @param {Object} opts - Object options diff --git a/tests/unit.js b/tests/unit.js index 21d0574..ca921b1 100644 --- a/tests/unit.js +++ b/tests/unit.js @@ -114,7 +114,6 @@ describe("Crypto", function() { }); }); -// TODO(Kagami): Add tests for encodePayload/decodePayload as well. describe("Common structures", function() { describe("message", function() { it("should decode", function() { @@ -246,6 +245,24 @@ describe("Common structures", function() { objectPayload: Buffer("test"), }))).to.throw(/insufficient/i); }); + + it("should allow to validate object", function() { + var verackmsg = message.encode("verack"); + var err = object.validate(verackmsg); + expect(err.message).to.match(/not an object/i); + + var obj = object.encodePayload({ + nonce: Buffer(8), + ttl: 111, + type: object.MSG, + version: 1, + objectPayload: Buffer(0), + }); + err = object.validatePayload(obj); + expect(err.message).to.match(/insufficient pow/i); + + expect(object.validatePayload(obj, {skipPow: true})).to.not.exist; + }); }); describe("var_int", function() {