[ERC2680] Ethereumウォレットとキーストアの保存形式の仕組みを理解しよう！

# はじめに

『DApps開発入門』という本や色々記事を書いているかるでねです。

https://amzn.asia/d/gxvJ0Pw

今回は、Ethereumウォレットとキーストアの保存形式を定め、異なるソフトウェア間でウォレットや鍵を扱える仕組みを提案している**ERC2680**についてまとめていきます！

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

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

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

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

# 概要

Ethereumウォレットに関して、現在はウォレットやキーストアの保存場所やファイル名の標準が存在しません。そのため、異なるソフトウェア同士で同じウォレットや鍵を共有・再利用することが困難です。

**ERC2680**では、ウォレットストア（walletstore）とキーストア（keystore）に関する配置や名前の形式について、階層構造を持つストレージ（例：ファイルシステムやAmazon S3）と、階層構造を持たないストレージ（例：キー/バリュー型ストレージ）の両方に対応した標準を定めています。
これにより、異なるソフトウェアが同じウォレットや鍵にアクセスできるようになります。

# 動機

ウォレットやアカウントのレイアウトに標準を設けることで、検証ノード（validator）間の互換性が生まれ、ユーザーはあるソフトウェアから別のソフトウェアへとスムーズに移行できるようになります。

これはセキュリティ面でも重要です。
秘密鍵を含むファイルの移動は、誤って削除してしまうリスクや、複製によってセキュリティを損なうリスクを伴うためです。
標準的なレイアウトがあれば、こうしたファイル移動の必要性が減り安全性が高まります。

# 仕様

## 基本構成要素

ウォレットに関する標準仕様では、以下の4つの要素が定義されています。

* Base location（基準パス）
* Wallet container（ウォレットコンテナ）
* Walletstore（ウォレットストア）
* Keystore（キーストア）

これらの要素を組み合わせることで、異なるストレージシステム間でも共通の形式でウォレットや鍵を保存・読み取りできるようになります。

## Base location（基準パス）

基準パスとは、ウォレットや鍵の保存場所を示す共通のルートです。
階層型と非階層型のストレージにより定義が異なります。

### ファイルシステムの場合（階層型）

各OSにおける基準パスは以下の通りです。

* Windows: `%APPDATA%\ethereum2\wallets`
* MacOSX: `${HOME}/Library/Application Support/ethereum2/wallets`
* Linux: `${HOME}/.config/ethereum2/wallets`

### Amazon S3などの他の階層型ストレージ

「Ethereum 2 wallet:」にストレージ識別子（例：アカウントID）を連結した文字列をSHA-256でハッシュ化し、その16進小文字文字列を基準パスとします。

例）

* 文字列: `Ethereum 2 wallet:AbC0438EB`
* SHA-256ハッシュ: `0x991ec1...c9229`
* 基準パス: `991ec14a8d13836b10d8c3039c9e30876491cb8aa9c9c16967578afc815c9229`

### 非階層型ストレージ

非階層型ストレージ（例：キー/バリューストア）では、基準パスの概念は存在しません。

## Wallet container（ウォレットコンテナ）

ウォレットコンテナは、ウォレットストアとそれに紐づくキーストアを格納する単位です。

* コンテナの識別にはウォレットのUUID（RFC 4122に準拠）を使用します。

## Walletstore（ウォレットストア）

ウォレットストアは、ウォレット全体の設定や情報を格納します。

* ウォレットコンテナ内に保存されます。
* ファイル名またはオブジェクト名はウォレットのUUIDです。

## Keystore（キーストア）

キーストアは、1つの鍵に対応する情報（例：秘密鍵）を格納します。

* ウォレットコンテナ内に保存されます。
* ファイル名またはオブジェクト名は鍵のUUIDです。

## 階層型ストレージの例

ウォレットUUIDと複数の鍵UUIDを以下のように構成します。

```
- 1f031fff-c51d-44fc-8baf-d6b304cb70a7
  +- 1302106c-8441-4e2e-b687-6c77f49fc624
  +- 1f031fff-c51d-44fc-8baf-d6b304cb70a7
  +- 4a320100-83fd-4db7-8126-6d6d205ba834
```

## 非階層型ストレージの例

キーを結合してオブジェクト名を生成します。

```
1f031fff-c51d-44fc-8baf-d6b304cb70a7:1302106c-8441-4e2e-b687-6c77f49fc624
1f031fff-c51d-44fc-8baf-d6b304cb70a7:1f031fff-c51d-44fc-8baf-d6b304cb70a7
1f031fff-c51d-44fc-8baf-d6b304cb70a7:4a320100-83fd-4db7-8126-6d6d205ba834
```

## 同時書き込みへの保護

**ERC2680**では、同時に複数のプロセスが書き込む場合の対策はまだ定義されていません（TBD: To Be Determined）。

## ウォレットの列挙

階層型および反復可能な非階層型ストレージでは、基準パス内のファイルをスキャンすることでウォレットを列挙できます。

* 実装者がインデックスを導入する場合、その形式は次に述べる「インデックス形式」に準拠する必要があります。

## アカウントの列挙

階層型ストレージでは、ウォレットコンテナ内のファイルをスキャンすることでアカウントを列挙できます。

* こちらもインデックス導入時には、同様に「インデックス形式」に従う必要があります。

## インデックス形式

ウォレットやアカウントの一覧を格納する際の形式は以下のJSONスキーマに従います。

```json
{
  "type": "array",
  "items": {
    "type": "object",
    "properties": {
      "uuid": {
        "type": "string"
      },
      "name": {
        "type": "string"
      }
    },
    "required": [
      "uuid",
      "name"
    ]
  }
}
```

* インデックスファイルの名前は必ず `index` とします。
* インデックスには公開鍵を含めてはいけません。

# 補足

ウォレットストアに関する標準を定めることで、キーストアと同様に異なるウォレット間での互換性が向上します。
これにより、ユーザーは異なるソフトウェア間でウォレットや鍵を簡単に移行・共有できるようになります。

例えば、ある検証ノード（validator）ソフトから別のソフトへウォレットを切り替える場合でも、ファイルの中身や構造を気にせずに使えるようになるため、操作が簡素化されて移行時のミスも減ります。

# セキュリティ

ウォレットストアの保存場所は、各ユーザーのホームディレクトリ内などに限定されています。
これにより、他人が誤ってアクセスしてしまう可能性を減らしています。

しかし、OSの設定次第では、これらのファイルが「**全員に読み取り可能**」な状態になる場合もあります。
したがって、この標準に基づいて実装するアプリケーションは、ファイルのアクセス権限を必ず適切に設定・確認し、対象ユーザーだけがアクセスできるようにする必要があります。

また、ウォレットストアやキーストアのファイル名にはUUID（ランダムな一意識別子）が使われます。
これにより、ファイル名から個人情報や鍵の内容が推測されるリスクが排除され、メタデータからの情報漏洩を防ぐ仕組みになっています。

# 引用

Jim McDonald <Jim@mcdee.net>, "ERC-2680: Ethereum 2 wallet layout [DRAFT]," Ethereum Improvement Proposals, no. 2680, May 2020. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-2680.

# 最後に

今回は「Ethereumウォレットとキーストアの保存形式を定め、異なるソフトウェア間でウォレットや鍵を扱える仕組みを提案している**ERC2680**」についてまとめてきました！
いかがだったでしょうか？

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

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

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

https://chaldene.net/

https://zenn.dev/heku

https://cardene.substack.com/

https://mirror.xyz/0xcE77b9fCd390847627c84359fC1Bc02fC78f0e58

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