Toccata 101 · Part 2 · card 1

Kaspa script: Programs carried by outputs

What a script is made of

script

A script is a list of instructions that a computer runs from top to bottom to complete a task. Most of them are text files. A Kaspa script is not, it is a string of bytes sitting inside a transaction.

Programs in general are built from these. A Kaspa script uses four of them.

bitsbytescharacters stringslinestokens namesnumberssymbols expressionsstatementsblocks

A valid Kaspa lock can be a single byte, 0x51, one instruction that is enough to let a UTXO be spent.

Basic transaction scripts

For every input a node gets, it creates a fresh new stack. In this stack the node verifies the input is valid.

How?

A UTXO carries a lock, the script_public_key. It was written by the wallet when the output was created.
On a normal wallet coin it's 34 bytes:

script_public_key1 byte32 bytes1 byte

2071ad52824cc1fd78c096dfadfa3482d57a4d33a8015b80c8dfcf2946dabfd9b3ac

Written as it really is. The 0x in the list above is only a way of writing that says "this is hexadecimal". The script itself carries the bytes without it.

The spend carries an unlock, the signature_script. The spender writes it on that input.
For this we have 66 bytes:

signature_script1 byte64 bytes1 byte

417cb79c11bfdda0776db020638c10d5a997b273b2a5c2e2ae9c00a0de442334cbe2edebc2cc7836f649e67cb7ac7a92c7f4ce990e130844b5f952a1465f868c9301

These 2 scripts exist specifically for this purpose, and written automatically by the wallet. The stack is thrown away after the verification is cleared.

Hexadecimal

Quick crash course on how computers hold information

Computer chips contain billions of transistors. Transistors are tiny switches, a few of them together hold one bit of data.
A bit is a digit, a 1 or a 0, where 1 means ON and 0 means OFF. For the sake of this simplification, let's say transistors move information on 1 and halt it on 0.

A byte is 8 bits. 11111111 and 00000000 both represent one byte. It can be any combination of eight 0s and 1s.
A byte can be used to represent a letter or a symbol. So you can actually write and talk using zeros and ones! But to type a simple "Hey!", you would need a whopping 32 bits (01001000 01100101 01111001 00100001 translates to Hey!), not something anything but a computer can work with. Humans did human things, and compressed these bytes into a 16 digit system they can work with.

Why 16? A power of 2

It's a math thing: a bit has 2 modes (0, 1). Take half a byte, 4 bits, and there are exactly 16 (2 × 2 × 2 × 2) different ways to order them .

To represent each way, humans picked 16 digits. The most comfortable digits were: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F. Now you can write "Hey!" using only 8 characters (48 65 79 21 translates to Hey!) instead of 32, and you can shrink every huge string of bits like this.

In our case

0x is a flag that tells whoever reads the bytes: "the characters coming next are in hexadecimal format." Meaning:

0x20 - 0x read in hex: 2, 0 Two halves of one byte - 0010, 0000.
0xac is one byte, 1010 1100.
0x41 is one byte, 0100 0001.
0x01 is one byte, 0000 0001.
0x51 is one byte, 0101 0001.

To combine this logic together, understand this:
20 in this system is 32 in ordinary counting, and 41 is 65. That is why 0x20 says "the next 32 bytes" and 0x41 says "the next 65 bytes", the byte is the count itself. Try playing with this hexadecimal box to experiment with the idea. Can you decode this phrase?

01011001 01101111 01101110 01100001 01110100 01100001 01101110 00100000 01101001 01110011 00100000 01010011 01100001 01110100 01101111 01110011 01101000 01101001

from
to
result

KISS: Keep It Short, Stupid

Sources

In rusty-kaspa, an input is checked by running two scripts in order on one stack that is created for that input and discarded after it: the input's signature script, then the script public key of the UTXO it spends. The signature script may hold only push instructions (crypto/txscript/src/lib.rs, from_transaction_input, execute_inner, execute_script). A push instruction is the number of bytes that follow it, for every length from 1 to 75, and OpCheckSig is 0xac, OpTrue is 0x51 (crypto/txscript/src/opcodes/mod.rs). The standard key lock is OpData32 key OpCheckSig (crypto/txscript/src/standard.rs). A single 0x51 lock is valid for consensus and non standard for a node's mempool, which refuses both the transaction that creates such an output and the one that spends it (mining/src/mempool/check_transaction_standard.rs). Read at release v2.0.1. The bytes on this page are the real ones from 60a2f205…f145914, read from api.kaspa.org on 12 September 2026. The letters and symbols a byte stands for in the hexadecimal window, Hey! and the phrase to decode, follow the ASCII table, one byte per character.