---
eip: 2098
title: Compact Signature Representation
description: A compact representation of an Ethereum Signature.
status: Final
type: Standards Track
category: ERC
author: Richard Moore (@ricmoo), Nick Johnson <nick@ethereum.org>
discussions-to: https://github.com/ethereum/EIPs/issues/2440
created: 2019-03-14
requires: 2
---


## 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](./eip-2.md).

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

```
[256-bit r value][1-bit yParity value][255-bit s value]
```


### Example Implementation In Python

```python
# Assume yParity is 0 or 1, normalized from the canonical 27 or 28
def to_compact(r, s, yParity):
    return {
        "r": r,
        "yParityAndS": (yParity << 255) | s
    }

def to_canonical(r, yParityAndS):
    return {
        "r": r,
        "s": yParityAndS & ((1 << 255) - 1),
        "yParity": (yParityAndS >> 255)
    }
```


## 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

```
Private Key: 0x1234567890123456789012345678901234567890123456789012345678901234
Message: "Hello World"
Signature:
  r:  0x68a020a209d3d56c46f38cc50a33f704f4a9a10a59377f8dd762ac66910e9b90
  s:  0x7e865ad05c4035ab5792787d4a0297a43617ae897930a6fe4d822b8faea52064
  v:  27
Compact Signature:
  r:           0x68a020a209d3d56c46f38cc50a33f704f4a9a10a59377f8dd762ac66910e9b90
  yParityAndS: 0x7e865ad05c4035ab5792787d4a0297a43617ae897930a6fe4d822b8faea52064
```

```
Private Key: 0x1234567890123456789012345678901234567890123456789012345678901234
Message: "It's a small(er) world"
Signature:
  r:  0x9328da16089fcba9bececa81663203989f2df5fe1faa6291a45381c81bd17f76
  s:  0x139c6d6b623b42da56557e5e734a43dc83345ddfadec52cbe24d0cc64f550793
  v:  28
Compact Signature:
  r:           0x9328da16089fcba9bececa81663203989f2df5fe1faa6291a45381c81bd17f76
  yParityAndS: 0x939c6d6b623b42da56557e5e734a43dc83345ddfadec52cbe24d0cc64f550793  
```


## Reference Implementation

The ethers.js library [supports this in v5](https://github.com/ethers-io/ethers.js/blob/ethers-v5-beta/packages/bytes/src.ts/index.ts#L323)
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](../LICENSE.md).
