Create Raw Multi-Sig P2SH Bitcoin Transaction in Golang
Bitcoin scripting language called Script is a stack-based (stack: first in, last out) execution language. It is designed to simplifying the security model of Bitcoin, so the Script has not any loop or jump op-code, and the language is not turing-complete. But this limited language provides a lot of capabilities to Bitcoin to write programs. You can find detailed information about Bitcoin script language in this link .
Pay to Script Hash (P2SH)
Pay to script hash (P2SH) transactions were standardized in BIP16. That update allows transactions to be sent to a redeem hash (addresses starting with 3 in main-net and 2 in test-net) rather than a public key hash (addresses starting with 1 in main-net and m in test-net). The sender doesn’t know anything about the redeem and only knows the redeem hash, and the redeem can be anything from a multi-sig checking or a password verification or anything else.
To spend Bitcoins in a P2SH UTXO, the recipient must provide a redeem-script that matches with the redeem hash in the UTXO and also a signature-script (known as sig-script) to spend Bitcoins.
In this tutorial, I will explain how to build a multi-sig address in the format of P2SH and then spend it with Go language.
Multi-Sig Redeem Script
m = the minimum number of signatures that are required to spend the UTXO (OP_2 = 2)
n = the total number of public keys, used in multi-sig script (OP_3 =3)
m and n can be up to 16
redeem script = <OP_2> <pubkey A> <pubkey B> <pubkey C> <OP_3> OP_CHECKMULTISIG
This is the return value of the above function: (public keys are bold)
2 0265e6f7fb614a369c9230912a3bb09c33c5c5be2e1bcfc2293ecaed46708e0b5c 03f546edf7b434b50aa0115c1c82a0f9a96505d9eff55d2fe3b848c4b51c06b643 02908375f301c7ea583f7e113939eab1164abda4ac27898b1cf78abf1c82f02da9 3 OP_CHECKMULTISIG
signature script = <OP_0> <sig A> <sig C>
(in the final code I’ll describe step by step how to construct this signature script)
The signature script along with redeem script will result a true in the stack.
signature script + redeem script = <OP_0> <sig A> <sig C> <OP_2> <pubkey A> <pubkey B> <pubkey C> <OP_3> OP_CHECKMULTISIG
- From left to right, each op-code or data added at the top of the stack, and at last OP_CHECKMULTISIG is added
- OP_CHECKMULTISIG gets the total number of public keys to check from the top of the stack (in this case OP_3)
- and then gets the specified number of public keys (in this case 3, OP_3 = 3) from the top of the stack
- and then gets the number of signatures that must be provided from the top of the stack (in this case OP_2 = 2)
- at last check the stack for needed signatures, if the signatures would be correct, then leave a true on the stack and you can spend your Bitcoin
(OP_0 is added because of a known bug in Bitcoin script language that is now is a part of consensus, you can find full description here )
This is how Bitcoin script language works. Now we can dive into P2SH.
anyone who send to a P2SH address only need the redeem-hash (extracted from the address)
redeem-hash = Hash160(redeem script)
If somebody wants to build a P2SH address firstly have to generate the redeem script (that in our case generated Multi-Sig Redeem Script section), and hash it with hash160. so the redeem-hash is 20-byte length.
(hash160 is a two-step hash algorithm, that first hashing the input with Sha256 and hashing again its result with RIPEMD160, the final result would be the result of RIPEMD160 hash function)
After that build a P2SH address with the redeem-hash (starting with 3 in main-net and 2 in test-net)
The return value of the function would be:
(starting with 2 because generated to use in test-net)
Now anyone can send bitcoin to this address. When a sender wants to send some amount of Bitcoin to this address, its wallet extracts the redeem-hash from the address and build a locking script to put in the output of the transaction.
locking script = OP_HASH160 <redeem-hash> OP_EQUAL
You can also use this link to get some test Bitcoin.
after getting some Bitcoin (test or real), you can check a block-explorer, for example api.blockchair.com to check the locking script, it’s also known as script hex or pubKey script.
The return value of the above function, which dis assemble the locking script into human readable Bitcoin script language is:
OP_HASH160 f63e2cbcc678236f683d267e7bb298ffdcd57b04 OP_EQUAL
Spend Multi-Sig P2SH
When the recipient wants to spend this UTXO should provide an unlocking script, that is the signature script concatenated with the redeem script.
unlocking script = <OP_0> <sig A> <sig C> <redeem script>
The miners add this unlocking script to the locking script that is on the blockchain and then run the program.
script program = unlocking script + locking script
script program = <OP_0> <sig A> <sig C> <redeem script> OP_HASH160 <redeem-hash> OP_EQUAL
- <OP_0>, <sig A>, <sig C>, and <redeem script> will be added to the stack one by one
- Then OP_HASH160 added and calculate the hash of the top element of the stack, which is <redeem script> and leaves the result on the top of it
- Then <redeem-hash> added on the top of the stack
- at last OP_EQUAL will be added
- OP_EQUAL checks two top elements of the stack, (which in this case are HASH160(redeem script) , and <redeem-hash>)
- if they would equal leaves a true and continues the program and if they would not equal leaves a false at the top of the stack and breaks the program
- So if the recipient provides the same redeem script, that is used for building the redeem-hash and the address, then we reach to the same state as Script Execution section, with the same op-codes and data on the stack
this is the code that sign a multi-sig transaction in go, if you are not familiar with bitcoin transaction and its structure, you can see my previous post .
this is the return value of the above function:
this is a raw bitcoin transaction that can be push in the test network, you push your one from blockstream.info or anywhere else.
the txid of the above raw transaction is:
you can search it in any block explorer for Bitcoin test-net.
You can find about P2PKH transaction, transaction structure, and fee in my previos post .
Thanks for your attention
- Learn about Ethereum and Web3
- The Best Crypto Trading Bot
- 3Commas Review
- AAX Exchange Review | Referral Code, Trading Fee, Pros and Cons
- Deribit Review | Options, Fees, APIs and Testnet
- FTX Crypto Exchange Review
- NGRAVE ZERO review
- Bybit Exchange Review
- 3Commas vs Cryptohopper
- The Best Bitcoin Hardware wallet
- Crypto Copy Trading Platforms
- Best monero wallet
- ledger nano s vs x
- Bitsgap vs 3Commas vs Quadency
- The Best Crypto Tax Software
- Best Crypto Trading Platforms
- Best Crypto Lending Platforms
- Ledger Nano S vs Trezor one vs Trezor T vs Ledger Nano X
- BlockFi vs Celsius vs Hodlnaut
- Bitsgap review — A Crypto Trading Bot That Makes Easy Money
- Quadency Review- A Crypto Trading Bot Made For Professionals
- PrimeXBT Review | Leverage Trading, Fee and Covesting
- Altrady review
- Ellipal Titan Review
- SecuX Stone Review
- BlockFi Review | Earn up to 8.6% interests on your Crypto
- Best Crypto APIs for Developers
- Best Blockchain Analysis Tools
- Crypto arbitrage guide: How to make money as a beginner
- Best Crypto Charting Tool
- What are the best books to learn about Bitcoin?