<blockquote>
<p>My question is: in those old days, how did we know that we had to run a P2PKH to validate the transaction?</p>
</blockquote>
<p>We didn't &quot;know that we had to run...&quot; Rather, in the old days, one would pay to public key instead of pay to public key <em>hash</em>. This made the validation scripts look simple.</p>
<p>The combined validation script for P2PK literally just looks like:</p>
<pre><code>(sig) (pubkey) (checksig)
</code></pre>
<p>Contrast this with the P2PKH combined validation script, which looks like:</p>
<pre><code>(sig) (pubkey) (dup) (hash160) (pubkeyhash) (equal?) (checksig),
</code></pre>
<p>where all the stuff in the middle of the P2PKH script, between (pubkey) and (checksig), is basically just to go from the public key hash (which is the only thing the person creating the transaction knows) to the actual public key (stored on the sigScript side for P2PKH).</p>
<p>So, you can tell them apart because the validation scripts look different. For example, you could look for the &quot;OP_DUP OP_HASH160 public-key-hash OP_EQUAL&quot; sequence.</p>

CC BY-SA 4.0
2021-11-20T19:34:22.580Z
Thanks for the explanation!
StashOfCode
CC BY-SA 4.0
2021-11-22T17:44:11.280Z
P2PK was used with P2IP, meaning nobody had to interact with raw public keys. An exception is block rewards, which remained P2PK long after that went out of fashion.
Claris
CC BY-SA 4.0
2021-11-22T17:51:15.443Z
Support for P2PKH addresses was present in the first released Bitcoin code. And I think this answer misses the most important point: the script interpreter doesn't _have to_ tell scripts apart (and doesn't). It just executes them, indiscriminately.
Pieter Wuille
CC BY-SA 4.0
2021-11-22T19:44:10.687Z
Yeah, that's true. I guess I didn't parse the question fully. (But apparently well enough to answer the question OP must have had in mind.) I didn't mean to imply that the script interpreter has to tell the difference--just that OP can tell the scripts apart using the suggested method. I edited my answer.
hft
CC BY-SA 4.0
2021-11-20T01:59:41.393Z
2021-11-24T21:03:57.000Z
2021-11-24T21:03:57.000Z
hft
<blockquote>
<p>My question is: in those old days, how did we know that we had to run a P2PKH to validate the transaction?</p>
</blockquote>
<p>We didn't, and we don't.</p>
<p>The validation code simply executes the scripts, instruction by instruction. The fact that we (now) call these particular scripts P2PK or P2PKH scripts is just a human designation, that determines how they get shown by wallets. But the validation code doesn't care.</p>
<p>Perhaps this helps: script is a programming language. Any time a transaction output was created, the wallet would construct in the transaction outputs a little program that determined how that output can be spent. Most commonly, the transaction output would be one of a very small number of specific types (e.g. P2PKH), which we've given special names. But transactions weren't, and aren't, restricted to just those two types. Scripts could use whatever opcodes they wanted, to encode whatever conditions they wanted.</p>
<hr />
<p>Now, some things have changed since &quot;the old days&quot;, which do factor in here:</p>
<ul>
<li>Very early on, the scriptSig (unlocking script in the input) and the scriptPubKey (locking script in the output) were concatenated, and then executed as one, together. This is no longer the case since this was discovered to be trivially insecure, in 2010. Now the scriptSig is executed first, and then the scriptPubKey is executed separately, copying just the final state of the first as initial state for the second.</li>
<li>The introduction of P2SH in 2012 (BIP16) <strong>did</strong> actually introduce a special pattern that validation nodes do specifically recognize. BIP16's rule in short is &quot;IF the scriptPubKey exactly matches this template, some additional validation rules are triggered&quot;. That's because P2SH moved the actually executed script logic from the scriptPubKey to the scriptSig, and the scriptPubKey only contains a magic hash of the real script, redirecting execution to the script in the scriptSig. So since P2SH, senders don't actually &quot;know&quot; what script they are sending to anymore, only its hash.</li>
<li>Something similar to P2SH was done again in 2017 with the introduction of segwit (BIP141).</li>
<li>There used to be support for pay-to-IP addresses, where your node would literally connect to that IP, ask it for a scriptPubKey to send to, and then construct a transaction that paid that did. This was very insecure (no encryption or authentication, just whatever the IP responds), and has long since been removed. Such pay-to-IP scripts were generally P2PK ones.</li>
</ul>

CC BY-SA 4.0
2021-11-22T18:30:25.007Z
2021-11-22T19:18:45.323Z
2021-11-22T19:18:45.323Z
Pieter Wuille
<p>I'm trying to understand how to validate the first non-coinbase transaction, that is transaction 1 of block 169, as it was validated in the old days.</p>
<p>This transaction has one input, which decoded ScriptSig is exactly:</p>
<blockquote>
<p>PUSH (71 bytes: 70 bytes ECDSA signature ANS.1 in DER format and trailing SIGHASH_ALL byte)</p>
</blockquote>
<p>This input refers to output 0 of transaction 0 of block 9, which ScriptPubKey is exactly:</p>
<blockquote>
<p>PUSH (65 bytes: not-compressed flag byte and 64 public key x and y)
OP_CHECKSIG</p>
</blockquote>
<p>My question is: in those old days, how did we know that we had to run a P2PKH to validate the transaction? Simply put, did we just concatenate ScriptSig and ScriptPubKey...:</p>
<blockquote>
<p>PUSH (71 bytes) PUSH (65 bytes) OP_CHECKSIG</p>
</blockquote>
<p>..and run the resulting script (that is: running OP_CHECKSIG as it is coded in EvalScript() in src/interpreter.cpp of the Bitcoin Core), which was supposed to be a P2PKH script, or did we create a more elaborate script from those scripts to validate?</p>
<p>Because nowadays, after some BIPs (witnesses, and so on), the P2PKH script looks more elaborated:</p>
<blockquote>
<p>OP_DUP OP_HASH160  OP_EQUALVERIFY OP_CHECKSIG</p>
</blockquote>
<p><strong>Addendum</strong></p>
<p>For those like me who are interested in learning about the bitcoin by coding it from scratch and using the first blocks as a data reference, I later found <a href="https://www.oreilly.com/library/view/programming-bitcoin/9781492031482/" rel="nofollow noreferrer">this very good book</a>. You may also find interesting to check the first Bitcoin code <a href="https://satoshi.nakamotoinstitute.org/code/" rel="nofollow noreferrer">here</a>.</p>

CC BY-SA 4.0
2021-11-19T16:49:32.723Z
The input on transaction f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16 is P2PK not P2PKH.
Murch
CC BY-SA 4.0
2021-11-19T18:09:40.377Z
This really has absolutely nothing to do with any differences in modern bitcoin, it’s just how it has always been. That’s a pay2ip transaction and they weren’t P2PKH “offline addresses” in the nomenclature of the time.
Claris
CC BY-SA 4.0
2021-11-19T18:58:08.427Z
Thanks, it's more clear now. A follow-up: nowadays, what would be the criteria for a node to identify this transaction as a P2PK transaction ? The length of the scripts ? The contents of the scripts ?
StashOfCode
CC BY-SA 4.0
2021-11-20T02:04:38.657Z
You could tell because there would be no need for the "OP_DUP OP_HASH160 Public-Key-Hash OP_EQUAL" sequence.
hft
CC BY-SA 4.0
2021-11-22T17:42:15.457Z
In the original Bitcoin, you sent money by putting an IP address in the "to" field, your node connected to that IP address directly and requested a public key, and then you paid to that public key. Addresses were originally "offline addresses" for when the person wasn't running a node at the time, or for some other reason it wasn't possible to use this method.
Claris
CC BY-SA 4.0
2021-11-22T17:58:23.507Z
@StashOfCode Nodes **don't** classify transactions or inputs as P2PK or P2PKH or whatever. That's something we do as humans, because some have well-defined address representations. But nodes don't care - they just execute the scripts as they are told.
Pieter Wuille
<transactions><transaction-verification><validation><p2pk>
Block 170 transaction validation in the old days
StashOfCode
# Block 170 transaction validation in the old days

(Asked by: username_0 on 2021-11-19)

I'm trying to understand how to validate the first non-coinbase transaction, that is transaction 1 of block 169, as it was validated in the old days.

This transaction has one input, which decoded ScriptSig is exactly:

> PUSH (71 bytes: 70 bytes ECDSA signature ANS.1 in DER format and trailing SIGHASH\_ALL byte)

This input refers to output 0 of transaction 0 of block 9, which ScriptPubKey is exactly:

> PUSH (65 bytes: not-compressed flag byte and 64 public key x and y)
> OP\_CHECKSIG

My question is: in those old days, how did we know that we had to run a P2PKH to validate the transaction? Simply put, did we just concatenate ScriptSig and ScriptPubKey...:

> PUSH (71 bytes) PUSH (65 bytes) OP\_CHECKSIG

..and run the resulting script (that is: running OP\_CHECKSIG as it is coded in EvalScript() in src/interpreter.cpp of the Bitcoin Core), which was supposed to be a P2PKH script, or did we create a more elaborate script from those scripts to validate?

Because nowadays, after some BIPs (witnesses, and so on), the P2PKH script looks more elaborated:

> OP\_DUP OP\_HASH160 OP\_EQUALVERIFY OP\_CHECKSIG

**Addendum**

For those like me who are interested in learning about the bitcoin by coding it from scratch and using the first blocks as a data reference, I later found [this very good book](https://www.oreilly.com/library/view/programming-bitcoin/9781492031482/). You may also find interesting to check the first Bitcoin code [here](https://satoshi.nakamotoinstitute.org/code/).

**Tags:** transactions, transaction-verification, validation, p2pk

> **Comments:**
> **username_1**: The input on transaction f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16 is P2PK not P2PKH.  
> **username_2**: This really has absolutely nothing to do with any differences in modern bitcoin, it’s just how it has always been. That’s a pay2ip transaction and they weren’t P2PKH “offline addresses” in the nomenclature of the time.  
> **username_0**: Thanks, it's more clear now. A follow-up: nowadays, what would be the criteria for a node to identify this transaction as a P2PK transaction ? The length of the scripts ? The contents of the scripts ?  
> **username_3**: You could tell because there would be no need for the "OP_DUP OP_HASH160 Public-Key-Hash OP_EQUAL" sequence.  
> **username_2**: In the original Bitcoin, you sent money by putting an IP address in the "to" field, your node connected to that IP address directly and requested a public key, and then you paid to that public key. Addresses were originally "offline addresses" for when the person wasn't running a node at the time, or for some other reason it wasn't possible to use this method.  
> **username_4**: @username_0 Nodes **don't** classify transactions or inputs as P2PK or P2PKH or whatever. That's something we do as humans, because some have well-defined address representations. But nodes don't care - they just execute the scripts as they are told.  

---

## 2 answers

### Answer by username_3 on 2021-11-20. Score: 0 | Accepted answer

> My question is: in those old days, how did we know that we had to run a P2PKH to validate the transaction?

We didn't "know that we had to run..." Rather, in the old days, one would pay to public key instead of pay to public key *hash*. This made the validation scripts look simple.

The combined validation script for P2PK literally just looks like:

```
(sig) (pubkey) (checksig)

```

Contrast this with the P2PKH combined validation script, which looks like:

```
(sig) (pubkey) (dup) (hash160) (pubkeyhash) (equal?) (checksig),

```

where all the stuff in the middle of the P2PKH script, between (pubkey) and (checksig), is basically just to go from the public key hash (which is the only thing the person creating the transaction knows) to the actual public key (stored on the sigScript side for P2PKH).

So, you can tell them apart because the validation scripts look different. For example, you could look for the "OP\_DUP OP\_HASH160 public-key-hash OP\_EQUAL" sequence.

> **Comments:**
> **username_0**: Thanks for the explanation!  
> **username_2**: P2PK was used with P2IP, meaning nobody had to interact with raw public keys. An exception is block rewards, which remained P2PK long after that went out of fashion.  
> **username_4**: Support for P2PKH addresses was present in the first released Bitcoin code. And I think this answer misses the most important point: the script interpreter doesn't _have to_ tell scripts apart (and doesn't). It just executes them, indiscriminately.  
> **username_3**: Yeah, that's true. I guess I didn't parse the question fully. (But apparently well enough to answer the question OP must have had in mind.) I didn't mean to imply that the script interpreter has to tell the difference--just that OP can tell the scripts apart using the suggested method. I edited my answer.  

---

### Answer by username_4 on 2021-11-22. Score: 1

> My question is: in those old days, how did we know that we had to run a P2PKH to validate the transaction?

We didn't, and we don't.

The validation code simply executes the scripts, instruction by instruction. The fact that we (now) call these particular scripts P2PK or P2PKH scripts is just a human designation, that determines how they get shown by wallets. But the validation code doesn't care.

Perhaps this helps: script is a programming language. Any time a transaction output was created, the wallet would construct in the transaction outputs a little program that determined how that output can be spent. Most commonly, the transaction output would be one of a very small number of specific types (e.g. P2PKH), which we've given special names. But transactions weren't, and aren't, restricted to just those two types. Scripts could use whatever opcodes they wanted, to encode whatever conditions they wanted.

---

Now, some things have changed since "the old days", which do factor in here:

* Very early on, the scriptSig (unlocking script in the input) and the scriptPubKey (locking script in the output) were concatenated, and then executed as one, together. This is no longer the case since this was discovered to be trivially insecure, in 2010. Now the scriptSig is executed first, and then the scriptPubKey is executed separately, copying just the final state of the first as initial state for the second.
* The introduction of P2SH in 2012 (BIP16) **did** actually introduce a special pattern that validation nodes do specifically recognize. BIP16's rule in short is "IF the scriptPubKey exactly matches this template, some additional validation rules are triggered". That's because P2SH moved the actually executed script logic from the scriptPubKey to the scriptSig, and the scriptPubKey only contains a magic hash of the real script, redirecting execution to the script in the scriptSig. So since P2SH, senders don't actually "know" what script they are sending to anymore, only its hash.
* Something similar to P2SH was done again in 2017 with the introduction of segwit (BIP141).
* There used to be support for pay-to-IP addresses, where your node would literally connect to that IP, ask it for a scriptPubKey to send to, and then construct a transaction that paid that did. This was very insecure (no encryption or authentication, just whatever the IP responds), and has long since been removed. Such pay-to-IP scripts were generally P2PK ones.


---

