@@ -3,8 +3,7 @@ import BN from 'bn.js'
3
3
import { toBuffer , setLengthLeft , bufferToHex , bufferToInt } from './bytes'
4
4
import { keccak } from './hash'
5
5
import { assertIsBuffer } from './helpers'
6
- import { BNLike } from './types'
7
- import { isHexString } from '.'
6
+ import { BNLike , toType , TypeOutput } from './types'
8
7
9
8
export interface ECDSASignature {
10
9
v : number
@@ -22,79 +21,40 @@ export interface ECDSASignatureBuffer {
22
21
* Returns the ECDSA signature of a message hash.
23
22
*/
24
23
export function ecsign ( msgHash : Buffer , privateKey : Buffer , chainId ?: number ) : ECDSASignature
25
- export function ecsign (
26
- msgHash : Buffer ,
27
- privateKey : Buffer ,
28
- chainId : BN | string | Buffer
29
- ) : ECDSASignatureBuffer
24
+ export function ecsign ( msgHash : Buffer , privateKey : Buffer , chainId : BNLike ) : ECDSASignatureBuffer
30
25
export function ecsign ( msgHash : Buffer , privateKey : Buffer , chainId : any ) : any {
31
- const sig = ecdsaSign ( msgHash , privateKey )
32
- const recovery : number = sig . recid
33
-
34
- let ret
35
- const r = Buffer . from ( sig . signature . slice ( 0 , 32 ) )
36
- const s = Buffer . from ( sig . signature . slice ( 32 , 64 ) )
37
- if ( ! chainId || typeof chainId === 'number' ) {
38
- if ( chainId && ! Number . isSafeInteger ( chainId ) ) {
39
- throw new Error (
40
- 'The provided chainId is greater than MAX_SAFE_INTEGER (please use an alternative input type)'
41
- )
42
- }
43
- return {
44
- r,
45
- s,
46
- v : chainId ? recovery + ( chainId * 2 + 35 ) : recovery + 27
47
- }
26
+ const { signature, recid : recovery } = ecdsaSign ( msgHash , privateKey )
27
+
28
+ const r = Buffer . from ( signature . slice ( 0 , 32 ) )
29
+ const s = Buffer . from ( signature . slice ( 32 , 64 ) )
30
+
31
+ if ( ! chainId ) {
32
+ return { r, s, v : recovery + 27 }
48
33
} else {
49
- // BN, string, Buffer
50
- if ( typeof chainId === 'string' && ! isHexString ( chainId ) ) {
51
- throw new Error ( `A chainId string must be provided with a 0x-prefix, given: ${ chainId } ` )
52
- }
53
- ret = {
54
- r,
55
- s,
56
- v : toBuffer (
57
- new BN ( toBuffer ( chainId ) )
58
- . muln ( 2 )
59
- . addn ( 35 )
60
- . addn ( recovery )
61
- )
62
- }
34
+ const chainIdBN = toType ( chainId , TypeOutput . BN )
35
+ const vValue = chainIdBN
36
+ . muln ( 2 )
37
+ . addn ( 35 )
38
+ . addn ( recovery )
39
+ const v = typeof chainId === 'number' ? vValue . toNumber ( ) : vValue . toArrayLike ( Buffer )
40
+ return { r, s, v }
63
41
}
64
-
65
- return ret
66
42
}
67
43
68
44
function calculateSigRecovery ( v : BNLike , chainId ?: BNLike ) : BN {
69
- const vBN = new BN ( toBuffer ( v ) )
70
- const chainIdBN = chainId ? new BN ( toBuffer ( chainId ) ) : undefined
71
- return chainIdBN ? vBN . sub ( chainIdBN . muln ( 2 ) . addn ( 35 ) ) : vBN . subn ( 27 )
45
+ const vBN = toType ( v , TypeOutput . BN )
46
+ if ( ! chainId ) {
47
+ return vBN . subn ( 27 )
48
+ }
49
+ const chainIdBN = toType ( chainId , TypeOutput . BN )
50
+ return vBN . sub ( chainIdBN . muln ( 2 ) . addn ( 35 ) )
72
51
}
73
52
74
53
function isValidSigRecovery ( recovery : number | BN ) : boolean {
75
54
const rec = new BN ( recovery )
76
55
return rec . eqn ( 0 ) || rec . eqn ( 1 )
77
56
}
78
57
79
- function vAndChainIdTypeChecks ( v : BNLike , chainId ?: BNLike ) {
80
- if ( typeof v === 'string' && ! isHexString ( v ) ) {
81
- throw new Error ( `A v value string must be provided with a 0x-prefix, given: ${ v } ` )
82
- }
83
- if ( typeof chainId === 'string' && ! isHexString ( chainId ) ) {
84
- throw new Error ( `A chainId string must be provided with a 0x-prefix, given: ${ chainId } ` )
85
- }
86
- if ( typeof v === 'number' && ! Number . isSafeInteger ( v ) ) {
87
- throw new Error (
88
- 'The provided v is greater than MAX_SAFE_INTEGER (please use an alternative input type)'
89
- )
90
- }
91
- if ( typeof chainId === 'number' && ! Number . isSafeInteger ( chainId ) ) {
92
- throw new Error (
93
- 'The provided chainId is greater than MAX_SAFE_INTEGER (please use an alternative input type)'
94
- )
95
- }
96
- }
97
-
98
58
/**
99
59
* ECDSA public key recovery from signature.
100
60
* @returns Recovered public key
@@ -106,8 +66,6 @@ export const ecrecover = function(
106
66
s : Buffer ,
107
67
chainId ?: BNLike
108
68
) : Buffer {
109
- vAndChainIdTypeChecks ( v , chainId )
110
-
111
69
const signature = Buffer . concat ( [ setLengthLeft ( r , 32 ) , setLengthLeft ( s , 32 ) ] , 64 )
112
70
const recovery = calculateSigRecovery ( v , chainId )
113
71
if ( ! isValidSigRecovery ( recovery ) ) {
@@ -122,7 +80,6 @@ export const ecrecover = function(
122
80
* @returns Signature
123
81
*/
124
82
export const toRpcSig = function ( v : BNLike , r : Buffer , s : Buffer , chainId ?: BNLike ) : string {
125
- vAndChainIdTypeChecks ( v , chainId )
126
83
const recovery = calculateSigRecovery ( v , chainId )
127
84
if ( ! isValidSigRecovery ( recovery ) ) {
128
85
throw new Error ( 'Invalid signature v value' )
@@ -167,7 +124,6 @@ export const isValidSignature = function(
167
124
homesteadOrLater : boolean = true ,
168
125
chainId ?: BNLike
169
126
) : boolean {
170
- vAndChainIdTypeChecks ( v , chainId )
171
127
const SECP256K1_N_DIV_2 = new BN (
172
128
'7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0' ,
173
129
16
@@ -182,8 +138,8 @@ export const isValidSignature = function(
182
138
return false
183
139
}
184
140
185
- const rBN : BN = new BN ( r )
186
- const sBN : BN = new BN ( s )
141
+ const rBN = new BN ( r )
142
+ const sBN = new BN ( s )
187
143
188
144
if ( rBN . isZero ( ) || rBN . gt ( SECP256K1_N ) || sBN . isZero ( ) || sBN . gt ( SECP256K1_N ) ) {
189
145
return false
0 commit comments