Skip to main content

Common Algorithms

For performance reasons, many commonly used algorithms in ckb-js-vm are implemented in C (more may be added as needed in the future):

  • Sha256
  • Keccak256
  • Blake2b
  • Ripemd160
  • secp256k1
  • schnorr
  • Smt
  • hex
  • base64

Hasher

Currently, only HasherCkb and HasherKeccak256 are provided. To use other hash algorithms, you need to call the interfaces provided by the bindings.

Syntax

interface Hasher {
update(data: BytesLike): Hasher;
digest(): Bytes;
}

Example

const hasher = new HasherCkb();
hasher.update(bindings.hex.decode("aaaa"));
const hash = hasher.digest();

hashCkb

Computes the CKB hash of the given data using the Blake2b algorithm.

Syntax

function hashCkb(...data: BytesLike[]): Bytes;

Parameters

data: The data to hash.

Return

The hash (Fixed 32 bytes)

Example

const hash2 = hashCkb(bindings.hex.decode("aaaa"));

Secp256k1

Secp256k1 signature verification.

Syntax

const secp256k1: {
recover(
signature: ArrayBuffer,
recoveryId: number,
messageHash: ArrayBuffer
): ArrayBuffer;
serializePubkey(pubkey: ArrayBuffer, compressed?: boolean): ArrayBuffer;
parsePubkey(serializedPubkey: ArrayBuffer): ArrayBuffer;
verify(
signature: ArrayBuffer,
messageHash: ArrayBuffer,
pubkey: ArrayBuffer
): boolean;
};

recover

Recover raw public key from signature and message hash

Parameters

signature: The 64-byte signature

recoveryId: The recovery ID (0-3)

messageHash: The 32-byte message hash

Return

The recovered raw public key (64-bytes)

serializePubkey

Serialize a raw public key (64-bytes) to serialized format(compressed or uncompressed)

Parameters

pubkey: The raw public key to serialize

compressed: Whether to use compressed format (33 bytes) or uncompressed (65 bytes)

Return

The serialized public key (33 or 65 bytes)

parsePubkey

Parse a serialized public key(compressed or uncompressed) to raw public key. It is the reverse function of serializePubkey.

Parameters

serializedPubkey - The serialized format public key (33 or 65 bytes)

Return

The parsed raw public key (64-bytes)

verify

Verify an ECDSA signature

Parameters

signature: The 64-byte signature

messageHash: The 32-byte message hash

pubkey: The raw public key (64-bytes)

Return

True if signature is valid, false otherwise

Remarks

verify is more performant than recover. When the public key is available, verify is preferable.

However, in many cases, the public key is not stored directly but rather as its hash (for example, in the contract's args). In such cases, you need to:

  1. Use recover to extract the public key from the signature.
  2. Hash the public key.
  3. Compare it with the hash stored in the arguments.

Note on messageHash

Both verify and recover require the messageHash parameter. This is typically derived from the contract data and can be generated using the generateSighashAll function. It hashes the transaction using the TxHash and the witnesses.

In CKB contracts, the TxHash doesn't include Witnesses, but signature data must be placed inside the Witnesses. Therefore, the corresponding witness field is zeroed out before hashing.

Similarly, in tests, you must first create a transaction with an empty signature, then sign it, and finally insert the signature into the Witnesses.

Example

See the example in ckb-js-vm: secp256k1_blake160_lock And the corresponding test.

SMT

Sparse Merkle Tree implementation

Syntax

export class Smt {
constructor();
insert(key: ArrayBuffer, value: ArrayBuffer): void;
verify(root: ArrayBuffer, proof: ArrayBuffer): boolean;
}

insert

Insert a key-value pair into the tree

Parameters

  • key: The key to insert (32 bytes)
  • value: The value to insert (32 bytes)

verify

Verify a Merkle proof

Parameters

  • root: The 32-byte Merkle root
  • proof: The proof data

Return

True if proof is valid, false otherwise

parseExtJSON

Parse a JSON string with extended options.

Syntax

function parseExtJSON(json: string): Object;

Parameters

  • json: The JSON string to parse

Return

The parsed JSON object