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.

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.

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

Parameters

  • data: The data to hash.

Return

  • Bytes: The 32-byte hash

Example

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

Secp256k1

Secp256k1 signature verification.

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

  • ArrayBuffer: 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

  • ArrayBuffer: 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

  • boolean: True if signature is valid, false otherwise
note

verify is more performant than recover, so it should be preferred whenever the public key is already available.

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

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

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

In CKB Scripts, 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, sign it, and finally insert the signature into the Witnesses.

Example

SMT

Sparse Merkle Tree implementation

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

  • boolean: True if proof is valid, false otherwise

parseExtJSON

Parse a JSON string with extended options.

function parseExtJSON(json: string): Object;

Parameters

  • json: The JSON string to parse

Return

  • Object: The parsed JSON object