はじめに
『DApps開発入門』という本や色々記事を書いているかるでねです。
今回は、スマートコントラクト内でファイルやディレクトリの書き込みと読み取りができる仕組みを提案しているERC5018についてまとめていきます!
以下にまとめられているものを翻訳・要約・補足しながらまとめていきます。
他にも様々なEIPについてまとめています。
概要
ERC5018は、コントラクト内でファイルやディレクトリを扱うためのAPIを標準化する提案です。
従来のファイルシステムと同様のインターフェースをEVM上で実現することを目的としています。
この標準によって、任意のサイズのバイナリオブジェクト(画像、HTMLファイル、アセットなど)を読み書きする基本機能が提供されます。
特に、オブジェクトが1回のトランザクションで収まりきらない場合には、チャンク(分割された一部分)単位で読み書きすることも可能です。
従来のようにファイルを一括して処理するのではなく、大きなデータを複数の処理に分割して扱える柔軟な仕組みが提供されています。
動機
EVMベースのブロックチェーン上で扱われるバイナリオブジェクト(画像、HTML、スクリプトなど)を、他のDAppsと再利用できるようにしています。
異なるDApps間でコンテンツをシームレスに共有・活用するためには、統一されたインターフェースが必要です。
加えて、ERC5018はERC4804と連携する形で設計されています。
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などからお気軽に質問してください!
他の媒体でも情報発信しているのでぜひ他も見ていってください!