From f26074b92b0fc8efd3d85c68e84cc6ff8897e4a8 Mon Sep 17 00:00:00 2001 From: Richard Moore Date: Fri, 18 Feb 2022 18:54:00 -0500 Subject: [PATCH] Add support for EIP-2098 compact signatures (#2246). --- docs.wrm/api/utils/bytes.wrm | 4 +++- packages/bytes/src.ts/index.ts | 36 ++++++++++++++++++++++++++-------- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/docs.wrm/api/utils/bytes.wrm b/docs.wrm/api/utils/bytes.wrm index 15c61c246b..ecfbcddaa2 100644 --- a/docs.wrm/api/utils/bytes.wrm +++ b/docs.wrm/api/utils/bytes.wrm @@ -38,8 +38,10 @@ _heading: Signature @ - **r** and **s** --- The x co-ordinate of **r** and the **s** value of the signature - **v** --- The parity of the y co-ordinate of **r** -- **_vs** --- The [compact representation](link-eip-2098) of the **s** and **v** +- **yParityAndS** --- The [compact representation](link-eip-2098) of the **s** and **v** +- **_vs** --- Deprecated property; renamed to yParityAndS - **recoveryParam** --- The normalized (i.e. 0 or 1) value of **v** +- **compact** - The full siggnature using [compact representation](link-eip-2098) _heading: Raw Signature @ @inherit\>> diff --git a/packages/bytes/src.ts/index.ts b/packages/bytes/src.ts/index.ts index ab550b5236..4ff3326646 100644 --- a/packages/bytes/src.ts/index.ts +++ b/packages/bytes/src.ts/index.ts @@ -46,6 +46,9 @@ export interface Signature { recoveryParam: number; v: number; + + yParityAndS: string + compact: string; } /////////////////////////////// @@ -328,24 +331,38 @@ export function hexZeroPad(value: BytesLike, length: number): string { } export function splitSignature(signature: SignatureLike): Signature { + const result = { r: "0x", s: "0x", _vs: "0x", recoveryParam: 0, - v: 0 + v: 0, + yParityAndS: "0x", + compact: "0x" }; if (isBytesLike(signature)) { - const bytes: Uint8Array = arrayify(signature); - if (bytes.length !== 65) { - logger.throwArgumentError("invalid signature string; must be 65 bytes", "signature", signature); - } + let bytes: Uint8Array = arrayify(signature); // Get the r, s and v - result.r = hexlify(bytes.slice(0, 32)); - result.s = hexlify(bytes.slice(32, 64)); - result.v = bytes[64]; + if (bytes.length === 64) { + // EIP-2098; pull the v from the top bit of s and clear it + result.v = 27 + (bytes[32] >> 7); + bytes[32] &= 0x7f; + + result.r = hexlify(bytes.slice(0, 32)); + result.s = hexlify(bytes.slice(32, 64)); + + } else if (bytes.length === 65) { + result.r = hexlify(bytes.slice(0, 32)); + result.s = hexlify(bytes.slice(32, 64)); + result.v = bytes[64]; + } else { + + logger.throwArgumentError("invalid signature string", "signature", signature); + } + // Allow a recid to be used as the v if (result.v < 27) { @@ -448,6 +465,9 @@ export function splitSignature(signature: SignatureLike): Signature { } } + result.yParityAndS = result._vs; + result.compact = result.r + result.yParityAndS.substring(2); + return result; }