# preimage - Chinese

## 脚本操作码 `OP_CODESEPARATOR` 下的 preimage 原象

`OP_CHECKSIG` 检查的签名是对 preimage 原象的哈希的签名。原象包含整个交易的输出、输入和锁定脚本。通常锁定脚本是完整的。但是如果 `OP_CHECKSIG` 之前执行了 `OP_CODESEPARATOR`，那么原象只包含锁定脚本从最近执行的 `OP_CODESEPARATOR` 的位置直到脚本结束，即只包含部分锁定脚本。利用这个特性，可以用来减少原象的大小，从而减少整个交易的大小。

sCrypt 标准库 `Tx` 提供了以下函数来检查这种只包含部分锁定脚本的原象：

| 函数名                              | 描述                                                                    |
| -------------------------------- | --------------------------------------------------------------------- |
| `Tx.checkPreimageOCS`            | 检查的原象只包含部分锁定脚本的，默认检查的签名类型是 `SigHash.ALL \| SigHash.FORKID` ，不支持选择签名类型 |
| `Tx.checkPreimageSigHashTypeOCS` | 支持选择签名类型                                                              |
| `Tx.checkPreimageAdvancedOCS`    | 持选择签名类型以及自定义临时密钥                                                      |
| `Tx.checkPreimageOptOCS`         | 优化版的 `Tx.checkPreimageOCS`                                            |
| `Tx.checkPreimageOptOCS_`        | 优化版的 `Tx.checkPreimageOCS`，支持选择签名类型                                   |

下面是一个使用 `Tx.checkPreimageOCS()` 来检查原象的例子：

```
contract CheckLockTimeVerifyOCS {
    int time;

    public function unlock(SigHashPreimage preimage) {
        require(Tx.checkPreimageOCS(preimage));
        require(SigHash.nLocktime(preimage) > this.time);
    }
}
```

执行这个合约的 [交易](https://classic-test.whatsonchain.com/tx/430b65cde01692579be1159077c7c09b29f96aa654771301dbae5d6e602b2284) 大小是 `288` 字节，包含一个 `288` 字节的 preimage 原象。 而执行使用 `Tx.checkPreimage()` 版本的 [CheckLockTimeVerify](https://github.com/sCrypt-Inc/boilerplate/blob/master/contracts/cltv.scrypt) 合约的 [交易](https://classic-test.whatsonchain.com/tx/7b72fc1e8cc8229d9c54675bf1011ec96291257927e989e53d98a3130f2d9248) 大小是 `1005` 字节，包含一个 `915` 字节的 preimage 原象。 这两个合约的功能是完全一样的，但是交易的大小却优化了 `80%` 。

下面是如何部署和调用使用 `CheckLockTimeVerifyOCS` 合约的例子：

```
const amount = 2000

// get locking script
const CLTVOCS = buildContractClass(loadDesc('cltvOCS_debug_desc.json'));
cltv = new CLTVOCS(1422674);

// lock fund to the script
const lockingTx = await deployContract(cltv, amount)
console.log('funding txid:      ', lockingTx.id);

// unlock
const unlockingTx = new bsv.Transaction();

unlockingTx.addInput(createInputFromPrevTx(lockingTx))
    .setLockTime(1422674 + 1)
    .change(privateKey.toAddress())
    .setInputScript(0, (tx, output) => {
        const preimage = getPreimage(tx, output.script.subScript(0), output.satoshis)
        return cltv.spend(new SigHashPreimage(toHex(preimage))).toScript()
    })
    .seal()


const unlockingTxid = await sendTx(unlockingTx)
console.log('unlocking txid:   ', unlockingTxid)

console.log('Succeeded on testnet')
```

在使用 `getPreimage` 计算原象时，不能传递整个锁定脚本了。需要使用 `subScript(opsIndex: number)` 来裁剪锁定脚本。其参数 `index` 是本脚本中 `OP_CODESEPARATOR` 的索引，即第几个 `OP_CODESEPARATOR`。需要注意的是，该函数没有考虑动态执行的情况。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://radiantblockchain.gitbook.io/wiki/programming/scryptlib/preimage/preimage-chinese.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
