Skip to content

Commit 4ca587e

Browse files
authored
Merge pull request #287 from spalladino/handle-large-chainid-on-rpcsig
Handle signatures for chainIds greater than 110
2 parents e19262e + cc7850d commit 4ca587e

File tree

2 files changed

+53
-6
lines changed

2 files changed

+53
-6
lines changed

src/signature.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const { ecdsaSign, ecdsaRecover, publicKeyConvert } = require('ethereum-cryptography/secp256k1')
22
import * as BN from 'bn.js'
3-
import { toBuffer, setLengthLeft, bufferToHex } from './bytes'
3+
import { toBuffer, setLengthLeft, bufferToHex, bufferToInt } from './bytes'
44
import { keccak } from './hash'
55
import { assertIsBuffer } from './helpers'
66

@@ -71,12 +71,11 @@ export const toRpcSig = function(v: number, r: Buffer, s: Buffer, chainId?: numb
7171
export const fromRpcSig = function(sig: string): ECDSASignature {
7272
const buf: Buffer = toBuffer(sig)
7373

74-
// NOTE: with potential introduction of chainId this might need to be updated
75-
if (buf.length !== 65) {
74+
if (buf.length < 65) {
7675
throw new Error('Invalid signature length')
7776
}
7877

79-
let v = buf[64]
78+
let v = bufferToInt(buf.slice(64))
8079
// support both versions of `eth_sign` responses
8180
if (v < 27) {
8281
v += 27

test/signature.spec.ts

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,20 @@ describe('ecsign', function() {
4646
)
4747
assert.equal(sig.v, 41)
4848
})
49+
50+
it('should produce a signature for chainId=150', function() {
51+
const chainId = 150
52+
const sig = ecsign(echash, ecprivkey, chainId)
53+
assert.deepEqual(
54+
sig.r,
55+
Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex'),
56+
)
57+
assert.deepEqual(
58+
sig.s,
59+
Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', 'hex'),
60+
)
61+
assert.equal(sig.v, chainId * 2 + 35)
62+
})
4963
})
5064

5165
describe('ecrecover', function() {
@@ -63,6 +77,14 @@ describe('ecrecover', function() {
6377
const pubkey = ecrecover(echash, v, r, s, chainId)
6478
assert.deepEqual(pubkey, privateToPublic(ecprivkey))
6579
})
80+
it('should recover a public key (chainId = 150)', function() {
81+
const chainId = 150
82+
const r = Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex')
83+
const s = Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', 'hex')
84+
const v = chainId * 2 + 35
85+
const pubkey = ecrecover(echash, v, r, s, chainId)
86+
assert.deepEqual(pubkey, privateToPublic(ecprivkey))
87+
})
6688
it('should fail on an invalid signature (v = 21)', function() {
6789
const r = Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex')
6890
const s = Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', 'hex')
@@ -160,6 +182,13 @@ describe('isValidSignature', function() {
160182
const v = 41
161183
assert.equal(isValidSignature(v, r, s, false, chainId), true)
162184
})
185+
it('should work otherwise(chainId=150)', function() {
186+
const chainId = 150
187+
const r = Buffer.from('99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9', 'hex')
188+
const s = Buffer.from('129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66', 'hex')
189+
const v = chainId * 2 + 35
190+
assert.equal(isValidSignature(v, r, s, false, chainId), true)
191+
})
163192
// FIXME: add homestead test
164193
})
165194

@@ -194,13 +223,32 @@ describe('message sig', function() {
194223
)
195224
})
196225

197-
it('should throw on invalid length', function() {
226+
it('should return hex strings that the RPC can use (chainId=150)', function() {
227+
const chainId = 150
228+
const v = chainId * 2 + 35
229+
assert.equal(
230+
toRpcSig(v, r, s, chainId),
231+
'0x99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66014f',
232+
)
233+
assert.deepEqual(
234+
fromRpcSig(
235+
'0x99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca66014f',
236+
),
237+
{
238+
v,
239+
r: r,
240+
s: s,
241+
},
242+
)
243+
})
244+
245+
it('should throw on shorter length', function() {
198246
assert.throws(function() {
199247
fromRpcSig('')
200248
})
201249
assert.throws(function() {
202250
fromRpcSig(
203-
'0x99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca660042',
251+
'0x99e71a99cb2270b8cac5254f9e99b6210c6c10224a1579cf389ef88b20a1abe9129ff05af364204442bdb53ab6f18a99ab48acc9326fa689f228040429e3ca',
204252
)
205253
})
206254
})

0 commit comments

Comments
 (0)