Skip to main content

Use Script inside sCrypt

Script is a low-level language and acts as assembly for the Bitcoin Virtual Machine. Usually, developers do not have to deal with it directly and can use high-level languages like sCrypt. However, there are cases where using script is desirable. For example, customized script is optimized and thus smaller and more efficient than Script generated by sCrypt. Or script is generated using external tools like Baguette and needs to be integrated into sCrypt.

To achieve this currently, you have to edit the auto-generated .scrypt files under your project's artifacts directory.

First you create a project called P2PKH:

npx scrypt-cli project P2PKH --asm

Notice the --asm option must be enabled, meaning you are going to use inline assembly format of script.

Your contract is at src/contracts/p2pkh.ts:

export class P2PKH extends SmartContract {
@prop()
readonly address: Addr

constructor(address: Addr) {
super(...arguments)
this.address = address
}

@method()
public unlock(sig: Sig, pubkey: PubKey) {
assert(
pubKey2Addr(pubkey) == this.address,
'public key does not correspond to address'
)
assert(this.checkSig(sig, pubkey), 'signature check failed')
}
}

Say you want to substitute the unlock function with manual script, you edit the file .asm/asm.json.

{
"P2PKH": {
"unlock": "OP_DUP OP_HASH160 $pubKeyHash OP_EQUALVERIFY OP_CHECKSIG"
}
}

Variables can be defined by prefix $, as in $pubKeyHash.

We could also define multiple substitutions for multiple methods, if needed.

Now, you can compile the contracts with --asm option:

npx scrypt-cli compile --asm

Now, after compiling, the function body will be replaced with script, as could be seen in artifacts/P2PKH.scrypt.

Set Inline Assembly Variables

Assembly variables can be replaced with literal Script in ASM format using setAsmVars(). Each variable is prefixed by its unique scope, namely, the contract and the function it is under.

p2pkh = new P2PKH(Addr(myAddress.toByteString()))

// Set ASM variable
// Keep in mind that these are NOT constructor parameters and must be set separately.
asmVarValues = {
'P2PKH.unlock.address': myAddress.toByteString()
}
p2pkh.setAsmVars(asmVarValues)

Full code can be found on GitHub. For more information about inline script/assembly, please refer to here.

note

Inline script bypasses many features of sCrypt such as type checking. Extreme caution has to be taken when using this advanced feature.