sCrypt contract development and debugging skills: locate and resolve checkSig / checkPreimage exceptions

During the development and debugging of the sCrypt contract, the two most common and most troublesome problems are the checkSig and checkPreimage exceptions. Although we can locate the specific location of the error in the source code during Debug, we always feel confused about why it failed and how to fix it. Today we are going to talk about some tips on how to quickly locate and repair these two types of problems, hoping to be helpful to everyone.

The sCrypt boilerplate project contains some specific sample codes of the sCrypt contract and is constantly being updated, so sometimes you may encounter a situation where the configuration fails and the Debug cannot be completed normally. Let's take the tokenUtxo contract in this project as an example to see how to locate and solve these two types of problems.

Note: The version of the sCrypt plugin used in this article is 0.4.3 .

checkPreimage exception

First, look at tokenUtxo.scryptthe Debug launch configuration (located .vscode / launch.json for convenience view partially omitted values):

{
            "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
            }
        }

Debug above configuration specifies the start function split, and entryMethodParamsthe parameters specify the starting number; the same time txContextspecified context parameter related to tx. When we started this configuration in vscode to prepare for debugging, we found that the following exception was output in the Debug Console:

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

The abnormal location shown here is on line 14, and the code is require(Tx.checkPreimage(txPreimage));. From this, it can be inferred that there is a problem with txPreimage, but what is the specific reason?

In the previous article , we introduced Sighash Preiamge, which is called the pre-image of the transaction and can be calculated by the transaction tx. Here Tx.checkPreimagefails, the boot configuration parameters entryMethodParamspassed in the value and use txContextthe result calculated parameters are inconsistent.

sighashPreimage

As shown in the figure above, Sighash Preimage is composed of multiple parts. If the two preimages are inconsistent, some of the fields must be different. Which field is the problem? Let's look at the following log again:

----- 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 -----

This journal provides us regarding checkPreimagefurther details abnormalities, primarily compared the specific differences between the two original images previously mentioned. Shown here both scriptCodeMD5 values are different, i.e., both the description itself scriptCode(corresponding to the locking input script) is inconsistent.

The basic point found where the problem is, given some of the recent changes, presumably entryMethodParams, and txContextsome of the configuration parameters may be ineffective. So recalculated and updated preimage, txContext.hex, txContext.opReturnthe other parameters, Debug finally got the correct results.

checkSig exception

There is a kind of common error is checkSigabnormal, often due to problems caused signature. Here we can next be freely modified senderSigto simulate the error parameter value of a signature issue, after restarting Debug you can see the following information:

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...

The above prompt information covers the main checkpoints when resolving signature errors, namely:

1. Determine whether the private key used to generate the signature is correct;

2. Confirm whether the preimage of the tx to be signed (automatically calculated according to txContext) is consistent with the incoming parameters.

To compare whether two preimage same, may be used SigHashPreimagein toJSON()a method to view its internal details, to obtain results similar to the following:

{
  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'
}

The trick here is: insert a piece of code where the input parameter preimage is generated, compare it with the preimage output in the above exception prompt, and find out the possible differences between the two. As shown in the following code:

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())

I should remind you once again that the startup configuration txContextwill affect the field under the attribute preimagecalculations, and so one by one to confirm whether the same comparison when a problem requires.

Guess you like

Origin blog.csdn.net/freedomhero/article/details/108917575