[ERC7406] ブロックチェーン上での多様なデータ管理を実現するマルチネームスペースレジストリについて理解しよう！

# はじめに

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

https://cryptogames.co.jp/

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

https://cryptospells.jp/

今回は、マッピング構造でデータを保存し、ブロックチェーン上での多様なデータ管理を実現するマルチネームスペースレジストリの仕組みを提案している**ERC7406**についてまとめていきます！

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

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

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

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

# 概要

このEIP（Ethereum Improvement Proposal、イーザリアム改善提案）は、マルチネームスペースをサポートするマッピングタイプ（キーと値のペア）の構造を取り入れることを提案しています。
このマルチネームスペースレジストリにより、ブロックチェーン内にキーと値のマッピングの集合を保存できるようになります。

:::note info
キーと値のマッピングの集合は、日常生活でよく使用される辞書や電話帳のようなものと考えることができます。
これは、ある特定の「**キー**」（識別子）が対応する「**値**」（情報）に結びつけられる仕組みです。
ブロックチェーンのコンテキストでは、このマッピングはより複雑なデータ構造や関連性を持つことができます。

### 具体例

あなたがオンライン書店を運営していて、書籍のISBN（国際標準図書番号）をキーとして、その書籍の詳細情報（著者、タイトル、価格など）を値とするデータベースを持っているとします。

- **キー**
    - `978-4-123456-78-9` (ある本のISBN)
- **値**
    - `{ 著者: "山田太郎", タイトル: "ブロックチェーン入門", 価格: 2000円 }`

このマッピングを使うことで、特定のISBNを検索するだけで、その書籍のすべての情報を瞬時に取得できます。

### ブロックチェーンでの応用

ブロックチェーンのマルチネームスペースレジストリでは、この概念がさらに拡張されます。
たとえば、あるデジタルアセットに対して、異なる種類の情報（所有者、購入履歴、ライセンス情報など）を異なるネームスペースに分けて管理することができます。

- **ネームスペース1（所有者情報）**
    - キー
        - `アセットID`
    - 値
        - `所有者のウォレットアドレス`
- **ネームスペース2（購入履歴）**
    - キー
        - `アセットID`
    - 値
        - `[購入日: "2023-01-01", 購入者: "ウォレットアドレスA", 価格: 500円]`
- **ネームスペース3（ライセンス情報）**
    - キー
        - `アセットID`
    - 値
        - `{ ライセンス種類: "商用", 有効期限: "2024-12-31" }`

このように、マルチネームスペースレジストリを使用することで、同じキー（この場合はアセットID）に対して複数の異なる種類の値を持つことができ、それぞれのネームスペースで整理された情報を効率的に管理することが可能になります。
この柔軟性と組織化の能力は、複雑なアプリケーションやシステムでのデータ管理を大幅に改善します。
:::

これは、変更履歴が追跡可能な情報の確実なソースとして機能します。
これらのマッピングレコードは、オンチェーン資産と組み合わせてポインターのように機能し、様々な詳細情報をカプセル化することで、さまざまな用途において高い汎用性を提供します。

:::note info
ブロックチェーン上に保存されるマッピングレコード（キーと値のペア）が、オンチェーン資産（トークンやスマートコントラクトで表されるデジタルアセットなど）とどのように関連づけられるか、そしてそれがどのような利点を提供するかについて説明しています。

### ポインターとしての機能
「**ポインターのように機能する**」とは、これらのマッピングレコードが、ブロックチェーン上の特定の資産を指し示す役割を果たすということを意味します。
例えば、特定のデジタルアートの所有権を表すトークンがあったとします。
このトークンに関連付けられたマッピングレコードは、そのアートの作者、作成日、購入履歴などの詳細情報を保持できます。
このように、マッピングレコードは資産についての追加情報を「**指し示す**」ために使用されます。

### 様々な詳細情報をカプセル化
「**様々な詳細情報をカプセル化する**」とは、このシステムが様々な種類の情報を保持し、整理できることを意味します。
カプセル化とは、情報を一箇所にまとめて管理することで、情報が整理され、アクセスや管理がしやすくなるプロセスです。
つまり、マッピングレコードは様々な情報を一つの場所で効率的に管理するための方法を提供します。

### 高い汎用性を提供
これらの特徴により、マッピングレコードは非常に汎用的に使用することができます。
つまり、どのような種類のオンチェーン資産にも適用可能であり、多様な情報を保持することができます。
これにより、さまざまな用途やアプリケーションにおいて、拡張された機能や詳細情報の管理が可能になります。

これらのマッピングレコードはブロックチェーン上の資産に関連する追加情報を保持するために使われ、情報は効率的に管理されて資産の使用や理解に大きな柔軟性を提供します。
:::

提案されたソリューションは、様々な状況に対応し、互換性を持つことができる柔軟なマッピングデータ構造を導入します。
これにより、現在のENS（Ethereum Name Service、イーザリアム名前サービス）のようなレジストリに比べて、よりスケーラブルで強力な代替手段が提供されます。

:::note info
この提案は、ブロックチェーン上での情報の管理を、複数のカテゴリー（ネームスペース）にわたって柔軟に、そしてより効率的に行えるようにする新しい方法を提案しています。
これにより、開発者は、アプリケーションのニーズに合わせて、より詳細な情報を簡単に保存し、参照することが可能になります。
:::

# 動機

ブロックチェーンベースのレジストリは、分散型アプリケーションのための基本的な構成要素であり、重要な情報の保存と取得を可能にします。
既存のソリューション（例えばENSレジストリ）は特定の用途に役立ちますが、より複雑なシナリオを受け入れるための柔軟性に欠ける場合があります。
より一般的なマッピングデータ構造で、マルチネームスペースをサポートする必要性があり、開発者が多様な用途を効率的に扱える単一のレジストリを使えるようにすることが求められています。

提案されたマルチネームスペースレジストリはいくつかのメリットを提供します。

### 多様性
開発者は、それぞれ独自のキーセットを持つ複数のネームスペースを定義して管理できます。
これにより、データのより細かい制御と整理が可能になります。
例えば、同じキーが異なるネームスペースに基づいて異なる値へのポインターとして機能する場合、ネームスペースはセッションタイプとして指定されるかもしれません（このレジストリがセッションを保存する場合）、または短縮URLから完全なURLへのマッピングが保存されるタイプのデータである場合です。

### 追跡可能な履歴
マルチネームスペースの機能を活用することで、レジストリはエントリのバージョニングをサポートし、マルチネームスペースをバージョン番号として使用して、データ変更の履歴を追跡したり、データを復元したり、使用しないデータのマーキングを行うことができます。
これにより、単一のコントラクト内でのデータ管理とガバナンスが容易になります。

### 拡張された互換性
提案された構造は、従来のENSのようなレジストリの範囲を超えた様々な用途と互換性があるように設計されており、多様な分散型アプリケーションでの採用を促進します。

:::note info
この新しいレジストリシステムは、情報をもっと柔軟に、効率的に、そして組織的に管理できるようにするための改良版です。
異なるカテゴリーのデータをよりよく整理し、時間とともにどのようにデータが変化したかを追跡しやすくし、そしてさまざまなタイプのアプリケーションで使いやすくしています。
:::

# 仕様

### `owner`

```javascript
function owner(bytes32 namespace, bytes32 key) external view returns (address);
```

**概要**

指定されたネームスペースとキーの所有者を返す関数。

**詳細**

この関数は、特定のネームスペースの下で指定されたキーの現在の所有者のアドレスを返します。
異なるネームスペースでは、同じキーが異なる所有者を持つことができます。

**引数**

- `namespace`
	- 検索するキーが存在するネームスペース。
- `key`
	- 所有者を検索するキー。

**戻り値**

- `address`
	- 指定されたキーとネームスペースの所有者のアドレス。

### `resolver`

```javascript
function resolver(bytes32 namespace, bytes32 key) external view returns (address);
```

**概要**

指定されたネームスペースとキーに対するリゾルバのアドレスを返す関数。

**詳細**

この関数は、特定のネームスペースの下で指定されたキーに関連付けられたリゾルバのアドレスを返します。
異なるネームスペースでは、同じキーに対して異なるリゾルバが設定されることがあります。

**引数**

- `namespace`
	- 検索するキーが存在するネームスペース。
- `key`
	- リゾルバアドレスを検索するキー。

**戻り値**

- `address`
	- 指定されたキーとネームスペースに関連付けられたリゾルバのアドレス。

### `setOwner`

```javascript
function setOwner(bytes32 namespace, bytes32 key, address newOwner) external;
```

**概要**

指定されたネームスペースとキーの所有者を新しいアドレスに変更する関数。

**詳細**

この関数は、特定のネームスペースの下で指定されたキーの所有者を新しい所有者に変更します。
この機能は現在の所有者によってのみ実行できます。
異なるネームスペースでは、同じキーが異なる所有者を持つことができます。
関数の処理が成功した場合、`Transfer`イベントがログに記録されます。

**引数**

- `namespace`
	- キーが存在するネームスペース。
- `key`
	- 所有者を変更するキー。
- `newOwner`
	- 新しい所有者のアドレス。

### `createNamespace`

```javascript
function createNamespace(bytes32 namespace) external;
```

**概要**

新しいネームスペースを作成する関数。

**詳細**

この関数は、新しいバージョンや新しいプロトコルタイプなど、現在のレジストリに新しいネームスペースを作成します。
関数の処理が成功した場合、`NewNamespace`イベントがログに記録されます。

**引数**

- `namespace`
	- 作成する新しいネームスペース。

### `setResolver`

```javascript
function setResolver(bytes32 namespace, bytes32 key, address newResolver) external;
```

**概要**

指定されたネームスペースとキーに対する新しいリゾルバのアドレスを設定する関数。

**詳細**

この関数は、特定のネームスペースの下で指定されたキーに対するリゾルバのアドレスを新しいものに設定します。
この機能はキーの現在の所有者によってのみ実行できます。
異なるネームスペースでは、同じキーに対して異なるリゾルバが設定されることがあります。
関数の処理が成功した場合、`NewResolver`イベントがログに記録されます。

**引数**

- `namespace`
	- キーが存在するネームスペース。
- `key`
	- リゾルバを設定するキー。
- `newResolver`
	- 新しいリゾルバのアドレス。

## リゾルバ仕様

複数名前空間リゾルバコントラクトは、**ERC137**で定義されているものと同じ仕様を利用できます。

:::note info
**ERC137**については以下の記事を参考にしてください。
:::

https://qiita.com/cardene/items/17e6e1a452006f08a197

# 補足

マルチネームスペースをサポートするレジストリは、さまざまな用途に適応できるように設計されています。
これには、身元確認、セッション管理、記録追跡、分散型コンテンツの公開などが含まれます。
この柔軟性により、開発者は複雑な分散型アプリケーションを容易に設計し、実装することができます。

### 身元確認
ユーザーの身元情報を安全に保存し、管理することができます。
例えば、ユーザーがサービスにログインする時に使用される情報です。

### セッション管理
ユーザーがアプリケーションとのセッション（ログイン状態など）を保持するのに役立ちます。
これにより、ユーザーがサービスを利用している間、そのセッション情報を追跡できます。

### 記録追跡
特定のトランザクションやイベントの履歴を追跡し、記録することができます。
これは、透明性を高め、監査が必要な場合に役立ちます。

### 分散型コンテンツの公開
コンテンツクリエーターが自分の作品を分散型の方法で公開し、管理することを可能にします。
これにより、中央集権的なプラットフォームに依存せずに、コンテンツの公開が可能になります。

マルチネームスペースのレジストリはこれらの用途に柔軟に対応することができ、各ネームスペースは異なる種類のデータや情報を管理するために設計されています。
開発者はこの柔軟性を利用して、様々なニーズに合わせた分散型アプリケーションを作成することが可能になります。
これにより、より複雑で、ユーザーニーズに密接に合わせたアプリケーションの開発が容易になります。

# 互換性

このEIPは新機能を導入し、既存の動作を変更しないため互換性の問題はありません。

# 実装

## レジストリの実装

```ts
pragma solidity ^0.8.12;

import "./IERC7406Interface.sol";

contract ERC7406 {
    struct Record {
        address owner;
        address resolver;
    }


    // A map is used to record namespace existence
    mapping(byte32=>uint) namespaces;
    mapping(bytes32=>mapping(bytes32=>Record)) records;

    event NewOwner(bytes32 indexed namespace, bytes32 indexed key, address owner);
    event Transfer(bytes32 indexed namespace, bytes32 indexed key, address owner);
    event NewResolver(bytes32 indexed namespace, bytes32 indexed key, address resolver);
    event NewNamespace(bytes32 namespace)

    modifier only_owner(bytes32 namespace, bytes32 key) {
        if(records[namespace][key].owner != msg.sender) throw;
        _
    }

    modifier only_approver() {
        if(records[0][0].owner != msg.sender) throw;
        _
    }

    function ERC7406(address approver) {
        records[0][0].owner = approver;
    }

    function owner(bytes32 namespace, bytes32 key) constant returns (address) {
        return records[namespace][key].owner;
    }
  
    function createNamespace(bytes32 namespace) only_approver() {
       if (status == 0) throw;
       NewNamespace(namespace);
       if (namespaces[namespace] != 0) {
           return;
       }
       namespaces[namespace] = 1;
    }

    function resolver(bytes32 namespace, bytes32 key) constant returns (address) {
        if (namespaces[namespace] == 0) throw;
        return records[namespace][key].resolver;
    }

    function setOwner(bytes32 namespace, bytes32 key, address owner) only_owner(namespace, key) {
        Transfer(key, namespace, owner);
        records[namespace][key].owner = owner;
    }

    function setResolver(bytes32 namespace, bytes32 key, address resolver) only_approver() {
        if (namespaces[namespace] == 0) {
            this.createNamespace(namespace, 1);
        }
        NewResolver(key, namespace, resolver);
        records[namespace][key].resolver = resolver;
    }
}
```

# セキュリティ

提案されたマルチネームスペースレジストリは、さまざまなネームスペースとアクセス制御を管理する能力があるため、いくつかのセキュリティ上の考慮事項を導入します。
これは、様々な種類のデータやアクセス権限を一つのシステム内で扱うことができるため、不正アクセスやデータ漏洩といったセキュリティリスクが生じる可能性があることを意味します。

このようなリスクを特定し、軽減するために、徹底的なテスト、監査、および同僚レビューが行われます。
これらのプロセスを通じて、攻撃者が利用可能な攻撃ベクトルや脆弱性を見つけ出し、それらを修正することが目指されます。

セキュリティを意識した開発者には、この監査プロセスに貢献することが奨励されます。
これは、セキュリティの専門知識を持つ人々が監査に参加することで、システムの安全性をより高めることができるという考えに基づいています。
開発者がこのように協力することで、レジストリが安全に運用され、信頼性の高い基盤となることが期待されます。

:::note info
マルチネームスペースレジストリの導入は、その柔軟性とパワフルな機能によりセキュリティ上の課題を引き起こす可能性がありますが、慎重なテスト、監査、そしてコミュニティの協力によって、これらのリスクは管理され、軽減されることになります。
:::

# 引用

Mengshi Zhang (@MengshiZhang), Zihao Chen (@zihaoccc), "ERC-7406: Multi-Namespace Onchain Registry [DRAFT]," Ethereum Improvement Proposals, no. 7406, July 2023. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7406.

# 最後に

今回は「マッピング構造でデータを保存し、ブロックチェーン上での多様なデータ管理を実現するマルチネームスペースレジストリの仕組みを提案している**ERC7406**」についてまとめてきました！
いかがだったでしょうか？

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