ERC-2098: Compact Signature Representation

A compact representation of an Ethereum Signature.


Metadata
Status: FinalStandards Track: ERCCreated: 2019-03-14
Authors
Richard Moore (@ricmoo), Nick Johnson (nick@ethereum.org)
Requires

Abstract


The secp256k1 curve permits the computation of the public key of signed digest when coupled with a signature, which is used implicitly to establish the origin of a transaction from an Externally Owned Account as well as on-chain in EVM contracts for example, in meta-transactions and multi-sig contracts.

Currently signatures require 65 bytes to represent, which when aligned to 256-bit words, requires 96 bytes (with 31 zero bytes injected). The yParity in RLP-encoded transactions also require (on average) 1.5 bytes. With compact signatures, this can be reduced to 64 bytes, which remains 64 bytes when word-aligned, and in the case of RLP-encoded transactions saves the 1.5 bytes required for the yParity.

Motivation


The motivations for a compact representation are to simplify handling transactions in client code, reduce gas costs and reduce transaction sizes.

Specification


A secp256k1 signature is made up of 3 parameters, r, s and yParity. The r represents the x component on the curve (from which the y can be computed), and the s represents the challenge solution for signing by a private key. Due to the symmetric nature of an elliptic curve, a yParity is required, which indicates which of the 2 possible solutions was intended, by indicating its parity (odd-ness).

Two key observations are required to create a compact representation.

First, the yParity parameter is always either 0 or 1 (canonically the values used have historically been 27 and 28, as these values didn't collide with other binary prefixes used in Bitcoin).

Second, the top bit of the s parameters is always 0, due to the use of canonical signatures which flip the solution parity to prevent negative values, which was introduced as a constraint in Homestead.

So, we can hijack the top bit in the s parameter to store the value of yParity, resulting in:


Example Implementation In Python


Rationale


The compact representation proposed is simple to both compose and decompose in clients and in Solidity, so that it can be easily (and intuitively) supported, while reducing transaction sizes and gas costs.

Backwards Compatibility


The Compact Representation does not collide with canonical signature as it uses 2 parameters (r, yParityAndS) and is 64 bytes long while canonical signatures involve 3 separate parameters (r, s, yParity) and are 65 bytes long.

Test Cases




Reference Implementation


The ethers.js library supports this in v5 as an unofficial property of split signatures (i.e. sig._vs), but should be considered an internal property that may change at discretion of the community and any changes to this EIP.

Security Considerations


There are no additional security concerns introduced by this EIP.

Copyright


Copyright and related rights waived via CC0.