Ethereumの状態遷移関数
Ethereumの状態遷移関数、APPLY(S,TX) -> S' は以下のように定義されます:
トランザクションが正しく形成されているか(つまり、適切な数の値があるか)、署名が有効で、送信者のアカウントのnonceと一致するかをチェックします。そうでなければ、エラーを返します。
トランザクション料金をSTARTGAS * GASPRICEとして計算し、署名から送信アドレスを決定します。送信者のアカウント残高から料金を差し引き、送信者のnonceを増加させます。支払うための十分な残高がない場合は、エラーを返します。
GAS = STARTGASを初期化し、トランザクションのバイトに支払うために、バイトごとに特定量のガスを取り除きます。
送信者のアカウントから受信アカウントへトランザクションの値を転送します。受信アカウントがまだ存在しない場合は、それを作成します。受信アカウントがコントラクトの場合、コントラクトのコードを完了するか、実行がガスを使い果たすまで実行します。
値の転送が失敗した場合(送信者に十分なお金がないか、コードの実行がガスを使い果たした場合)、料金の支払いを除くすべての状態変更を元に戻し、料金をマイナーのアカウントに追加します。
それ以外の場合は、残ったガスの料金を送信者に払い戻し、消費されたガスに対して支払われた料金をマイナーに送ります。
例として、コントラクトのコードが以下のような場合を想定します:
if !self.storage[calldataload(0)]:
self.storage[calldataload(0)] = calldataload(32)
このコードは、特定の条件下でストレージの更新を行う簡単なロジックを示しています。Ethereumのスマートコントラクトでは、このように条件式を用いてデータの操作や状態の変更を行うことが一般的です。
この例では、コントラクトのストレージが最初は空であり、10イーサの価値、2000ガス、0.001イーサのガスプライス、そして64バイトのデータを持つトランザクションが送信されます。データの最初の32バイトは数字の2を、次の32バイトは文字列CHARLIEを表しています。この場合の状態遷移関数のプロセスは以下の通りです:
トランザクションが有効かつ適切に形成されているかをチェックします。
トランザクション送信者が少なくとも2000 * 0.001 = 2イーサを持っているかをチェックします。そうであれば、送信者のアカウントから2イーサを差し引きます。
ガスを2000で初期化します。トランザクションが170バイトで、バイト料金が5であると仮定すると、850を差し引き、残りは1150ガスです。
送信者のアカウントからさらに10イーサを差し引き、それをコントラクトのアカウントに追加します。
コードを実行します。このケースでは、コントラクトのストレージのインデックス2が使用されているかをチェックし、使用されていないことを認識し、インデックス2のストレージをCHARLIEという値に設定します。これに187ガスを消費すると仮定すると、残りのガス量は1150 - 187 = 963です。
963 * 0.001 = 0.963イーサを送信者のアカウントに戻し、結果として得られた状態を返します。
トランザクションの受信側にコントラクトがなかった場合、トランザクション料は単純に提供されたGASPRICEとトランザクションのバイト長を掛けたものに等しくなり、トランザクションと一緒に送信されたデータは関係ありません
よろしければサポートお願いします!よりいい情報を発信します。