DEV Community

CoinMonks
CoinMonks

Posted on • Originally published at Medium on

Build P2SH Address and Spend its Fund in Golang

Photo by Florian Olivo on Unsplash

Create Raw Multi-Sig P2SH Bitcoin Transaction in Golang

Bitcoin Script Language

Bitcoin scripting language called Scrip t 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
Enter fullscreen mode Exit fullscreen mode

This is the return value of the above function: (public keys are bold)

2 **0265e6f7fb614a369c9230912a3bb09c33c5c5be2e1bcfc2293ecaed46708e0b5c**  **03f546edf7b434b50aa0115c1c82a0f9a96505d9eff55d2fe3b848c4b51c06b643**  **02908375f301c7ea583f7e113939eab1164abda4ac27898b1cf78abf1c82f02da9** 3 OP_CHECKMULTISIG
Enter fullscreen mode Exit fullscreen mode

signature script =

(in the final code I’ll describe step by step how to construct this signature script)

Script Execution

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
Enter fullscreen mode Exit fullscreen mode
  • 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.

Multi-Sig P2SH

anyone who send to a P2SH address only need the redeem-hash (extracted from the address)

redeem-hash = Hash160(redeem script)
Enter fullscreen mode Exit fullscreen mode

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:

2NFhEhTAiXJ8z8yEYnXe6SJX5E8bRgB5ZgY
Enter fullscreen mode Exit fullscreen mode

(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
Enter fullscreen mode Exit fullscreen mode

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.

locking script in block-explorer

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
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode
  • , , , and 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 and leaves the result on the top of it
  • Then 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 )
  • 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:

0100000001fe75a438b72fdc302b80cc216d66d5e3bbb0359bce3bb4cecf743f5fda1f4eb101000000fdfd000048304502210096b617a5b2bd676ee8d3f8d8d91bf60c599e16382d1e12a61a1f9562c35b2cb102204379706a55c07bb45d20336159f80ebe9786938e34b9309e49ed422e6d2a44470147304402201550a8bb0c28107098289fe6fe64488bdee46800d28bfbb0b0a1e1b2d64b9fb4022004684015095b999185b3da1a23d239452ad73b199a032f71978760f8ae42313f014c6952210265e6f7fb614a369c9230912a3bb09c33c5c5be2e1bcfc2293ecaed46708e0b5c2103f546edf7b434b50aa0115c1c82a0f9a96505d9eff55d2fe3b848c4b51c06b6432102908375f301c7ea583f7e113939eab1164abda4ac27898b1cf78abf1c82f02da953aeffffffff01f8a70000000000001976a914bd63bf79e39f4cd52361c092c3fba9264662285688ac00000000
Enter fullscreen mode Exit fullscreen mode

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:

c7d1582d4cf85fbd10732002c5bb06068d4b86cfd5cca151ef88104c6702435a
Enter fullscreen mode Exit fullscreen mode

you can search it in any block explorer for Bitcoin test-net.

bitcoin test-net block-explorer

You can find about P2PKH transaction, transaction structure, and fee in my previos post .

Thanks for your attention

Also, Read

Get Best Software Deals Directly In Your Inbox


Top comments (0)