【完全保存版】Astar におけるSubstrateとEVMのアカウントの関係について
当記事は、こちらの記事を翻訳・編集したものです。
0 はじめに
本日は、Substrate内で使用できる様々な種類のアカウントと、Substrate内でEVMを使用する方法をご紹介します。
Substrateの鍵の概念は非常に拡張性があり複雑です。
そのため、Substrate内の異なるレイヤー(ネイティブブロックチェーンレイヤーやEVMレイヤーなど)の鍵を管理するユーザーとして焦点を絞ります。
TL;DR:(要約)
Substrateは複数の署名者タイプをサポートしています。
Substrate内でEVMを使用するためにEVMパレットを追加できます。
SubstrateのネイティブアカウントはSS58形式ですが、EVMアカウントはH160形式です。
SubstrateはEVMの状態にアクセスできますが、EVMはSubstrateの状態にアクセスできません。
SS58アカウントをH160にマッピングすることで、2つのアカウント間を移行することができます。
1 SubstrateとSS58
Substrateはレイヤー1のブロックチェーンフレームワークで、カスタム機能を持つ様々なブロックチェーンを作成するために使用されます。
デフォルトでは、Substrateブロックチェーンはトランザクションの送受信にSS58アドレスフォーマットを使用します。
SS58はBitcoinのBase-58-checkに若干の変更を加えたものです。
特に、このフォーマットには、アドレスが特定のネットワークに属していることを識別するアドレスタイプのプレフィックスが含まれています。
SS58アドレスの例aLoNHLwqd75cniRoF2k2DrXgsbUWacuCxqc6d6BBmvG3NVQ
2 EVMとH160
EVMはイーサリアム内のトランザクションで任意のコード実行を可能にする仮想マシンである。
EVMはイーサリアムから始まりましたが、現代のブロックチェーンでは、EVMはむしろブロックチェーンが「イーサリアム互換」であることを可能にしています。
「EVM」は他のブロックチェーン内で広大なイーサリアムのエコシステムを共有するための標準です。
SubstrateにはFrontier framework と呼ばれるパレットがあり、Substrateネイティブ環境とともにイーサリアム互換性とアカウントを追加しています。
イーサリアムは160ビットの16進文字列をパブリックアドレスとして使用しており、ユーザーはこのアドレスでトランザクションを送受信することができる。
Substrateでは、この形式を160ビットハッシュを意味するH160と呼んでいます。
ブロックチェーンがイーサリアムと互換性を持つためには、H160アカウントを使用する必要があります。
これはEVMとイーサリアムエコシステム内のすべてのツールが認識できる唯一のアカウント形式だからです。
このルールはEVMパレットを使用したサブストレートチェーンにも適用されます。
H160アドレスの例
0x4C40D74739A7C95D8358191D68E6d5C77a867E12
1 アカウント
1 Substrate 公開鍵の種類
Substrateは3種類のアカウント(ソース)をネイティブにサポートしています。
ECDSA:secp256k1曲線を使った署名スキーム。これはBitcoinやEthereumのセキュリティに使われている暗号アルゴリズムと同じ。
Ed25519:Ed25519は、Curve25519を使用したEdDSA署名スキームです。セキュリティを損なうことなく超高速を実現するために、設計と実装のいくつかのレベルで慎重に設計されている。
SR25519: SR25519はEd25519と同じ曲線に基づいている。しかし、EdDSAスキームの代わりにSchnorr署名を使用しています。SR25519は公開鍵を公開しません。
ユーザーは、Polkadot-jsウォレットや同じフレームワークに基づくウォレットから、これらの鍵のいずれかを使ってトランザクションに署名したり、外部コールを呼び出したりできます。
一般的に、SR25519スキームは、Auraを使用してブロックを生成できる鍵を生成するために使用されます。
SR25519と同じシードフレーズを持つEd25519スキームは、Grandpa を使ってブロックを確定するための鍵を生成するのに使われます。
ECDSAは、2019年にGavin Woodによって初めてSubstrateに追加された、Substrateトランザクションに署名できる鍵の代替スキームです。
ECDSAスキームは、BitcoinやEthereumで使用されるアカウントの公開鍵の互換性を追加するために使用されます。
Substrateは複数の暗号アルゴリズムに対応していますが、ユーザーがトランザクションを受け取ったり行ったりする際には、3つとも全く同じ挙動を示すため、アルゴリズムは全く問題になりません。
例えば、「chimney manage ritual space armed kick angle cram indoor valid pipe margin」 というシードフレーズを考えてみましょう。
このフレーズを使用すると、以下のようなアカウントになります。
1つのシードフレーズで3つの異なるパブリックアドレスを作成し、暗号スキームを変更することで、ユーザーはこれら3つのアカウントすべてを制御することができます。
2 イーサリアム鍵
イーサリアムは、すべてのイーサリアム互換ネットワークを通じて同じであるECDSA署名スキームのみをサポートしています。
Substrate ECDSAとEthereum ECDSAの大きな違いは、生成されるアドレス形式です。
プロセスを簡略化すると、SubstrateとEthereum ECDSAの両アカウントは公開鍵を共有しますが、最終的なハッシュアルゴリズムは異なるため、異なる結果が得られます。
SubstrateアカウントはBlake2でハッシュ化された公開鍵をSS58にエンコードします。
一方、Ethereumアドレスは異なるハッシュ化アルゴリズムを使用します。
これは非常に一般的な説明であるため、いくつかの技術的な詳細は無視されていることに注意してください。
エンドユーザーにとって、Substrate取引とEthereum取引の署名に使用するアカウントの違いは、使用するウォレットの種類によって異なります。
例えば、MetaMaskで署名するユーザーはイーサリアム互換のネットワークトランザクションにのみ署名でき、Polkadot-jsウォレットを使用するユーザーはSubstrateベースのトランザクションにのみ署名できます。
2 Substrate上のEVM
1 アーキテクチャ
EVMパレットを実装するSubstrateブロックチェーンのアーキテクチャは一見複雑に見えるかもしれません。
しかし、EVMが独自のアカウントと残高を持つ独立したサンドボックスであり、ホストであるSubstrateブロックチェーンとブロック状態を共有するだけであることを理解すれば、分離して理解することがはるかに容易になります。
全体的なアーキテクチャは上図のように表現できます。
注意すべき重要な点がいくつかあります。
① EVM環境はSubstrateの上で動作します。
つまり、EVMサンドボックスのブロック高はホストSubstrateネットワークに依存します。
ホストSubstrateネットワークはEVMの状態にアクセスできます。
一方、EVMサンドボックスは通常の手段でホストSubstrateネットワークの状態にアクセスしたり、状態を変更したりすることはできません。
EVMからのSubstrateの状態遷移は、EVMのプリコンパイルされたカスタムコントラクトによってのみ実現できます。
② EVM環境は独自のRPCエンドポイントを公開します。
このエンドポイントはFrontier RPCクライアントを実装することで公開することができ、EIP-1474と互換性があります。
MetaMaskを使用してネットワークに接続し、他のイーサリアム互換チェーンと同様にトークンを表示または送信することができます。
③ EVM環境はEVMデポジットを持ちます。
EVM環境にはEVMデポジットと呼ばれる独自の残高があり、Substrateネイティブアカウントから引き出すことができます。
SubstrateネイティブのSS58アドレスは、EVMデポジットにマッピングされたH160アドレスに変換でき、EVM H160アドレスはSS58アドレスに変換できる。
これにより、アカウントはネイティブ残高からEVM残高へトークンを転送することができます。
しかし、これは非可逆的な変換であるため、SS58をH160に変換して同じSS58アドレスに戻すことはできません。
さらに、アカウントが作成された環境内でのみトランザクションに署名することができます。
例えば、通常の方法では、ネイティブ・アカウントでEVMトランザクションに署名することはできませんし、その逆もできません。
④ まとめ
EVMとネイティブSubstrateの残高間のアドレス変換とトランザクションを無視すれば、EVMを備えたSubstrateの全体的なアーキテクチャは、単一のノードで動作する2つの別々のブロックチェーンを持っていると見なすことができます。
ユーザーは、Substrateに触れたり理解したりすることなくMetaMaskでEVMを使用したり、EVMにまったく触れることなくPolkadot-jsウォレットでSubstrateを使用したりすることができます。
2 EVMレイヤーの視点
EVMパレットがSubstrate上で機能することを説明するために、次の例を考えてみましょう。
Astarメインネットブロック539982では、6つの外部呼び出し(Extrinsic call)がありました。
3つのイントリンシックコール(ブロックチェーンによって実行されたコール)を除くと、2つのSubstrate残高移動と1つのイーサリアム取引があります。
EVMエクスプローラーで同じブロック番号を見ると、トランザクションが1つしかないことがわかります。
Substrate RPCでは、ネイティブトランザクションとEVMサンドボックス内のトランザクションを表示できます。
一方、EVM RPCでチェーンにアクセスすると、EVMパレット内で発生したトランザクションしか表示できません。
Ethereumの外部呼び出しは、呼び出し元のH160アドレス、ターゲットのH160アドレス、EVMトランザクションハッシュ(Substrateトランザクションハッシュとは異なる)を含むethereum.Executedイベントを発行します。
(EVMコールはSubstrateトランザクションハッシュを持たないことに注意。)
このイベントは、サブストレートネットワークがEVMサンドボックス内の状態遷移を受動的に読み取るためのフォーマットです。
EVM RPCからトランザクションハッシュを見ると、詳細なトランザクションが返されます。
EVM RPCはトランザクションの詳細データを返しますが、fromとtoのアドレスはSubstrateブロックイベントのものと同じであることがわかります。
これはブリッジ取引で、ユーザーは別のブロックチェーンから610 WASTRトークンをスワップしています。
ブロック・イベントを見ると、トークンのミントとトークンのバーンが行われていることがわかります。
しかし、Substrate内でこのアカウントの状態遷移を調べると、興味深いことが起こります。
イーサリアムの取引イベントを詳細に見ると、トークンのミントとバーンの金額は正しいことは確認できる。
しかし、興味深いのはアカウントです。
EVM RPCはH160アドレスを返しますが、Substrate RPCはEVMサンドボックス内のすべてのアカウントに対してSS58アドレスを返します。
これは、Substrateではデフォルトのアドレス形式が常にSS58だからです。
では、Substrateはどのようにアドレス形式を変換し、どのように残高を処理するのでしょうか?
3 EVMへの入金とアドレス変換
polkadot-js/util-cryptoパッケージは関数evmToAddressをエクスポートします。
この関数はH160アドレスを受け取り、その前にevm:を付け、文字列をバイト配列に変換し、バイトをBlake2でハッシュし、公開鍵をSS58にエンコードします。
提供されたH160アドレスが有効なEVM署名者のものである場合(アカウントがMetaMaskのようなウォレットから作成された場合)、SS58アドレスがマッピングされます。
SS58アカウントからこのマッピングされたSS58アドレスにトークンを送信すると、元のH160アカウントはEVMサンドボックス内の資金にアクセスできるようになります。
同じパッケージのaddressToEvm関数を使用して、SS58アドレスをH160アドレスに変換することも可能です。
SubstrateはまずSS58文字列をデコードしてハッシュ化された公開鍵(180ビットのハッシュ、つまりH180)を取得し、末尾の20ビットを削除して160ビットのハッシュになるようにアドレスを変換します。
提供されたSS58アドレスが有効なサブストレート署名者のものである場合、結果の文字列は マップされたH160アドレスとなります。
EVM署名者がこのアドレスにトークンを送付すると、トークンは元のSS58アカウントのEVMデポジットに保管されます。
このアカウントは、evm.withdraw外部呼び出しによってトークンを取り戻すことができます。
EVMパレットはH160アカウントとSS58アカウントのハッシュマップを保持しており、SubstrateはマッピングされたH160アドレスとマッピングされたSS58アドレスを関連付けることができます。
また、アドレス変換は非可逆処理であり、変換処理を元に戻すことはできないことにお気づきかもしれません。
一度SS58アドレスをH160アドレスに変換すると、それを元に戻すことはできません。
そのため、アドレスを有効なマップ済みアドレスに変換する際には、元の署名者に注意する必要があります。
Substrateの署名者はSS58アドレスからH160アドレスに変換でき、EVM署名者はSS58アドレスに変換できます。
他の方法では、有効なマッピングされたアドレスは作成されません。
さて、外部呼び出しの539982-5とEVMトランザクションハッシュの話に戻ります。
SubstrateのRPCから表示されたSS58アドレスはどこから来たのでしょう?
EVMトランザクションは、アドレス「0x3c..e0」が610 ASTRトークンをアドレス「0x7c..bc」に送信したことを示しています。
しかし、Substrateイベントは、アドレス「Z3..7i」が610 ASTRトークンをアドレス「bV..BK」に送信したことを示しています。
ひとつ確かなことは、EVM RPCのH160アドレスの両方がオリジナルの署名者であるということです。
これは、EVMトランザクションに署名できたからです。
マップされたH160アドレスは、元の署名者がサブストレートアカウントであるため、EVMトランザクションに署名できません。
そこで、アドレスをSS58に変換してみましょう。
擬似コードを使用すると、変換プロセスを以下のように表現できます(オンラインツールを使用して、自分でアドレスを変換することもできます。)
「Z3..7i」は、「0x3c..e0」アドレスがマッピングされていることがわかります。(これは、「bV..BK」と「0x7c..bc」も同様にわかります。)
これは前節で示したアドレスと一致します。
では、SS58からH160への変換はどうでしょう。
SS58のアカウントXdBhqfbg5Jsqp5YgNJVNLzMMBrzGsmBkZypS5Z7nr214fkKをマッピングされたH160アドレスに変換したいとします。
このプロセスは次のように表現できます。
また、Substrate keyユーティリティを使えば、SS58アドレスのデコードされた公開鍵を見ることもできます。
「Xd…kK」の公開鍵は「0x4a..ed6204baeceb461cd568a7cf56」です。
一方、マップされたH160アドレスは「0x4a..ed」です。
マップされたH160を作成する際、公開鍵から末尾の6204baeceb461cd568a7cf56が消えていることに注意してください。
これで、アドレス変換の仕組みとSubstrate RPCがEVMアカウントを表示する仕組みがわかりました。
マップされたアドレスにトークンを送付してEVMアカウントからアクセスし、SubstrateアカウントからEVM預金を引き出してみましょう。
この例では、2つの異なるウォレットから2つのアカウントを作成しました。
では、Substrateアカウントから、EVMサンドボックスにしかアクセスできないMetaMaskアカウントに、10ASTRを送ってみましょう。
全体像としては、次のことをやろうとしています。
これを行うには、まずMetaMaskアドレスをマップされたSS58アドレスに変換する必要があります。
0xA843c5d2B2dFc45e6799EA9b8dbEE0189e6CcAaを変換すると、ZaZgWyUczTxo8Zi8V4frbdHtnjbPr8RE24b3qCjCaMsKUfMになります。
このSS58アドレスにpolkadot-jsから10トークンを送ります。
すると、残高がMetaMaskに表示されます。
残高の変化はEVMエクスプローラにも反映されています。
しかし、ブロックイベントを見ると、Substrateレイヤー内でSubstrate署名者からトークンを送信したため、この転送のブロックイベントは表示されません。
そのため、このイベントは、Substrate RPC内では表示されていても、EVM内ではアクセスできません。
では、トークンをSS58アカウントに戻してみましょう。ZyakNoVJnDXcKFLYfnsTY9EZLYd6PHifzXG5jFyTbSM9dvdを変換すると、0xb2aed18d6495133a43dd6ecd9a5abd1fcae57150になります。
マップされたH160アカウントに9.99トークン(ガス代を差し引いた額)を送金しました。
しかし、このトークンは、アカウントZyakNoVJnDXcKFLYfnsTY9EZLYd6PHifzXG5jFyTbSM9dvdのSubstrate残高には直接送られません。
このトークンはEVMサンドボックス内のマッピングされたH160アカウントの残高であるEVMデポジットに保管されます。
EVMデポジットのトークンを引き出すには、元のSS58アカウントはevm.withdraw関数を呼び出す必要があります。
この関数は、マップされた H160 アドレスと、引き出したいトークン数をパラメータとして要求します。
この例では、polkadot-js ポータルを使って 9.9 トークンを引き出しています。
関数を呼び出した後、ZyakNoVJnDXcKFLYfnsTY9EZLYd6PHifzXG5jFyTbSM9dvdの残高が9.9 ASTRトークン増えているのがわかります。
これで、EVMアカウントとSubstrateアカウントの間を行き来できるようになりました。
以上で、Substrate内でEVMを使用する方法について知る必要があることは全てです!