Add object.validate API

This commit is contained in:
Kagami Hiiragi 2015-02-16 19:47:19 +03:00
parent c2cd98fe7f
commit 49e4aa4158
2 changed files with 66 additions and 6 deletions

View File

@ -316,12 +316,13 @@ var object = exports.object = {
* @param {Object=} opts - Decoding options * @param {Object=} opts - Decoding options
* @param {boolean} opts.allowExpired - Allow expired objects * @param {boolean} opts.allowExpired - Allow expired objects
* @param {boolean} opts.skipPow - Do not validate object POW * @param {boolean} opts.skipPow - Do not validate object POW
* @return {DecodeResult} * @return {DecodeResult} [Decoded `object` structure.]{@link
* [Decoded `object` structure.]{@link module:bitmessage/structs.object.DecodeResult} * module:bitmessage/structs.object.DecodeResult}
* @throws {Error} Invalid object
*/ */
decode: function(buf, opts) { decode: function(buf, opts) {
var decoded = message.decode(buf); 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); return object.decodePayload(decoded.payload, opts);
}, },
@ -331,11 +332,15 @@ var object = exports.object = {
*/ */
decodePayload: function(buf, opts) { decodePayload: function(buf, opts) {
opts = opts || {}; opts = opts || {};
// 8 + 8 + 4 + (1+) + (1+) // 8 + 8 + 4 + (1+) + (1+)
assert(buf.length >= 22, "object message payload is too small"); assert(buf.length >= 22, "object message payload is too small");
assert(buf.length <= 262144, "object message payload is too big"); assert(buf.length <= 262144, "object message payload is too big");
var nonce = new Buffer(8); var nonce;
buf.copy(nonce, 0, 0, 8); if (!opts._validate) {
nonce = new Buffer(8);
buf.copy(nonce, 0, 0, 8);
}
// TTL. // TTL.
var expiresTime = util.readTimestamp64BE(buf.slice(8, 16)); 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 decodedVersion = var_int.decode(buf.slice(20));
var decodedStream = var_int.decode(decodedVersion.rest); var decodedStream = var_int.decode(decodedVersion.rest);
var headerLength = 20 + decodedVersion.length + decodedStream.length; var headerLength = 20 + decodedVersion.length + decodedStream.length;
if (opts._validate) { return; }
var objectPayload = new Buffer(decodedStream.rest.length); var objectPayload = new Buffer(decodedStream.rest.length);
decodedStream.rest.copy(objectPayload); 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. * Encode `object` message.
* @param {Object} opts - Object options * @param {Object} opts - Object options

View File

@ -114,7 +114,6 @@ describe("Crypto", function() {
}); });
}); });
// TODO(Kagami): Add tests for encodePayload/decodePayload as well.
describe("Common structures", function() { describe("Common structures", function() {
describe("message", function() { describe("message", function() {
it("should decode", function() { it("should decode", function() {
@ -246,6 +245,24 @@ describe("Common structures", function() {
objectPayload: Buffer("test"), objectPayload: Buffer("test"),
}))).to.throw(/insufficient/i); }))).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() { describe("var_int", function() {