Skip to content

Commit

Permalink
fixes web3#1340, web3#1341, 1342
Browse files Browse the repository at this point in the history
  • Loading branch information
frozeman committed Feb 13, 2018
1 parent 42acda0 commit 097ceb8
Show file tree
Hide file tree
Showing 7 changed files with 531 additions and 224 deletions.
2 changes: 1 addition & 1 deletion .jshintrc
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"eqeqeq": true,
"freeze": true,
"funcscope": false,
"maxcomplexity": 10,
"maxcomplexity": 15,
"maxdepth": 4,
"maxerr": 50,
/*"maxlen": 80*/ /*this should be our goal*/
Expand Down
61 changes: 38 additions & 23 deletions packages/web3-core-helpers/src/formatters.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,20 +65,27 @@ var inputBlockNumberFormatter = function (blockNumber) {
/**
* Formats the input of a transaction and converts all values to HEX
*
* @method inputCallFormatter
* @method _txInputFormatter
* @param {Object} transaction options
* @returns object
*/
var inputCallFormatter = function (options){
*/
var _txInputFormatter = function (options){

var from = options.from || (this ? this.defaultAccount : null);
if (options.to) { // it might be contract creation
options.to = inputAddressFormatter(options.to);
}

if (from) {
options.from = inputAddressFormatter(from);
if (options.data && options.input) {
throw new Error('You can\'t have "data" and "input" as properties of transactions at the same time, please use either "data" or "input" instead.');
}

if (options.to) { // it might be contract creation
options.to = inputAddressFormatter(options.to);
if (!options.data && options.input) {
options.data = options.input;
delete options.input;
}

if(options.data && !utils.isHex(options.data)) {
throw new Error('The data field must be HEX encoded data.');
}

// allow both
Expand All @@ -95,6 +102,27 @@ var inputCallFormatter = function (options){
return options;
};

/**
* Formats the input of a transaction and converts all values to HEX
*
* @method inputCallFormatter
* @param {Object} transaction options
* @returns object
*/
var inputCallFormatter = function (options){

options = _txInputFormatter(options);

var from = options.from || (this ? this.defaultAccount : null);

if (from) {
options.from = inputAddressFormatter(from);
}


return options;
};

/**
* Formats the input of a transaction and converts all values to HEX
*
Expand All @@ -104,6 +132,8 @@ var inputCallFormatter = function (options){
*/
var inputTransactionFormatter = function (options) {

options = _txInputFormatter(options);

// check from, only if not number, or object
if (!_.isNumber(options.from) && !_.isObject(options.from)) {
options.from = options.from || (this ? this.defaultAccount : null);
Expand All @@ -115,21 +145,6 @@ var inputTransactionFormatter = function (options) {
options.from = inputAddressFormatter(options.from);
}

if (options.to) { // it might be contract creation
options.to = inputAddressFormatter(options.to);
}

// allow both
if (options.gas || options.gasLimit) {
options.gas = options.gas || options.gasLimit;
}

['gasPrice', 'gas', 'value', 'nonce'].filter(function (key) {
return options[key] !== undefined;
}).forEach(function(key){
options[key] = utils.numberToHex(options[key]);
});

return options;
};

Expand Down
4 changes: 1 addition & 3 deletions packages/web3-core-method/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -513,9 +513,7 @@ Method.prototype.buildCall = function() {

// If wallet was found, sign tx, and send using sendRawTransaction
if (wallet && wallet.privateKey) {
var signature = method.accounts.signTransaction(_.omit(tx, 'from'), wallet.privateKey);

return (_.isFunction(signature.then)) ? signature.then(sendSignedTx) : sendSignedTx(signature);
return method.accounts.signTransaction(_.omit(tx, 'from'), wallet.privateKey).then(sendSignedTx);
}

// ETH_SIGN
Expand Down
117 changes: 72 additions & 45 deletions packages/web3-eth-accounts/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,61 +130,88 @@ Accounts.prototype.privateKeyToAccount = function privateKeyToAccount(privateKey
};

Accounts.prototype.signTransaction = function signTransaction(tx, privateKey, callback) {
var _this = this;
var _this = this,
error = false,
result;

callback = callback || function () {};

if (!tx) {
error = new Error('No transaction object given!');

callback(error);
return Promise.reject(error);
}

function signed (tx) {

if (!tx.gas && !tx.gasLimit) {
throw new Error('"gas" is missing');
error = new Error('"gas" is missing');
}

var transaction = {
nonce: utils.numberToHex(tx.nonce),
to: tx.to ? helpers.formatters.inputAddressFormatter(tx.to) : '0x',
data: tx.data || '0x',
value: tx.value ? utils.numberToHex(tx.value) : "0x",
gas: utils.numberToHex(tx.gasLimit || tx.gas),
gasPrice: utils.numberToHex(tx.gasPrice),
chainId: utils.numberToHex(tx.chainId)
};

var rlpEncoded = RLP.encode([
Bytes.fromNat(transaction.nonce),
Bytes.fromNat(transaction.gasPrice),
Bytes.fromNat(transaction.gas),
transaction.to.toLowerCase(),
Bytes.fromNat(transaction.value),
transaction.data,
Bytes.fromNat(transaction.chainId || "0x1"),
"0x",
"0x"]);

var hash = Hash.keccak256(rlpEncoded);

var signature = Account.makeSigner(Nat.toNumber(transaction.chainId || "0x1") * 2 + 35)(Hash.keccak256(rlpEncoded), privateKey);

var rawTx = RLP.decode(rlpEncoded).slice(0, 6).concat(Account.decodeSignature(signature));

rawTx[7] = makeEven(trimLeadingZero(rawTx[7]));
rawTx[8] = makeEven(trimLeadingZero(rawTx[8]));

var rawTransaction = RLP.encode(rawTx);

var values = RLP.decode(rawTransaction);
var result = {
messageHash: hash,
v: trimLeadingZero(values[6]),
r: trimLeadingZero(values[7]),
s: trimLeadingZero(values[8]),
rawTransaction: rawTransaction
};
if (_.isFunction(callback)) {
callback(null, result);
if (tx.nonce < 0 ||
tx.gas < 0 ||
tx.gasPrice < 0 ||
tx.chainId < 0) {
error = new Error('Gas, gasPrice, nonce or chainId is lower than 0');
}

if (error) {
callback(error);
return Promise.reject(new Error('"gas" is missing'));
}

try {
tx = helpers.formatters.inputCallFormatter(tx);

var transaction = tx;
transaction.to = tx.to || '0x';
transaction.data = tx.data || '0x';
transaction.value = tx.value || '0x';
transaction.chainId = utils.numberToHex(tx.chainId);

var rlpEncoded = RLP.encode([
Bytes.fromNat(transaction.nonce),
Bytes.fromNat(transaction.gasPrice),
Bytes.fromNat(transaction.gas),
transaction.to.toLowerCase(),
Bytes.fromNat(transaction.value),
transaction.data,
Bytes.fromNat(transaction.chainId || "0x1"),
"0x",
"0x"]);


var hash = Hash.keccak256(rlpEncoded);

var signature = Account.makeSigner(Nat.toNumber(transaction.chainId || "0x1") * 2 + 35)(Hash.keccak256(rlpEncoded), privateKey);

var rawTx = RLP.decode(rlpEncoded).slice(0, 6).concat(Account.decodeSignature(signature));

rawTx[7] = makeEven(trimLeadingZero(rawTx[7]));
rawTx[8] = makeEven(trimLeadingZero(rawTx[8]));

var rawTransaction = RLP.encode(rawTx);

var values = RLP.decode(rawTransaction);
result = {
messageHash: hash,
v: trimLeadingZero(values[6]),
r: trimLeadingZero(values[7]),
s: trimLeadingZero(values[8]),
rawTransaction: rawTransaction
};

} catch(e) {
callback(e);
return Promise.reject(e);
}

callback(null, result);
return result;
}

// Returns synchronously if nonce, chainId and price are provided
// Resolve immediately if nonce, chainId and price are provided
if (tx.nonce !== undefined && tx.chainId !== undefined && tx.gasPrice !== undefined) {
return Promise.resolve(signed(tx));
}
Expand Down
8 changes: 6 additions & 2 deletions packages/web3-utils/src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -256,10 +256,14 @@ var hexToNumberString = function (value) {
* @return {String}
*/
var numberToHex = function (value) {
if (!isFinite(value) && !_.isString(value)) {
if (_.isNull(value) || _.isUndefined(value)) {
return value;
}

if (!isFinite(value) && !isHexStrict(value)) {
throw new Error('Given input "'+value+'" is not a number.');
}

var number = toBN(value);
var result = number.toString(16);

Expand Down Expand Up @@ -369,7 +373,7 @@ var isHexStrict = function (hex) {
* @returns {Boolean}
*/
var isHex = function (hex) {
return ((_.isString(hex) || _.isNumber(hex)) && /^(-0x)?(0x)?[0-9a-f]*$/i.test(hex));
return ((_.isString(hex) || _.isNumber(hex)) && /^(-0x|0x)?[0-9a-f]*$/i.test(hex));
};


Expand Down
4 changes: 1 addition & 3 deletions test/contract.js
Original file line number Diff line number Diff line change
Expand Up @@ -2901,9 +2901,7 @@ describe('typical usage', function() {
assert.equal(newContract.options.address, address);
assert.isTrue(newContract !== contract, 'contract objects shouldn\'t the same');

setTimeout(function () {
done();
}, 1);
done();
});
// .on('error', function (value) {
// console.log('error', value);
Expand Down
Loading

0 comments on commit 097ceb8

Please sign in to comment.