0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[ERC5018] ファイルをコントラクトに保存する仕組みを理解しよう!

Posted at

はじめに

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

今回は、スマートコントラクト内でファイルやディレクトリの書き込みと読み取りができる仕組みを提案しているERC5018についてまとめていきます!

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

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

概要

ERC5018は、コントラクト内でファイルやディレクトリを扱うためのAPIを標準化する提案です。
従来のファイルシステムと同様のインターフェースをEVM上で実現することを目的としています。
この標準によって、任意のサイズのバイナリオブジェクト(画像、HTMLファイル、アセットなど)を読み書きする基本機能が提供されます。
特に、オブジェクトが1回のトランザクションで収まりきらない場合には、チャンク(分割された一部分)単位で読み書きすることも可能です。

従来のようにファイルを一括して処理するのではなく、大きなデータを複数の処理に分割して扱える柔軟な仕組みが提供されています。

動機

EVMベースのブロックチェーン上で扱われるバイナリオブジェクト(画像、HTML、スクリプトなど)を、他のDAppsと再利用できるようにしています。
異なるDApps間でコンテンツをシームレスに共有・活用するためには、統一されたインターフェースが必要です。

加えて、ERC5018ERC4804と連携する形で設計されています。

ERC4804については以下の記事を参考にしてください。

ERC4804では、HTTPのようなURI(例えばhttps://example.eth/.well-known/resource のような形式)を用いてブロックチェーン上のリソースにアクセスできる仕組みが導入されました。
ERC4804と組み合わせることで、例えばHTMLやSVGのようなWebコンテンツが相対パスを使って他のリソースを参照している場合でも、ローカル環境とオンチェーン上での構成が一致するようになります。

仕様

ERC5018は、EVMベースのブロックチェーン上でディレクトリとファイルを管理するための標準的なインターフェースを定義しています。
大きなファイルの分割管理や相対パスを活かしたWeb3リソースの参照に対応しており、オンチェーン上でファイルシステム的な操作を可能にします。

このAPI仕様を使うことで、従来のWeb2におけるファイル管理と同じような構造でEVM上でもデータを柔軟に扱えるようになります。
特に以下のようなユースケースに適しています。

  • オンチェーンHTMLやSVG、画像、スクリプトの保存・配信
  • IPFSやArweaveに依存しないオンチェーンWebホスティング
  • ストレージ分割を活かした大容量データの管理
  • 相対パスとHTTPスタイルURIによるWeb3アクセス(ERC4804との連携)

ディレクトリ構造とファイル操作

ERC5018では、ファイル名は bytes 型で扱われ、バイナリデータとして記録・取得が可能です。
基本的なファイル操作として以下の関数が定義されています。

write

function write(bytes memory name, bytes memory data) external payable

書き込み権限のあるアカウントによって、指定されたファイル名にバイナリデータを書き込む関数。
既に存在する場合は上書きされます。

read

function read(bytes memory name) external view returns (bytes memory data, bool exist)

指定されたファイル名のバイナリデータと、そのファイルが存在するかどうかのbool値を返す関数。

fallback

fallback(bytes calldata prefixedName) external returns (bytes memory data)

/ で始まる名前に対してフォールバック的にファイルを取得する関数。
外部からの直接アクセスなどに対応するための関数です。

size

function size(bytes memory name) external view returns (uint256 size, uint256 chunks)

指定ファイルの全体サイズ(バイト数)と、チャンク数を返す関数。

remove

function remove(bytes memory name) external returns (uint256 numOfChunksRemoved)

指定ファイルを削除する関数。
削除されたチャンク数を返し、存在しない場合は0が返ります。
実行には書き込み権限が必要です。

チャンク単位の操作

大きなファイルはチャンク(分割データ)として扱うことができ、個別の読み書き・削除が可能です。

countChunks

function countChunks(bytes memory name) external view returns (uint256 numOfChunks);

指定ファイルのチャンク数を取得する関数。

writeChunk

function writeChunk(bytes memory name, uint256 chunkId, bytes memory chunkData) external payable;

ファイルの指定チャンクにデータを書き込む関数。
chunkId が現在のチャンク数を超えると失敗し、追記または置換のみに対応します。

readChunk

function readChunk(bytes memory name, uint256 chunkId) external view returns (bytes memory chunkData, bool exist);

指定チャンクのデータと、そのチャンクが存在するかを返す関数。

chunkSize

function chunkSize(bytes memory name, uint256 chunkId) external view returns (uint256 chunkSize, bool exist);

チャンクのサイズと存在しているかを返す関数。

removeChunk

function removeChunk(bytes memory name, uint256 chunkId) external returns (bool exist);

チャンク単位で削除を行う関数。
成功すると true を、存在しない場合は false を返します。
書き込み権限が必要です。

truncate

function truncate(bytes memory name, uint256 chunkId) external returns (uint256 numOfChunksRemoved);

指定チャンクID以降の全チャンクを削除する関数。
chunkId = 0 の場合、ファイル全体を削除する remove() と同様の動作になります。

その他のユーティリティ関数

getChunkHash

function getChunkHash(bytes memory name, uint256 chunkId) external view returns (bytes32);

指定チャンクのデータに対して keccak256 によるハッシュ値を返す関数。
データの整合性検証や変更検知に利用できます。

補足

単一トランザクションでは収まらない大容量データの課題

ブロックチェーンにWebコンテンツ(HTML、画像、スクリプトなど)をアップロードする時、ファイルサイズが大きすぎて1回のトランザクションで全てを送信できないことがあります。
EVMでは、トランザクションの calldata サイズに制限があります。

この問題を解決するため、ERC5018ではファイルを複数のチャンク(部分データ)に分けてアップロードできるようになっています。
これにより、ファイル全体を数回のトランザクションに分けて送ることが可能になります。

チャンクベースの書き込みと読み込みの統合

チャンク単位で書き込まれたデータも、最終的には read 関数でファイル全体を一括取得できる設計になっています。
以下の例でその挙動を確認できます。

動作例

read("hello.txt") => ""         // 初期状態。ファイルは空。
writeChunk("hello.txt", 0, "abc") // チャンク0に"abc"を書き込み
read("hello.txt") => "abc"

writeChunk("hello.txt", 1, "efg") // チャンク1に"efg"を書き込み
read("hello.txt") => "abcefg"

writeChunk("hello.txt", 0, "aaa") // チャンク0の内容を"aaa"に上書き
read("hello.txt") => "aaaefg"

writeChunk("hello.txt", 3, "hij") // チャンク2が存在しないため失敗(appendでもreplaceでもない)
 書き込み失敗

このように、writeChunk による部分的な追記・上書き操作が可能であり、read によって結合された全体の内容を取得できます。
データの整合性と連続性が維持される仕組みです。

write関数の動作とwriteChunkとの関係

write 関数は、ファイル全体を一括して書き込む関数です。
内部的には次の2つの処理で構成されていると考えることができます。

  • チャンクID 0 に write で渡されたデータを writeChunk で書き込む
  • チャンクID 1 以降を truncate によって削除する

この実装方法により、すでに存在していたファイルの中身が新しいデータで置き換えられます。
これにより、チャンクベースの一部上書きとは異なる「全体上書き」が可能になります。

大容量Webオブジェクト対応の利点

この仕様により、以下のような大容量オンチェーンデータの管理が現実的になります。

  • HTMLページ(ERC4804によりWeb3 URIでアクセス可能)
  • SVG、PNG、JPGなどの画像
  • 複数ファイルで構成されるWebアプリケーションのアセット群

特に read 関数によって、チャンク単位でアップロードされたデータを1回のトランザクションで一括取得できるため、ERC4804で提案されているHTTPのようなURIでアクセスする時にもユーザー体験が損なわれません。

引用

Qi Zhou (@qizhou), "ERC-5018: Filesystem-like Interface for Contracts [DRAFT]," Ethereum Improvement Proposals, no. 5018, April 2022. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-5018.

最後に

今回は「スマートコントラクト内でファイルやディレクトリの書き込みと読み取りができる仕組みを提案しているERC5018」についてまとめてきました!
いかがだったでしょうか?

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

Twitter @cardene777

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

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?