[ERC1062] IPFSのハッシュをENSに登録する仕組みを理解しよう！

# はじめに

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

https://amzn.asia/d/gxvJ0Pw

今回は、IPFSのハッシュをENSに登録・取得できるようにする仕組みを提案している**ERC1062**についてまとめていきます！

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

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

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

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

# 概要

**ERC1062**は、IPFS（InterPlanetary File System）に保存されたリソースと、Ethereum上のネーミングサービスであるENS（Ethereum Naming Service）との間のマッピング手法を提案しています。

具体的には、IPFSの暗号学的ハッシュ（ファイルの一意の指紋）をENSのPublic Resolverと連携させることで、IPFS上のリソースをENSから「取得」および「設定」できる機能を提供します。

この仕組みによって、開発者やコミュニティはより多くのユースケースを提供できるようになるだけでなく、ENSの人間にとって読みやすい名前を通じて、ユーザーが分散型リソースへより簡単にアクセスできるようになります。
IPFSとENSの連携は、今後のWeb3.0サービスの基盤技術として重要な役割を担うと位置づけられています。

# 動機

完全な分散型Webサービスを構築するためには、分散型のファイルストレージが必要です。
IPFSは、以下の3つの利点からその要件を満たす存在です。

* **大容量データの管理と一意の識別**
  IPFSでは、すべてのファイルに暗号学的に一意なハッシュが与えられるため、整合性のあるデータ管理が可能です。

* **P2Pネットワークによる効率的な配信**
  IPFSはピア・ツー・ピア型のネットワークで構成されており、分散的かつ安全に大量のデータを配信できます。これにより、中央集権的なサーバーに依存せずに帯域コストの削減が可能となります。

* **バージョン管理と重複排除による効率化**
  ファイルごとに履歴が追跡され、ネットワーク全体で重複を排除する仕組みにより、ストレージ効率が向上します。

この特徴はENSとの統合に非常に適しており、ユーザーは通常のブラウザを使ってENS名を入力するだけでIPFS上のコンテンツに簡単にアクセスできるようになります。

# 仕様

IPFSのファイル識別子（フィンガープリント）はBase58形式で表現されますが、EthereumのAPIではバイナリデータを16進数（Hex）形式で扱います。
そのため、IPFSのアドレスをENSに保存・取得する際には、Base58とHexの間で相互変換が必要になります。

この変換には「**バイナリバッファ**」を用いることで両者の橋渡しを行います。

具体的には、以下の流れで処理します。

1. IPFSのBase58文字列をバイナリバッファに変換。
2. そのバッファをHex形式に変換して、ENSのコントラクトに保存。
3. ENSからIPFSアドレスを取得する時には、Hex形式の値を取り出して再びバッファに戻してからBase58文字列に再変換。

この仕組みによって、ENSのレコードとIPFS上のファイルを正確に紐付けることができます。

## 実装

この仕様を実装するには、ENSのPublic Resolverが提供する以下の2つの関数が必要になります。

* `setMultihash`
    * ENSの特定ノードに対してIPFSのハッシュを登録。
* `multihash`
    * 登録されたIPFSのハッシュを取得。

### `setMultihash`

```javascript
function setMultihash(bytes32 node, bytes hash) public only_owner(node);
```

IPFSハッシュをENSノードに保存する関数。
ENSノードに対して、Base58→Hexに変換されたIPFSのハッシュを登録します。
この関数は、対象ノードのオーナーによってのみ呼び出すことができます。

**引数**

* `node`
    * ENSノード（ドメイン名）を示す32バイトの識別子（`bytes32`形式）。
* `hash`
    * Hex形式に変換されたIPFSハッシュ（`bytes`型）。

### `multihash`

```javascript
function multihash(bytes32 node) public view returns (bytes);
```

IPFSハッシュをENSノードから取得する関数。
指定されたENSノードに紐付けられたIPFSハッシュ（Hex形式）を取得します。
取得後はそれをBase58形式に再変換することで、対応するIPFS上のリソースアドレスが得られます。

**引数**

* `node`
    * ENSノード（ドメイン名）を示す32バイトの識別子（`bytes32`形式）。

**戻り値**

* `bytes`
    * 保存されているIPFSハッシュのHex形式データ。

### `only_owner`

```javascript
modifier only_owner(bytes32 node);
```

ENSノードのオーナーのみが操作できるようにする修飾子。
この修飾子が付与された関数は、対象のENSノードのオーナーであるアドレスのみが実行可能です。
これにより、勝手に他人のENSレコードを書き換えることを防ぎます。

**パラメータ**

* `node`
    * アクセス制御を行う対象のENSノード識別子（`bytes32`形式）。

# テストケース

IPFSのBase58形式とEthereumが扱うHex形式との相互変換を行うために、`multihashes`というライブラリを使用します。
このライブラリは、IPFSハッシュのエンコード／デコード処理に最適化されています。

### Base58 → Hexへの変換

IPFSのBase58形式のハッシュを、ENSコントラクトで保存できるHex形式に変換します。

```javascript
import multihash from 'multihashes'

export const toHex = function(ipfsHash) {
  let buf = multihash.fromB58String(ipfsHash);
  return '0x' + multihash.toHexString(buf);
}
```

この関数では以下の手順で処理を行います。

1. `fromB58String`を使って、Base58文字列からバイナリバッファに変換。
2. そのバッファを`toHexString`でHex文字列に変換。
3. `0x`プレフィックスを付与して返却。

### Hex → Base58への変換

ENSコントラクトから取得したHex形式のIPFSハッシュを、元のBase58形式に戻します。

```javascript
import multihash from 'multihashes'

export const toBase58 = function(contentHash) {
  let hex = contentHash.substring(2)
  let buf = multihash.fromHexString(hex);
  return multihash.toB58String(buf);
}
```

この関数では以下の手順で処理を行います。

1. 先頭の`0x`を削除。
2. `fromHexString`を使ってHex文字列からバイナリバッファに変換。
3. `toB58String`を使ってBase58形式に再エンコード。

これらの変換処理により、IPFSとENSの相互運用が可能になります。

# 参考実装

この仕組みは、ブラウザ拡張機能として実装されています。
ユーザーはこの拡張機能を導入することで、通常のDNSのようにENSドメインをブラウザのアドレスバーに入力するだけで、IPFS上の分散コンテンツにアクセスできます。

これにより、以下のようなユーザー体験が実現されます。

* ENS名をURLとして入力（例: `vitalik.eth`）
* 拡張機能が自動的に対応するIPFSハッシュを解決
* 分散型コンテンツを直接ブラウザに表示

この仕組みにより、一般ユーザーでも直感的に利用できる環境が整います。

参考実装リポジトリ
[https://github.com/PortalNetwork/portal-network-browser-extension](https://github.com/PortalNetwork/portal-network-browser-extension)

このリポジトリには、実際に機能する拡張機能のコードが含まれており、IPFS-ENSのマッピングの仕組みが具体的に実装されています。
開発者はこれを参考にして、独自のユースケースにも応用可能です。

# 引用

Phyrex Tsai <phyrex@portal.network>, Portal Network Team, "ERC-1062: Formalize IPFS hash into ENS(Ethereum Name Service) resolver [DRAFT]," Ethereum Improvement Proposals, no. 1062, May 2018. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-1062.

# 最後に

今回は「IPFSのハッシュをENSに登録・取得できるようにする仕組みを提案している**ERC1062**」についてまとめてきました！
いかがだったでしょうか？

質問などがある方は以下の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