Definition
OP_CHECKSIG (opcode 0xac) is the workhorse signature-verification operation in Bitcoin Script. It pops two items from the stack — a public key on top, and a signature below it — and checks whether that signature was produced by the private key corresponding to the public key, over the transaction data selected by the signature's SIGHASH flag. If the check succeeds it pushes true (1) onto the stack; otherwise it pushes false (0). Its strict variant, OP_CHECKSIGVERIFY, aborts the script immediately on failure instead of leaving a boolean.
Where it appears
OP_CHECKSIG sits at the end of nearly every common locking script. In a Pay-to-Public-Key-Hash (P2PKH) output the script OP_DUP OP_HASH160 <hash> OP_EQUALVERIFY OP_CHECKSIG first proves the spender's key hashes to the committed value, then confirms a valid signature over it. The much simpler Pay-to-Public-Key (P2PK) form is just <pubkey> OP_CHECKSIG.
What changed under Taproot
In legacy and SegWit v0 scripts, OP_CHECKSIG validates ECDSA signatures. Under Tapscript (BIP 342), the same opcode is redefined to validate 64-byte Schnorr signatures per BIP 340, and an empty signature is treated as a clean failure rather than an error — a property that makes batched and conditional spending paths far cleaner to construct.
OP_CHECKSIG is the foundation that opcodes like OP_CHECKSIGADD and the consensus structure of the sigop budget build upon, and it works alongside hashing primitives such as OP_HASH160 in standard address scripts.
SIGHASH Flags: Choosing What You Sign
A signature checked by OP_CHECKSIG never covers the raw transaction bytes; it covers a digest selected by the signature's appended SIGHASH flag. SIGHASH_ALL — the overwhelming default — commits to all inputs and outputs, freezing the transaction exactly as signed. SIGHASH_NONE signs the inputs but no outputs, and SIGHASH_SINGLE commits only to the output at the same index as the signed input. The ANYONECANPAY modifier restricts the commitment to just the input being signed, letting others add inputs later — the building block behind collaborative constructions like crowdfunding-style transactions and some CoinJoin variants. Powerful, and sharp: a carelessly chosen flag can leave parts of a transaction malleable by anyone, which is why wallets expose anything beyond SIGHASH_ALL reluctantly.
The Standardization Cleanups
OP_CHECKSIG's history is a case study in tightening consensus. Early ECDSA validation tolerated multiple encodings of the same signature, which meant third parties could tweak a signature's bytes without invalidating it — changing the transaction ID in flight. The fixes came in layers: BIP66 made strict DER encoding a consensus rule, the low-S rule eliminated the remaining “flip” malleability at the policy level, and SegWit ultimately moved signatures out of the txid calculation altogether. Each step traces back to the same lesson — that a verification opcode must accept exactly one encoding of a valid signature, or the network inherits every ambiguity as an attack surface.
Cost, Counting, and Why Verification Is Budgeted
Signature verification is the most expensive operation a script can demand, so consensus has always budgeted it: legacy rules count “sigops” per block against a hard cap, and Tapscript replaces crude counting with a per-input validation budget that scales with the input's size. This is not bureaucracy — it forecloses denial-of-service blocks stuffed with maximal verification work. It also shapes real designs: large multisig policies were historically expensive precisely because each key check consumed budget, one of the motivations for OP_CHECKSIGADD's batched approach and for aggregating keys before they ever reach the script. Every one of these checks ultimately gates the spend of a UTXO — OP_CHECKSIG is the lock on the money, and the budget keeps the locksmith honest. For anyone reading raw scripts, it is the opcode to anchor on: find the signature check, and the rest of the script is the story of what must be true before it runs.
In Simple Terms
OP_CHECKSIG (opcode 0xac) is the workhorse signature-verification operation in Bitcoin Script. It pops two items from the stack — a public key on top, and…
