<blockquote>
  <p>From what I understand, a non-SegWit P2PH address is obtained by hashing the redeem script</p>
</blockquote>

<h2>ScriptPubKey</h2>

<p>I had the same problem and I have resolved it with this C++ code, and I think this code is self-describing.
If you have the ScriptPubKey extract from the blk file, this is code calculate the correct address P2SH.</p>

<pre><code>string opcode = hex.substr(0, 2);
int32_t optValue = std::stoul(opcode, nullptr, 16);
auto optMap = bitcoinOpCode.opCodeList.find(optValue);
string optCode = optMap-&gt;second;
if (optCode == "OP_HASH160") {
 cout &lt;&lt; "Finded the P2SH";
 string scriptHash = hex.substr(4, hex.length() - 6);
 Bytes bytes = hexBytes(scriptHash.c_str());
 bytes.insert(bytes.begin(), 1, 5);

 string address = EncodeBase58Check(bytes);
 cout &lt;&lt; "P2SH addresss is " &lt;&lt; address;
 string endOpCode = hex.substr(hex.length() - 2, 2);
 int32_t optValueEnd = std::stoul(endOpCode, nullptr, 16);
 auto optMapEnd = bitcoinOpCode.opCodeList.find(optValueEnd);
 string optCodeEnd = optMapEnd-&gt;second;
 if(optCodeEnd == "OP_EQUAL"){
   cout &lt;&lt; "\n\t----------------------------------------| Results |-----------------------------------" &lt;&lt; endl;
   cout &lt;&lt; "\t                               ###  Script PUB KEY HASH  ###                            " &lt;&lt; endl;
   cout &lt;&lt; "\t" &lt;&lt; optCode &lt;&lt; " "  &lt;&lt; scriptHash &lt;&lt; " " &lt;&lt; optCodeEnd &lt;&lt; endl;
   cout &lt;&lt; "\t                                                                                      " &lt;&lt; endl;
   cout &lt;&lt; "\t The public key: " &lt;&lt; address &lt;&lt; "                                   " &lt;&lt; endl;
   cout &lt;&lt; endl;
   cout &lt;&lt; "\t https://blockstream.info/address/" &lt;&lt; address &lt;&lt; endl;
   cout &lt;&lt; "\t______________________________________________________________________________________"&lt;&lt; endl;
  }
}
</code></pre>

<p>how I do calculate the correct address?</p>

<p>You know the complete P2SH, an example this</p>

<pre><code>OP_0 &lt;A Signature&gt; &lt;B Signature&gt; OP_2 &lt;Public key A&gt; &lt;Public key B&gt;
&lt;Public key C&gt; OP_3 OP_CHECKMULTISIG
OP_HASH160 &lt;ScriptSig Hash&gt; OP_EQUAL
</code></pre>

<p>Inside the this code you can find the scriptSig, so this:</p>

<pre><code>OP_0 &lt;A Signature&gt; &lt;B Signature&gt; OP_2 &lt;Public key A&gt; &lt;Public key B&gt;
&lt;Public key C&gt; OP_3 OP_CHECKMULTISIG
</code></pre>

<p>and the ScriptPubKey, so this:</p>

<pre><code>OP_HASH160 &lt;ScriptSig Hash&gt; OP_EQUAL
</code></pre>

<p>With my code, I work only with the scriptPubKey and I found the dimension with the following mode</p>

<pre><code>OP_HASH160 = hex.substr(0, 2);
&lt;ScriptSig Hash&gt; = hex.substr(4, hex.length() - 6);
OP_EQUAL = hex.substr(hex.length() - 2, 2);
</code></pre>

<p>on the data hex <code>&lt;ScriptSig Hash&gt;</code> I can run the EncodeBase58Check encoding, I have to change the code of bitcoin core(<a href="https://github.com/bitcoin/bitcoin/blob/master/src/base58.h" rel="nofollow noreferrer">this</a>) for change the hash library.
Inside the bitcoin core code you can find the correct execution of EncodeBase58 (<a href="https://github.com/bitcoin/bitcoin/blob/b7bc9b8330096d1f4f1fa563b855b88da425226e/src/base58.cpp#L134" rel="nofollow noreferrer">here</a>)</p>

<p>Another important code is this to insert the mainet flag inside the byte.</p>

<pre><code>bytes.insert(bytes.begin(), 1, 5);
</code></pre>

<h2>ScriptSig</h2>

<p>The scriptSig inside is composed to two component, so:</p>

<ul>
<li><p>the Sighnature: <code>OP_0 &lt;A Signature&gt; &lt;B Signature&gt;</code></p></li>
<li><p>the program control: <code>OP_2 &lt;Public key A&gt; &lt;Public key B&gt;
   &lt;Public key C&gt; OP_3 OP_CHECKMULTISIG</code></p></li>
</ul>

<p>I didn't have to try to decode with code the script sig but I think this is more difficult to others because the dimension is not standard because the program control is a script P2MS and this script has more combination.
I can suggest you create a decompiler intelligent for scriptSig because if you get the OP_2 hex inside the script you can read 2 signature but it is possible to get the OP_14 and your parser must be read 14 signature.
I can suggest you to start decompiler the ScriptSig to end because you know the dimension end hexadecimal.</p>

<p>When you have extracted the pubkey and if you want an address bitcoin you can read my <a href="https://bitcoin.stackexchange.com/questions/91473/how-extracting-address-bitcoin-to-script-multi-signature">question here</a></p>

CC BY-SA 4.0
2019-11-21T11:15:16.233Z
Thanks a lot for the detailed algorithm explanation, but my question was more about the standard ScriptSig follows, creating a loop that extracts the redeem script is not hard, yet I must be sure the format is always of the form:

<OP_0><{data1 size}{data1}><{data2 size}{data2}>...<OP_1><OP-PUSHDATA1><redeemScript>
iMil
CC BY-SA 4.0
2019-11-21T14:04:47.793Z
@iMil No because the signature depends on the combination of P2MS script, I have mentioned this argument in the ScriptSig section.
vincenzopalazzo
CC BY-SA 4.0
2019-11-21T09:21:29.173Z
2019-11-21T11:01:40.533Z
2019-11-21T11:01:40.533Z
vincenzopalazzo
<p>A P2SH locking script on an output has the following structure:</p>
<pre><code>         Output (scriptPubKey)
--------------------------------
OP_HASH160 &lt;scripthash&gt; OP_EQUAL
</code></pre>
<p>The address comes for this comes from the <code>&lt;scripthash&gt;</code>, creating a &quot;3address&quot;. This is the standard format for a P2SH, so you can identify it and work out the address from there.</p>
<p>That's all you need to get the address, but explaining a little further...</p>
<hr />
<p>Interestingly, the <code>&lt;scripthash&gt;</code> can be the hash of any kind of script you like. However, it's most commonly used for putting the hash of a P2MS in there. So when you come to unlock this script, the <code>scriptSig</code> may look something like this:</p>
<pre><code>          Input (scriptSig)
-------------------------------------------
OP_0 &lt;signature&gt; &lt;signature&gt; &lt;redeemscript&gt;
</code></pre>
<p>What you're seeing here is basically a complete script for what would have been a classic P2MS <em>scriptPubKey</em> and <em>scriptSig</em>, where the <code>&lt;redeemscript&gt;</code> is a data push of a normal script with opcodes.</p>
<pre><code>          Input (scriptSig)
-------------------------------------------
              scriptSig       scriptPubKey (as a data push)
---------------------------- -------------- 
OP_0 &lt;signature&gt; &lt;signature&gt; &lt;redeemscript&gt;
</code></pre>
<p>With P2SH it's like you have a complete scriptSig+scriptPubKey contained inside the scriptSig, and it can contain any script so it <strong>doesn't have a standard form</strong>.</p>
<p>Anyway, this complete P2MS script starts with a <code>OP_O</code>, because all P2MS scriptSigs have to start with that due to the off-by-one bug that the <code>OP_CHECKMULTISIG</code> opcode. This is nothing to do with the <code>OP_0</code> you get in Segwit scriptPubKeys.</p>
<p>When this script executes, the <code>&lt;redeemscript&gt;</code> will firstly be hashed and compared with the <code>&lt;scripthash&gt;</code> in the output to make sure it matches. If it does, the <code>&lt;redeemscript&gt;</code> is deserialized to see the opcodes:</p>
<pre><code>      Input (scriptSig)
-------------------------------------------
              scriptSig       scriptPubKey
---------------------------- -------------- 
OP_0 &lt;signature&gt; &lt;signature&gt; OP_2 &lt;pubkey&gt; &lt;pubkey&gt; &lt;pubkey&gt; OP_3 OP_CHECKMULTISIG
</code></pre>
<p>So this is what you would see on a classic P2MS output, but this just happened to be wrapped in a P2SH script because it's cheaper for the sender. So this is the standard format for a P2MS: (<code>OP_N &lt;pubkeys...&gt; OP_M OP_CHECKMULTISIG</code>).</p>
<p>This particular scriptPubKey does not actually have an address. There are <code>&lt;pubkeys&gt;</code> in there, but it wouldn't be technically correct to say those <code>&lt;pubkeys&gt;</code> have an &quot;address&quot;, because an address refers to a specific locking script pattern, and is not just the friendlier version of any <code>&lt;pubkey&gt;</code>.</p>
<p><strong>Examples:</strong></p>
<ul>
<li>P2SH with a P2MS inside it: <a href="https://learnmeabitcoin.com/explorer/transaction/d3adb18d5e118bb856fbea4b1af936602454b44a98fc6c823aedc858b491fc13/output/0#scriptPubKey" rel="nofollow noreferrer">https://learnmeabitcoin.com/explorer/transaction/d3adb18d5e118bb856fbea4b1af936602454b44a98fc6c823aedc858b491fc13/output/0#scriptPubKey</a></li>
<li>P2SH with a non-standard script inside it: <a href="https://learnmeabitcoin.com/explorer/transaction/7d46745463a28049cb93d2c964320912d9c296c1038cb24cc3716255c397a87f/output/1#scriptPubKey" rel="nofollow noreferrer">https://learnmeabitcoin.com/explorer/transaction/7d46745463a28049cb93d2c964320912d9c296c1038cb24cc3716255c397a87f/output/1#scriptPubKey</a></li>
</ul>
<p><strong>Links:</strong></p>
<ul>
<li><a href="https://learnmeabitcoin.com/guide/p2sh" rel="nofollow noreferrer">https://learnmeabitcoin.com/guide/p2sh</a></li>
<li><a href="https://learnmeabitcoin.com/guide/p2ms" rel="nofollow noreferrer">https://learnmeabitcoin.com/guide/p2ms</a></li>
<li><a href="https://learnmeabitcoin.com/guide/address" rel="nofollow noreferrer">https://learnmeabitcoin.com/guide/address</a></li>
</ul>

CC BY-SA 4.0
2021-01-17T15:52:02.947Z
Thank you for this great answer! One puzzle piece is missing for me: How does the validator decide where the redeem script starts so that it can hash it?
schmijos
CC BY-SA 4.0
2021-01-18T22:57:49.270Z
The <redeemscript> is the last item in the `scriptSig` (it's actually a data push and not individual opcodes), so you can just look at that last item.
inersha
CC BY-SA 4.0
2021-01-19T08:43:39.240Z
Ok, I repeat to see if I understood it:
So the the <redeemscript> is pushed bytecode. So it's on top of the stack when the <scriptSig> has been executed (pushes only). So by convention we interpret the top stack element as Bitcoin Script and load it into a new script stack for execution if the corresponding UXTO was a P2SH?
schmijos
CC BY-SA 4.0
2021-01-20T14:50:30.190Z
@schmijos Yes that's correct.
inersha
CC BY-SA 4.0
2019-11-22T13:13:25.407Z
2021-01-18T23:03:44.313Z
2021-01-18T23:03:44.313Z
inersha
<p>I'm working on a bitcoin block explorer in <em>golang</em>, in which I'd like to gather as much informations as possible about transactions.<br>
I am able to extract addresses from every type of <em>output</em>, and mostly every type of <em>input</em>, except I am struggling to find clear <code>P2SH</code> documentation.<br>
<em>BIP16</em> doesn't say much about non-SegWit <code>P2SH</code> byte structure. I read many examples where <code>OP_0</code> is the first byte, as opposed to <code>P2WPKH in P2SH</code> and <code>P2WSH in P2SH</code> where the first field is <em>scriptSig</em>'s total length followed by <code>0x0</code>/<code>OP_0</code>.<br>
From what I understand, a non-SegWit <code>P2PH</code> address is obtained by hashing the redeem script, but I'd need something to anchor to, like for example 1st byte is <code>OP_0</code>, then comes the size of the data (probably a signature), loop until finding <code>OP_TRUE</code> followed by <code>OP_PUSHDATA1</code>?<br>
But is this the unique, standard format?</p>

<development><script><p2sh>
Non SegWit P2SH bytes structure
iMil
# Non SegWit P2SH bytes structure

(Asked by: username_0 on 2019-11-21)

I'm working on a bitcoin block explorer in *golang*, in which I'd like to gather as much informations as possible about transactions.  
I am able to extract addresses from every type of *output*, and mostly every type of *input*, except I am struggling to find clear `P2SH` documentation.  
*BIP16* doesn't say much about non-SegWit `P2SH` byte structure. I read many examples where `OP_0` is the first byte, as opposed to `P2WPKH in P2SH` and `P2WSH in P2SH` where the first field is *scriptSig*'s total length followed by `0x0`/`OP_0`.  
From what I understand, a non-SegWit `P2PH` address is obtained by hashing the redeem script, but I'd need something to anchor to, like for example 1st byte is `OP_0`, then comes the size of the data (probably a signature), loop until finding `OP_TRUE` followed by `OP_PUSHDATA1`?  
But is this the unique, standard format?

**Tags:** development, script, p2sh


---

## 2 answers

### Answer by username_2 on 2019-11-22. Score: 3 | Accepted answer

A P2SH locking script on an output has the following structure:
         Output (scriptPubKey)
--------------------------------
OP_HASH160  OP_EQUAL

The address comes for this comes from the , creating a "3address". This is the standard format for a P2SH, so you can identify it and work out the address from there.
That's all you need to get the address, but explaining a little further...

Interestingly, the  can be the hash of any kind of script you like. However, it's most commonly used for putting the hash of a P2MS in there. So when you come to unlock this script, the scriptSig may look something like this:
          Input (scriptSig)
-------------------------------------------
OP_0   

What you're seeing here is basically a complete script for what would have been a classic P2MS scriptPubKey and scriptSig, where the  is a data push of a normal script with opcodes.
          Input (scriptSig)
-------------------------------------------
              scriptSig       scriptPubKey (as a data push)
---------------------------- -------------- 
OP_0   

With P2SH it's like you have a complete scriptSig+scriptPubKey contained inside the scriptSig, and it can contain any script so it doesn't have a standard form.
Anyway, this complete P2MS script starts with a OP_O, because all P2MS scriptSigs have to start with that due to the off-by-one bug that the OP_CHECKMULTISIG opcode. This is nothing to do with the OP_0 you get in Segwit scriptPubKeys.
When this script executes, the  will firstly be hashed and compared with the  in the output to make sure it matches. If it does, the  is deserialized to see the opcodes:
      Input (scriptSig)
-------------------------------------------
              scriptSig       scriptPubKey
---------------------------- -------------- 
OP_0   OP_2    OP_3 OP_CHECKMULTISIG

So this is what you would see on a classic P2MS output, but this just happened to be wrapped in a P2SH script because it's cheaper for the sender. So this is the standard format for a P2MS: (OP_N  OP_M OP_CHECKMULTISIG).
This particular scriptPubKey does not actually have an address. There are  in there, but it wouldn't be technically correct to say those  have an "address", because an address refers to a specific locking script pattern, and is not just the friendlier version of any .
Examples:

P2SH with a P2MS inside it: https://learnmeabitcoin.com/explorer/transaction/d3adb18d5e118bb856fbea4b1af936602454b44a98fc6c823aedc858b491fc13/output/0#scriptPubKey
P2SH with a non-standard script inside it: https://learnmeabitcoin.com/explorer/transaction/7d46745463a28049cb93d2c964320912d9c296c1038cb24cc3716255c397a87f/output/1#scriptPubKey

Links:

https://learnmeabitcoin.com/guide/p2sh
https://learnmeabitcoin.com/guide/p2ms
https://learnmeabitcoin.com/guide/address

> **Comments:**
> **username_3**: Thank you for this great answer! One puzzle piece is missing for me: How does the validator decide where the redeem script starts so that it can hash it?  
> **username_2**: The <redeemscript> is the last item in the `scriptSig` (it's actually a data push and not individual opcodes), so you can just look at that last item.  
> **username_3**: Ok, I repeat to see if I understood it: So the the <redeemscript> is pushed bytecode. So it's on top of the stack when the <scriptSig> has been executed (pushes only). So by convention we interpret the top stack element as Bitcoin Script and load it into a new script stack for execution if the corresponding UXTO was a P2SH?  
> **username_2**: @username_3 Yes that's correct.  

---

### Answer by username_1 on 2019-11-21. Score: 1

From what I understand, a non-SegWit P2PH address is obtained by hashing the redeem script

ScriptPubKey
I had the same problem and I have resolved it with this C++ code, and I think this code is self-describing.
If you have the ScriptPubKey extract from the blk file, this is code calculate the correct address P2SH.
string opcode = hex.substr(0, 2);
int32_t optValue = std::stoul(opcode, nullptr, 16);
auto optMap = bitcoinOpCode.opCodeList.find(optValue);
string optCode = optMap->second;
if (optCode == "OP_HASH160") {
 cout << "Finded the P2SH";
 string scriptHash = hex.substr(4, hex.length() - 6);
 Bytes bytes = hexBytes(scriptHash.c_str());
 bytes.insert(bytes.begin(), 1, 5);

 string address = EncodeBase58Check(bytes);
 cout << "P2SH addresss is " << address;
 string endOpCode = hex.substr(hex.length() - 2, 2);
 int32_t optValueEnd = std::stoul(endOpCode, nullptr, 16);
 auto optMapEnd = bitcoinOpCode.opCodeList.find(optValueEnd);
 string optCodeEnd = optMapEnd->second;
 if(optCodeEnd == "OP_EQUAL"){
   cout << "\n\t----------------------------------------| Results |-----------------------------------" << endl;
   cout << "\t                               ###  Script PUB KEY HASH  ###                            " << endl;
   cout << "\t" << optCode << " "  << scriptHash << " " << optCodeEnd << endl;
   cout << "\t                                                                                      " << endl;
   cout << "\t The public key: " << address << "                                   " << endl;
   cout << endl;
   cout << "\t https://blockstream.info/address/" << address << endl;
   cout << "\t______________________________________________________________________________________"<< endl;
  }
}

how I do calculate the correct address?
You know the complete P2SH, an example this
OP_0   OP_2  
 OP_3 OP_CHECKMULTISIG
OP_HASH160  OP_EQUAL

Inside the this code you can find the scriptSig, so this:
OP_0   OP_2  
 OP_3 OP_CHECKMULTISIG

and the ScriptPubKey, so this:
OP_HASH160  OP_EQUAL

With my code, I work only with the scriptPubKey and I found the dimension with the following mode
OP_HASH160 = hex.substr(0, 2);
 = hex.substr(4, hex.length() - 6);
OP_EQUAL = hex.substr(hex.length() - 2, 2);

on the data hex  I can run the EncodeBase58Check encoding, I have to change the code of bitcoin core(this) for change the hash library.
Inside the bitcoin core code you can find the correct execution of EncodeBase58 (here)
Another important code is this to insert the mainet flag inside the byte.
bytes.insert(bytes.begin(), 1, 5);

ScriptSig
The scriptSig inside is composed to two component, so:

the Sighnature: OP_0  
the program control: OP_2  
 OP_3 OP_CHECKMULTISIG

I didn't have to try to decode with code the script sig but I think this is more difficult to others because the dimension is not standard because the program control is a script P2MS and this script has more combination.
I can suggest you create a decompiler intelligent for scriptSig because if you get the OP_2 hex inside the script you can read 2 signature but it is possible to get the OP_14 and your parser must be read 14 signature.
I can suggest you to start decompiler the ScriptSig to end because you know the dimension end hexadecimal.
When you have extracted the pubkey and if you want an address bitcoin you can read my question here

> **Comments:**
> **username_0**: Thanks a lot for the detailed algorithm explanation, but my question was more about the standard ScriptSig follows, creating a loop that extracts the redeem script is not hard, yet I must be sure the format is always of the form:  <OP_0><{data1 size}{data1}><{data2 size}{data2}>...<OP_1><OP-PUSHDATA1><redeemScript>  
> **username_1**: @username_0 No because the signature depends on the combination of P2MS script, I have mentioned this argument in the ScriptSig section.  

---

