sCryptコントラクトの開発とデバッグのスキル:checkSig / checkPreimageの例外を見つけて解決します

sCryptコントラクトの開発とデバッグ中に、最も一般的で最も厄介な2つの問題は、checkSigとcheckPreimageの例外です。デバッグ中にソースコード内のエラーの特定の場所を見つけることはできますが、エラーが発生した理由と修正方法について常に混乱を感じています。今日は、これら2種類の問題をすばやく見つけて修復する方法について、すべての人に役立つことを願って、いくつかのヒントについて説明します。

sCryptボイラープレートプロジェクトには、sCryptコントラクトの特定のサンプルコードがいくつか含まれており、常に更新されているため、構成が失敗してデバッグが正常に完了できない場合があります。このプロジェクトのtokenUtxoコントラクト例として取り上げて、これら2つのタイプの問題を見つけて解決する方法を見てみましょう

注:この記事で使用されているsCryptプラグインのバージョンは0.4.3です。

checkPreimage例外

まず、tokenUtxo.scryptデバッグ起動構成を確認します(便宜上、.vscode / launch.jsonにあり、値が部分的に省略されています)。

{
            "type": "scrypt",
            "request": "launch",
            "name": "Debug tokenUtxo",
            "program": "${workspaceFolder}/contracts/tokenUtxo.scrypt",
            "constructorParams": "",
            "entryMethod": "split",
            "entryMethodParams": "Sig(b'304402200...'), PubKey(b'0251c866a29a93b6eb51197be1e9ccdcc5e822caa69c7593905347e3ec310bebad'), 60, 22222, PubKey(b'0291e61f25a92c94103f0f4ef1f70bf3582f44cff95d497ceb3efdb945f4ce3cbe'), 40, 22222, SigHashPreimage(b'0100000028bc...')",
            "txContext": {
                "hex": "01000000015884e5...",
                "inputSatoshis": 100000,
                "opReturn": "029a77564154c6ed13ffcc387342692480e7e15f2e3ad832cf2ac6de1c3ccf28230a5a",
                "inputIndex": 0
            }
        }

構成上デバッグスタート機能を特定splitし、entryMethodParamsパラメータが開始番号を指定し、同じ時間txContextTXに関連するコンテキスト・パラメータを指定しました。デバッグの準備のためにvscodeでこの構成を開始すると、デバッグコンソールに次の例外が出力されたことがわかりました。

Execution failed with error SCRIPT_ERR_NULLFAIL.
Stacktrace:
  /Users/hero/work/boilerplate/contracts/tokenUtxo.scrypt:14:in 'Token.split'

ここに示されている異常な場所は14行目で、コードはrequire(Tx.checkPreimage(txPreimage));です。これから、txPreimageに問題があると推測できますが、具体的な理由は何ですか。

では前の記事、私たちは、取引の前イメージと呼ばれ、トランザクションTXによって計算することができSighash Preiamgeを導入しました。ここでTx.checkPreimage失敗entryMethodParamsすると、値で渡されたブート構成パラメーターtxContext結果を使用して計算されたパラメーターに一貫性がありません。

sighashPreimage

上の図に示すように、Sighash Preimageは複数の部分で構成されています。2つのpreimageに一貫性がない場合は、一部のフィールドが異なっている必要があります。どの分野が問題ですか?次のログをもう一度見てみましょう。

----- CheckPreimage Fail Hints Begin -----
You should check the differences in detail listed below:

Fields with difference | From preimage in entry method params | From preimage calculated with tx
md5(scriptCode) | 148dd2b3fcc09d6baf15c9fcf5d961d3 | 6393778445f442466414464ee3be7cc7

Preimage calculated with tx:
0100000028bce...

----- CheckPreimage Fail Hints End -----

このジャーナルはcheckPreimage、主に前述の2つの元の画像間の特定の違いを比較して、異常の詳細について説明します。ここに示されているのは、両方のscriptCodeMD5値が異なることです。つまり、両方の説明自体scriptCode(ロック入力スクリプトに対応)に一貫性がありません。

最近の変更のいくつかを考えるentryMethodParams、おそらく問題がどこにあるかを見つけた基本的なポイント、およびtxContextいくつかの構成パラメーターは効果がない可能性があります。だから、再計算され、更新preimagetxContext.hextxContext.opReturn他のパラメータは、デバッグは最終的に正しい結果を得ました。

checkSig例外

ある種の一般的なエラーがcheckSig異常であり、多くの場合、署名に起因する問題が原因です。ここで、次にsenderSig、署名の問題のエラーパラメータ値をシミュレートするように自由に変更できます。デバッグを再起動すると、次の情報が表示されます。

Execution failed with error SCRIPT_ERR_NULLFAIL.
Stacktrace:
  /Users/hero/work/boilerplate/contracts/tokenUtxo.scrypt:25:in 'Token.split'
 
----- CheckSig Fail Hints Begin -----
You should make sure the following check points all passed:
1. private key used to sign should be corresponding to the public key 028f46cb8ec957dcda049ac549fc46d451e0095a5b6f95950bc58830a7dc21167c
2. the preimage of the tx to be signed should be 0100000028bcef7e73248aa273...

上記のプロンプト情報は、署名エラーを解決する際の主なチェックポイントをカバーしています。

1.署名の生成に使用された秘密鍵が正しいかどうかを判断します。

2.署名するtxのプリイメージ(txContextに従って自動的に計算される)が入力パラメーターと一致しているかどうかを確認します。

2つのプリイメージが同じであるかどうかを比較するには、その内部の詳細を表示するメソッドで使用SigHashPreimagetoJSON()て、次のような結果を取得できます。

{
  nVersion: 1,
  hashPrevouts: '1029c58f269f3a1f0165149921e7a726d13bf29883f80ec3bb08c75fabaa06ad',
  hashSequence: '3bb13029ce7b1f559ef5e747fcac439f1455a2ec7c5f09b72290795e70665044',
  outpoint: {
    hash: '5884e5db9de218238671572340b207ee85b628074e7e467096c267266baf77a4',
    index: 0
  },
  scriptCode: 'fd860f5101400...',
  amount: 100000,
  nSequence: 4294967295,
  hashOutputs: '1029c58f269f3a1f0165149921e7a726d13bf29883f80ec3bb08c75fabaa06ad',
  nLocktime: 0,
  sighashType: 'SigHash.ALL | SigHash.FORKID'
}

ここでの秘訣は、入力パラメーターpreimageが生成されるコードを挿入し、それを上記の例外プロンプトのpreimage出力と比較して、2つの間に考えられる違いを見つけることです。次のコードに示すように:

const {
    
     getPreimage, SigHashPreimage, signTx } = require('scryptlib');

...

const preimage = getPreimage(tx_, token.lockingScript.toASM(), inputSatoshis, inputIndex)
const sig = signTx(tx_, privKey, token.lockingScript.toASM(), inputSatoshis)

// compare two preimages for debugging purpose
const preimage2 = new SigHashPreimage('fd860f51014001760...'); // use hex from checkSig fail hints
console.log(preimage2.toString() === preimage.toString())
console.log(preimage.toJSON())
console.log(preimage2.toJSON())

スタートアップの構成txContextは属性preimage計算のフィールドに影響を与えることをもう一度思い出してください。問題が発生したときに同じ比較が必要かどうかを1つずつ確認してください。

おすすめ

転載: blog.csdn.net/freedomhero/article/details/108917575