函数

用户自定义函数

sCrypt允许开发者定义自己的函数,如下所示:

function sum(int a, int b): int {
    return a + b;
}

这些函数只在合约内可见,类似Solidity里的 private 函数。

公有函数

A public function returns true if it runs to completion and false otherwise. It does not have return type and return parts, as they are included implicitly. In other words,

public function isZero(int a) {
    require(a == 0);
}

功能上等同于

public function isZero(int a): bool {
    require(a == 0);
    return true;
}

静态函数和静态属性

A static property/function can be referenced with contract name as prefix without an instantiated contract, similar to a static function/property in Javascript or C++. A static property/function can also be referenced without the contract prefix, but only in the contract it is defined in.

library Foo {
    static int N = 0;

    static function incByN(int a): int {
        // N is used with and without Foo prefix
        return a + Foo.N + N;
    }

    static function double(int x): int {
        // incByN() is called with prefix and without
        return Foo.incByN(x) + incByN(x);
    }
}

contract Bar {
    public function unlock(int y) {
        require(y == Foo.double(2));
        require(y == Foo.N);
        // N cannot be referenced without Foo prefix
        // require(y == N);
    }
}

return

由于比特币脚本缺乏对 return 语义的支持,所以函数必须以 return 语句结尾,并且 return 语句只能放在函数末尾,不能放在其他位置。将来可能会放松这个限制。一般来说这不是问题,可以用如下方式避免在其他位置返回:

function abs(int a): int {
    if (a > 0) {
        return a;
    } else {
        return -a;
    }
}

可以改写成

function abs(int a): int {
    int ret = 0;

    if (a > 0) {
        ret = a;
    } else {
        ret = -a;
    }
    return ret;
}

递归

Recursion is disallowed. A function cannot call itself in its body, either directly or indirectly.

库函数

sCrypt实现了如下库函数,在全局可见。

数学

  • int abs(int a)
  • int min(int a, int b)
  • int max(int a, int b)
  • bool within(int x, int min, int max)

哈希

  • Ripemd160 ripemd160(bytes b)

  • Sha1 sha1(bytes b)

  • Sha256 sha256(bytes b)

  • Ripemd160 hash160(bytes b)

    ripemd160(sha256(b))

  • Sha256 hash256(bytes b)

    sha256(sha256(b))

签名校验

  • bool checkSig(Sig sig, PubKey pk)
  • bool checkMultiSig(Sig[] sigs, PubKey[] pks)

字节数组 操作

  • int 互相转换

用函数 unpack 可以把 bytes 类型转换为 int 类型。采用小端格式的 符号-值 表示法 ,最高位比特表示符号( 0 为正, 1 为负)。 用函数 pack 可以把 int 类型转换为 bytes 类型。

int a1 = unpack(b'36');    // 54 decimal
int a2 = unpack(b'b6');    // -54
int a3 = unpack(b'e803');  // 1000
int a4 = unpack(b'e883');  // -1000
bytes b = pack(a4);        // b'e883'
  • bytes num2bin(int num, int size)

    把数字 num 转换为字节数为 size 的字节数组,包括符号比特。如果字节数组无法容纳被转换的数字,则会转换失败。

  • len() Returns the length.

    int a = len(b'ffee11'); // a == 3
    
  • Slicing Opeartor - b[start:end] returns subarray of b from index start (inclusive) to end (exclusive). start is 0 if omitted, end is length of array if omitted.

    bytes b = b'0011223344556677';
    // b[3:6] == b'334455'
    // b[:4] == b'00112233'
    // b[5:] = b'556677'
    
  • Concatenation

    bytes b = b'00112233' + b'334455'  // b == b'00112233334455'
    
  • reverseBytes(bytes b, static const int size)

    Returns reversed bytes of b, which is of size bytes. Note size must be a compile time constant. It is often useful when converting a number between little-endian and big-endian.

    // returns b'6cfeea2d7a1d51249f0624ee98151bfa259d095642e253d8e2dce1e79df33f79'
    reverseBytes(b'793ff39de7e1dce2d853e24256099d25fa1b1598ee24069f24511d7a2deafe6c', 32)