私は、あるトランザクションの意味は、そのバイト列が存在した瞬間に固定されるものだと考えていました。つまり一度デコードすれば、どこでも同じ答えが得られるはずだ、という前提です。ところが、Dusk自身のRuskの「Boreas」アップグレードに関するチェンジログでは、それを当然視するのではなく、設計として扱う必要があるものとして扱っています。
Boreasでは、特定のハードフォークに紐づけたバージョン対応のトランザクションデコードを追加し、さらに旧いブロックをリプレイする際のフォーマット選択もハードフォークの統治に従うようにしました。コードベースには、明示的に2種類の型、CanonicalTransaction と LedgerTransaction が追加され、トランザクションのメモリ上の表現を、実際に台帳へ永続化されるフォーマットから分離しています。さらに、ブロックシリアライズの際に pre-Aegis 時代のトランザクションを正しくデコードすることに特化した回帰テストまで用意されています。
それが必要になるのは、トランザクションデコードが、異なるプロトコルの時代や処理段階を考慮しなければならなくなった時だけです。つまり、クライアントからワイヤ越しに新たに受信したばかりのものを、メモリ上では canonical なオブジェクトとして保持し、さらに現在のルールより前の規則で作られたブロックからリプレイされる場合です。
つまり、プロトコルのアップグレードは「新しいルールで新しいトランザクションが動く」だけでは安全ではありません。新しいルールが、当時のルールによって生成された古い台帳状態を、正しくリプレイできる能力を、黙って壊さない場合にのみ安全です。歴史的リプレイの互換性と、ハードフォークにより制御されたデコードは、この種のバージョン不一致による失敗を防ぐために設計されています。
"トランザクションは、それに触れるすべての段階が、それが意味するものに同意している場合にのみ信頼できる。"
私が本当に見たいのは、適用されるルールのもとで、歴史的なトランザクションがデコードされる挙動を変えずに、現在のノードで pre-Aegis の実際のブロックをリプレイすることです。単に分離した状態での通過回帰テストを見るだけではありません。
#dusk $DUSK @Dusk
Boreasでは、特定のハードフォークに紐づけたバージョン対応のトランザクションデコードを追加し、さらに旧いブロックをリプレイする際のフォーマット選択もハードフォークの統治に従うようにしました。コードベースには、明示的に2種類の型、CanonicalTransaction と LedgerTransaction が追加され、トランザクションのメモリ上の表現を、実際に台帳へ永続化されるフォーマットから分離しています。さらに、ブロックシリアライズの際に pre-Aegis 時代のトランザクションを正しくデコードすることに特化した回帰テストまで用意されています。
それが必要になるのは、トランザクションデコードが、異なるプロトコルの時代や処理段階を考慮しなければならなくなった時だけです。つまり、クライアントからワイヤ越しに新たに受信したばかりのものを、メモリ上では canonical なオブジェクトとして保持し、さらに現在のルールより前の規則で作られたブロックからリプレイされる場合です。
つまり、プロトコルのアップグレードは「新しいルールで新しいトランザクションが動く」だけでは安全ではありません。新しいルールが、当時のルールによって生成された古い台帳状態を、正しくリプレイできる能力を、黙って壊さない場合にのみ安全です。歴史的リプレイの互換性と、ハードフォークにより制御されたデコードは、この種のバージョン不一致による失敗を防ぐために設計されています。
"トランザクションは、それに触れるすべての段階が、それが意味するものに同意している場合にのみ信頼できる。"
私が本当に見たいのは、適用されるルールのもとで、歴史的なトランザクションがデコードされる挙動を変えずに、現在のノードで pre-Aegis の実際のブロックをリプレイすることです。単に分離した状態での通過回帰テストを見るだけではありません。
#dusk $DUSK @Dusk
