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 signaturerecoveryId
: 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 serializecompressed
: 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 signaturemessageHash
: The 32-byte message hashpubkey
: The raw public key (64-bytes)
Return
boolean
: True if signature is valid, false otherwise
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:
- Use
recover
to extract the public key from the signature. - Hash the recovered public key.
- 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 rootproof
: 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