Advanced Bitcoin Scripting (P2SH - Discussion

Welcome to the discussion about this section. Here you can ask questions or post feedback about this specific lecture.

Is there not a video intro for this section? “Advanced Bitcoin Scripting (P2SH)”

@filip, there’s nothing to watch or read on the Introduction section, why does this section exist?

Also, why did we get so far without any practice assignments? Can’t we put in practice on regtest mode what we learned so far?

Sorry about that. It is up now. Don’t know why it wasn’t showing. @tcooksey1972 @cata


Thank you for the work. I learned a lot today!

I think there was a mistake at Pay-To-Script-Hash Transaction Part 2 - How to Redeem at around minute 8.
You said, that the number 2 on the stack would indicate that there are 2 signatures coming and thus OP_MULTISIG would pop/drop the next 2 elements from the stack.
I think the number 2 indicates, that at least 2 signatures (M) must match to verify against the given pubkeys (N) for the particular multisig transaction and thus the function will simply drop all items left from the stack to finish its operation.

@filip . Hi Filip, Just to clarify my understanding of things. In the basic Pay to Public Key Hash scenario, to spend what you own you have to prove you own it first . So you supply the unlocking script. The unlocking script is applied to the locking script of your UTXO input (the output from a previous transaction). So the locking script is originally created by a previous transaction (correct ?) Once that is “solved” by you , you are deemed to be the rightful owner and the “redeemed” amount is spendable in the current transaction. Is that a correct summary please ?

If the above is correct then my next question covers the multisig use-case. I am trying to get my head around the specifics of WHO provides the locking script. It sounds like to me that the previous transaction has to magically know that you have a multisig wallet which will receive the funds and the previous sender must produce a multi-sig locking script. Then when you want to redeem the funds, you provide the unlocking solution to the multisig script. Is this correct please ?

many thanks, Paul


Well, they both are true. It indicates the number of signatures in the script. That is used to say that 2 out of 3 signatures need to match, correct. But it also tells the computer that 2 elements should be popped from the stack.

Let’s say that the 2 was only for saying that at least 2 signatures need to match. Then I could in theory put 5 signatures on the stack, even though only 2 need to match. But that won’t work. The computer would only pop 2 of them. Then you would get an error.

So the nr 2 is required for both of these reasons. Good question!

I love that you are questioning all of this, it shows you are really going to understand this.

Your first understanding is basically correct, as far as I understand your reasoning.

The second part is not totally correct. When we are talking about a pay to script hash transaction. We have to separate the locking script (which only contains a hash) and the redeem script (which contains the multisig script). The sender of the previous transaction therefor doesn’t need to know that it is a multisig wallet, since that person will only create the locking script containing the script hash.

The script hash is created by the multisig wallet owner, given to the sender. The sender doesn’t know the content of that script. It’s just a hash. That’s the beauty of the P2SH type.

To summarice. the receiver creates the redeem script, containing the multisig redeem script, hashes it. Now he gives the hash to the sender. Then the sender just constructs a P2SH transaction to that hash. Then when the receiver (multisig owner) wants to spend those funds, they use the original redeem script and their keys and can spend the tx.

Let me know if you understand it better now :slight_smile:


Thanks Filip for taking the time out to respond in detail. I do get the process (as you outlined) concerning the P2SH transaction and i get the original basic Pay-To-PublicKey-Hash transaction type. In my second question I was really referring to the long-winded multisig scenario that didnt involve a P2SH. I revisited your videos and from what i can see in a standard multisig where it is not a P2SH tranacgion, all the “work” is put back onto the sender of the transaction. So that seems to be the answer in that case. Much appreciated, Paul

Yes that’s correct. And that’s why P2SH tx’s is a lot more popular in those kinds of use cases. But we also have to remember that the wallet does most of the work when it comes to constructing transactions. But the sender in that case needs to know that it is a multisig tx.

@filip Sorry if I missed this in a previous video but are signature 2 and 3 encoded with some kind of nonce or timestamp? Otherwise I am struggling to see how you can’t just replay those sigs in some future transaction. Or are we saying that because everything is going to be hashed, it doesn’t matter that we use publicly available information?

I don’t know exactly anymore how Filip showed it, but signatures are always different for every transaction. A signature is derived from the private key, partical utxo to send to a particular bitcoin address. So you never can use the same signature twice because the utxo would be on a different bitcoin address.

Check this video to see how digital signatures work:


Thank you for this Fabrice :slight_smile:

1 Like

Im still puzzling to solve a challenge I would like to accomplish. The challenge is to divide a payment over three public keys. Looking to the BTCPayServer solution, you are able to add a multisig adress in the store, which means you can solve the wish that you need more than 1 people to spend the amount the shop received. But suppose you want to divide the amount of money in the multisig where 1 person can redeem only 60% and an other 40%, is this possible to build with a P2SH? Probably we come on the terrain where we need smartcontracts though? Or do we have to create an other script as soon the payment is in which will send the bitcoin further to two other addresses? What could be the path to realize this? @filip

1 Like

Hello sir, it could be a way to do it, but that is a really complex challenge, you might going to need to create your own script or app that can monitor the address at any moment:

Once a transaction is received

  • It should calculate the amount received, divided into the % established.
  • Build a P2SH (or more), each to send the % calculated.
  • Participant signatures must be collected and assembled in the transaction.
  • All the mention steps should be inside the logic of the script/app.

It could be more easy to do it by using an smart contract.

Remember all of this is just theory, maybe in a near future we might see some wallets/apps that could integrate this ideas into their logic.

Hope this gives you a clear view of the subject, keep learning! :slight_smile:

If you have any doubt, please let us know so we can help you!

Carlos Z.

1 Like

Thanks! Seems I found a nice challenge :slight_smile: I will finish this course further to see how far I can come. The fact that it’s probably easy to do this by smart contracts, on which blockchain we should build this? I’m looking to RSK (rootstock) Komodo and Elements. What would be handy, taking the fact that when we want to make use of BTCPayServer on a raspberrypi it should be not to heavy. I’m also curious what you can do with transmuter Seems it can solve something in this challenge as well. Will activate this as soon my BTCPayServer is synced on the Raspberry. Thanks!

1 Like

I’m running into a hard error which I still can’t solve after tryiung all kind of solutions I find on Google.

When I run the transaction.js which has this content:
‘use strict’

const fs = require(‘fs’);

const assert = require(‘assert’);

const bcoin = require(‘bcoin’);

const KeyRing = bcoin.wallet.WalletKey;

const Script = bcoin.Script;

const MTX = bcoin.MTX;

const Amount = bcoin.Amount;

const Coin = bcoin.Coin;

const privateKey1 = fs.readFileSync(’./regtest-key1.wif’).toString();

const privateKey2 = fs.readFileSync(’./regtest-key2.wif’).toString();

const keyPair1 = KeyRing.fromSecret(privateKey1);

const keyPair2 = KeyRing.fromSecret(privateKey2);

const publicKey1 = keyPair1.publicKey;

const publicKey2 = keyPair2.publicKey;

const m = 2;

const n = 2;

//Redeem Script

const redeem = Script.fromMultisig(m, n [publicKey1, publicKey2]);

//P2SH Script

const script = Script.fromScripthash(redeem.hash160());


I get this

error in my terminal:

Seems something wrong with the assert module. I checked my code, update the module, used an other nodejs version. This moment I have v12.13.0

I’m working on Ubuntu 18.04 machine.

Maybe I can find any help here?

In the meantime I found a great add on on BTCPayServer. The create Payment Forwarder. You can forward funds when there is any balance and give a percentage of the balance to pay forward. Incredible fantastic :slight_smile: Here a screenshot of the interface:

More info on:

It’s still in Alpha but will test it next week. Thanks for this great course BTW, what a big lessons :slight_smile:


1 Like

Hello sir, the issue is on the variable “redeem”, you must have a “comma” between the #of signs require and the publickeys

Here is your variable

const redeem = Script.fromMultisig(m, n [publicKey1, publicKey2]);

Just need to add the ", " like this:

const redeem = Script.fromMultisig(m, n, [publicKey1, publicKey2]);

After that, you should be able to get P2SH without any issue from your “console.log(script);” variable.

This was mine, has an example:

<Script: OP_HASH160 0x14 0xe1cf9cfb8a2507f052eafc534f84e18087e2b4cb OP_EQUAL>

Hope you find this useful! :slight_smile:

If you have any doubt, please let us know so we can help you!

Carlos Z.

1 Like

Excellent! thats a great news that you find a way to fullfil that objective, today while i was researching about your issue, i was thinking to advice you to check about the “bcoin” library to see if they have something like that!, glad to know that you find it 1st! :muscle:

Please keep me notice it about your achievements on this subject! :grin:

Carlos Z.