Skip to content
This repository was archived by the owner on Apr 6, 2020. It is now read-only.

Commit 002172c

Browse files
authored
Merge pull request #143 from ethereumjs/fix-signing-eip155-transactions
Correctly support signing and serializing of EIP155 valid transaction
2 parents 80eb355 + eb7ae3c commit 002172c

File tree

3 files changed

+83
-9
lines changed

3 files changed

+83
-9
lines changed

index.js

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ class Transaction {
100100
}, {
101101
name: 'v',
102102
allowZero: true,
103-
default: new Buffer([0x1c])
103+
default: new Buffer([opts.chain || opts.common ? this._common.chainId() : 0x1c])
104104
}, {
105105
name: 'r',
106106
length: 32,
@@ -184,10 +184,15 @@ class Transaction {
184184
// elements (i.e. nonce, gasprice, startgas, to, value, data), hash nine elements, with v replaced by
185185
// CHAIN_ID, r = 0 and s = 0.
186186

187-
const onEIP155BlockOrLater = this._common.gteHardfork('spuriousDragon')
188187
const v = ethUtil.bufferToInt(this.v)
188+
const onEIP155BlockOrLater = this._common.gteHardfork('spuriousDragon')
189189
const vAndChainIdMeetEIP155Conditions = v === this._chainId * 2 + 35 || v === this._chainId * 2 + 36
190-
if (vAndChainIdMeetEIP155Conditions && onEIP155BlockOrLater) {
190+
const meetsAllEIP155Conditions = vAndChainIdMeetEIP155Conditions && onEIP155BlockOrLater
191+
192+
const unsigned = !this.r.length && !this.s.length
193+
const seeksReplayProtection = this._chainId > 0
194+
195+
if (unsigned && seeksReplayProtection || !unsigned && meetsAllEIP155Conditions) {
191196
const raw = this.raw.slice()
192197
this.v = this._chainId
193198
this.r = 0
@@ -229,8 +234,8 @@ class Transaction {
229234
* @return {Buffer}
230235
*/
231236
getSenderPublicKey () {
232-
if (!this._senderPubKey || !this._senderPubKey.length) {
233-
if (!this.verifySignature()) throw new Error('Invalid Signature')
237+
if (!this.verifySignature()) {
238+
throw new Error('Invalid Signature')
234239
}
235240
return this._senderPubKey
236241
}

test/api.js

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ tape('[Transaction]: Basic functions', function (t) {
88
var transactions = []
99

1010
t.test('should decode transactions', function (st) {
11-
txFixtures.slice(0, 3).forEach(function (tx) {
11+
txFixtures.slice(0, 4).forEach(function (tx) {
1212
var pt = new Transaction(tx.raw)
1313
st.equal('0x' + pt.nonce.toString('hex'), tx.raw[0])
1414
st.equal('0x' + pt.gasPrice.toString('hex'), tx.raw[1])
@@ -32,15 +32,15 @@ tape('[Transaction]: Basic functions', function (t) {
3232
})
3333

3434
t.test('should hash', function (st) {
35-
var tx = new Transaction(txFixtures[2].raw)
35+
var tx = new Transaction(txFixtures[3].raw)
3636
st.deepEqual(tx.hash(), new Buffer('375a8983c9fc56d7cfd118254a80a8d7403d590a6c9e105532b67aca1efb97aa', 'hex'))
3737
st.deepEqual(tx.hash(false), new Buffer('61e1ec33764304dddb55348e7883d4437426f44ab3ef65e6da1e025734c03ff0', 'hex'))
3838
st.deepEqual(tx.hash(true), new Buffer('375a8983c9fc56d7cfd118254a80a8d7403d590a6c9e105532b67aca1efb97aa', 'hex'))
3939
st.end()
4040
})
4141

4242
t.test('should hash with defined chainId', function (st) {
43-
var tx = new Transaction(txFixtures[3].raw)
43+
var tx = new Transaction(txFixtures[4].raw)
4444
st.equal(tx.hash().toString('hex'), '0f09dc98ea85b7872f4409131a790b91e7540953992886fc268b7ba5c96820e4')
4545
st.equal(tx.hash(true).toString('hex'), '0f09dc98ea85b7872f4409131a790b91e7540953992886fc268b7ba5c96820e4')
4646
st.equal(tx.hash(false).toString('hex'), 'f97c73fdca079da7652dbc61a46cd5aeef804008e057be3e712c43eac389aaf0')
@@ -153,7 +153,7 @@ tape('[Transaction]: Basic functions', function (t) {
153153
var tx = new Transaction()
154154
st.equals(tx.getDataFee().toNumber(), 0)
155155

156-
tx = new Transaction(txFixtures[2].raw)
156+
tx = new Transaction(txFixtures[3].raw)
157157
st.equals(tx.getDataFee().toNumber(), 2496)
158158

159159
st.end()
@@ -185,6 +185,42 @@ tape('[Transaction]: Basic functions', function (t) {
185185
st.end()
186186
})
187187

188+
t.test('Verify EIP155 Signature before and after signing with private key', function (st) {
189+
// Inputs and expected results for this test are taken directly from the example in https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md
190+
var txRaw = [
191+
'0x09',
192+
'0x4a817c800',
193+
'0x5208',
194+
'0x3535353535353535353535353535353535353535',
195+
'0x0de0b6b3a7640000',
196+
'0x'
197+
]
198+
var privateKey = Buffer.from('4646464646464646464646464646464646464646464646464646464646464646', 'hex')
199+
var pt = new Transaction(txRaw, { chain: 1 })
200+
st.equal(pt.serialize().toString('hex'), 'ec098504a817c800825208943535353535353535353535353535353535353535880de0b6b3a764000080018080')
201+
pt.sign(privateKey)
202+
st.equal(pt.hash(false).toString('hex'), 'daf5a779ae972f972197303d7b574746c7ef83eadac0f2791ad23db92e4c8e53')
203+
st.equal(pt.serialize().toString('hex'), 'f86c098504a817c800825208943535353535353535353535353535353535353535880de0b6b3a76400008025a028ef61340bd939bc2195fe537567866003e1a15d3c71ff63e1590620aa636276a067cbe9d8997f761aecb703304b3800ccf555c9f3dc64214b297fb1966a3b6d83')
204+
st.end()
205+
})
206+
207+
t.test('Serialize correctly after being signed with EIP155 Signature for tx created on ropsten', function (st) {
208+
var txRaw = [
209+
'0x1',
210+
'0x02540be400',
211+
'0x5208',
212+
'0xd7250824390ec5c8b71d856b5de895e271170d9d',
213+
'0x0de0b6b3a7640000',
214+
'0x'
215+
]
216+
217+
var privateKey = Buffer.from('DE3128752F183E8930D7F00A2AAA302DCB5E700B2CBA2D8CA5795660F07DEFD5', 'hex')
218+
var pt = new Transaction(txRaw, { chain: 3 })
219+
pt.sign(privateKey)
220+
st.equal(pt.serialize().toString('hex'), 'f86c018502540be40082520894d7250824390ec5c8b71d856b5de895e271170d9d880de0b6b3a76400008029a0d3512c68099d184ccf54f44d9d6905bff303128574b663dcf10b4c726ddd8133a0628acc8f481dea593f13309dfc5f0340f83fdd40cf9fbe47f782668f6f3aec74')
221+
st.end()
222+
})
223+
188224
t.test('sign tx with chainId specified in params', function (st) {
189225
var tx = new Transaction({ chainId: 42 })
190226
st.equal(tx.getChainId(), 42)
@@ -202,4 +238,21 @@ tape('[Transaction]: Basic functions', function (t) {
202238
st.equal(tx.getChainId(), 0x16b2)
203239
st.end()
204240
})
241+
242+
t.test('EIP155 hashing when singing', function (st) {
243+
txFixtures.slice(0, 3).forEach(function (txData) {
244+
const tx = new Transaction(txData.raw.slice(0, 6), {chain: 1})
245+
246+
var privKey = new Buffer(txData.privateKey, 'hex')
247+
tx.sign(privKey)
248+
249+
st.equal(
250+
tx.getSenderAddress().toString('hex'),
251+
txData.sendersAddress,
252+
'computed sender address should equal the fixture\'s one'
253+
)
254+
})
255+
256+
st.end()
257+
})
205258
})

test/txs.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,22 @@
1414
"0x5e1d3a76fbf824220eafc8c79ad578ad2b67d01b0c2425eb1f1347e8f50882ab",
1515
"0x5bd428537f05f9830e93792f90ea6a3e2d1ee84952dd96edbae9f658f831ab13"
1616
]
17+
}, {
18+
"privateKey": "4646464646464646464646464646464646464646464646464646464646464646",
19+
"sendersAddress": "9d8a62f656a8d1615c1294fd71e9cfb3e4855a4f",
20+
"type": "message",
21+
"cost": 500,
22+
"raw": [
23+
"0x09",
24+
"0x04a817c800",
25+
"0x2710",
26+
"0x3535353535353535353535353535353535353535",
27+
"0x0de0b6b3a7640000",
28+
"0x",
29+
"0x25",
30+
"0x28ef61340bd939bc2195fe537567866003e1a15d3c71ff63e1590620aa636276",
31+
"0x67cbe9d8997f761aecb703304b3800ccf555c9f3dc64214b297fb1966a3b6d83"
32+
]
1733
}, {
1834
"privateKey": "e0a462586887362a18a318b128dbc1e3a0cae6d4b0739f5d0419ec25114bc722",
1935
"sendersAddress": "d13d825eb15c87b247c4c26331d66f225a5f632e",

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy