signature.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.Signature = void 0;
  4. const index_js_1 = require("../constants/index.js");
  5. const index_js_2 = require("../utils/index.js");
  6. // Constants
  7. const BN_0 = BigInt(0);
  8. const BN_1 = BigInt(1);
  9. const BN_2 = BigInt(2);
  10. const BN_27 = BigInt(27);
  11. const BN_28 = BigInt(28);
  12. const BN_35 = BigInt(35);
  13. const _guard = {};
  14. function toUint256(value) {
  15. return (0, index_js_2.zeroPadValue)((0, index_js_2.toBeArray)(value), 32);
  16. }
  17. /**
  18. * A Signature @TODO
  19. *
  20. *
  21. * @_docloc: api/crypto:Signing
  22. */
  23. class Signature {
  24. #r;
  25. #s;
  26. #v;
  27. #networkV;
  28. /**
  29. * The ``r`` value for a signautre.
  30. *
  31. * This represents the ``x`` coordinate of a "reference" or
  32. * challenge point, from which the ``y`` can be computed.
  33. */
  34. get r() { return this.#r; }
  35. set r(value) {
  36. (0, index_js_2.assertArgument)((0, index_js_2.dataLength)(value) === 32, "invalid r", "value", value);
  37. this.#r = (0, index_js_2.hexlify)(value);
  38. }
  39. /**
  40. * The ``s`` value for a signature.
  41. */
  42. get s() { return this.#s; }
  43. set s(_value) {
  44. (0, index_js_2.assertArgument)((0, index_js_2.dataLength)(_value) === 32, "invalid s", "value", _value);
  45. const value = (0, index_js_2.hexlify)(_value);
  46. (0, index_js_2.assertArgument)(parseInt(value.substring(0, 3)) < 8, "non-canonical s", "value", value);
  47. this.#s = value;
  48. }
  49. /**
  50. * The ``v`` value for a signature.
  51. *
  52. * Since a given ``x`` value for ``r`` has two possible values for
  53. * its correspondin ``y``, the ``v`` indicates which of the two ``y``
  54. * values to use.
  55. *
  56. * It is normalized to the values ``27`` or ``28`` for legacy
  57. * purposes.
  58. */
  59. get v() { return this.#v; }
  60. set v(value) {
  61. const v = (0, index_js_2.getNumber)(value, "value");
  62. (0, index_js_2.assertArgument)(v === 27 || v === 28, "invalid v", "v", value);
  63. this.#v = v;
  64. }
  65. /**
  66. * The EIP-155 ``v`` for legacy transactions. For non-legacy
  67. * transactions, this value is ``null``.
  68. */
  69. get networkV() { return this.#networkV; }
  70. /**
  71. * The chain ID for EIP-155 legacy transactions. For non-legacy
  72. * transactions, this value is ``null``.
  73. */
  74. get legacyChainId() {
  75. const v = this.networkV;
  76. if (v == null) {
  77. return null;
  78. }
  79. return Signature.getChainId(v);
  80. }
  81. /**
  82. * The ``yParity`` for the signature.
  83. *
  84. * See ``v`` for more details on how this value is used.
  85. */
  86. get yParity() {
  87. return (this.v === 27) ? 0 : 1;
  88. }
  89. /**
  90. * The [[link-eip-2098]] compact representation of the ``yParity``
  91. * and ``s`` compacted into a single ``bytes32``.
  92. */
  93. get yParityAndS() {
  94. // The EIP-2098 compact representation
  95. const yParityAndS = (0, index_js_2.getBytes)(this.s);
  96. if (this.yParity) {
  97. yParityAndS[0] |= 0x80;
  98. }
  99. return (0, index_js_2.hexlify)(yParityAndS);
  100. }
  101. /**
  102. * The [[link-eip-2098]] compact representation.
  103. */
  104. get compactSerialized() {
  105. return (0, index_js_2.concat)([this.r, this.yParityAndS]);
  106. }
  107. /**
  108. * The serialized representation.
  109. */
  110. get serialized() {
  111. return (0, index_js_2.concat)([this.r, this.s, (this.yParity ? "0x1c" : "0x1b")]);
  112. }
  113. /**
  114. * @private
  115. */
  116. constructor(guard, r, s, v) {
  117. (0, index_js_2.assertPrivate)(guard, _guard, "Signature");
  118. this.#r = r;
  119. this.#s = s;
  120. this.#v = v;
  121. this.#networkV = null;
  122. }
  123. [Symbol.for('nodejs.util.inspect.custom')]() {
  124. return `Signature { r: "${this.r}", s: "${this.s}", yParity: ${this.yParity}, networkV: ${this.networkV} }`;
  125. }
  126. /**
  127. * Returns a new identical [[Signature]].
  128. */
  129. clone() {
  130. const clone = new Signature(_guard, this.r, this.s, this.v);
  131. if (this.networkV) {
  132. clone.#networkV = this.networkV;
  133. }
  134. return clone;
  135. }
  136. /**
  137. * Returns a representation that is compatible with ``JSON.stringify``.
  138. */
  139. toJSON() {
  140. const networkV = this.networkV;
  141. return {
  142. _type: "signature",
  143. networkV: ((networkV != null) ? networkV.toString() : null),
  144. r: this.r, s: this.s, v: this.v,
  145. };
  146. }
  147. /**
  148. * Compute the chain ID from the ``v`` in a legacy EIP-155 transactions.
  149. *
  150. * @example:
  151. * Signature.getChainId(45)
  152. * //_result:
  153. *
  154. * Signature.getChainId(46)
  155. * //_result:
  156. */
  157. static getChainId(v) {
  158. const bv = (0, index_js_2.getBigInt)(v, "v");
  159. // The v is not an EIP-155 v, so it is the unspecified chain ID
  160. if ((bv == BN_27) || (bv == BN_28)) {
  161. return BN_0;
  162. }
  163. // Bad value for an EIP-155 v
  164. (0, index_js_2.assertArgument)(bv >= BN_35, "invalid EIP-155 v", "v", v);
  165. return (bv - BN_35) / BN_2;
  166. }
  167. /**
  168. * Compute the ``v`` for a chain ID for a legacy EIP-155 transactions.
  169. *
  170. * Legacy transactions which use [[link-eip-155]] hijack the ``v``
  171. * property to include the chain ID.
  172. *
  173. * @example:
  174. * Signature.getChainIdV(5, 27)
  175. * //_result:
  176. *
  177. * Signature.getChainIdV(5, 28)
  178. * //_result:
  179. *
  180. */
  181. static getChainIdV(chainId, v) {
  182. return ((0, index_js_2.getBigInt)(chainId) * BN_2) + BigInt(35 + v - 27);
  183. }
  184. /**
  185. * Compute the normalized legacy transaction ``v`` from a ``yParirty``,
  186. * a legacy transaction ``v`` or a legacy [[link-eip-155]] transaction.
  187. *
  188. * @example:
  189. * // The values 0 and 1 imply v is actually yParity
  190. * Signature.getNormalizedV(0)
  191. * //_result:
  192. *
  193. * // Legacy non-EIP-1559 transaction (i.e. 27 or 28)
  194. * Signature.getNormalizedV(27)
  195. * //_result:
  196. *
  197. * // Legacy EIP-155 transaction (i.e. >= 35)
  198. * Signature.getNormalizedV(46)
  199. * //_result:
  200. *
  201. * // Invalid values throw
  202. * Signature.getNormalizedV(5)
  203. * //_error:
  204. */
  205. static getNormalizedV(v) {
  206. const bv = (0, index_js_2.getBigInt)(v);
  207. if (bv === BN_0 || bv === BN_27) {
  208. return 27;
  209. }
  210. if (bv === BN_1 || bv === BN_28) {
  211. return 28;
  212. }
  213. (0, index_js_2.assertArgument)(bv >= BN_35, "invalid v", "v", v);
  214. // Otherwise, EIP-155 v means odd is 27 and even is 28
  215. return (bv & BN_1) ? 27 : 28;
  216. }
  217. /**
  218. * Creates a new [[Signature]].
  219. *
  220. * If no %%sig%% is provided, a new [[Signature]] is created
  221. * with default values.
  222. *
  223. * If %%sig%% is a string, it is parsed.
  224. */
  225. static from(sig) {
  226. function assertError(check, message) {
  227. (0, index_js_2.assertArgument)(check, message, "signature", sig);
  228. }
  229. ;
  230. if (sig == null) {
  231. return new Signature(_guard, index_js_1.ZeroHash, index_js_1.ZeroHash, 27);
  232. }
  233. if (typeof (sig) === "string") {
  234. const bytes = (0, index_js_2.getBytes)(sig, "signature");
  235. if (bytes.length === 64) {
  236. const r = (0, index_js_2.hexlify)(bytes.slice(0, 32));
  237. const s = bytes.slice(32, 64);
  238. const v = (s[0] & 0x80) ? 28 : 27;
  239. s[0] &= 0x7f;
  240. return new Signature(_guard, r, (0, index_js_2.hexlify)(s), v);
  241. }
  242. if (bytes.length === 65) {
  243. const r = (0, index_js_2.hexlify)(bytes.slice(0, 32));
  244. const s = bytes.slice(32, 64);
  245. assertError((s[0] & 0x80) === 0, "non-canonical s");
  246. const v = Signature.getNormalizedV(bytes[64]);
  247. return new Signature(_guard, r, (0, index_js_2.hexlify)(s), v);
  248. }
  249. assertError(false, "invalid raw signature length");
  250. }
  251. if (sig instanceof Signature) {
  252. return sig.clone();
  253. }
  254. // Get r
  255. const _r = sig.r;
  256. assertError(_r != null, "missing r");
  257. const r = toUint256(_r);
  258. // Get s; by any means necessary (we check consistency below)
  259. const s = (function (s, yParityAndS) {
  260. if (s != null) {
  261. return toUint256(s);
  262. }
  263. if (yParityAndS != null) {
  264. assertError((0, index_js_2.isHexString)(yParityAndS, 32), "invalid yParityAndS");
  265. const bytes = (0, index_js_2.getBytes)(yParityAndS);
  266. bytes[0] &= 0x7f;
  267. return (0, index_js_2.hexlify)(bytes);
  268. }
  269. assertError(false, "missing s");
  270. })(sig.s, sig.yParityAndS);
  271. assertError(((0, index_js_2.getBytes)(s)[0] & 0x80) == 0, "non-canonical s");
  272. // Get v; by any means necessary (we check consistency below)
  273. const { networkV, v } = (function (_v, yParityAndS, yParity) {
  274. if (_v != null) {
  275. const v = (0, index_js_2.getBigInt)(_v);
  276. return {
  277. networkV: ((v >= BN_35) ? v : undefined),
  278. v: Signature.getNormalizedV(v)
  279. };
  280. }
  281. if (yParityAndS != null) {
  282. assertError((0, index_js_2.isHexString)(yParityAndS, 32), "invalid yParityAndS");
  283. return { v: (((0, index_js_2.getBytes)(yParityAndS)[0] & 0x80) ? 28 : 27) };
  284. }
  285. if (yParity != null) {
  286. switch ((0, index_js_2.getNumber)(yParity, "sig.yParity")) {
  287. case 0: return { v: 27 };
  288. case 1: return { v: 28 };
  289. }
  290. assertError(false, "invalid yParity");
  291. }
  292. assertError(false, "missing v");
  293. })(sig.v, sig.yParityAndS, sig.yParity);
  294. const result = new Signature(_guard, r, s, v);
  295. if (networkV) {
  296. result.#networkV = networkV;
  297. }
  298. // If multiple of v, yParity, yParityAndS we given, check they match
  299. assertError(sig.yParity == null || (0, index_js_2.getNumber)(sig.yParity, "sig.yParity") === result.yParity, "yParity mismatch");
  300. assertError(sig.yParityAndS == null || sig.yParityAndS === result.yParityAndS, "yParityAndS mismatch");
  301. return result;
  302. }
  303. }
  304. exports.Signature = Signature;
  305. //# sourceMappingURL=signature.js.map