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