aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--package.json2
-rw-r--r--src/ts/0x.js.ts3
-rw-r--r--src/ts/globals.d.ts4
-rw-r--r--src/ts/schemas/ec_signature_schema.ts20
-rw-r--r--src/ts/utils/assert.ts13
-rw-r--r--src/ts/utils/schema_validator.ts14
-rw-r--r--test/0x.js.ts16
7 files changed, 58 insertions, 14 deletions
diff --git a/package.json b/package.json
index f88442f37..950ad0d38 100644
--- a/package.json
+++ b/package.json
@@ -33,6 +33,7 @@
"devDependencies": {
"@types/bignumber.js": "^4.0.2",
"@types/chai": "^3.5.2",
+ "@types/jsonschema": "^1.1.1",
"@types/mocha": "^2.2.41",
"@types/node": "^7.0.22",
"awesome-typescript-loader": "^3.1.3",
@@ -54,6 +55,7 @@
"dependencies": {
"bignumber.js": "^4.0.2",
"ethereumjs-util": "^5.1.1",
+ "jsonschema": "^1.1.1",
"lodash": "^4.17.4",
"web3": "^0.19.0"
}
diff --git a/src/ts/0x.js.ts b/src/ts/0x.js.ts
index 89d049bec..d189b48b1 100644
--- a/src/ts/0x.js.ts
+++ b/src/ts/0x.js.ts
@@ -1,6 +1,7 @@
import * as BigNumber from 'bignumber.js';
import * as ethUtil from 'ethereumjs-util';
import {assert} from './utils/assert';
+import {ECSignatureSchema} from './schemas/ec_signature_schema';
/**
* Elliptic Curve signature
@@ -21,7 +22,7 @@ export class ZeroEx {
*/
public static isValidSignature(dataHex: string, signature: ECSignature, signer: ETHAddressHex): boolean {
assert.isHexString('dataHex', dataHex);
- assert.isObject('signature', signature);
+ assert.doesConformToSchema('signature', signature, ECSignatureSchema);
assert.isETHAddressHex('signer', signer);
const dataBuff = ethUtil.toBuffer(dataHex);
diff --git a/src/ts/globals.d.ts b/src/ts/globals.d.ts
index c9cc0d481..58efe136a 100644
--- a/src/ts/globals.d.ts
+++ b/src/ts/globals.d.ts
@@ -2,6 +2,10 @@ declare type ETHPublicKey = string;
declare type ETHAddressHex = string;
declare type ETHAddressBuff = Buffer;
+declare interface Schema {
+ id: string;
+}
+
declare module 'ethereumjs-util' {
const toBuffer: (dataHex: string) => Buffer;
const hashPersonalMessage: (msg: Buffer) => Buffer;
diff --git a/src/ts/schemas/ec_signature_schema.ts b/src/ts/schemas/ec_signature_schema.ts
new file mode 100644
index 000000000..94e58e53c
--- /dev/null
+++ b/src/ts/schemas/ec_signature_schema.ts
@@ -0,0 +1,20 @@
+export const ECSignatureParameter = {
+ id: '/ECSignatureParameter',
+ type: 'string',
+ pattern: '^0[xX][0-9A-Fa-f]{64}$',
+};
+
+export const ECSignatureSchema = {
+ id: '/ECSignature',
+ properties: {
+ v: {
+ type: 'number',
+ minimum: 27,
+ maximum: 28,
+ },
+ r: {$ref: '/ECSignatureParameter'},
+ s: {$ref: '/ECSignatureParameter'},
+ },
+ required: ['v', 'r', 's'],
+ type: 'object',
+};
diff --git a/src/ts/utils/assert.ts b/src/ts/utils/assert.ts
index 602361233..58182dac0 100644
--- a/src/ts/utils/assert.ts
+++ b/src/ts/utils/assert.ts
@@ -1,6 +1,7 @@
import * as _ from 'lodash';
import * as BigNumber from 'bignumber.js';
import Web3 = require('web3');
+import {SchemaValidator} from './schema_validator';
const HEX_REGEX = /^0x([0-9A-F]{2})*$/i;
@@ -20,12 +21,18 @@ export const assert = {
const web3 = new Web3();
this.assert(web3.isAddress(value), this.typeAssertionMessage(variableName, 'ETHAddressHex', value));
},
- isObject(variableName: string, value: object) {
- this.assert(_.isObject(value), this.typeAssertionMessage(variableName, 'object', value));
- },
isNumber(variableName: string, value: number) {
this.assert(_.isFinite(value), this.typeAssertionMessage(variableName, 'number', value));
},
+ doesConformToSchema(variableName: string, value: object, schema: Schema) {
+ const schemaValidator = new SchemaValidator();
+ const validationResult = schemaValidator.validate(value, schema);
+ const hasValidationErrors = validationResult.errors.length > 0;
+ const msg = `Expected ${variableName} to conform to schema ${schema.id}
+Encountered: ${JSON.stringify(value, null, '\t')}
+Validation errors: ${validationResult.errors.join(', ')}`;
+ this.assert(!hasValidationErrors, msg);
+ },
assert(condition: boolean, message: string) {
if (!condition) {
throw new Error(message);
diff --git a/src/ts/utils/schema_validator.ts b/src/ts/utils/schema_validator.ts
new file mode 100644
index 000000000..bd2f97d2b
--- /dev/null
+++ b/src/ts/utils/schema_validator.ts
@@ -0,0 +1,14 @@
+import {Validator, ValidatorResult} from 'jsonschema';
+import {ECSignatureSchema, ECSignatureParameter} from '../schemas/ec_signature_schema';
+
+export class SchemaValidator {
+ private validator: Validator;
+ constructor() {
+ this.validator = new Validator();
+ this.validator.addSchema(ECSignatureParameter, ECSignatureParameter.id);
+ this.validator.addSchema(ECSignatureSchema, ECSignatureSchema.id);
+ }
+ public validate(instance: object, schema: Schema): ValidatorResult {
+ return this.validator.validate(instance, schema);
+ }
+}
diff --git a/test/0x.js.ts b/test/0x.js.ts
index 2da026694..2ac6a2bea 100644
--- a/test/0x.js.ts
+++ b/test/0x.js.ts
@@ -14,15 +14,14 @@ describe('ZeroEx library', () => {
s: '0x2d887fd3b17bfdce3481f10bea41f45ba9f709d39ce8325427b57afcfc994cee',
};
const address = '0x9b2055d370f73ec7d8a03e965129118dc8f5bf83';
- describe('should return false for malformed signature', () => {
+ describe('should throw if passed a malformed signature', () => {
it('malformed v', () => {
const malformedSignature = {
v: 34,
r: signature.r,
s: signature.s,
};
- const isValid = ZeroEx.isValidSignature(data, malformedSignature, address);
- expect(isValid).to.be.false;
+ expect(() => ZeroEx.isValidSignature(data, malformedSignature, address)).to.throw();
});
it('r lacks 0x prefix', () => {
const malformedR = signature.r.replace('0x', '');
@@ -31,18 +30,16 @@ describe('ZeroEx library', () => {
r: malformedR,
s: signature.s,
};
- const isValid = ZeroEx.isValidSignature(data, malformedSignature, address);
- expect(isValid).to.be.false;
+ expect(() => ZeroEx.isValidSignature(data, malformedSignature, address)).to.throw();
});
it('r is too short', () => {
const malformedR = signature.r.substr(10);
const malformedSignature = {
v: signature.v,
r: malformedR,
- s: signature.s,
+ s: signature.s.replace('0', 'z'),
};
- const isValid = ZeroEx.isValidSignature(data, malformedSignature, address);
- expect(isValid).to.be.false;
+ expect(() => ZeroEx.isValidSignature(data, malformedSignature, address)).to.throw();
});
it('s is not hex', () => {
const malformedS = signature.s.replace('0', 'z');
@@ -51,8 +48,7 @@ describe('ZeroEx library', () => {
r: signature.r,
s: malformedS,
};
- const isValid = ZeroEx.isValidSignature(data, malformedSignature, address);
- expect(isValid).to.be.false;
+ expect(() => ZeroEx.isValidSignature(data, malformedSignature, address)).to.throw();
});
});
it('should return false if the data doesn\'t pertain to the signature & address', () => {