Non SegWit P2SH bytes structure 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?
A P2SH locking script on an output has the following structure:
         Output (scriptPubKey)
--------------------------------
OP_HASH160 &lt;scripthash&gt; OP_EQUAL

The address comes for this comes from the &lt;scripthash&gt;, 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.
That's all you need to get the address, but explaining a little further...

Interestingly, the &lt;scripthash&gt; 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 &lt;signature&gt; &lt;signature&gt; &lt;redeemscript&gt;

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

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 &lt;redeemscript&gt; will firstly be hashed and compared with the &lt;scripthash&gt; in the output to make sure it matches. If it does, the &lt;redeemscript&gt; is deserialized to see the opcodes:
      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

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 &lt;pubkeys...&gt; OP_M OP_CHECKMULTISIG).
This particular scriptPubKey does not actually have an address. There are &lt;pubkeys&gt; in there, but it wouldn't be technically correct to say those &lt;pubkeys&gt; have an &quot;address&quot;, because an address refers to a specific locking script pattern, and is not just the friendlier version of any &lt;pubkey&gt;.
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