Inline Assembly¶
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 more efficient than script generated by sCrypt. Or script is generated using external tools (like MiniForth) and needs to be integrated into sCrypt.
Script can be embedded directly into sCrypt source code using assembly representation. An sCrypt function can be written in Script and called like a regular sCrypt function.
Calling Convention¶
For a function to be written in Script, its entire body must be enclosed by asm
mode. Function parameters are on top of the stack, in reverse order as declared.
For example, for a function with signature function foo(int p0, bytes p1, bool p2): int
, p2
will be top of the stack, p1
second from top, and p0
third from top
when entering asm
mode. When exiting asm
mode, the return value is on top of the stack.
All other items in the stack before the call must remain intact.
Three assembly functions are shown below.
// compute length of "b" in bytes
function len(bytes b): int {
asm {
op_size
}
}
// this is also fine since the return is on top and none in the old stack is changed
function len(bytes b): int {
asm {
op_size
op_nip
}
}
function lenFail(bytes b): int {
// this is wrong since the original top of stack is dropped
asm {
op_drop
op_size
}
}
Assembly Variable¶
Variables can be used inside asm
mode by prefix $
. Unlike the rest of Script, which is copied verbatim into the final script output,
a variable is prefixed by its scope to avoid name collision, uniquely identified by the function and contract it is within. For example, supposed a variable $var
is used
inside function func
inside contract contractFoo
, it will show up in the final script output as $contractFoo.func.var
.
An example is shown below.
function p2pkh(Sig sig, PubKey pubKey): bool {
asm {
op_dup
op_hash160
$pkh
op_equalverify
op_checksig
}
}
Loop¶
Loop syntax can also be used inside asm
.
public function unlock(int x) {
asm {
OP_DUP
loop (N) : i {
loop (N) : j {
i
j
OP_ADD
OP_ADD
}
}
13
OP_NUMEQUAL
OP_NIP
}
}
The equivalent sCrypt code is:
public function unlock(int x) {
int sum = x;
loop (N) : i {
loop (N) : j {
sum += (i + j);
}
}
require(sum == 0x13);
}
i
and j
are Induction variables .
String Literal¶
String literal is a double quoted UTF8 string, which can be used inside asm
.
static function equal(bytes msg) : bool {
asm {
"你好world! 😊"
OP_EQUAL
}
}
Notes¶
Inline assembly bypasses many features of sCrypt such as type checking. Extreme caution has to be taken using this advanced feature. Also it is case-insensitive for compatibility with external tools.