Skip to main content

Nostr Lock

Nostr lock is a Lock Script designed for interoperability with the

Nostr protocol. It uses Nostr events as witnesses to unlock CKB transactions. It is designed to improve user experience and simplify the development of Nostr-based dApps on CKB.

How It Works

Script Structure

{
hash_type: "data2"
code_hash: "<NOSTR_LOCK_DATA_HASH>"
args: "<PoW difficulty, 1 byte> <schnorr pubkey hash, 20 bytes>"
}
  • If PoW difficulty = 0: Unlocking is done via public key signature verifaction
  • If PoW difficulty ≠ 0: The public key hash is not used and should be all zero, and another unlock method, NIP-13, is used

Unlocking

There are 2 methods to unlock nostr lock script: by key(PoW difficulty is zero) or by PoW difficulty(PoW difficulty is non-zero).

A 32-byte sighash_all message can be calculated via ckbhash with following data:

  • Transaction hash
  • Witness length and content in same script group covered by inputs, excluding lock field
  • Other witness length and content that not covered by inputs

A reference implementation in C can be found here.

The event in witness has following format:

{
"id": <32-bytes lowercase hex-encoded sha256 of the serialized event data>,
"pubkey": <32-bytes lowercase hex-encoded public key of the event creator>,
"created_at": <unix timestamp in seconds>,
"kind": <integer between 0 and 65535>,
"tags": [
[<arbitrary string>...],
// ...
],
"content": <arbitrary string>,
"sig": <64-bytes lowercase hex of the signature of the sha256 hash of the serialized event data, which is the same as the "id" field>
}

Each tag is an array of one or more strings, with some conventions around them. The first element of the tag array is referred to as the tag name or key and the second as the tag value.

Rule 1: A tag key with "ckb_sighash_all" must be present. Its corresponding tag value must be equal to sighash_all in hexadecimal string format.

Here is an example of such tag:

[
"ckb_sighash_all",
"00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
]

Rule 2: The id in the event is calculated based on NIP-01.

Rule 3: The kind in the event should be equal to 23334. The content in the event should be identical to following fixed string:

"Signing a CKB transaction\n\nIMPORTANT: Please verify the integrity and authenticity of connected Nostr client before signing this message\n"

These 3 rules(1,2,3) should be followed by both of the two unlocking methods described below.

Unlocking by PoW

When PoW difficulty is non-zero, this unlocking method is used. It follows NIP-13.

Rule 4: A tag key with nonce must be present. Its corresponding tag value can be any string. This tag value will be mutated to mimic mining behavior.

Rule 5: The third entry to the nonce tag should contain the PoW difficulty in decimal string described in script args.

Rule 6: The id in event should has a difficulty no less than PoW difficulty specified in script args.

Rule 7: The pubkey in script args should be all zeros.

When the rules above(1,2,3,4,5,6,7) are met, the validation is successful.

The sighash_all is affected by the length of the event in the witness. It is suggested to reserve the nonce tag value as a very long string, like the example below:

["nonce", "000000000000000000000000000000000000", "24"]

For each mining attempt, only mutate the long string while keeping the length unchanged.

Unlocking by Key

When PoW difficulty is zero, this unlocking method is used.

Rule 8: The blake160 of binary format of pubkey field in event should be equal to schnorr pubkey hash in script args. The pubkey in hexadecimal string should be converted into binary first.

Rule 9: The sig field, along with the pubkey and id fields in the event, can be validated via Schnorr verification.

When the rules above(1,2,3,8,9) are met, the validation is successful.

Deployment

  • Mainnet
parametervalue
code_hash0x641a89ad2f77721b803cd50d01351c1f308444072d5fa20088567196c0574c68
hash_typetype
tx_hash0x1911208b136957d5f7c1708a8835edfe8ae1d02700d5cb2c3a6aacf4d5906306
index0x0
dep_typecode
  • Testnet
parametervalue
code_hash0x6ae5ee0cb887b2df5a9a18137315b9bdc55be8d52637b2de0624092d5f0c91d5
hash_typetype
tx_hash0xa2a434dcdbe280b9ed75bb7d6c7d68186a842456aba0fc506657dc5ed7c01d68
index0x0
dep_typecode