はじめに

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

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

今回は、トランザクションがアクセスする予定のアドレスとストレージキーのリストであるアクセスリストを含む新しいトランザクションタイプを導入する提案しているEIP2930についてまとめていきます!

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

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

概要

EIP2718はイーサリアムのトランザクションに関する改善提案の一つで、新しいトランザクションタイプを導入しています。 この新しいタイプの主な特徴は「アクセスリスト」の追加です。 アクセスリストは、トランザクションがアクセスを計画しているアドレスとストレージキーのリストで、これによりトランザクションの処理がより効率的になります。

アクセスリストの概念

アクセスリストとは、トランザクションがアクセスする予定のアドレスとストレージキーのリストです。 このリストに含まれるアドレスやキーへのアクセスは、リスト外のアクセスよりもガスコストが割引されます。

トランザクションの形式

新しいトランザクションタイプの形式は、以下のように定義されています。

text
0x01 || rlp([chainId, nonce, gasPrice, gasLimit, to, value, data, accessList, signatureYParity, signatureR, signatureS])

ここで、

  • 0x01は新しいトランザクションタイプを示します。
  • rlp(...)はトランザクションデータを符号化するためのメソッドです。
  • chainId, nonce, gasPrice, gasLimit, to, value, dataは従来のトランザクションと同様のパラメーターです。
  • accessListは上述のアクセスリストを表します。
  • signatureYParity, signatureR, signatureSはトランザクションの署名に関連するパラメーターです。

ガスコストと効率性

アクセスリストに含まれるアドレスやストレージキーにアクセスする時には、割引されたガスコストが適用されます。 これは、トランザクション処理の効率性を高めるための措置です。 しかし、リスト外へのアクセスは可能ですが、より高いコストがかかります。

EIP-2929との関連

この新しいトランザクションタイプは、EIP2929で導入されたaccessed_addressesとaccessed_storage_keysというグローバルセットと連携します。 アクセスリストに含まれるアドレスとキーは、これらのセットに追加され、トランザクションの処理中に参照されます。

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

このように、EIP2718の導入によって、トランザクションの処理効率が向上し、ガスコストの節約が期待できます。 特に、頻繁にアクセスされるアドレスやキーを事前にリストアップしておくことで、スマートコントラクトの実行コストを下げることが可能になります。

動機

このEIP(イーサリアム改善提案)は、主に2つの機能を果たすことで、特定の問題を解決し、新しい機能を導入しています。 以下でそれぞれの機能について簡単に説明します。

EIP-2929によるコントラクトのリスク軽減

背景

EIP2929は、スマートコントラクトのセキュリティを強化するために、特定の操作(SLOADやEXT*オペコード)のガスコストを増加させました。 しかし、この変更により、既存のコントラクトが想定外の高いガスコストに直面し、機能しなくなる("スタック"する)可能性がありました。

解決策

このEIPにより、トランザクションはアクセス予定のアカウントとストレージスロットを事前に特定し、その使用料を事前に支払うことができます。 結果として、実際の実行時には、SLOADやEXT*オペコードのコストは100ガスにまで低減され、EIP2929によって引き起こされる問題を防ぎ、EIP1884によって"スタック"したコントラクトを"アンスタック"することが可能になります。

アクセスリスト形式とその処理ロジックの導入

アクセスリスト

トランザクションがアクセスする予定のアドレスとストレージキーのリスト。 これは、トランザクションの効率化とガスコストの節約に役立ちます。

多目的利用

このEIPによって導入されるアクセスリスト形式と処理ロジックは、将来的に様々な目的で再利用可能です。 例えば、ブロック全体の証人(witnesses)の使用、ReGenesis(イーサリアムのスケーラビリティと持続可能性を向上させる提案)での利用、時間とともに静的な状態アクセスへの移行など、幅広い応用が考えられます。

イーサリアムの改善提案であるEIPによって導入された新しい概念や機能は、イーサリアムのスケーラビリティ(取引処理能力の拡張性)や持続可能性を向上させるために、様々な応用が考えられます。 具体的な応用例として、「ブロック全体の証人(witnesses)の使用」、「ReGenesis」、「時間とともに静的な状態アクセスへの移行」があります。

ブロック全体の証人(Witnesses)の使用

ブロックの証人とは、そのブロックが正当であることを証明するために必要なデータのことです。 これには、トランザクションのデータや、トランザクションによって変更された状態の情報が含まれます。 証人データを使用することで、ブロックチェーンの各ノードは、全てのトランザクションデータや完全な状態情報を持たなくても、ブロックの正当性を確認できるようになります。 これは、ネットワークのスケーラビリティを向上させることに貢献します。

ReGenesis

ReGenesisは、イーサリアムの状態を定期的にリセットすることで、ブロックチェーンのサイズ増加の問題を解決しようとする提案です。 状態のリセットによって、ノードが保持するデータ量を減らし、新しいノードの同期を容易にすることが目的です。 この提案は、ネットワークの持続可能性を高めることを目指しています。

時間とともに静的な状態アクセスへの移行

イーサリアムの状態は、トランザクションが発生するたびに動的に変化します。 時間とともに静的な状態アクセスへの移行とは、イーサリアムの状態をより予測可能で、変更が少ない形にすることを意味します。 これにより、データの取得や検証が容易になり、ネットワークの効率が向上します。

これらの応用は、イーサリアムをより高速で、使いやすく、そして持続可能なプラットフォームにするための取り組みの一部です。 技術の進化と共に、これらの提案や機能がどのように実装され、影響を与えるかを見ていくのは興味深いことです。

これらの機能により、EIPはイーサリアムの効率性と柔軟性を高め、将来のブロックチェーン技術の発展に貢献することを目指しています。

仕様

TransactionType

トランザクションタイプを示す識別子です。 EIP2718では、新しいトランザクションの封入形式(envelope format)が導入され、それによって様々なトランザクションタイプをサポートすることが可能になりました。 1はその中の一つのトランザクションタイプを示し、特定の構造やルールを持つトランザクションを意味します。

ChainId

トランザクションが有効とされる特定のネットワークを識別するためのIDです。 イーサリアムはメインネットと多数のテストネット(例えばRopstenやRinkebyなど)を含む複数のネットワークから構成されており、ChainIdはトランザクションが意図された正しいネットワーク上でのみ処理されることを保証します。 これにより、異なるネットワーク間でのトランザクションのリプレイ攻撃を防ぐことができます。

YParity

secp256k1署名(イーサリアムのトランザクション署名に使用される楕円曲線暗号)のy座標の偶奇性(parity)を示します。 署名にはr、s、そしてy座標の偶奇性を示す値が含まれます。 YParityが0ならy座標は偶数、1なら奇数です。 この値はトランザクションの署名を一意に特定し検証するために使用されます。

これらの定義は、イーサリアムのトランザクションが安全かつ効率的に処理されるための基礎を形成しています。 TransactionTypeはトランザクションの形式を、ChainIdはトランザクションが処理されるべきネットワークを、YParityはトランザクションの署名が正しいことを保証するために重要です。

パラメータ

新しいトランザクションタイプと、アクセスリストを使用したガスコストの計算方法について説明しています。 ここで紹介される概念を簡単に要約すると、新しいトランザクションタイプが導入され、トランザクションに含めることができる「アクセスリスト」に基づいて追加のガスコストが計算されます。 このアクセスリストは、トランザクションがアクセスする予定のアドレスとストレージキーを指定し、それによってネットワークの帯域幅の使用と状態のアクセスコストをカバーします。

以下の表は、EIP2718に関連する主要なパラメータを示しています。

定数 値
FORK_BLOCK 12244000
ACCESS_LIST_STORAGE_KEY_COST 1900
ACCESS_LIST_ADDRESS_COST 2400
  • FORK_BLOCK
    • このブロック番号をもって、新しいトランザクションタイプが導入されます。
  • ACCESS_LIST_STORAGE_KEY_COST
    • アクセスリストに含まれる各ストレージキーのガスコストです。
  • ACCESS_LIST_ADDRESS_COST
    • アクセスリストに含まれる各アドレスのガスコストです。

アクセスリストの処理

  • アクセスリスト
    • トランザクションがアクセスする予定のアドレスとストレージキーのリスト。
    • 形式は[[アドレス, [ストレージキー, ...]], ...]です。
    • アドレスは20バイト、ストレージキーは32バイトのデータで表されます。
  • ガスコストの計算
    • トランザクションの実行開始時に、アクセスリストに含まれるアドレスとストレージキーごとに定められたガスコストが追加で請求されます。
    • 例えば、アクセスリストが2つのアドレスと2つのストレージキーを含む場合、計算されるガスコストはACCESS_LIST_ADDRESS_COST * 2 + ACCESS_LIST_STORAGE_KEY_COST * 2になります。

実装例

process_access_list関数は、アクセスリストを処理し、アクセスされるアドレスとストレージキーのセット、および合計ガスコストを返します。 この関数は、アクセスリストの検証とガスコストの計算を行います。 アクセスリストに重複するアドレスやストレージキーがあっても実行上の問題はありませんが、それらは複数回請求されます。

py
def process_access_list(access_list) -> Tuple[List[Set[Address], Set[Pair[Address, Bytes32]]], int]:
    accessed_addresses = set()
    accessed_storage_keys = set()
    gas_cost = 0
    assert isinstance(access_list, list)
    for item in access_list:
        assert isinstance(item, list) and len(item) == 2
        # Validate and add the address
        address = item[0]
        assert isinstance(address, bytes) and len(address) == 20
        accessed_addresses.add(address)
        gas_cost += ACCESS_LIST_ADDRESS_COST
        # Validate and add the storage keys
        assert isinstance(item[1], list)
        for key in item[1]:
            assert isinstance(key, bytes) and len(key) == 32
            accessed_storage_keys.add((address, key))
            gas_cost += ACCESS_LIST_STORAGE_KEY_COST
    return (
        accessed_addresses,
        accessed_storage_keys,
        gas_cost
    )

注意点

アクセスリストは、トランザクションデータのようにバイトごとに請求されるわけではありません。 上記のアイテムごとのコストは、アクセスリストデータの帯域幅のコストと、トランザクション評価時のそれらのアカウントおよびストレージキーへのアクセスコストをカバーするためのものです。

補足

イーサリアムの改善提案(EIP)に関連するトランザクションのアクセスリストを用いた機能の意図と設計哲学について説明しています。

アクセスリストでのアクセスコストの削減

アクセスリストをできるだけ多く使用することを奨励し、トランザクションのストレージ読み取りが予測可能である場合にトランザクションを処理しやすくするために、アクセスリスト内のアクセスには低いコストがかかります。 予測可能なストレージ読み取りにより、クライアントはデータベースからデータを事前に読み込んだり、トランザクション受信時に証人を要求したり、少なくともデータを並行して読み込むことができます。 これにより、ネットワーク全体の効率が向上します。

重複の許容

重複を許容する理由は、システムの単純性を最大化し、重複を何に対して防ぐべきか(アクセスリスト内のアドレス/キーだけ、アクセスリストとトランザクション送信者/受信者/新しく作成されたコントラクトとの間、その他の制限など)という問題を避けるためです。 アイテムごとにガスが請求されるため、アクセスリストに値を2回含めても利益はなく、コストだけがかかります。そのため、実際には余計なチェーンの膨張を引き起こすことはないでしょう。

トランザクションタイプとデータの署名

署名がトランザクションタイプとトランザクションデータの両方に対して行われるのは、トランザクションが異なるタイプのトランザクションとして「再解釈」されることを防ぐためです。 これにより、トランザクションの完全性と、その実行が意図したとおりに行われることが保証されます。

これらの設計選択は、イーサリアムの効率性、セキュリティ、そしてシンプルさを向上させることを目的としています。 アクセスリストの利用促進、システムの単純化、トランザクションの一貫性と不変性の確保が、これらの選択の背後にある主な理由です。

互換性

このEIP(イーサリアム改善提案)は、予想外のSLOAD(ストレージからの読み込み)やアカウントアクセスを行う時のガスコストを増加させます。 ガスはトランザクション送信時に前払いされるため、固定ガス消費のローカルコール(スマートコントラクト内の関数呼び出しなど)には影響を与えず、以前のガスコスト増加がもたらすリスク(契約の破綻など)を回避します。 しかし、ストレージアクセスに大きく依存するアプリケーションにとっては、経済的に実行が困難になる可能性があります。

ガスコストの増加

予想外のストレージ読み込みやアカウントアクセスには、以前よりも多くのガスが必要になります。 これは、ネットワークのリソースを無駄に消費する行為に対するペナルティとして機能します。

コントラクトの破綻リスクの回避

ガスはトランザクションを送信する時に前払いされるため、ローカルコール(スマートコントラクト内での関数呼び出しなど)の実行には影響しません。 これにより、過去のガスコスト増加が引き起こす可能性のあるコントラクトの破綻というリスクを避けることができます。

「コントラクトの破綻」とは、スマートコントラクトが想定通りに機能しなくなる状態を指します。 これは一般に、以下のような理由で発生することがあります。

ガスコストの増加

イーサリアムネットワークのアップグレードや改善提案(EIP)の導入によって、特定のオペコードのガスコストが増加することがあります。 スマートコントラクトがこれらのオペコードを頻繁に使用している場合、トランザクションの実行コストが予期せず増大し、トランザクションが失敗するか、非経済的(コストが収益や利益を上回る状態)になる可能性があります。 これにより、コントラクトの機能が実質的に「破綻」することになります。

セキュリティ問題

スマートコントラクトには、コーディングの誤りや設計上の欠陥が存在することがあり、これらの問題が悪用されるとコントラクトの資産が盗まれたり、コントラクトが不正な方法で操作されたりする可能性があります。 例えば、再入可能性攻撃(reentrancy attack)は、ある関数が完全に実行を終える前に同じ関数が再度呼び出されることを悪用するもので、有名な「The DAO」事件で見られました。

依存関係の問題

スマートコントラクトは他のコントラクトや外部のデータソースに依存して動作することがあります。 これらの外部依存関係が変更されたり、利用できなくなったりすると、スマートコントラクトは正しく機能しなくなることがあります。

不完全なアップグレード可能性

スマートコントラクトは不変であり、デプロイ後にコードを直接変更することはできません。 アップグレード可能なコントラクトパターンを使用することでこの問題を回避することができますが、このパターンの実装が不完全だと、コントラクトの破綻を引き起こす可能性があります。

これらの問題を避けるためには、スマートコントラクトの設計と実装に際して、十分な検証とテストが必要です。 また、ネットワークのアップグレードやEIPの導入による影響を常に監視し、必要に応じてコントラクトの設計を見直すことが重要です。

ストレージ依存アプリケーションの経済性

ストレージアクセスに頻繁に依存するアプリケーションは、ガスコストの増加により経済的に実行が難しくなります。 これは、開発者がより効率的なデータアクセスパターンを考案することを促す一方で、ストレージを頻繁に利用する既存のアプリケーションには影響を与える可能性があります。

このEIPの目的は、イーサリアムネットワークの効率性とセキュリティを向上させることにありますが、アプリケーションの設計においても慎重な検討が求められるようになります。

セキュリティ

EIP(イーサリアム改善提案)におけるアクセスリストの生成とそれがブロックサイズに与える影響に関する説明です。

アクセスリストの生成

アクセスリストをリアルタイムで構築することは多くの状況で困難です。 特に、トランザクションの生成と署名の間に時間差が大きい環境や、トランザクションジェネレータのシンプルさが重視される環境(例えばハードウェアウォレットなど)では、この問題はさらに悪化します。

しかし、このEIPではアクセスリストに対して最初は10%の割引のみを提案しており、アクセスリストを生成せずにシンプルなトランザクションを行うことのコストはほとんどありません。 アクセスリスト外の状態にアクセスするコストは、将来のハードフォークで徐々に引き上げられる予定ですが、これはツールが開発され、アクセスリストの生成が成熟してくるにつれて行われます。

トランザクションサイズの膨張

アクセスリストが使用されることで平均ブロックサイズが増加します。 ただし、アクセスリストのバイトあたりのコストは、ストレージキーの場合は1900 / 32 = 59.375、アドレスの場合は2400 / 20 = 120であり、これはcalldata(トランザクションデータの一部)よりもはるかに高価です。 そのため、最悪の場合のブロックサイズが増加することはありません。 さらに、平均ブロックサイズの増加は、トランザクション受信時やブロック受信時にストレージを並行してロードする能力によって部分的に補償されます。

この説明から、アクセスリストの導入はイーサリアムネットワークの効率性を高める可能性を持ちながらも、初期段階ではその生成と利用において柔軟性が求められることがわかります。 また、ブロックサイズに関する懸念はありますが、その影響は管理可能であり、将来的にはより効率的なネットワーク運用に寄与すると考えられます。

引用

Vitalik Buterin (@vbuterin), Martin Swende (@holiman), "EIP-2930: Optional access lists," Ethereum Improvement Proposals, no. 2930, August 2020. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-2930.

最後に

今回は「トランザクションがアクセスする予定のアドレスとストレージキーのリストであるアクセスリストを含む新しいトランザクションタイプを導入する提案しているEIP2930」についてまとめてきました! いかがだったでしょうか?

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

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