見出し画像

【Jaguar's Blog 10】トランザクションを理解する(リンク編)

この記事は2024年1月13日にNEM/Symgolのコア開発者Jaguar氏によって投稿された記事「Understanding TXes - Links」をChatGPTを用いて翻訳したものです。


Symbolには、アカウント、ノード、投票、およびVRFの4つのタイプのキーリンクトランザクションがあります。これらそれぞれが異なる目的を持っていますが、いずれもサプリメンタルキーをアカウントに事前登録することで、効果的にチェーン上にコミットメントを作成します。これらは単独のトランザクションとしても、アグリゲートトランザクションに埋め込まれても良いです。トランザクションのより深い理解については、Symbol Technical Referenceの第6章を読むことを推奨します。

この記事の目的では、これらのトランザクションの各部分を調査し、それらを設計する際の意思決定について学びます。では、始めましょう!


Account Key Link

アカウントキーリンクトランザクションは、Symbolにおいて非管理型のステーキングを可能にします。これがどういう意味で、なぜこれが重要なのかを理解するために、ブロックの生成方法を見直してみましょう。アカウントがブロックを生成する確率は、そのステーク(または所有するXYMの量)と強く相関しています。ブロックをアカウントに関連付けるには、そのブロックに対してアカウントが署名する必要があります。管理型システムでは、ブロックを署名するためにアカウント(XYMを含む)が必要です。これはつまり、これらの高額なアカウントの秘密鍵がネットワークに接続されたノード上に存在する必要があることを意味します。セキュリティの観点から見ると、これは最適ではありません。ノードが侵害されると、貴重なハーベストアカウントの秘密鍵も盗まれ、所有者は大きな損失を被る可能性があります。

ハーベスティングをよりリスクの少ないものにするために、Symbolでは非管理型システムが採用されています。ハーベスティングが可能なアカウントは「メインアカウント」と呼ばれます。このアカウントは、そのハーベスティング権限を別のアカウントに委任する特別なアカウントキーリンクトランザクションを作成します。この別のアカウントは、リンクされたアカウントまたはリモートアカウントとも呼ばれます。これは新しいアカウントでなければならず、以前にどんな理由であれ使用されたことがないアカウントである必要があります。アカウントリンクが存在する状態でリモートアカウントが署名した任意のブロックは、コンセンサスの目的でメインアカウントによって署名されたものとして扱われます。このシステムでは、ネットワークに接続されたノードにはリモートアカウントの秘密鍵のみが必要です。リモートアカウントは決して資産を所有することがないため、攻撃者はその盗難から利益を得ることはできません。もしリモートアカウントが侵害された場合、推奨される対策は単に新しいリモートアカウントに再リンクすることです。

⚠️ 51%攻撃は、攻撃者がネットワークのハーベスティング能力の51%を取得するときに実行されます。攻撃者は、ハーベスティング権限が与えられているため、アクティブなリモートハーベスティングキーを収集して51%攻撃を試みる可能性があります。これが、委任されたハーベスターをノード全体に均等に分散させることが重要な理由の一つです。さらに、リモートの秘密鍵を注意深く取り扱うか、定期的にそれらを入れ替えることは、そのような攻撃を緩和するために重要です。

メインアカウントは、一度に正確に1つのリモートアカウントにハーベスティング権限を委任できます。同様に、リモートアカウントは一度に1つのメインアカウントからハーベスティング権限を委任できます。リモートアカウントに変更を許可するためには、既存のリンクをまず解除する必要があります。

完全なスキーマはここにあります。

静的プロパティ

TRANSACTION_VERSION = make_const(uint8, 1)
TRANSACTION_TYPE = make_const(TransactionType, ACCOUNT_KEY_LINK)

この記事で取り上げられているアカウントキーリンクトランザクションのバージョンは1です。ACCOUNT_KEY_LINKトランザクションのタイプは0x414Cです - エンティティタイプ(0x1 << 14)、コード(0x1 << 8)、ファシリティコード(0x4C)。

レイアウト

# Linked public key.
linked_public_key = PublicKey

リンクされた公開鍵は、リンクされた(またはリモート)アカウントの公開鍵です。ハーベスティング権限は、トランザクションに署名するアカウントからこのアカウントに委任されます。

# Account link action.
link_action = LinkAction

リンクアクションには、次の2つの値のいずれかがあります:

  • LINK - ハーベスティング権限を新しく委任する必要があります

  • UNLINK - ハーベスティング権限を解除する必要があります

ℹ️ アンリンク時には、linked_public_keyにはアクティブなリモートアカウントの公開鍵を指定する必要があります。これは技術的にはアカウントキャッシュから取得できるかもしれませんが、トランザクションの一部として設定することで、実装ロジックがかなり簡素化されます。ロールバック中には、アンリンク(リンク)を元に戻すための完全な情報が存在します。その結果、キャッシュははるかに簡素化され、アカウントキーリンクの履歴を維持する必要はありません。

Node Key Link

ノードキーリンクトランザクションは、Symbolにおいてハーベスティングの委任を可能にします。リモートノードにハーベスティングを委任したいノードは、特別なノードキーリンクトランザクションを作成します。ハーベスティングを委任したいノードの公開鍵を指定する必要があります。

アカウントは一度に正確に1つのリモートノードにのみハーベスティングを委任できます。対照的に、ノードは同時に多くの委任されたハーベスターをホストできます。リモートノードへの変更を許可するためには、既存のリンクをまず解除する必要があります。

⚠️ 良い振る舞いをするノードは、アカウントがノードキーリンクを切り替える際に、自発的にハーベスティングを停止します。残念ながら、これはプロトコルによって強制されていません。アカウントがハーベスティングを1つのノードから別のノードに移動する場合、リンクされたリモートおよびVRFのキーを入れ替えることが強くお勧めされています。これにより、リモートノードがその情報を使用し続けてハーベスティングを行うのを防ぎます。また、ある場所でのハーベスティング能力の過度な集中を防ぐのにも役立ちます。

完全なスキーマはここにあります。

静的プロパティ

TRANSACTION_VERSION = make_const(uint8, 1)
TRANSACTION_TYPE = make_const(TransactionType, NODE_KEY_LINK)

この記事で取り上げられているノードキーリンクトランザクションのバージョンは1です。NODE_KEY_LINKトランザクションのタイプは0x424Cです - エンティティタイプ(0x1 << 14)、コード(0x2 << 8)、ファシリティコード(0x4C)。

レイアウト

# Linked public key.
linked_public_key = PublicKey

リンクされた公開鍵は、リモートノードの公開鍵です。疑念を避けるために、これは通常、ノードの最下位のSSL証明書(通常はnode.key.pemに見つかります)からの公開鍵です。良い振る舞いをするリモートノードは、そのノードの公開鍵が自身と一致する場合にのみ、委任されたハーベスターをホストします。

# Account link action.
link_action = LinkAction

リンクアクションには、次の2つの値のいずれかがあります:

  • LINK - 指定されたノードでのハーベスティングの委任を許可する

  • UNLINK - 指定されたノードでのハーベスティングの委任を禁止する

ℹ️ アンリンク時には、他のすべてのフィールドはリンク時と同じ値でなければなりません。

VRF Key Link

Symbolでは、すべての適格なハーベスターアカウントは、検証可能なランダム関数(VRF)の公開鍵を事前登録する必要があります。このVRFは、親ブロックの生成ハッシュが与えられた場合に、ブロックの生成ハッシュを生成するために使用されます。その結果は疑似ランダムですが、完全に検証可能です。この生成された値の証拠は、各ブロックのgeneration_hash_proofフィールドに格納されます。

VRF関数の1つの入力はプライベートであるため、VRFの秘密鍵です。他のノードはこれを直接計算することはできません。彼らはただそれが正しく計算されたことを証明することができます。その結果、悪意のある行為者はプライベートでブロックの長い連鎖を用意することや、ブロック生成を有利に操ることはできません。全体的には、これがより公正で(かつランダムな)ブロック生成につながります。

ℹ️ チェーンにブロックが受け入れられるためには、そのヒットが対象よりも小さい必要があります。ヒットはブロックの生成ハッシュから派生し、対象はブロックの署名者のアカウント状態から派生します。逆に、ブロックの生成ハッシュは親ブロックの生成ハッシュから派生します(これはブロックが連鎖される方法の一つです)。生成ハッシュがいかなるプライベートデータもなしに計算できると仮定します。攻撃者は理論的には、次のNブロックですべての適格なハーベスターが生成できるであろう生成ハッシュを計算できます。その後、攻撃者はそのすべての連鎖で同時に採掘を試み、利益(またはEV)を最大化することができます。

VRFの公開鍵が事前に登録されていることは極めて重要です。もし登録されていなければ、攻撃者はそれらを自分の非表示の連鎖で要求または使用できます。攻撃者がその値を知っているため、すべての生成ハッシュを生成することができます。これにより、VRFが最初に提供するべき保護が実質的に無効になります!

アカウントは一度に正確に1つのVRFを登録できます。VRFに変更を許可するためには、既存のリンクをまず解除する必要があります。

完全なスキーマはここにあります。

静的プロパティ

TRANSACTION_VERSION = make_const(uint8, 1)
TRANSACTION_TYPE = make_const(TransactionType, VRF_KEY_LINK)

この記事で取り上げられているVRFキーリンクトランザクションのバージョンは1です。VRF_KEY_LINKトランザクションのタイプは0x4243です - エンティティタイプ(0x1 << 14)、コード(0x2 << 8)、ファシリティコード(0x43)。

レイアウト

# Linked public key.
linked_public_key = PublicKey

リンク先の公開鍵は、VRF鍵ペアの公開鍵です。

# Account link action.
link_action = LinkAction

リンクアクションは2つの値のいずれかを持ちます:

  • LINK - アカウントにVRFを登録します

  • UNLINK - アカウントからVRFを登録解除します

ℹ️ アンリンク時には、他のすべてのフィールドはリンク時と同じ値でなければなりません。

Voting Key Link

Symbolでは、投票は確率的コンセンサス(PoS+)の上に決定論的コンセンサスを追加します。ブロックチェーンはエポック(mainnetでは720ブロック)に分割されます。投票キーは正確に1つのエポックに対して有効です。各エポックごとにキーを明示的に登録するのは面倒で無駄なので、代わりにルート投票キーペアが複数のエポックの範囲に登録されます。範囲内のすべての投票キーペアは、ルート投票キーペアから導出できます。各投票キーペアはそのエポックが経過すると削除されます。

ℹ️ この削除は将来の機密性の形態です。攻撃者がノードを侵害し、投票の秘密鍵にアクセスできた場合、被害は制限されます。攻撃者は現在および将来のエポックの確定にのみ影響を与えることができ、過去のエポックには影響を与えることができません。これにより、ブロックが一度確定されると、それらは永遠に確定されたものとなります。過去のエポックの投票の秘密鍵はすでに破棄されているため、攻撃者は代替のブロックチェーンを確定することはできません。

VRFと同様に、投票キーも事前に登録する必要があります。そうでないと、攻撃者が必要に応じてそれらを使用または登録しようとする可能性があります。これにより、投票の利点が大きく制限されます。

投票キーペアが時間制限されている結果として、同時に複数のルート投票キーペアを登録できます。mainnetでは、単一のアカウントに最大で3つのルート投票キーペアが関連付けられ、それぞれが最大720のエポックにわたって有効になります。登録されたすべてのルート投票キーペアは、重複しない範囲を持たなければなりません。2つの登録があれば、アカウントがルート投票キーペアを変更する際に任意のエポックで投票をスキップする必要がないようにクリーンなロールオーバーが可能です。3つの登録が許可されているのは、余分な登録の可能性がいくつかの運用ワークフローを簡略化するからです。

完全なスキーマはここにあります。

静的プロパティ

TRANSACTION_VERSION = make_const(uint8, 1)
TRANSACTION_TYPE = make_const(TransactionType, VOTING_KEY_LINK)

この記事で取り上げられている投票キーリンクトランザクションのバージョンは1です。VOTING_KEY_LINKトランザクションのタイプは0x4143です - エンティティタイプ(0x1 << 14)、コード(0x1 << 8)、ファシリティコード(0x43)。

レイアウト

# Linked public key.
linked_public_key = PublicKey

リンクされた公開鍵は、ルート投票キーペアの公開鍵です。

# Starting finalization epoch.
start_epoch = FinalizationEpoch

ルート投票キーペアが有効であるべき最初のエポック。

# Ending finalization epoch.
end_epoch = FinalizationEpoch

ルート投票キーペアが有効であるべき最後のエポック。

# Account link action.
link_action = LinkAction

リンクアクションは2つの値のいずれかを持ちます。

  • LINK - アカウントにルート投票キーペアを登録します

  • UNLINK - アカウントからルート投票キーペアを登録解除します

ℹ️ アンリンク時には、他のすべてのフィールドはリンク時と同じ値でなければなりません。

この記事が気に入ったらサポートをしてみませんか?