# [ERC2098] Ethereumの署名をよりコンパクトにする仕組みを理解しよう！

> Ethereumのブロックチェーンでは、トランザクション（取引）を確認するために、特定の数学的な方法（secp256k1曲線）を使ってデジタル署名が作られます。この署名によって、トランザクションの送信者が本当に自分であることを証明できます。

- URL: https://cardene.dev/articles/2fb8f63af3b22eb72e33
- 公開日: 2023-12-22
- 更新日: 2023-12-22
- トピック: Blockchain
- タグ: ethereum, solidity, smartcontract, ブロックチェーン

## はじめに

初めまして。
**CryptoGames**というブロックチェーンゲーム企業でエンジニアをしている **cardene（かるでね）** です！
スマートコントラクトを書いたり、フロントエンド・バックエンド・インフラと幅広く触れています。

https://cryptogames.co.jp/

代表的なゲームは**クリプトスペルズ**というブロックチェーンゲームです。

https://cryptospells.jp/

今回は、Ethereumの署名をよりコンパクトにする仕組みを提案している規格である**ERC2098**についてまとめていきます！

:::message
以下にまとめられているものを翻訳・要約・補足しながらまとめていきます。
:::

https://eips.ethereum.org/EIPS/eip-2098

他にも様々なERCについてまとめています。

https://cardene.notion.site/ERC-EIP-2a03fa3ea33d43baa9ed82288f98d4a9?pvs=4

## 概要

Ethereumのブロックチェーンでは、トランザクション（取引）を確認するために、特定の数学的な方法（secp256k1曲線）を使ってデジタル署名が作られます。
この署名によって、トランザクションの送信者が本当に自分であることを証明できます。

現在のシステムでは、この署名には`65`バイトのデータが必要です。
しかし、Ethereumのシステムの特性上、実際には`96`バイト分のスペースを使用し、残りは`0`で埋められます。
また、トランザクションの一部として、追加の情報（**yParity**）も必要ですが、これには`1.5`バイトが必要です。

ここで、「**コンパクト署名**」という新しい方法が登場します。
この方法を使うと、署名のサイズを`64`バイトまで減らすことができ、システム上のアライメント（配置調整）のために余分なデータを加える必要もありません。
つまり、署名のサイズを小さくすることで、トランザクション処理の効率が良くなり、データの保存スペースも節約できるわけです。

:::message
この技術の改善によって、Ethereumのトランザクションがより速く、省スペースで行えるようになります。
:::

## 動機

トランザクションのデータをコンパクトにする理由を説明します。

### クライアントコードでの簡単な扱い
トランザクションのデータがコンパクトだと、開発者がコントラクトやトランザクションを扱いやすくなります。
これは、プログラムをシンプルにし、エラーを減らすのに役立ちます。

### ガスコストの削減
Ethereumでトランザクションを起こすにはガスという手数料がかかります。
データがコンパクトだと、トランザクションに必要なガスが少なくなり、結果的に手数料が安くなります。

### トランザクションサイズの削減
データが小さくなると、Ethereumネットワーク全体で保存するデータ量も減ります。
これにより、ネットワークの効率が良くなり、パフォーマンスが向上します。

:::message
トランザクションのデータをコンパクトにすると、開発者が扱いやすくなり、コストが下がり、ネットワークの効率が上がります。
これは、Ethereumのようなブロックチェーン技術にとって重要な改善点です。
:::

## 仕様

**secp256k1**署名について説明します。

**secp256k1**署名とは、Ethereumなどのブロックチェーン技術で使われる特定の署名方法です。
この署名は、3つの重要な部分、「`r`」、「`s`」、「`yParity`」というパラメーターから構成されています。

- **「r」**
    - これは楕円曲線上の特定の点のx座標を表します。
    - この「`r`」値からy座標も計算することができます。

- **「s」**
    - これは、秘密鍵を使って行われる署名プロセスの一部です。
    - 署名が正しいことを証明するための数値です。

- **「yParity」**
    - 楕円曲線は対称的な形をしているため、2つの可能な解があります。
    - この「**yParity**」は、そのうちのどちらの解が正しいかを示すためのものです。
    - 通常、この値は`0`か`1`のどちらかです。

コンパクトな署名を作るためには、これらのパラメーターをうまく組み合わせる必要があります。
特に、「`s`」の最上位ビットは常に`0`であることから、この部分を使って「**yParity**」の情報を格納することができます。
その結果、署名は以下のような形になります。

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

- 256ビットの「`r`」値
- 1ビットの「`yParity`」値
- 255ビットの「`s`」値

この方法により、署名のデータ量を減らすことができ、結果的にEthereumネットワークの効率が向上します。
これは、トランザクションの速度を上げたり、コストを下げたりするのに役立ちます。

### 実装例

```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)
    }
```

このPythonのコードは、**secp256k1**署名をより小さなデータ形式で表現するためのものです。
ここでは2つの関数、`to_compact` と `to_canonical` があります。

#### `to_compact`
- **目的**
    - 署名をコンパクトな形式に変換します。
- **入力**
    - `r`, `s`, `yParity`（`yParity`は`0`か`1`の値です）。
- **処理**
    - `yParity`を255ビット左にシフトし（これで最上位ビットになります）、それを`s`の値と組み合わせます。
- **結果**
    - `r`値と組み合わされた`yParity`と`s`の新しいコンパクトな表現。

#### `to_canonical`
- **目的**
    - コンパクトな形式を元の形式に戻します。
- **入力**
    - `r`とコンパクトに統合された`yParityAndS`。
- **処理**
    - `yParityAndS`から`s`を取り出すために、最下位255ビットにビットマスクを適用し、`yParity`を取り出すために255ビット右にシフトします。
- **結果**
    - 元の`r`, `s`, `yParity`の値。

これらの関数を使用することで、Ethereumのトランザクション処理をより効率的に行うことができます。
署名のデータサイズを小さくすることで、ネットワークの負担を軽減し、ガスコストを削減することが可能になります。

## 補足

提案されているコンパクトな表現法は、Ethereumのトランザクションに関わるデータをより小さく、簡単に扱えるようにするものです。
これは、クライアント側（ユーザーが使うソフトウェア）やSolidity（Ethereumでスマートコントラクトを作成するための言語）で使う時に、非常に扱いやすいです。

この方法を使うと、開発者が署名データを簡単に理解して適用できます。
また、トランザクションのデータサイズが小さくなるため、Ethereumネットワークでトランザクションを処理する時のコスト（ガスコスト）が削減されます。

:::message
このコンパクトな表現法は、Ethereumのトランザクションをよりスムーズに、そして安価に処理するための便利な方法です。
開発者にとっては扱いやすく、ネットワーク全体にとってはコスト効率が良いという利点があります。
:::

## 後方互換性

提案されている「**コンパクト表現**」は、Ethereumの署名方法をより効率的にする新しい方式です。
この方法では、署名に必要なデータが2つのパラメーター（「`r`」と「`yParityAnd`」）にまとめられており、全体の長さは`64`バイトです。
これに対して、従来の「**標準的な署名**」では、3つのパラメーター（「`r`」、「`s`」、「`yParity`」）を使用し、合計で65バイトの長さがあります。

コンパクト表現の特徴は、署名に必要な情報をより少ないバイト数で表現することです。
これにより、Ethereumのトランザクション処理がより効率的になり、必要なデータ保存量やガスコスト（トランザクションの処理費用）を削減できます。

:::message
コンパクト表現は、同じ情報をより小さなサイズで表現することで、Ethereumネットワークのパフォーマンスを向上できます。
開発者やユーザーにとっては、トランザクション処理が早くてコストも低いというメリットがあります。
:::

## テスト

これらのテストケースは、Ethereumでの署名方法とその新しいコンパクトな形式を示しています。
各ケースで、特定の秘密鍵とメッセージを使って、2種類の署名が生成されています。

### ケース1

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

- **秘密鍵**
    - `0x1234567890123456789012345678901234567890123456789012345678901234`
- **メッセージ**
    - "Hello World"
- **標準的な署名**
    - `r`
        - 署名の一部。
    - `s`
        - 署名の一部。
    - `v`
        - yParity。
- **コンパクト署名**
  - `r`
      - 標準的な署名と同じ。
  - `yParityAndS`
      - ここでは、`s`の値と`yParity`が一つの数値に統合されています。

### ケース2

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

- **秘密鍵**
    - `0x1234567890123456789012345678901234567890123456789012345678901234`
- **メッセージ**
    - "It's a small(er) world"
- **標準的な署名**
    - 同じく`r`、`s`、`v`という3つのパラメーターを含む。
- **コンパクト署名**
  - `r`
      - 標準的な署名と同じ。
  - `yParityAndS`
      - ここでも、`s`の値と`yParity`が一つに統合されています。

:::message
これらのケースは、通常の署名とコンパクト署名の違いを示しており、コンパクト署名はより少ないデータで同じ情報を表現する効率的な方法です。
これにより、Ethereumのトランザクション処理のデータサイズが小さくなり、ネットワークの効率が向上します。
:::

## セキュリティ

このEIPによって新たにセキュリティ上の懸念が生じることはありません。

## 引用

Richard Moore (@ricmoo), Nick Johnson <nick@ethereum.org>, "ERC-2098: Compact Signature Representation," Ethereum Improvement Proposals, no. 2098, March 2019. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-2098.

## 最後に

今回は「Ethereumの署名をよりコンパクトにする仕組みを提案している規格である**ERC2098**」についてまとめてきました！
いかがだったでしょうか？

質問などがある方は以下のTwitterのDMなどからお気軽に質問してください！

[Twitter @cardene777](https://twitter.com/cardene777)

他の媒体でも情報発信しているのでぜひ他も見ていってください！

https://chaldene.net/

https://zenn.dev/heku

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58


https://cardene.notion.site/ERC-EIP-2a03fa3ea33d43baa9ed82288f98d4a9?pvs=4
