はじめに

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

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

今回は、Ethereumスマートコントラクトのパッケージ標準をアップデートする提案している規格であるERC2678についてまとめていきます!

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

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

概要

このEIPは、スマートコントラクトのための新しいファイル形式を提案しています。 この形式は「パッケージマニフェスト」と呼ばれ、スマートコントラクトの集まり、オプションでソースコードや異なるネットワーク上で動作するコントラクトの情報などを含むことができます。 これらの情報は、IPFSのような特別なネットワークを使って共有され、最小化されたJSON形式で保存されます。

IPFS

IPFS(InterPlanetary File System) は、分散型のファイルシステムであり、インターネットの構造をよりピアツーピア(P2P)中心のものに変えることを目的としています。 従来のHTTPベースのインターネットでは、ユーザーは特定のサーバーからファイルをダウンロードしますが、IPFSではファイルはネットワーク上の多数のピアにまたがって保存されます。

主な特徴は以下の通りです。

分散型 ファイルはネットワーク上の複数のノードに分散して保存されます。 これにより、中央のサーバーがダウンしてもファイルが利用可能な状態を保つことができます。

内容ベースのアドレッシング IPFSはファイルの内容に基づいてアドレスを生成します。 これは各ファイルが持つユニークなハッシュによって実現され、ファイルの内容が変わればアドレスも変わります。 これにより、ユーザーが受け取る内容の真正性が保証されます。

効率的な配信 ユーザーがファイルを要求するとき、IPFSは最も近いまたは最も利用可能なノードからファイルを取得します。 これにより、データの配信が速くなり、帯域幅も節約されます。

永続性 ファイルはピアによって保存され、要求に応じて他のピアに再配布されるため、ファイルはネットワークに永続的に存在する可能性があります。

IPFSは、分散アプリケーション(dApps)、分散型ウェブサイト、オフラインのストレージシステムなど、多くの用途に適しています。 また、Ethereumのようなブロックチェーン技術と組み合わせることで、分散型アプリケーションの開発において重要な役割を果たすことが期待されています。

さらに、これらのコントラクトパッケージはEIP1319で定義されたEthPMレジストリという、ブロックチェーン上の特定の場所に公開されます。 これにより、誰でもこれらのパッケージに簡単にアクセスして使用できるようになります。

EthPM

EthPMは、主にEthereumブロックチェーン上で動作するプロジェクトのためのパッケージマネージャーです。 Ethereumは、スマートコントラクトと呼ばれるプログラムをブロックチェーン上で実行できる分散型プラットフォームで、EthPMはこれらのスマートコントラクトの開発、配布、そして管理を容易にするためのツールです。

再利用可能なコンポーネントの共有と利用 スマートコントラクトやライブラリなどの再利用可能なコードをパッケージとして公開し、他の開発者がそれらを簡単に利用できるようになります。

バージョン管理 コントラクトの異なるバージョンを管理し、プロジェクトが特定のバージョンに依存するように設定できます。 これにより、コードの互換性や更新が容易になります。

依存関係の管理 スマートコントラクトが他のコントラクトやライブラリに依存している場合、EthPMはこれらの依存関係を解決し、必要なコードを適切にリンクします。

EthPMは、npmやpipのような他のプログラミング言語で一般的に使われているパッケージマネージャーと似た役割を果たしますが、ブロックチェーンという特殊な環境に特化している点が異なります。 Ethereum開発者はEthPMを利用することで、より速く、安全に、効率的にスマートコントラクトを開発できるようになります。

この提案はスマートコントラクトをより効率的に管理・再利用し、異なるネットワークにわたって簡単にデプロイできるようにするための手法です。 これは、開発者がコントラクトをより簡単に共有し、互いに作業を再利用できるようにすることを目的としています。

動機

この標準は、Ethereumの開発環境におけるコードの再利用というベストプラクティスを推進することを目指しています。 具体的には、コミュニティが主導するオープンなパッケージデータフォーマットを定義し、これまでの一般的な方法を踏まえた汎用的な解決策を提供して、パッケージ管理ツールの開発をサポートします。

この標準により、パッケージマニフェスト(コードの集まりを説明する文書)の形式が更新され、コンパイラ(コードをコンピュート可能な形式に変換するプログラム)が出力するメタデータと互換性を持つようになります。 また、「sources」オブジェクトもアップデートされ、さまざまなタイプのソースファイルをサポートし、コンパイラのためのJSON入力として機能するようになります。

さらに、コンパイラの情報を最上位の「compilers」配列に移動することで、コンパイラのバージョン、ソースコード、コンパイルされた成果物の関連を簡単にし、複数のコンパイラバージョンを使用するパッケージを扱いやすくしています。

また、より一般的なJSONの書式に合わせるため、キーの形式をスネークケース(snake_case)からキャメルケース(camelCase)に変更しています。 これらの更新により、Ethereumの開発者はより効率的にコードを管理し、再利用することができるようになると期待されています。

指針

この仕様は、パッケージマニフェストという文書がどのように扱われるべきかについての基本的な考え方を示しています。

自動生成

ソフトウェアの新バージョンをリリースする時、パッケージマニフェストは自動的に作成されます。 これは、パッケージ管理ソフトウェアが行う作業の一部であり、手作業ではなくプログラムによって行われることを意味します。

パッケージマネージャによる利用

開発者がソフトウェアの依存関係をインストールしたり、新しいバージョンを構築・配布したりする時、パッケージマネージャはこのマニフェストを読み取って必要な情報を取得します。 つまり、マニフェストは開発プロセスをスムーズにするための重要な情報源です。

分散保存

マニフェストはソースコードと一緒に保存されるわけではありません。 代わりに、パッケージレジストリがこれを保管したり、IPFSのような分散型ストレージに保存するための参照情報として使われたりします。 これにより、必要な時にいつでもアクセスできるようになります。

公開デプロイメントの検証

ブロックチェーン上で公開されたコントラクトが、正しいソースコードから生成されているかどうかを検証する時に、パッケージマニフェストを使用することができます。 これは、公開されているコントラクトが予期される振る舞いをするかどうかを確認するための重要なステップです。

この仕様は開発プロセスを自動化し、効率化するためのルールを提供しています。 パッケージマニフェストはその中心的な役割を担っており、開発者がより簡単にコードを管理し、共有し、確認できるようにするためのツールとして機能します。

ユースケース

この仕様で考慮された使用例は、さまざまなタイプのパッケージとそれらが提供する機能に焦点を当てています。

owned

他のコントラクトに機能を提供するために使われる基本コントラクトを含むパッケージです。 これらは単独では使われず、他のコントラクトがこれらを継承して利用します。

transferable

唯一の依存関係を持つパッケージです。 これは、他のコントラクトと特定の機能やモジュールを共有するために使用されます。

standard-token

再利用可能なERC20コントラクトを含むパッケージです。 これは一般的なトークンの機能を提供し、多くのプロジェクトで使用されます。

safe-math-lib

数学的演算をより安全に行うためのライブラリを含むパッケージです。 これには、特定のコントラクトのデプロイされたインスタンスが含まれています。

piper-coin

依存関係からの再利用可能なコントラクトのデプロイされたインスタンスを含むパッケージです。 これを使って、既存のコントラクトをベースに新しいコントラクトを作成できます。

escrow

ローカルライブラリにリンクされたローカルコントラクトのデプロイされたインスタンスを含むパッケージです。 これは、取引や合意のために資金を一時的に保管する機能を提供します。

wallet

依存関係からのライブラリにリンクされたローカルコントラクトのデプロイされたインスタンスを含むパッケージです。 ユーザーが資金を安全に管理するための機能を提供します。

wallet-with-send

より深い依存関係にリンクされたデプロイされたインスタンスを含むパッケージです。 これは、より複雑なウォレットの機能や相互作用を作成するために使われます。

simple-auction

オークションコントラクトのような特定の機能を持つアプリケーションを作成する時に役立つ、コンパイラの「metadata」フィールドの出力に関連しています。

これらの使用例は、パッケージマニフェストがどのように開発者が効率的にコードを再利用し、デプロイメントを簡素化するための多様なニーズに対応できるかを示しています。

仕様

規約

Prefixed vs Unprefixed(接頭辞付き vs 接頭辞なし)

16進数を示す時には、「0x」の接頭辞が付く場合と付かない場合があります。 例えば、「0xdeadbeef」と「deadbeef」です。 この文書では、特に指定がなければ「0x」を付けることが推奨されています。 これにより、数値が16進数であることが明確になり、読み手が理解しやすくなります。

これらの規約は、提案内容が正確かつ一貫性をもって理解されるようにするためのものです。 キーワードや表記方法を統一することで、誤解を防ぎ、誰もが同じ基準で情報を読み解くことができるようにしています。

ドキュメントフォーマット

このドキュメントの形式は、整理された単一のJSONオブジェクトとして設定されています。 この形式を保つため、以下のシンプルなルールに従う必要があります。

密なフォーマット

文書はコンパクトに保たれるべきです。 余計な空間や改行は入れず、できるだけスペースを節約する形で記述します。

キーの順序

オブジェクト内のすべてのキーはアルファベット順に並べられるべきです。 これにより、特定のキーを見つけやすくなり、一貫性が保たれます。

重複キーの禁止

1つのオブジェクト内に同じ名前のキーが2つあるのは不正です。 すべてのキーはユニークでなければなりません。

UTF-8エンコーディング

文書はUTF-8形式でエンコードされるべきです。 これは国際的な標準であり、様々な言語の文字を正確に表現できます。

末尾改行の禁止

文書の最後に改行を入れてはいけません。 ファイルはピリオドや閉じカッコなどの文字で終了すべきです。

manifest_versionの使用禁止

このキーは将来の互換性を維持するために予約されています。 トップレベルでの使用は避けるべきです。

これらの規則は、パッケージのマニフェストがどこでも一貫して読み取り可能で、シンプルでエラーが少ない形で保持されることを保証します。

ドキュメント仕様

このドキュメントの仕様では、パッケージに定義されるべきいくつかのフィールドが規定されています。 加えて、カスタムフィールドを含めることもできますが、将来の仕様バージョンとの名前衝突を避けるために、カスタムフィールドは「x-」で始まるべきです。

また、この仕様の形式化された(JSON-Schema)バージョン(package.spec.json)を参照することもできます。

このドキュメントはパッケージの標準フィールドとカスタムフィールドの両方をどのように扱うべきかについてのガイドラインを提供します。 カスタムフィールドを使用する時は、将来の問題を避けるために特定の命名規則に従う必要があります。

EthPM Manifest Version

「EthPM Manifest Version」は、パッケージがどのバージョンのEthPMマニフェスト仕様に従っているかを示すための重要なフィールドです。 すべてのパッケージにはこの情報が必要で、以下のように設定されます。

  • 必須

    • はい、このフィールドはパッケージに必ず含めなければなりません。
  • キー

    • このフィールドの名前は「manifest」です。
  • タイプ

    • 値は文字列(String)である必要があります。
  • 許可される値

    • 「ethpm/3」という値だけが許可されています。
    • これは、パッケージがEthPMのバージョン3の仕様に従っていることを意味します。

このフィールドはパッケージの互換性と解釈を正しく行うために非常に重要です。 正しいバージョン情報があることで、ツールやシステムはパッケージを適切に扱い、必要な操作を正確に行うことができます。

パッケージ名

「name」フィールドは、パッケージのわかりやすい名前を設定するためのものです。 EthPMレジストリで公開する時には、この名前を含めることが推奨されています。 パッケージの名前を決める時には、以下のような簡単なルールに従う必要があります。

  • 最初の文字

    • パッケージ名は必ず小文字のアルファベットで始めなければなりません。
  • 使える文字

    • 名前に使えるのは小文字のアルファベット(a-z)、数字(0-9)、そしてダッシュ(-)のみです。
  • 長さ

    • パッケージ名は255文字以内に収める必要があります。

この名前は、バージョン情報と共にパッケージに含まれるべきです。 つまり、バージョンが指定されている場合は「name」フィールドも必須となります。

  • 必須

    • バージョンが指定されている場合は、このフィールドの記入が必須です。
  • キー

    • このフィールドの識別子は「name」です。
  • タイプ

    • 値は文字列(String)であるべきです。
  • 形式

    • 名前は正規表現^[a-z][-a-z0-9]{0,255}$に一致する必要があります。
    • これは、上記のルールに従っているかを確認するためのものです。

これらの指針は、パッケージの名前がEthPMレジストリ上で一意であること、そして一貫性が保たれることを保証するために設計されています。

パッケージバージョン

パッケージがどのバージョンであるかを示すためのラベルです。 EthPMレジストリにパッケージを公開する時には、このバージョン情報を含めることが望ましいです。 このバージョン番号は、セマンティックバージョニング(semver)の規則に従って設定されるべきです。 これは、メジャー、マイナー、パッチという3つの部分から成る「X.Y.Z」の形式で、それぞれ大きな変更、小さな変更、バグ修正を表します。

セマンティックバージョニング

セマンティックバージョニング(Semantic Versioning、略してSemVer)は、ソフトウェアのバージョン番号を割り当てるための規則体系です。 この規則によるバージョン番号は「メジャー.マイナー.パッチ」という形式で構成されており、それぞれの部分は以下のような変更を表します:

  • メジャー(Major)
    • 互換性のないAPIの変更が含まれているときにインクリメントします。
    • 例えば、1.0.0から2.0.0への変更は、大きな変更や既存の機能の削除など、以前のバージョンと互換性のない変更があったことを示しています。
  • マイナー(Minor)
    • 互換性を保った機能追加が含まれるときにインクリメントします。
    • 例えば、1.2.0から1.3.0への変更は、新しい機能が追加されたが、既存の機能との互換性は保たれていることを示しています。
  • パッチ(Patch)
    • 互換性を保ったバグ修正が含まれるときにインクリメントします。
    • 例えば、1.3.1から1.3.2への変更は、小さなバグ修正やパフォーマンスの改善など、既存の機能の小規模な変更が行われたことを示しています。

具体例

  • バージョン1.0.0は、ソフトウェアの最初の安定版リリースを示します。
  • その後、小さなバグが修正された場合、バージョンは1.0.1になります(パッチ番号がインクリメント)。
  • 新しい機能が追加されたが、既存のAPIと互換性がある場合、バージョンは1.1.0になります(マイナー番号がインクリメント)。
  • 既存のAPIを変更するか削除するなど、大きな変更が行われた場合、バージョンは2.0.0になります(メジャー番号がインクリメント)。

セマンティックバージョニングを使用することで、開発者はソフトウェアのバージョンから、そのリリースに含まれる変更の性質と範囲を簡単に理解できるようになります。 これにより、依存関係の管理が容易になり、ソフトウェアアップデートの際のリスクが低減されます。

もし「name」フィールド(パッケージの名前)が設定されている場合、このバージョン情報は必須となります。 つまり、パッケージに名前があるなら、そのバージョンも明確にする必要があります。

  • 必須
    • 名前がある場合、バージョンも必ず指定してください。
  • キー
    • この情報を指定するためのフィールド名は「version」です。
  • タイプ
    • バージョンの値は文字列型で表されます。

パッケージバージョンはパッケージの特定のリリースを識別し、開発者が依存するパッケージの正しいバージョンを使えるようにするための重要な情報です。 適切なバージョン番号を使うことで、パッケージの更新や互換性の管理がはるかに簡単になります。

パッケージメタデータ

パッケージに関する追加の情報を格納するためのフィールドです。 この情報はパッケージをインストールする時には直接必要ではありませんが、パッケージの詳細を知るためや他の目的で便利な情報を提供します。

このメタデータを含めることは必須ではありませんが、パッケージに関してより多くの情報を提供したい場合には、全てのパッケージにこのフィールドを含めることが推奨されています。

  • 必須
    • いいえ。
    • このフィールドは必須ではないですが、パッケージに関する有用な情報を提供するために推奨されます。
  • キー
    • フィールドの名前は「meta」です。
  • タイプ
    • このフィールドのタイプは「Package Meta Object」で、パッケージに関する様々な追加情報を含むオブジェクトを指します。

「パッケージメタデータ」は、パッケージの使用者に対して有益な情報を提供するためのオプションフィールドです。 これにより、パッケージの内容や使い方、パッケージの背景にある情報などをより深く理解することができます。

ソース

パッケージに含まれるコントラクトを再構築するのに必要なソースコード全体の構成を示します。 これは、パッケージのコントラクトの元のコードの場所や内容を指し示すために使われ、パッケージの再利用や検証を行う時に重要な役割を果たします。

このフィールドの記載は必須ではありませんが、コントラクトを完全に理解したり再コンパイルしたりするためには非常に有益です。 特に、コントラクトの信頼性やセキュリティを検証する際には、ソースコードへのアクセスが不可欠です。

  • 必須
    • いいえ。
    • このフィールドは常に必要というわけではありませんが、包括的なパッケージ情報を提供するためには推奨されます。
  • キー
    • このフィールドを識別するための名前は「sources」です。
  • タイプ
    • このフィールドの型はオブジェクトで、具体的には文字列(ソースファイルのパスや名前)をキーとし、そのキーに関連するソースオブジェクト(ファイルの内容や情報)を値とする形式です。

パッケージに含まれるコントラクトのソースコードを整理し、開発者が必要に応じて内容を確認しやすくするためのマップです。 この情報があれば、開発者はコントラクトの動作をより深く理解し、必要に応じて自分自身でコードを確認または改良することができます。

コントラクトタイプ

パッケージに含まれる各コントラクトの構造や定義を示すために使用されます。 このフィールドは、リリースに含まれる具体的なコントラクトの詳細を整理し、どのように構築されているかを明確にするのに役立ちます。

このフィールドには以下の特徴があります。

  • 必須性
    • このフィールドは必ずしも必要ではありません。
    • しかし、パッケージの内容をより詳細に理解したい場合や、コントラクトの構造を明らかにしたい場合には有用です。
  • 含めるべき内容
    • パッケージ内で直接見つかるコントラクトタイプのみを含めるべきです。
    • 依存関係のコントラクトや抽象コントラクトは含めないでください。
    • これにより、パッケージにはその中にある具体的なコントラクトのみが明示され、混乱が避けられます。
  • キー
    • このフィールドの名前は「contractTypes」です。
  • タイプ
    • フィールドの型はオブジェクトです。
    • 具体的には、コントラクトのエイリアス名をキーとし、そのコントラクトの定義や情報を含むオブジェクトを値とする形式を取ります。
  • 形式
    • キーは有効なコントラクトのエイリアスでなければなりません。
    • また、値はコントラクトタイプオブジェクトの定義に従う必要があります。

パッケージに含まれるコントラクトの詳細情報を整理し、開発者がそれぞれのコントラクトを理解しやすくします。 これにより、開発者はパッケージの内容をより深く把握し、必要に応じて各コントラクトを適切に利用することができます。

コンパイラ

このパッケージに含まれるコントラクトがどのように作成されたかについての情報を提供します。 具体的には、コントラクトをコンパイルするのに使われたツールや設定に関する詳細が含まれています。 このフィールドは、コントラクトのコンパイルに関する透明性を高め、開発者が同じ条件でコードをコンパイルできるようにするために役立ちますが、必ずしも必要なわけではありません。

このフィールドの特徴は以下の通りです。

  • 必須性

    • いいえ。
    • このフィールドは必須ではありませんが、コンパイルの詳細を提供することはコードの再現性と信頼性を高めるために有用です。
  • キー

    • この情報を指定するために使われる名前は「compilers」です。
  • タイプ

    • このフィールドの型は配列です。
    • 配列の各要素は、コンパイラの情報を含むオブジェクトであり、それぞれコンパイラのバージョン、設定、使用言語などを詳しく記述します。

パッケージのコントラクトがどのコンパイラでどのような設定でコンパイルされたかを示し、開発者が同様の環境を設定しやすくするための道しるべのようなものです。 これにより、コントラクトの挙動やセキュリティを検証する際の透明性が高まります。

デプロイメント

リリースされたコントラクトがどのブロックチェーン上に存在し、それぞれのコントラクトの詳細情報をどのように提供するかを定義します。 この情報は、開発者がどのブロックチェーンにコントラクトがデプロイされているかを把握し、具体的なコントラクトインスタンスに関する情報を取得するのに役立ちます。

  • 必須性
    • このフィールドはオプショナルです。
    • つまり、必ずしも必要というわけではありませんが、コントラクトのデプロイメント情報を明確にするためには役立ちます。
  • キー
    • このフィールドは「deployments」という名前で識別されます。
  • タイプ
    • フィールドの型はオブジェクトです。
    • このオブジェクトの各キーはBIP122 URIで定義されるユニークなブロックチェーンを表し、それぞれの値はそのブロックチェーンにデプロイされたコントラクトインスタンスの情報を含むオブジェクトです。

各コントラクトインスタンス情報のオブジェクトは、コントラクトの名前をキーとし、そのコントラクトの詳細を値とする形式で構成されます。 これにより、開発者は特定のコントラクトインスタンスの情報を簡単に見つけることができます。

リリースされたコントラクトがどのブロックチェーンに存在し、それぞれのコントラクトに関する具体的な情報をどこで見つけることができるかを示すためのものです。 これにより、開発者は必要なコントラクトインスタンスを簡単に特定し、アクセスすることができます。

ビルドの依存関係

あるプロジェクトが正しく構築されるために必要な他のEthPMパッケージへの依存関係を示します。 このフィールドは、プロジェクトがどの外部パッケージに依存しているかを明確にし、それぞれの依存パッケージへのリンクを提供します。

  • 必須性

    • このフィールドはオプショナルです。
    • つまり、全てのプロジェクトでこのフィールドを使用する必要はありませんが、他のパッケージに依存している場合にはその関係を明確にするために役立ちます。
  • キー

    • このフィールドの名前は「buildDependencies」です。
    • これは、プロジェクトのビルドプロセスに影響を与える他のパッケージへの依存関係を指定するための場所です。
  • タイプ

    • フィールドの型はオブジェクトです。
    • このオブジェクト内の各キーは、依存しているパッケージの名前を示し、各値はそのパッケージを指すコンテンツアドレス可能なURIを表します。
  • 形式

    • 各キー(パッケージ名)は有効な形式でなければなりません。
    • 各値(URI)は、親プロジェクトと同じEthPMマニフェストバージョンに準拠する有効なパッケージを指すものでなければなりません。

プロジェクトがスムーズにビルドされ、動作するために必要な他のEthPMパッケージへのリンクを提供します。 これにより、開発者はプロジェクトがどの外部リソースに依存しているかを簡単に把握し、必要なパッケージを適切に管理することができます。

オブジェクト定義

EthPMパッケージで使われるさまざまな種類のオブジェクトについてのルールや構造を説明します。 これには、パッケージの基本構造、コントラクトの詳細、ビルド時の依存関係など、パッケージに関連する情報が含まれます。 また、開発者がパッケージに独自の情報を追加できるように、カスタムフィールドを設定することも可能です。

カスタムフィールドを追加する時には、将来の仕様の更新で名前の衝突が起こらないように「x-」というプレフィックスを付けます。 例えば、独自の色情報を追加したい場合、「color」ではなく「x-color」として指定します。 これにより、仕様が更新されてもカスタムフィールドが正しく機能し続け、パッケージの互換性と安定性が保たれます。

パッケージの内容と構造を正確に記述するためのガイドであり、開発者が自分のニーズに合わせてカスタムフィールドを安全に追加できるようにするためのルールも提供しています。

リンク参照オブジェクト

リンク参照オブジェクトは、以下のキーと値のペアを持]持ちます。 すべてのリンク参照は、対応するバイトコードに関連付けられていると仮定されます。

Offsets(オフセット)

バイトコード内でリンク参照が現れる各開始位置に対応する整数の配列です。 位置はバイトコードの対応するバイト表現の始まりから0でインデックスされます。 このフィールドは、バイトコードの終わりを超える位置を参照している場合に無効です。

  • 必須

    • このフィールドは必須です。
  • タイプ

    • 配列。

Length(長さ)

リンク参照の長さをバイト数で定義する整数です。 このフィールドは、定義されたリンク参照の終わりがバイトコードの終わりを超える場合に無効です。

  • 必須

    • このフィールドは必須です。
  • タイプ

    • 整数。

Name(名前)

有効な識別子である必要がある文字列です。 同じリンク値でリンクされるべきリンク参照は、同じ名前を与えるべきです。

  • 必須
    • いいえ。
    • このフィールドは必須ではありませんが、リンク参照を識別するために有用です。
  • タイプ
    • 文字列。
  • 形式
    • 識別子の形式に準拠する必要があります。

これらのフィールドは、バイトコード内の特定のリンク参照の位置、長さ、および名前を記述するために使用され、コントラクトがどのようにリンクされているかを正確に理解するために役立ちます。 これにより、開発者はコントラクトのバイトコードを適切に管理し、必要に応じてリンクを行うことができます。

リンク値オブジェクト

単一のリンク値を記述します。 リンク値オブジェクトには以下のキー/値ペアが定義されています。

Offsets(オフセット)

このリンク値が書かれた、対応するバイトコード内の位置を定義します。 これらの位置は、対応するバイトコードのバイト表現の始まりから0でインデックスされます。

  • 必須
    • はい。
  • タイプ
    • 整数。
  • 形式
    • 整数の配列で、各整数は以下の条件を満たす必要があります。
    • ゼロ以上であること。
    • 対応するバイトコードの非プレフィックスの16進数表現の長さより厳密に小さいこと。

Type(タイプ)

対応するバイトコードをリンクする時にエンコードされる値のタイプを定義します。

  • 必須
    • はい。
  • タイプ
    • 文字列。
  • 許可される値
    • "literal"(バイトコードリテラルの場合)
    • "reference"(特定のコントラクトインスタンスへの名前付き参照の場合)

Value(値)

対応するバイトコードをリンクする時に書かれるべき値を定義します。

  • 必須
    • はい。
  • タイプ
    • 文字列。
  • 形式
    • タイプに基づいて決定されます。
    • 静的な値リテラル(例: アドレス)の場合、値は0xで始まる16進数の文字列で、バイトを表す必要があります。
    • 現在のパッケージからコントラクトインスタンスのアドレスを参照する場合、値はそのコントラクトインスタンスの名前であるべきです。
    • 依存関係ツリー内のどこかからパッケージのコントラクトインスタンスを参照する場合、値は特定の形式で構築されます。

リンク値オブジェクトは、コントラクトのバイトコード内で特定のリンク値がどこにあるか、何をリンクするのか、どのような値を使用するのかを定義するためのものです。 これにより、コントラクトのバイトコードを適切にリンクし、必要な情報を正確に埋め込むことができます。

バイトコードオブジェクト

「Bytecode Object(バイトコードオブジェクト)」は、コントラクトのバイトコードとそれをリンクするために必要な情報を含むオブジェクトです。

Bytecode(バイトコード)

これはコントラクトのバイトコードを0xでプレフィックスされた16進数の文字列として表したものです。 このフィールドは必須で、コントラクトの実行可能なコードを表します。

  • 必須
    • はい。
  • タイプ
    • 文字列。
  • 形式
    • 0xでプレフィックスされた16進数。

このフィールドは、バイトコード内のリンクが必要な位置を定義します。 各位置は、リンク参照オブジェクトとして表され、バイトコードを適切にリンクするために必要な情報を含みます。

  • 必須
    • いいえ。
  • タイプ
    • 配列。
  • 形式
    • すべての値は有効なリンク参照オブジェクトでなければなりません。
    • リンク参照がバイトコードに適用されたときに無効である場合、またはリンク参照が交差している(重なっている)場合、このフィールドは無効とみなされます。

このフィールドは、対応するバイトコードをリンクするために使用されたリンク値を定義します。 各リンク値は、バイトコードをリンクする時にどの値をどこに書き込むべきかについての情報を含むリンク値オブジェクトとして表されます。

  • 必須
    • いいえ。
  • タイプ
    • 配列。
  • 形式
    • すべての値は有効なリンク値オブジェクトでなければなりません。
    • 2つのリンク値オブジェクトは同じオフセットの値を含んではならず、各リンク値オブジェクトはリンク参照フィールドの対応するリンク参照オブジェクトを持たなければなりません。
    • 解決された値の長さは対応するリンク参照の長さと等しくなければなりません。

コントラクトのバイトコードとそれをリンクするために必要な参照や依存関係の情報を整理して提供するためのものです。 これにより、コントラクトのバイトコードを正確に理解し、適切にリンクすることが可能になります。

パッケージメタオブジェクト

「Package Meta Object(パッケージメタオブジェクト)」は、パッケージに関する追加情報を提供するためのキー/値ペアを定義します。

Authors(著者)

このフィールドは、このパッケージの著者の人間が読みやすい名前のリストを定義します。 パッケージにこのフィールドを含めることができます。

  • 必須
    • いいえ。
  • キー
    • authors
  • タイプ
    • 文字列の配列。

License(ライセンス)

このフィールドは、このパッケージに関連するライセンスを宣言します。 この値はSPDX形式に準拠するべきです。 パッケージにはこのフィールドを含めるべきです。 もし特定のファイルソースオブジェクトが独自のライセンスを定義している場合、そのファイルについてはそのライセンスがこのパッケージスコープのメタライセンスより優先されます。

  • 必須
    • いいえ。
  • キー
    • license
  • タイプ
    • 文字列。

SPDX

SPDX(Software Package Data Exchange)は、ソフトウェアパッケージのコンポーネント、ライセンス、著作権情報を標準化された形式で文書化し共有するための仕様です。 Linux Foundationによって支援されており、オープンソースソフトウェアやその他のタイプのソフトウェアで使用されているライセンスを識別、整理するために広く採用されています。

SPDXの主な目的は、ソフトウェアのライセンス情報を透明にし、様々なツールやフォーマット間で互換性を持たせることです。 これにより、ソフトウェア開発者、法務チーム、サプライチェーン管理者は、ソフトウェアパッケージのライセンス情報を簡単に理解、分析、共有することができます。

SPDX仕様には以下のような特徴があります。

ライセンスリスト SPDXは、一般的なオープンソースライセンスとそのバリエーションについての標準的な短い識別子(例: GPL-2.0、MIT)を提供します。 これにより、文書やメタデータ内で一貫性と正確性を持たせることができます。

文書形式 SPDXは、ソフトウェアコンポーネントやその依存関係、ライセンス、著作権情報などを文書化するためのフォーマットを提供します。 これには、タグ付き値形式、RDF、JSONなどが含まれます。

ツールサポート さまざまなSPDXツールが開発されており、SPDX文書の生成、検証、比較、分析を行うことができます。

SPDXは、特に複数のオープンソースコンポーネントを統合する大規模なソフトウェアプロジェクトや、ライセンスコンプライアンスを管理する必要がある組織で重宝されています。 また、オープンソースライセンスのコンプライアンスを維持するための重要なステップとして、ソフトウェアのサプライチェーン管理にも役立ちます。

Description(説明)

このフィールドは、パッケージに関連する追加の詳細を提供します。 パッケージにこのフィールドを含めることができます。

  • 必須
    • いいえ。
  • キー
    • description
  • タイプ
    • 文字列。

Keywords(キーワード)

このフィールドは、このパッケージに関連するキーワードを提供します。

  • 必須
    • いいえ。
  • キー
    • keywords
  • タイプ
    • 文字列の配列。

Links(リンク)

このフィールドは、このパッケージに関連するリソースへのURIを提供します。 可能な場合、著者は以下の共通リソースに対して以下のキーを使用すべきです。

  • website
    • パッケージの主要なウェブサイト。
  • documentation
    • パッケージのドキュメント。
  • repository
    • プロジェクトのソースコードの位置。
  • 必須
    • いいえ。
  • キー
    • links
  • タイプ
    • オブジェクト(文字列: 文字列)。

パッケージの著者、ライセンス、説明、キーワード、関連リンクなどの追加情報を提供し、より包括的なパッケージの概要を提供するために使用されます。 これにより、ユーザーはパッケージについてのより多くの背景情報を得ることができ、その使用を判断する際の参考になります。

ソースオブジェクト

「Sources Object(ソースオブジェクト)」は、パッケージ内の各ソースファイルに関する情報を含んでいます。 それぞれのソースファイルは一意な識別子(キー)とソースオブジェクト(値)で表されます。

ソースオブジェクトには以下のフィールドが含まれます。

Checksum(チェックサム)

ソースファイルのハッシュです。コンテンツフィールドが欠けており、提供されたURLのどれもコンテンツハッシュを含んでいない場合のみ必須です。

  • キー
    • checksum
  • 値
    • チェックサムオブジェクト

URLs(URL群)

同じソースファイルを解決するURLの配列です。 URLはコンテンツアドレス可能なファイルシステムに保存されるべきです。 そうでない場合は、コンテンツまたはチェックサムが含まれる必要があります。 コンテンツが含まれていない場合に必須です。

  • キー
    • urls
  • 値
    • 文字列の配列

Content(コンテンツ)

インラインのコントラクトソースです。 URLとコンテンツの両方が提供される場合、コンテンツ値はURLで特定されたファイルの内容と一致する必要があります。URLが含まれていない場合に必須です。

  • キー
    • content
  • 値
    • 文字列

Install Path(インストールパス)**

ソースファイルのファイルシステムパスです。 ディスクに書き込み可能なパッケージにはこのフィールドが必要です。

  • キー
    • installPath
  • 値
    • 文字列

Type(タイプ)

ソースファイルのタイプを宣言します。 値はsolidity, vyper, abi-json, solidity-ast-jsonのいずれかです。 必須ではありません。

  • キー
    • type
  • 値
    • 文字列

License(ライセンス)

このソースファイルに関連するライセンスタイプを宣言します。 定義されている場合、このライセンスはパッケージスコープのメタライセンスより優先されます。 必須ではありません。

  • キー
    • license
  • 値
    • 文字列

各ソースファイルの内容、場所、タイプ、ライセンスなどの詳細情報を提供し、パッケージ内のファイルを適切に管理し理解するためのものです。

チェックサムオブジェクト

「Checksum Object(チェックサムオブジェクト)」は、ソースファイルの内容のハッシュを生成し、その正確性を確認するための情報を含むオブジェクトです。 以下のキー/値ペアが定義されています。

Algorithm(アルゴリズム)

このフィールドは、対応するハッシュを生成するために使用されたアルゴリズムを示します 可能なアルゴリズムにはsha3、sha256、md5、keccak256などがありますが、これに限定されません。

  • 必須
    • はい。
  • タイプ
    • 文字列。

Hash(ハッシュ)

このフィールドは、対応するアルゴリズムを使用して生成されたソースファイルの内容のハッシュです。

  • 必須
    • はい。
  • タイプ
    • 文字列。

ソースファイルが改ざんされていないことを確認するために、ファイルの内容に対して計算されたハッシュ値と、そのハッシュ値を計算するために使用されたアルゴリズムを記録します。 これにより、ファイルの整合性が保証され、信頼性のあるソフトウェア開発プロセスがサポートされます。

コントラクトタイプオブジェクト

「Contract Type Object(コントラクトタイプオブジェクト)」は、特定のコントラクトタイプに関する詳細情報を定義するためのキー/値ペアを含んでいます。

Contract Name(コントラクト名)

このフィールドはコントラクトタイプの名前を定義します。 コントラクト名とコントラクトエイリアスが異なる場合に必須です。

  • タイプ
    • 文字列。
  • 形式
    • 有効なコントラクト名でなければなりません。

Source ID(ソースID)

このコントラクトタイプが生成されたソースファイルのグローバルな識別子です。 パッケージ内のソースオブジェクトに含まれる一意のソースIDと一致する必要がありますが、必須ではありません。

  • タイプ
    • 文字列。

Deployment Bytecode(デプロイメントバイトコード)

このコントラクトタイプのデプロイメントバイトコードを定義します。 バイトコードオブジェクト形式に準拠する必要がありますが、必須ではありません。

  • タイプ
    • オブジェクト。

Runtime Bytecode(ランタイムバイトコード)

このコントラクトタイプの未リンクの0xプレフィックス付きランタイムバイトコード部分を定義します。 バイトコードオブジェクト形式に準拠する必要がありますが、必須ではありません。

  • タイプ
    • オブジェクト。

ABI

このフィールドはコントラクトのアプリケーションバイナリインターフェース(ABI)を定義します。 EthereumコントラクトABI JSON形式に準拠する必要がありますが、必須ではありません。

  • タイプ
    • 配列。

UserDoc(ユーザードキュメント)

このフィールドはコントラクトのユーザードキュメントを定義します。 UserDoc形式に準拠する必要がありますが、必須ではありません。

  • タイプ
    • オブジェクト。

DevDoc(開発者ドキュメント)

このフィールドはコントラクトの開発者ドキュメントを定義します。 DevDoc形式に準拠する必要がありますが、必須ではありません。

  • タイプ
    • オブジェクト。

コントラクトの名前、ソース、バイトコード、ABI、ドキュメントなど、コントラクトの特性と動作を定義するための重要な情報を提供します。 これにより、コントラクトを適切に理解し、操作するための詳細なガイドラインが提供されます。

コントラクトインスタンスオブジェクト

「Contract Instance Object(コントラクトインスタンスオブジェクト)」は、単一のデプロイされたコントラクトインスタンスを表し、以下のキー/値ペアを持っています。

Contract Type(コントラクトタイプ)

このコントラクトインスタンスのコントラクトタイプを定義します。 これは、このパッケージに含まれる任意のコントラクトタイプまたは、パッケージマニフェストのbuildDependenciesセクションから見つかる任意のパッケージ依存関係のコントラクトタイプを参照できます。

  • 必須
    • はい。
  • タイプ
    • 文字列。
  • 形式
    • このパッケージからコントラクトタイプを参照する場合は<contract-alias>の形式、依存関係からコントラクトタイプを参照する場合は<package-name>:<contract-alias>の形式を使用します。

Address(アドレス)

コントラクトインスタンスのアドレスを定義します。

  • 必須
    • はい。
  • タイプ
    • 文字列。
  • 形式
    • 0xでプレフィックスされた16進数でエンコードされたEthereumアドレス。

Transaction(トランザクション)

このコントラクトインスタンスが作成されたトランザクションのハッシュを定義します。

  • 必須
    • いいえ。
  • タイプ
    • 文字列。
  • 形式
    • 0xでプレフィックスされた16進数でエンコードされたトランザクションハッシュ。

Block(ブロック)

このコントラクトインスタンスを作成したトランザクションがマイニングされたブロックのハッシュを定義します。

  • 必須
    • いいえ。
  • タイプ
    • 文字列。
  • 形式
    • 0xでプレフィックスされた16進数でエンコードされたブロックハッシュ。

Runtime Bytecode(ランタイムバイトコード)

このコントラクトインスタンスのランタイムバイトコード部分を定義します。 このフィールドが存在する場合、その値はこのコントラクトインスタンスのコントラクトタイプからのランタイムバイトコードを上書きします。

  • 必須
    • いいえ。
  • タイプ
    • オブジェクト。
  • 形式
    • バイトコードオブジェクト形式に準拠する必要があります。
    • このバイトコードのすべてのリンク参照には、linkDependenciesセクションに対応するエントリが必要です。

デプロイされたコントラクトインスタンスのタイプ、アドレス、トランザクション、ブロック、ランタイムバイトコードなどの重要な情報を提供し、コントラクトの実行と操作に関する詳細なガイドラインを提供します。

コンパイラ情報オブジェクト

「Compiler Information Object(コンパイラ情報オブジェクト)」は、パッケージ内のコントラクトタイプやコントラクトインスタンスをコンパイルする時に使用されたさまざまなコンパイラとその設定を定義します。

Name(名前)

どのコンパイラがコンパイルに使用されたかを定義します。

  • 必須
    • はい。
  • キー
    • `name
  • タイプ
    • 文字列。

Version(バージョン)

コンパイラのバージョンを定義します。 このフィールドはOSに依存しない形式であるべきです(OSは文字列に含まれません)。 安定版の場合はsemver形式、ナイトリービルドの場合は<semver>-<commit-hash>の形式で表されます。 例: 0.4.8-commit.60cc1668。

  • 必須
    • はい。
  • キー
    • version
  • タイプ
    • 文字列。

Settings(設定)

コンパイルに使用された設定や構成を定義します。 "solc"コンパイラの場合、これはCompiler Input and Output Descriptionに準拠するべきです。

  • 必須
    • いいえ。
  • キー
    • settings
  • タイプ
    • オブジェクト。

Compiler Input and Output Description

「Compiler Input and Output Description(コンパイラ入出力記述)」は、特にSolidityのようなスマートコントラクト言語のコンパイラに関する仕様です。 この仕様は、コンパイラに与える入力と、コンパイラから得られる出力のフォーマットを定義しています。 これにより、コンパイラの動作をより明確にし、開発者がコンパイラの動作を予測しやすくなります。

入力記述

コンパイラへの入力記述は、通常、以下の情報を含むJSONフォーマットで提供されます。

  • 言語バージョン
    • 使用するコンパイラのバージョン。
  • ソースコード
    • コンパイルするソースファイル。
    • 複数のファイルや依存関係が含まれる場合があります。
  • 設定
    • 最適化の有無、出力する詳細レベル、ライブラリのリンクなど、コンパイルプロセスに影響を与える設定。

出力記述

コンパイラからの出力記述は、以下の情報を含むことが一般的です。

  • バイトコード
    • コンパイルされたコントラクトのバイトコード。
    • これは、ブロックチェーンにデプロイされる時の実行可能コードです。
  • ABI(Application Binary Interface)
    • コントラクトとのやり取りに必要なインターフェース。外部からコントラクトの関数を呼び出す時に必要です。
  • メタデータ
    • コントラクトのバージョン、著者情報、ライセンスなどの追加情報。
  • ランタイムバイトコード
    • コントラクトがブロックチェーン上で実行される時のバイトコード。
  • その他のデバッグ情報
    • ソースマッピング、ガス推定値、その他のデバッグに役立つ情報。

この仕様により、開発者はコンパイラを効率的に使用し、出力されたバイトコードやABIなどを適切に理解し、スマートコントラクトをブロックチェーンにデプロイするための正確な情報を得ることができます。 また、異なる環境やコンパイラ間での互換性を保つためにも重要です。

Contract Types(コントラクトタイプ)

このコンパイラを使用して出力が生成された、このパッケージ内のコントラクトエイリアスまたはコントラクトタイプのリストです。 ローカルでruntimeBytecodeを宣言するすべてのcontractTypesは、コンパイラオブジェクトによって帰属されるべきです。 単一のcontractTypesが複数のコンパイラに帰属されてはいけません。

  • 必須
    • いいえ。
  • キー
    • contractTypes
  • タイプ
    • コントラクトエイリアスの配列。

コントラクトのコンパイルに使用されたコンパイラの名前、バージョン、設定、関連するコントラクトタイプなどの詳細情報を提供し、コントラクトのコンパイルプロセスを正確に理解するための重要なガイドラインを提供します。

BIP122 URI

BIP122 URIは、BIP122の仕様の一部を使用してブロックチェーンを定義するために使用されます。 具体的な形式は以下の通りです。

text
blockchain://<genesis_hash>/block/<latest confirmed block hash>

ここで、<genesis_hash>はチェーン上の最初のブロックのブロックハッシュを表し、<latest confirmed block hash>は信頼性が確認された最新のブロックのハッシュを表します。 パッケージマネージャーは、望ましい確認レベルを自由に選択することができます。

このURI形式により、特定のブロックチェーンとその特定の状態(最新確認済みブロック)を一意に識別することができます。 これは、特定のブロックチェーン上のコントラクトやトランザクションに関連付けられたパッケージや情報を特定する時に役立ちます。 また、異なるブロックチェーン間での混同を避けるためにも重要です。

用語集

ABI

アプリケーションバイナリインターフェースのJSON表現です。

Address

特定のチェーン上のアカウントの識別子です。

Bytecode

コンパイラによって生成されたEVM命令セットです。 特に指定がない場合、16進数エンコードされ、バイトの整数で表され、0xでプレフィックスされていると想定されます。 リンクされたバイトコードとリンクされていないバイトコードがあります。

Chain Definition

BIP122 URIから由来する定義です。 特定のブロックチェーンとその特定の状態を一意に識別するために使用されます。

Content Addressable URI

内容の整合性を検証するために使用できる暗号ハッシュを含むURIです。 URI形式はRFC3986で定義されています。

Contract Alias

特定のコントラクトタイプを参照するために使用される名前です。 パッケージ内で一意でなければなりません。

Contract Instance

特定のデプロイされたコントラクトタイプのバージョンです。

Contract Instance Name

単一のパッケージのデプロイメントから特定のチェーン上の特定のコントラクトインスタンスを参照するために使用される名前です。

Contract Name

ソースコードで特定のコントラクトタイプを定義する名前です。

Contract Type

パッケージソース内の特定のコントラクトを指します。 これには抽象コントラクト、通常のコントラクト、またはライブラリが含まれることがあります。

Identifier

パッケージ内の名前付きエンティティを一般的に指します。

コントラクトのバイトコード内でリンクする必要がある位置です。

リンク参照の代わりに挿入できる値です。

Linking

バイトコード内のリンク参照をリンク値で置き換える行為です。

Package

アプリケーションのソースまたはコンパイルされたバイトコードを、著作権、ライセンス、バージョン情報などのメタデータとともに配布します。

Package Manifest

パッケージの機械可読な説明です。

Prefixed

0xが先頭に付いたバイトコード文字列です。 例: 0xdeadbeef。

Unprefixed

プレフィックスが付いていない状態です。 例: deadbeef。

補足

Minification(最小化)

EthPMパッケージは、アルファベット順に並べられた最小化されたJSON形式で配布されます。 これは、コンテンツアドレス可能なファイルシステム(例:IPFS)上でパッケージを公開する時、任意のコントラクトアセットセットが常に同じコンテンツアドレスURIに解決されることを保証するためです。 これにより、パッケージの一貫性が保たれます。

Package Names(パッケージ名)

パッケージ名は小文字、数字、およびハイフン「-」に制限されています。 これは、パッケージ名の可読性を向上させ、結果的にパッケージのセキュリティ特性を高めるためです。 この制限された文字セットにより、ユーザーは目的のパッケージを正確に識別しやすくなり、信頼できるパッケージに似せた悪意のあるパッケージとの混同を防ぐことができます。

BIP122(ビットコイン改善提案122)

BIP-122標準はEthPMのバージョン1以降で使用されています。 これは、異なるブロックチェーンを識別し、フォーク間を区別するための業界標準URIスキームです。

Compilers(コンパイラ)

コンパイラは、コントラクトタイプやコントラクトインスタンスのコンパイルに使用されたさまざまなコンパイラとその設定を定義するトップレベルの配列として現在定義されています。 これにより、ツールがコントラクトアセットと対話または検証するために必要なコンパイラタイプを識別する作業が簡素化されます。 また、複数のコントラクトタイプが同じコンパイラタイプを共有している場合の不要な情報の重複も削除されます。

互換性

EthPMの仕様をより理解しやすくし、読みやすくするために、バージョン3では「manifest_version」フィールドが「manifest」に変更されました。 後方互換性を保つために、バージョン3のパッケージはトップレベルに「manifest」というキーを持ち、その値として「ethpm/3」を設定する必要があります。 加えて、「manifest_version」はバージョン3のパッケージでトップレベルのキーとして使用することが禁止されています。 これらの変更により、EthPMの新しいバージョンへの移行が容易になりつつ、古いバージョンとの互換性も維持されます。

セキュリティ

EthPMパッケージを使うということは、他人が書いたコードを取り入れたり実行したりすることを意味しています。 EthPMの仕様により、適切に作成されたEthPMパッケージを利用する場合、ユーザーはパッケージの作者が含めたのと全く同じコードを使用することが保証されます。 しかし、そのコードが安全に使用できるという保証はありません。 そのため、ユーザーは悪意のないコードだけを含むと信頼できる人や組織が作成・リリースしたEthPMパッケージのみを使用することが非常に重要です。 信頼できるソースからのパッケージのみを選ぶことで、セキュリティリスクを減らすことができます。

引用

g. nicholas d’andrea (@gnidan), Piper Merriam (@pipermerriam), Nick Gheorghita (@njgheorghita), Christian Reitwiessner (@chriseth), Ben Hauser (@iamdefinitelyahuman), Bryant Eisenbach (@fubuloubu), "ERC-2678: Revised Ethereum Smart Contract Packaging Standard (EthPM v3)," Ethereum Improvement Proposals, no. 2678, May 2020. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-2678.

最後に

今回は「Ethereumスマートコントラクトのパッケージ標準をアップデートする提案している規格であるERC2678」についてまとめてきました! いかがだったでしょうか?

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

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