Bitcoin Input Script: How scriptSig Unlocks UTXOs and What SegWit Changed
A Bitcoin input script, formally called the scriptSig, is the data a spending transaction provides to satisfy the locking conditions of a UTXO. Every transaction input references a previous output and must supply a valid scriptSig that, when evaluated against that output's scriptPubKey, resolves to TRUE on Bitcoin's stack machine. That is the core mechanism. What makes it technically interesting is how the execution model, the serialization format, and the very concept of an "input script" changed as Bitcoin evolved from P2PKH through SegWit and Taproot.
The Role of scriptSig in Transaction Structure
A Bitcoin transaction input contains four fields: the previous transaction ID (txid), the output index (vout), the scriptSig, and a sequence number. The scriptSig is the only field that varies based on the spending conditions being satisfied. Everything else is fixed once the UTXO being spent is identified.
For legacy transaction types, the scriptSig is a serialized sequence of data pushes. It does not contain logic or opcodes that perform operations; it only pushes data onto the stack. The actual logic resides in the scriptPubKey of the output being spent. This separation is deliberate: the output defines the rules, and the input provides the evidence. Bitcoin Script's interpreter runs the scriptSig pushes first, populating the stack, then executes the scriptPubKey opcodes against that stack state.
Understanding this execution order matters because it defines what a valid scriptSig must contain for each script type. The content of the input script is entirely determined by what the corresponding output script demands.
Two-Phase Stack Evaluation: How Input and Output Scripts Interact
The Bitcoin Script interpreter does not evaluate scriptSig and scriptPubKey independently. It runs them in sequence over a shared stack. Knowing the stack state at each step is the only way to verify that a given scriptSig is correct for a given scriptPubKey.
For a P2PKH output, the scriptPubKey is:
OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
The corresponding scriptSig must push exactly two items:
<DER-encoded signature> <compressed public key>
Execution across the shared stack proceeds as follows:
| Step | Operation | Stack State |
|---|---|---|
| 1 | Push signature (from scriptSig) | [sig] |
| 2 | Push pubKey (from scriptSig) | [sig, pubKey] |
| 3 | OP_DUP | [sig, pubKey, pubKey] |
| 4 | OP_HASH160 | [sig, pubKey, HASH160(pubKey)] |
| 5 | Push pubKeyHash (from scriptPubKey) | [sig, pubKey, HASH160(pubKey), expectedHash] |
| 6 | OP_EQUALVERIFY | [sig, pubKey] (aborts if hashes differ) |
| 7 | OP_CHECKSIG | [TRUE] |
The OP_EQUALVERIFY at step 6 is the critical gate. It confirms that the public key provided by the spender hashes to the value committed in the output. Only after that check passes does OP_CHECKSIG verify the cryptographic signature. A scriptSig that provides a valid signature under a different key will still fail here, because the key hash will not match.
One operational detail that matters in practice: the signature in a P2PKH scriptSig must be DER-encoded and must include a one-byte SIGHASH flag appended to the DER structure. The SIGHASH flag specifies which parts of the transaction are covered by the signature, with SIGHASH_ALL (0x01) being the standard. Scripts using other SIGHASH types (SIGHASH_NONE, SIGHASH_SINGLE, SIGHASH_ANYONECANPAY) commit to different transaction subsets, enabling more complex spending arrangements.
P2SH Inputs: The Redeem Script Push
P2SH (BIP-16, activated April 2012) changed the structure of the Bitcoin input script in a specific way. The output script for P2SH commits to a hash of a redeem script:
OP_HASH160 <scriptHash> OP_EQUAL
To spend a P2SH output, the scriptSig must include the full redeem script as its final push, preceded by the data required to satisfy that redeem script. For a 2-of-3 multisig P2SH output, the scriptSig looks like:
OP_0 <sig1> <sig2> <serialized redeem script>
The OP_0 at the beginning is the legacy dummy element required by OP_CHECKMULTISIG, which consumes one extra stack item due to an off-by-one implementation quirk in the original Bitcoin codebase.
The interpreter executes this in two phases. First, it verifies that the hash of the provided redeem script matches the hash in the scriptPubKey. Then it deserializes and executes the redeem script itself against the remaining stack items. The redeem script functions as a secondary scriptPubKey embedded within the input, evaluated at spend time. This is why P2SH is sometimes described as pushing the spending policy definition from the output creator to the spender: the output commits only to a hash, while the scriptSig carries and reveals the actual conditions.
Transaction Malleability: Why scriptSig Was the Problem
Transaction malleability refers to the ability to modify a transaction's byte representation without invalidating its signatures, thereby changing its txid. The scriptSig was the primary attack surface.
DER-encoded signatures have multiple valid encodings for the same cryptographic value. Before BIP-66 (activated July 2015), a third party could take a valid transaction, re-encode its signatures in an alternative DER format, broadcast the modified version, and cause the original transaction to be superseded by one with a different txid. The cryptographic validity was unchanged; only the byte representation differed. But because txids are SHA256d hashes of the raw transaction bytes, any byte change produces a different txid.
This was not merely a theoretical concern. Protocols that relied on txids before confirmation, including early Lightning Network designs and custodial exchange withdrawal tracking, were vulnerable. The Mt. Gox exchange cited transaction malleability in explaining discrepancies in its withdrawal records, though the full extent to which malleability versus internal accounting failures contributed remains disputed.
BIP-66 addressed DER encoding. But other scriptSig mutation vectors remained, including the ability to add extra data pushes that do not affect script evaluation outcome. SegWit addressed malleability structurally rather than incrementally.
How SegWit Restructured the Input Script (BIP-141)
SegWit's solution to malleability was architectural: move all witness data outside the transaction data used to compute the txid. For native SegWit input types (P2WPKH and P2WSH), the scriptSig field is empty. The data that would have occupied the scriptSig moves to a new per-input witness field, which is serialized separately and excluded from the legacy txid commitment.
This distinction is more precise than "scriptSig moved to witness." The witness field is not a serialized script. It is a structured vector of byte arrays, one per stack item, without the length-prefixed push opcodes that scriptSig serialization uses. A P2WPKH witness field contains exactly two items:
Witness item 0: <DER signature + SIGHASH flag>
Witness item 1: <compressed public key>
These are raw byte arrays. There are no push opcodes. The interpreter reads the witness items directly as stack inputs rather than executing push instructions to populate the stack. This structural difference closes a class of malleability vectors that existed because scriptSig push opcodes had multiple valid encodings for the same data.
For P2WPKH, the scriptPubKey is:
OP_1 <20-byte pubKeyHash>
Wait: that is P2TR. For P2WPKH the scriptPubKey is:
OP_0 <20-byte pubKeyHash>
The OP_0 version byte signals to the interpreter that this is a v0 witness program, triggering the SegWit evaluation path rather than the legacy Script interpreter. The interpreter then implicitly constructs the equivalent of a P2PKH check using the witness items, without the scriptSig playing any role.
P2SH-Wrapped SegWit: The Transitional Format
During the SegWit transition period, many wallets and exchanges supported P2SH-P2WPKH: a P2SH output whose redeem script is a SegWit witness program. This format exists because P2SH addresses ("3..." prefix) were universally supported before native bech32 addresses ("bc1..." prefix) were.
In this case, the scriptSig is not empty. It contains a single push: the witness program itself.
scriptSig: <OP_0 <20-byte pubKeyHash>>
This is the one modern context where a Bitcoin input script still carries data for a SegWit spend. The scriptSig push satisfies the P2SH hash check, and the actual signature and public key travel in the witness field as normal. Wallets that generate these inputs must correctly populate both fields; an input with only the scriptSig push and empty witness, or vice versa, will fail validation.
Taproot Inputs: scriptSig Is Always Empty
P2TR inputs (BIP-341, activated block 709,632, November 2021) always have an empty scriptSig. All spending data travels in the witness field regardless of whether the key path or script path is used.
For key path spends, the witness contains a single item: a 64-byte Schnorr signature (BIP-340). No public key is pushed; the spending key is derived from the output's tweaked public key, which the verifier reconstructs from the scriptPubKey.
For script path spends, the witness contains:
Witness item 0..n: inputs to satisfy the script
Witness item n+1: the script being executed
Witness item n+2: the control block (internal key + Merkle proof)
The control block is a new construct with no analog in legacy or SegWit input structures. It enables the verifier to confirm that the executed script is a leaf in the committed Merkle tree without revealing any other leaves. This is the mechanism that makes Taproot's privacy property work at the input level: a script path spend reveals one branch, not the policy.
The practical consequence for anyone constructing or parsing Bitcoin transactions is that inspecting the scriptSig field alone no longer tells you anything meaningful about how an input was authorized. For P2WPKH, P2WSH, and P2TR inputs, the scriptSig is empty bytes. All authorization evidence is in the witness.
What Input Script Analysis Reveals About Transaction History
Block explorers and chain analysis tools distinguish input types by inspecting the scriptSig structure and witness field together. A non-empty scriptSig with a specific pattern identifies legacy P2PKH or P2SH inputs. An empty scriptSig with a two-item witness identifies P2WPKH. An empty scriptSig with a multi-item witness ending in a script and control block identifies P2TR script path. This classification feeds into UTXO set analysis, fee estimation models, and privacy heuristics.
Fee rates also depend on input script type. Witness data is discounted in the weight calculation (1 weight unit per witness byte versus 4 weight units per non-witness byte). This means a P2WPKH input, where the authorization data is entirely in the witness, costs significantly less in fees than a P2PKH input carrying the same cryptographic material in the scriptSig. For those executing BTC transactions and comparing costs across input types, BYDFi's BTC/USDT spot market provides a practical environment for testing transaction fee behavior with live order book data.
The scriptSig in 2026: Legacy, Transitional, and Absent
The trajectory of the Bitcoin input script across protocol generations reflects a consistent direction: move authorization data out of the legacy serialization path, eliminate malleability vectors, and reduce on-chain footprint. P2PKH scriptSig fields remain common because legacy addresses have not disappeared from circulation. P2SH-wrapped SegWit inputs persist in wallets that have not upgraded to native bech32. But for new outputs created today, P2WPKH and P2TR dominate, and both types leave the scriptSig field empty.
Developers parsing raw transactions should treat a non-empty scriptSig as a signal that the input is either legacy, P2SH, or P2SH-wrapped SegWit, and adjust parsing logic accordingly. An assumption that scriptSig is always populated will silently misparse the majority of modern Bitcoin transactions.
BYDFi covers Bitcoin protocol mechanics alongside live network data, making it a useful reference for tracking how protocol-level changes translate into observable transaction patterns.
FAQ
What is the difference between scriptSig and witness data in a Bitcoin transaction?
scriptSig is a legacy field in the transaction input that carries unlocking data as serialized push opcodes. Witness data is a separate per-input structure introduced by SegWit (BIP-141) that carries the same authorization material as raw byte arrays, without push opcodes. The key difference is that witness data is excluded from the legacy txid computation, which eliminates the malleability vectors that existed in scriptSig serialization.
Why is the scriptSig empty for SegWit inputs?
Native SegWit inputs (P2WPKH, P2WSH, P2TR) place all spending data in the witness field, leaving scriptSig as zero bytes. This is required by BIP-141: the scriptSig for native SegWit inputs must be empty, and any non-empty scriptSig for these input types is invalid. The authorization data has not been removed; it has moved to a different serialization field with different weight calculation rules.
What is a redeem script and how does it appear in a P2SH input?
A redeem script is the full spending policy committed to by a P2SH output via its hash. At spend time, the scriptSig of a P2SH input must include the serialized redeem script as its final data push, preceded by the items needed to satisfy that script. The interpreter first verifies the redeem script hash matches the output, then evaluates the redeem script itself. The redeem script can encode multisig, timelocks, or any other valid Bitcoin Script logic.
Can a Bitcoin input script contain opcodes that perform operations?
In standard transaction types, no. The scriptSig is restricted to data push opcodes only (BIP-16, BIP-62). Permitting non-push opcodes in scriptSig would allow a spender to manipulate the stack state before scriptPubKey execution begins, creating potential vulnerabilities. Bitcoin Core has enforced push-only scriptSig as a relay policy since BIP-62 and as a consensus rule for P2SH inputs.
How does a Taproot script path spend differ from a legacy multisig input at the byte level?
A legacy 2-of-3 multisig P2SH input carries OP_0, two signatures, and the full redeem script in scriptSig, totaling several hundred bytes. A Taproot script path spend carries the satisfying inputs, the specific script branch, and a control block in the witness field, with witness discount applied. More importantly, unused script branches are never revealed. The on-chain footprint of the executed branch is often smaller than an equivalent P2SH input, and the privacy profile is categorically different: only one condition out of potentially many is visible.
This article is for educational purposes only and does not constitute financial advice.
0 Answer
Create Answer
Join BYDFi to Unlock More Opportunities!
Popular Questions
How to Use Bappam TV to Watch Telugu, Tamil, and Hindi Movies?
What Is the X Hamster Coin Price in Pakistan and Should You Be Paying Attention to HMSTR?
ISO 20022 Coins: What They Are, Which Cryptos Qualify, and Why It Matters for Global Finance
XMXXM X Stock Price — Market Data and Project Overview
How to Withdraw Money from Binance to a Bank Account in the UAE?