Skip to content
This repository was archived by the owner on Mar 5, 2025. It is now read-only.

Commit 02c0346

Browse files
authored
Signing fixes back-ported from 2.x (#3125)
* signing fixes back-ported from 2.x * CHANGELOG.md updated * transactionHash property added, docs updated, tests extended, and '0x' prefix added to messageHash for consistency reasons
1 parent d278254 commit 02c0346

File tree

7 files changed

+207
-60
lines changed

7 files changed

+207
-60
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,4 @@ Released with 1.0.0-beta.37 code base.
7171
- HttpProvider: CORS issue with Firefox and Safari (#2978)
7272
- Ensure the immutability of the `tx` object passed to function `signTransaction` (#2190)
7373
- Gas check fixed (#2381)
74+
- Signing issues #1998, #2033, and #1074 fixed (#3125)

docs/web3-eth-accounts.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ Returns
164164
- ``s`` - ``String``: Next 32 bytes of the signature
165165
- ``v`` - ``String``: Recovery value + 27
166166
- ``rawTransaction`` - ``String``: The RLP encoded transaction, ready to be send using :ref:`web3.eth.sendSignedTransaction <eth-sendsignedtransaction>`.
167+
- ``transactionHash`` - ``String``: The transaction hash for the RLP encoded transaction.
167168

168169

169170
-------
@@ -179,11 +180,12 @@ Example
179180
}, '0x4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318')
180181
.then(console.log);
181182
> {
182-
messageHash: '0x88cfbd7e51c7a40540b233cf68b62ad1df3e92462f1c6018d6d67eae0f3b08f5',
183+
messageHash: '0x31c2f03766b36f0346a850e78d4f7db2d9f4d7d54d5f272a750ba44271e370b1',
183184
v: '0x25',
184185
r: '0xc9cf86333bcb065d140032ecaab5d9281bde80f21b9687b3e94161de42d51895',
185186
s: '0x727a108a0b8d101465414033c3f705a9c7b826e596766046ee1183dbc8aeaa68',
186187
rawTransaction: '0xf869808504e3b29200831e848094f0109fc8df283027b6285cc889f5aa624eac1f55843b9aca008025a0c9cf86333bcb065d140032ecaab5d9281bde80f21b9687b3e94161de42d51895a0727a108a0b8d101465414033c3f705a9c7b826e596766046ee1183dbc8aeaa68'
188+
transactionHash: '0xde8db924885b0803d2edc335f745b2b8750c8848744905684c20b987443a9593'
187189
}
188190
189191
web3.eth.accounts.signTransaction({
@@ -201,6 +203,7 @@ Example
201203
s: '0x440ffd775ce91a833ab410777204d5341a6f9fa91216a6f3ee2c051fea6a0428',
202204
v: '0x25',
203205
rawTransaction: '0xf86a8086d55698372431831e848094f0109fc8df283027b6285cc889f5aa624eac1f55843b9aca008025a009ebb6ca057a0535d6186462bc0b465b561c94a295bdb0621fc19208ab149a9ca0440ffd775ce91a833ab410777204d5341a6f9fa91216a6f3ee2c051fea6a0428'
206+
transactionHash: '0xd8f64a42b57be0d565f385378db2f6bf324ce14a594afc05de90436e9ce01f60'
204207
}
205208
206209

packages/web3-eth-accounts/package-lock.json

Lines changed: 121 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/web3-eth-accounts/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"web3-core": "1.2.1",
1919
"web3-core-helpers": "1.2.1",
2020
"web3-core-method": "1.2.1",
21-
"web3-utils": "1.2.1"
21+
"web3-utils": "1.2.1",
22+
"ethereumjs-tx": "^2.1.1"
2223
}
2324
}

packages/web3-eth-accounts/src/index.js

Lines changed: 23 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -28,34 +28,20 @@ var Method = require('web3-core-method');
2828
var Promise = require('any-promise');
2929
var Account = require("eth-lib/lib/account");
3030
var Hash = require("eth-lib/lib/hash");
31-
var RLP = require("eth-lib/lib/rlp");
32-
var Nat = require("eth-lib/lib/nat");
33-
var Bytes = require("eth-lib/lib/bytes");
31+
var RLP = require("eth-lib/lib/rlp");// jshint ignore:line
32+
var Bytes = require("eth-lib/lib/bytes");// jshint ignore:line
3433
var cryp = (typeof global === 'undefined') ? require('crypto-browserify') : require('crypto');
3534
var scrypt = require('scrypt-shim');
3635
var uuid = require('uuid');
3736
var utils = require('web3-utils');
3837
var helpers = require('web3-core-helpers');
38+
var Transaction = require('ethereumjs-tx').Transaction;
39+
3940

4041
var isNot = function(value) {
4142
return (_.isUndefined(value) || _.isNull(value));
4243
};
4344

44-
var trimLeadingZero = function (hex) {
45-
while (hex && hex.startsWith('0x0')) {
46-
hex = '0x' + hex.slice(3);
47-
}
48-
return hex;
49-
};
50-
51-
var makeEven = function (hex) {
52-
if(hex.length % 2 === 1) {
53-
hex = hex.replace('0x', '0x0');
54-
}
55-
return hex;
56-
};
57-
58-
5945
var Accounts = function Accounts() {
6046
var _this = this;
6147

@@ -168,37 +154,30 @@ Accounts.prototype.signTransaction = function signTransaction(tx, privateKey, ca
168154
transaction.value = transaction.value || '0x';
169155
transaction.chainId = utils.numberToHex(transaction.chainId);
170156

171-
var rlpEncoded = RLP.encode([
172-
Bytes.fromNat(transaction.nonce),
173-
Bytes.fromNat(transaction.gasPrice),
174-
Bytes.fromNat(transaction.gas),
175-
transaction.to.toLowerCase(),
176-
Bytes.fromNat(transaction.value),
177-
transaction.data,
178-
Bytes.fromNat(transaction.chainId || "0x1"),
179-
"0x",
180-
"0x"]);
181-
182-
183-
var hash = Hash.keccak256(rlpEncoded);
157+
if (privateKey.startsWith('0x')) {
158+
privateKey = privateKey.substring(2);
159+
}
184160

185-
var signature = Account.makeSigner(Nat.toNumber(transaction.chainId || "0x1") * 2 + 35)(Hash.keccak256(rlpEncoded), privateKey);
161+
var ethTx = new Transaction(transaction);
162+
ethTx.sign(Buffer.from(privateKey, 'hex'));
186163

187-
var rawTx = RLP.decode(rlpEncoded).slice(0, 6).concat(Account.decodeSignature(signature));
164+
var validationResult = ethTx.validate(true);
188165

189-
rawTx[6] = makeEven(trimLeadingZero(rawTx[6]));
190-
rawTx[7] = makeEven(trimLeadingZero(rawTx[7]));
191-
rawTx[8] = makeEven(trimLeadingZero(rawTx[8]));
166+
if (validationResult !== '') {
167+
throw new Error('Signer Error: ' + validationResult);
168+
}
192169

193-
var rawTransaction = RLP.encode(rawTx);
170+
var rlpEncoded = ethTx.serialize().toString('hex');
171+
var rawTransaction = '0x' + rlpEncoded;
172+
var transactionHash = utils.keccak256(rawTransaction);
194173

195-
var values = RLP.decode(rawTransaction);
196-
result = {
197-
messageHash: hash,
198-
v: trimLeadingZero(values[6]),
199-
r: trimLeadingZero(values[7]),
200-
s: trimLeadingZero(values[8]),
201-
rawTransaction: rawTransaction
174+
return {
175+
messageHash: '0x' + Buffer.from(ethTx.hash(false)).toString('hex'),
176+
v: '0x' + Buffer.from(ethTx.v).toString('hex'),
177+
r: '0x' + Buffer.from(ethTx.r).toString('hex'),
178+
s: '0x' + Buffer.from(ethTx.s).toString('hex'),
179+
rawTransaction: rawTransaction,
180+
transactionHash: transactionHash
202181
};
203182

204183
} catch(e) {

test/contract.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3026,7 +3026,7 @@ describe('typical usage', function() {
30263026
var expected = eth.accounts.wallet[0].signTransaction({
30273027
data: '0x1234567000000000000000000000000' + account.address.toLowerCase().replace('0x', '') + '00000000000000000000000000000000000000000000000000000000000000c8',
30283028
from: account.address.toLowerCase(),
3029-
gas: '0xc350',
3029+
gas: '0xd658',
30303030
gasPrice: '0xbb8',
30313031
chainId: '0x1',
30323032
nonce: '0x1',
@@ -3085,7 +3085,7 @@ describe('typical usage', function() {
30853085
arguments: [account.address, 200]
30863086
}).send({
30873087
from: account.address,
3088-
gas: 50000,
3088+
gas: 54872,
30893089
gasPrice: 3000,
30903090
chainId: 1,
30913091
nonce: 1,

0 commit comments

Comments
 (0)