Added splitSignature and beginning of better error messages.
This commit is contained in:
parent
fdb7114511
commit
efb7dce524
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "ethers",
|
"name": "ethers",
|
||||||
"version": "3.0.9",
|
"version": "3.0.10",
|
||||||
"description": "Ethereum wallet library.",
|
"description": "Ethereum wallet library.",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -183,3 +183,31 @@ describe('Test Hash Functions', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Test Solidity splitSignature', function() {
|
||||||
|
var convert = require('../utils/convert');
|
||||||
|
|
||||||
|
it('splits a canonical signature', function() {
|
||||||
|
var r = '0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef';
|
||||||
|
var s = '0xcafe1a7ecafe1a7ecafe1a7ecafe1a7ecafe1a7ecafe1a7ecafe1a7ecafe1a7e';
|
||||||
|
for (var v = 27; v <= 28; v++) {
|
||||||
|
var signature = convert.concat([ r, s, [ v ] ]);
|
||||||
|
var sig = convert.splitSignature(signature);
|
||||||
|
assert.equal(sig.r, r, 'split r correctly');
|
||||||
|
assert.equal(sig.s, s, 'split s correctly');
|
||||||
|
assert.equal(sig.v, v, 'split v correctly');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('splits a legacy signature', function() {
|
||||||
|
var r = '0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef';
|
||||||
|
var s = '0xcafe1a7ecafe1a7ecafe1a7ecafe1a7ecafe1a7ecafe1a7ecafe1a7ecafe1a7e';
|
||||||
|
for (var v = 27; v <= 28; v++) {
|
||||||
|
var signature = convert.concat([ r, s, [ v - 27 ] ]);
|
||||||
|
var sig = convert.splitSignature(signature);
|
||||||
|
assert.equal(sig.r, r, 'split r correctly');
|
||||||
|
assert.equal(sig.s, s, 'split s correctly');
|
||||||
|
assert.equal(sig.v, v, 'split v correctly');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
@ -4,7 +4,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
var defineProperty = require('./properties.js').defineProperty;
|
var defineProperty = require('./properties.js').defineProperty;
|
||||||
var throwError = require('./throw-error');
|
|
||||||
|
var errors = require('./errors');
|
||||||
|
|
||||||
function addSlice(array) {
|
function addSlice(array) {
|
||||||
if (array.slice) { return array; }
|
if (array.slice) { return array; }
|
||||||
@ -32,7 +33,10 @@ function isArrayish(value) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function arrayify(value, name) {
|
function arrayify(value) {
|
||||||
|
if (value == null) {
|
||||||
|
errors.throwError('cannot convert null value to array', errors.INVALID_ARGUMENT, { arg: 'value', value: value });
|
||||||
|
}
|
||||||
|
|
||||||
if (value && value.toHexString) {
|
if (value && value.toHexString) {
|
||||||
value = value.toHexString();
|
value = value.toHexString();
|
||||||
@ -48,13 +52,19 @@ function arrayify(value, name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return addSlice(new Uint8Array(result));
|
return addSlice(new Uint8Array(result));
|
||||||
|
|
||||||
|
} else if (typeof(value) === 'string') {
|
||||||
|
if (value.match(/^[0-9a-fA-F]*$/)) {
|
||||||
|
errors.throwError('hex string must have 0x prefix', errors.INVALID_ARGUMENT, { arg: 'value', value: value });
|
||||||
|
}
|
||||||
|
errors.throwError('invalid hexidecimal string', errors.INVALID_ARGUMENT, { arg: 'value', value: value });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isArrayish(value)) {
|
if (isArrayish(value)) {
|
||||||
return addSlice(new Uint8Array(value));
|
return addSlice(new Uint8Array(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
throwError('invalid arrayify value', { name: name, input: value });
|
errors.throwError('invalid arrayify value', { arg: 'value', value: value, type: typeof(value) });
|
||||||
}
|
}
|
||||||
|
|
||||||
function concat(objects) {
|
function concat(objects) {
|
||||||
@ -113,7 +123,7 @@ function isHexString(value, length) {
|
|||||||
|
|
||||||
var HexCharacters = '0123456789abcdef';
|
var HexCharacters = '0123456789abcdef';
|
||||||
|
|
||||||
function hexlify(value, name) {
|
function hexlify(value) {
|
||||||
|
|
||||||
if (value && value.toHexString) {
|
if (value && value.toHexString) {
|
||||||
return value.toHexString();
|
return value.toHexString();
|
||||||
@ -121,7 +131,7 @@ function hexlify(value, name) {
|
|||||||
|
|
||||||
if (typeof(value) === 'number') {
|
if (typeof(value) === 'number') {
|
||||||
if (value < 0) {
|
if (value < 0) {
|
||||||
throwError('cannot hexlify negative value', { name: name, input: value });
|
errors.throwError('cannot hexlify negative value', errors.INVALID_ARG, { arg: 'value', value: value });
|
||||||
}
|
}
|
||||||
|
|
||||||
var hex = '';
|
var hex = '';
|
||||||
@ -154,7 +164,7 @@ function hexlify(value, name) {
|
|||||||
return '0x' + result.join('');
|
return '0x' + result.join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
throwError('invalid hexlify value', { name: name, input: value });
|
errors.throwError('invalid hexlify value', { arg: 'value', value: value });
|
||||||
}
|
}
|
||||||
|
|
||||||
function hexStripZeros(value) {
|
function hexStripZeros(value) {
|
||||||
@ -171,6 +181,31 @@ function hexZeroPad(value, length) {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* @TODO: Add something like this to make slicing code easier to understand
|
||||||
|
function hexSlice(hex, start, end) {
|
||||||
|
hex = hexlify(hex);
|
||||||
|
return '0x' + hex.substring(2 + start * 2, 2 + end * 2);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
function splitSignature(signature) {
|
||||||
|
signature = arrayify(signature);
|
||||||
|
if (signature.length !== 65) {
|
||||||
|
throw new Error('invalid signature');
|
||||||
|
}
|
||||||
|
|
||||||
|
var v = signature[64];
|
||||||
|
if (v !== 27 && v !== 28) {
|
||||||
|
v = 27 + (v % 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
r: hexlify(signature.slice(0, 32)),
|
||||||
|
s: hexlify(signature.slice(32, 64)),
|
||||||
|
v: v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
arrayify: arrayify,
|
arrayify: arrayify,
|
||||||
isArrayish: isArrayish,
|
isArrayish: isArrayish,
|
||||||
@ -180,6 +215,8 @@ module.exports = {
|
|||||||
padZeros: padZeros,
|
padZeros: padZeros,
|
||||||
stripZeros: stripZeros,
|
stripZeros: stripZeros,
|
||||||
|
|
||||||
|
splitSignature: splitSignature,
|
||||||
|
|
||||||
hexlify: hexlify,
|
hexlify: hexlify,
|
||||||
isHexString: isHexString,
|
isHexString: isHexString,
|
||||||
hexStripZeros: hexStripZeros,
|
hexStripZeros: hexStripZeros,
|
||||||
|
54
utils/errors.js
Normal file
54
utils/errors.js
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
var defineProperty = require('./properties').defineProperty;
|
||||||
|
|
||||||
|
var codes = { };
|
||||||
|
|
||||||
|
[
|
||||||
|
// Unknown Error
|
||||||
|
'UNKNOWN_ERROR',
|
||||||
|
|
||||||
|
// Missing new operator to an object
|
||||||
|
// - name: The name of the class
|
||||||
|
'MISSING_NEW',
|
||||||
|
|
||||||
|
// Invalid argument to a function:
|
||||||
|
// - arg: The argument name that was invalid
|
||||||
|
'INVALID_ARGUMENT'
|
||||||
|
|
||||||
|
].forEach(function(code) {
|
||||||
|
defineProperty(codes, code, code);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
defineProperty(codes, 'throwError', function(message, code, params) {
|
||||||
|
if (!code) { code = codes.UNKNOWN_ERROR; }
|
||||||
|
if (!params) { params = {}; }
|
||||||
|
|
||||||
|
var messageDetails = [];
|
||||||
|
Object.keys(params).forEach(function(key) {
|
||||||
|
messageDetails.push(key + '=' + JSON.stringify(params[key]));
|
||||||
|
});
|
||||||
|
var reason = message;
|
||||||
|
if (messageDetails.length) {
|
||||||
|
message += ' (' + messageDetails.join(', ') + ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
var error = new Error(message);
|
||||||
|
error.reason = reason;
|
||||||
|
error.code = code
|
||||||
|
|
||||||
|
Object.keys(params).forEach(function(key) {
|
||||||
|
error[key] = params[key];
|
||||||
|
});
|
||||||
|
|
||||||
|
throw error;
|
||||||
|
});
|
||||||
|
|
||||||
|
defineProperty(codes, 'checkNew', function(self, kind) {
|
||||||
|
if (!(self instanceof kind)) {
|
||||||
|
codes.throwError('missing new', codes.MISSING_NEW, { name: kind.name });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = codes;
|
@ -67,4 +67,6 @@ module.exports = {
|
|||||||
solidityPack: solidity.pack,
|
solidityPack: solidity.pack,
|
||||||
solidityKeccak256: solidity.keccak256,
|
solidityKeccak256: solidity.keccak256,
|
||||||
soliditySha256: solidity.sha256,
|
soliditySha256: solidity.sha256,
|
||||||
|
|
||||||
|
splitSignature: convert.splitSignature,
|
||||||
}
|
}
|
||||||
|
@ -21,15 +21,28 @@ var utils = (function() {
|
|||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
var errors = require('../utils/errors');
|
||||||
|
|
||||||
|
|
||||||
function SigningKey(privateKey) {
|
function SigningKey(privateKey) {
|
||||||
if (!(this instanceof SigningKey)) { throw new Error('missing new'); }
|
errors.checkNew(this, SigningKey);
|
||||||
|
|
||||||
|
try {
|
||||||
privateKey = utils.arrayify(privateKey);
|
privateKey = utils.arrayify(privateKey);
|
||||||
if (privateKey.length !== 32) {
|
if (privateKey.length !== 32) {
|
||||||
throw new Error('invalid private key');
|
errors.throwError('exactly 32 bytes required', errors.INVALID_ARGUMENT, { value: privateKey });
|
||||||
}
|
}
|
||||||
|
} catch(error) {
|
||||||
|
var params = { reason: error.reason, value: '[REDACTED]' }
|
||||||
|
if (error.value) {
|
||||||
|
if(typeof(error.value.length) === 'number') {
|
||||||
|
params.length = error.value.length;
|
||||||
|
}
|
||||||
|
params.type = typeof(error.value);
|
||||||
|
}
|
||||||
|
errors.throwError('invalid private key', error.code, params);
|
||||||
|
}
|
||||||
|
|
||||||
utils.defineProperty(this, 'privateKey', utils.hexlify(privateKey))
|
utils.defineProperty(this, 'privateKey', utils.hexlify(privateKey))
|
||||||
|
|
||||||
var keyPair = secp256k1.keyFromPrivate(privateKey);
|
var keyPair = secp256k1.keyFromPrivate(privateKey);
|
||||||
|
@ -28,6 +28,8 @@ var utils = (function() {
|
|||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
var errors = require('../utils/errors');
|
||||||
|
|
||||||
var HDNode = require('./hdnode');
|
var HDNode = require('./hdnode');
|
||||||
|
|
||||||
var secretStorage = require('./secret-storage');
|
var secretStorage = require('./secret-storage');
|
||||||
@ -49,7 +51,7 @@ var transactionFields = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
function Wallet(privateKey, provider) {
|
function Wallet(privateKey, provider) {
|
||||||
if (!(this instanceof Wallet)) { throw new Error('missing new'); }
|
errors.checkNew(this, Wallet);
|
||||||
|
|
||||||
// Make sure we have a valid signing key
|
// Make sure we have a valid signing key
|
||||||
var signingKey = privateKey;
|
var signingKey = privateKey;
|
||||||
|
Loading…
Reference in New Issue
Block a user