script (⏱,💰)

script (⏱,💰)

NG#9 - マルチサインアカウント

#NG9

合約アカウントには 3 つのサブタスクがあり、これらはすべて bad account シリーズを構成しています。この記事はシリーズの 2 番目のタスクである Bendy Signatures です。

分析#

問題には 2 つの契約があり、sphinx は抽象アカウント契約であり、アカウントが gates 契約の open メソッドを呼び出します。sphinx には多くの制限があり、3 つの公開鍵が与えられますが、そのうちの 1 つは秘密鍵を持っています。この問題は 2/3 マルチサインの問題をシミュレートしており、2 つの署名が認証に成功すると検証トランザクションを送信する必要があります。

アカウント契約の __validate__ では、starknet::get_tx_info().unbox() を使用してトランザクションの署名を取得し、長さ 6 の raw_sig を構築する必要があります。raw_sig [0] と raw_sig [3] は公開鍵であり、raw_sig [1] と raw_sig [4] は署名の r であり、raw_sig [2] と raw_sig [5] は署名の s です。公開鍵は事前に指定された 3 つの公開鍵のいずれかである必要があり、r と s は重複してはなりません。同時に、__execute__ では calls.len() == 1 が制限されているため、唯一の秘密鍵を使用して 2 つのトランザクションを生成して解決することはできません。

1 つの秘密鍵しかないため、この秘密鍵を使用して 2 つの r と s の組み合わせを生成し、両方の組み合わせが検証に合格し、重複しないようにする必要があります。問題は、SDK を使用してトランザクションを送信する方法であり、2 つの有効な署名を持つ必要があるという点になります。

手順#

まず、Starknet.js を使用して異なる maxFee を持つ 2 つの open トランザクションを生成し、それぞれに署名を付けてもテストネットで検証できないことがわかりました。

アドバイザーに問い合わせた後、この問題の実際の解決策は ECDSA の可変性の問題であることがわかりました。詳細については、ZK book を参照してください。

私は ECDSA を学ぶために時間を費やしましたが、それには多くの数学的な知識が必要でした。
ECDSA の原理を知らない場合は、深く学習することをお勧めします。上記の ZK Book の内容は素晴らしいです。

StarkNet も ECDSA を使用して署名を生成するため、ChatGPT が出力した ECDSA の署名手順は次のとおりです:

1. まず、ランダムに選択された整数であるプライベートキーが必要です。同時に、プライベートキーと基点 G の乗算である公開キーも必要です。これを Q = dG と書きます。ここで、d はプライベートキー、G は基点です。
2. メッセージに署名する場合、まずハッシュ関数を使用してメッセージを整数に変換します。これを z とします。
3. 次に、ランダムな整数 k を選択し、点 R = kG を計算します。R の x 座標は署名の一部であり、r とします。
4. 次に、s = (z + r * d) / k を計算します。この s が署名のもう一つの部分です。
最終的な署名は (r, s) です。

これに対応する各ステップは、Starknet.js では次のようになります:

  1. ec.starkCurve.getStarkKey(privateKey) を使用して公開キーを取得します。公開キーは既知のため、このステップはスキップできます。
  2. hash.calculateTransactionHash を使用してトランザクションの詳細をメッセージハッシュに変換します。トランザクションに必要な 6 つのパラメータは自分で設定する必要がありますが、calldata は transaction.getExecuteCalldata を使用して取得できます。
  3. r はランダムな数値であり、自分で設定する必要はありません。次のステップで直接取得できます。
  4. ec.starkCurve.sign(msgHash, privateKey) または signer.signTransaction を使用して r と s を取得します。

上記の ECDSA の可変性の参考資料によれば、対称性のため、1 つの r に対して 2 つの s を使用することで有効な署名が生成されます。2 番目の s の計算は非常に簡単で、必要なもう 1 つのパラメータは SDK のソースコードから見つけることができます。最終的に生成される r1 == r2, s1 != s2 です。

もう 1 つの方法は、異なる seed を使用して 2 つの r を生成することです。Python ライブラリ に対応するメソッドがあります。最終的に生成される r1 != r2, s1 != s2 です。

要件に従って、長さ 6 のリストを構築し、account.invokeFunction のシグネチャに渡し、他の必要なパラメータを埋めて送信することで、タスクを完了させることができます。

結論#

NG9 end

この問題は、マルチサインウォレット契約の動作方法を紹介するだけでなく、ECDSA の可変性の問題も関連しており、トランザクションの構成も理解する必要があります。解決することができれば、非常に有益な経験になるでしょう。

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。