btc_protocol

Bitcoins the hard way: Using the raw Bitcoin protocol

All the recent media attention on Bitcoin inspired me to learn how Bitcoin really works, right down to the bytes flowing through the network. Normal people use software[1] that hides what is really going on, but I wanted to get a hands-on understanding of the Bitcoin protocol. My goal was to use the Bitcoin system directly: create a Bitcoin transaction manually, feed it into the system as hex data, and see how it gets processed. This turned out to be considerably harder than I expected, but I learned a lot in the process and hopefully you will find it interesting.

(Feb 23: I have a new article that covers the technical details of mining. If you like this article, check out my mining article too.)

This blog post starts with a quick overview of Bitcoin and then jumps into the low-level details: creating a Bitcoin address, making a transaction, signing the transaction, feeding the transaction into the peer-to-peer network, and observing the results.

A quick overview of Bitcoin

I'll start with a quick overview of how Bitcoin works[2], before diving into the details. Bitcoin is a relatively new digital currency[3] that can be transmitted across the Internet. You can buy bitcoins[4] with dollars or other traditional money from sites such as Coinbase or MtGox[5], send bitcoins to other people, buy things with them at some places, and exchange bitcoins back into dollars.

To simplify slightly, bitcoins consist of entries in a distributed database that keeps track of the ownership of bitcoins. Unlike a bank, bitcoins are not tied to users or accounts. Instead bitcoins are owned by a Bitcoin address, for example 1KKKK6N21XKo48zWKuQKXdvSsCf95ibHFa.

Bitcoin transactions

A transaction is the mechanism for spending bitcoins. In a transaction, the owner of some bitcoins transfers ownership to a new address.

A key innovation of Bitcoin is how transactions are recorded in the distributed database through mining. Transactions are grouped into blocks and about every 10 minutes a new block of transactions is sent out, becoming part of the transaction log known as the blockchain, which indicates the transaction has been made (more-or-less) official.[6] Bitcoin mining is the process that puts transactions into a block, to make sure everyone has a consistent view of the transaction log. To mine a block, miners must find an extremely rare solution to an (otherwise-pointless) cryptographic problem. Finding this solution generates a mined block, which becomes part of the official block chain.

Mining is also the mechanism for new bitcoins to enter the system. When a block is successfully mined, new bitcoins are generated in the block and paid to the miner. This mining bounty is large - currently 25 bitcoins per block (about $19,000). In addition, the miner gets any fees associated with the transactions in the block. Because of this, mining is very competitive with many people attempting to mine blocks. The difficulty and competitiveness of mining is a key part of Bitcoin security, since it ensures that nobody can flood the system with bad blocks.

The peer-to-peer network

There is no centralized Bitcoin server. Instead, Bitcoin runs on a peer-to-peer network. If you run a Bitcoin client, you become part of that network. The nodes on the network exchange transactions, blocks, and addresses of other peers with each other. When you first connect to the network, your client downloads the blockchain from some random node or nodes. In turn, your client may provide data to other nodes. When you create a Bitcoin transaction, you send it to some peer, who sends it to other peers, and so on, until it reaches the entire network. Miners pick up your transaction, generate a mined block containing your transaction, and send this mined block to peers. Eventually your client will receive the block and your client shows that the transaction was processed.

Cryptography

Bitcoin uses digital signatures to ensure that only the owner of bitcoins can spend them. The owner of a Bitcoin address has the private key associated with the address. To spend bitcoins, they sign the transaction with this private key, which proves they are the owner. (It's somewhat like signing a physical check to make it valid.) A public key is associated with each Bitcoin address, and anyone can use it to verify the digital signature.

Blocks and transactions are identified by a 256-bit cryptographic hash of their contents. This hash value is used in multiple places in the Bitcoin protocol. In addition, finding a special hash is the difficult task in mining a block.

Bitcoins do not really look like this. Photo credit: Antana, CC:by-sa

Diving into the raw Bitcoin protocol

The remainder of this article discusses, step by step, how I used the raw Bitcoin protocol. First I generated a Bitcoin address and keys. Next I made a transaction to move a small amount of bitcoins to this address. Signing this transaction took me a lot of time and difficulty. Finally, I fed this transaction into the Bitcoin peer-to-peer network and waited for it to get mined. The remainder of this article describes these steps in detail.

It turns out that actually using the Bitcoin protocol is harder than I expected. As you will see, the protocol is a bit of a jumble: it uses big-endian numbers, little-endian numbers, fixed-length numbers, variable-length numbers, custom encodings, DER encoding, and a variety of cryptographic algorithms, seemingly arbitrarily. As a result, there's a lot of annoying manipulation to get data into the right format.[7]

The second complication with using the protocol directly is that being cryptographic, it is very unforgiving. If you get one byte wrong, the transaction is rejected with no clue as to where the problem is.[8]

The final difficulty I encountered is that the process of signing a transaction is much more difficult than necessary, with a lot of details that need to be correct. In particular, the version of a transaction that gets signed is very different from the version that actually gets used.

Bitcoin addresses and keys

My first step was to create a Bitcoin address. Normally you use Bitcoin client software to create an address and the associated keys. However, I wrote some Python code to create the address, showing exactly what goes on behind the scenes.

Bitcoin uses a variety of keys and addresses, so the following diagram may help explain them. You start by creating a random 256-bit private key. The private key is needed to sign a transaction and thus transfer (spend) bitcoins. Thus, the private key must be kept secret or else your bitcoins can be stolen.

The Elliptic Curve DSA algorithm generates a 512-bit public key from the private key. (Elliptic curve cryptography will be discussed later.) This public key is used to verify the signature on a transaction. Inconveniently, the Bitcoin protocol adds a prefix of 04 to the public key. The public key is not revealed until a transaction is signed, unlike most systems where the public key is made public.

How bitcoin keys and addresses are related

The next step is to generate the Bitcoin address that is shared with others. Since the 512-bit public key is inconveniently large, it is hashed down to 160 bits using the SHA-256 and RIPEM hash algorithms.[9] The key is then encoded in ASCII using Bitcoin's custom Base58Check encoding.[10] The resulting address, such as 1KKKK6N21XKo48zWKuQKXdvSsCf95ibHFa, is the address people publish in order to receive bitcoins. Note that you cannot determine the public key or the private key from the address. If you lose your private key (for instance by throwing out your hard drive), your bitcoins are lost forever.

Finally, the Wallet Interchange Format key (WIF) is used to add a private key to your client wallet software. This is simply a Base58Check encoding of the private key into ASCII, which is easily reversed to obtain the 256-bit private key. (I was curious if anyone would use the private key above to steal my 80 cents of bitcoins, and sure enough someone did.)

To summarize, there are three types of keys: the private key, the public key, and the hash of the public key, and they are represented externally in ASCII using Base58Check encoding. The private key is the important key, since it is required to access the bitcoins and the other keys can be generated from it. The public key hash is the Bitcoin address you see published.

I used the following code snippet[11] to generate a private key in WIF format and an address. The private key is simply a random 256-bit number. The ECDSA crypto library generates the public key from the private key.[12] The Bitcoin address is generated by SHA-256 hashing, RIPEM-160 hashing, and then Base58 encoding with checksum. Finally, the private key is encoded in Base58Check to generate the WIF encoding used to enter a private key into Bitcoin client software.[1] Note: this Python random function is not cryptographically strong; use a better function if you're doing this for real.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

def privateKeyToWif(key_hex):

return utils.base58CheckEncode(0x80, key_hex.decode('hex'))

def privateKeyToPublicKey(s):

sk = ecdsa.SigningKey.from_string(s.decode('hex'), curve=ecdsa.SECP256k1)

vk = sk.verifying_key

return ('\04' + sk.verifying_key.to_string()).encode('hex')

def pubKeyToAddr(s):

ripemd160 = hashlib.new('ripemd160')

ripemd160.update(hashlib.sha256(s.decode('hex')).digest())

return utils.base58CheckEncode(0, ripemd160.digest())

def keyToAddr(s):

return pubKeyToAddr(privateKeyToPublicKey(s))

# Warning: this random function is not cryptographically strong and is just for example

private_key = ''.join(['%x' % random.randrange(16) for x in range(0, 64)])

print keyUtils.privateKeyToWif(private_key)

print keyUtils.keyToAddr(private_key)

keyUtils.py hosted with ❤ by GitHub

Inside a transaction

A transaction is the basic operation in the Bitcoin system. You might expect that a transaction simply moves some bitcoins from one address to another address, but it's more complicated than that. A Bitcoin transaction moves bitcoins between one or more inputs and outputs. Each input is a transaction and address supplying bitcoins. Each output is an address receiving bitcoin, along with the amount of bitcoins going to that address.

A sample Bitcoin transaction. Transaction C spends .008 bitcoins from Transactions A and B.

The diagram above shows a sample transaction "C". In this transaction, .005 BTC are taken from an address in Transaction A, and .003 BTC are taken from an address in Transaction B. (Note that arrows are references to the previous outputs, so are backwards to the flow of bitcoins.) For the outputs, .003 BTC are directed to the first address and .004 BTC are directed to the second address. The leftover .001 BTC goes to the miner of the block as a fee. Note that the .015 BTC in the other output of Transaction A is not spent in this transaction.

Each input used must be entirely spent in a transaction. If an address received 100 bitcoins in a transaction and you just want to spend 1 bitcoin, the transaction must spend all 100. The solution is to use a second output for change, which returns the 99 leftover bitcoins back to you.

Transactions can also include fees. If there are any bitcoins left over after adding up the inputs and subtracting the outputs, the remainder is a fee paid to the miner. The fee isn't strictly required, but transactions without a fee will be a low priority for miners and may not be processed for days or may be discarded entirely.[13] A typical fee for a transaction is 0.0002 bitcoins (about 20 cents), so fees are low but not trivial.

Manually creating a transaction

For my experiment I used a simple transaction with one input and one output, which is shown below. I started by bying bitcoins from Coinbase and putting 0.00101234 bitcoins into address 1MMMMSUb1piy2ufrSguNUdFmAcvqrQF8M5, which was transaction 81b4c832.... My goal was to create a transaction to transfer these bitcoins to the address I created above, 1KKKK6N21XKo48zWKuQKXdvSsCf95ibHFa, subtracting a fee of 0.0001 bitcoins. Thus, the destination address will receive 0.00091234 bitcoins.

Structure of the example Bitcoin transaction.

Following the specification, the unsigned transaction can be assembled fairly easily, as shown below. There is one input, which is using output 0 (the first output) from transaction 81b4c832.... Note that this transaction hash is inconveniently reversed in the transaction. The output amount is 0.00091234 bitcoins (91234 is 0x016462 in hex), which is stored in the value field in little-endian form. The cryptographic parts - scriptSig and scriptPubKey - are more complex and will be discussed later.

Here's the code I used to generate this unsigned transaction. It's just a matter of packing the data into binary. Signing the transaction is the hard part, as you'll see next.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

# Makes a transaction from the inputs

# outputs is a list of [redemptionSatoshis, outputScript]

def makeRawTransaction(outputTransactionHash, sourceIndex, scriptSig, outputs):

def makeOutput(data):

redemptionSatoshis, outputScript = data

return (struct.pack("<Q", redemptionSatoshis).encode('hex') +

'%02x' % len(outputScript.decode('hex')) + outputScript)

formattedOutputs = ''.join(map(makeOutput, outputs))

return (

"01000000" + # 4 bytes version

"01" + # varint for number of inputs

outputTransactionHash.decode('hex')[::-1].encode('hex') + # reverse outputTransactionHash

struct.pack('<L', sourceIndex).encode('hex') +

'%02x' % len(scriptSig.decode('hex')) + scriptSig +

"ffffffff" + # sequence

"%02x" % len(outputs) + # number of outputs

formattedOutputs +

"00000000" # lockTime

)

txnUtils.py hosted with ❤ by GitHub

How Bitcoin transactions are signed

The following diagram gives a simplified view of how transactions are signed and linked together.[14] Consider the middle transaction, transferring bitcoins from address B to address C. The contents of the transaction (including the hash of the previous transaction) are hashed and signed with B's private key. In addition, B's public key is included in the transaction.

By performing several steps, anyone can verify that the transaction is authorized by B. First, B's public key must correspond to B's address in the previous transaction, proving the public key is valid. (The address can easily be derived from the public key, as explained earlier.) Next, B's signature of the transaction can be verified using the B's public key in the transaction. These steps ensure that the transaction is valid and authorized by B. One unexpected part of Bitcoin is that B's public key isn't made public until it is used in a transaction.

With this system, bitcoins are passed from address to address through a chain of transactions. Each step in the chain can be verified to ensure that bitcoins are being spent validly. Note that transactions can have multiple inputs and outputs in general, so the chain branches out into a tree.

How Bitcoin transactions are chained together.[14]

The Bitcoin scripting language

You might expect that a Bitcoin transaction is signed simply by including the signature in the transaction, but the process is much more complicated. In fact, there is a small program inside each transaction that gets executed to decide if a transaction is valid. This program is written in Script, the stack-based Bitcoin scripting language. Complex redemption conditions can be expressed in this language. For instance, an escrow system can require two out of three specific users must sign the transaction to spend it. Or various types of contracts can be set up.[15]

The Script language is surprisingly complex, with about 80 different opcodes. It includes arithmetic, bitwise operations, string operations, conditionals, and stack manipulation. The language also includes the necessary cryptographic operations (SHA-256, RIPEM, etc.) as primitives. In order to ensure that scripts terminate, the language does not contain any looping operations. (As a consequence, it is not Turing-complete.) In practice, however, only a few types of transactions are supported.[16]

In order for a Bitcoin transaction to be valid, the two parts of the redemption script must run successfully. The script in the old transaction is called scriptPubKey and the script in the new transaction is called scriptSig. To verify a transaction, the scriptSig executed followed by the scriptPubKey. If the script completes successfully, the transaction is valid and the Bitcoin can be spent. Otherwise, the transaction is invalid. The point of this is that the scriptPubKey in the old transaction defines the conditions for spending the bitcoins. The scriptSig in the new transaction must provide the data to satisfy the conditions.

In a standard transaction, the scriptSig pushes the signature (generated from the private key) to the stack, followed by the public key. Next, the scriptPubKey (from the source transaction) is executed to verify the public key and then verify the signature.

As expressed in Script, the scriptSig is:

PUSHDATA signature data and SIGHASH_ALL PUSHDATA public key data

The scriptPubKey is:

OP_DUP OP_HASH160 PUSHDATA Bitcoin address (public key hash) OP_EQUALVERIFY OP_CHECKSIG

When this code executes, PUSHDATA first pushes the signature to the stack. The next PUSHDATA pushes the public key to the stack. Next, OP_DUP duplicates the public key on the stack. OP_HASH160 computes the 160-bit hash of the public key. PUSHDATA pushes the required Bitcoin address. Then OP_EQUALVERIFY verifies the top two stack values are equal - that the public key hash from the new transaction matches the address in the old address. This proves that the public key is valid. Next, OP_CHECKSIG checks that the signature of the transaction matches the public key and signature on the stack. This proves that the signature is valid.

Signing the transaction

I found signing the transaction to be the hardest part of using Bitcoin manually, with a process that is surprisingly difficult and error-prone. The basic idea is to use the ECDSA elliptic curve algorithm and the private key to generate a digital signature of the transaction, but the details are tricky. The signing process has been described through a 19-step process (more info). Click the thumbnail below for a detailed diagram of the process.

The biggest complication is the signature appears in the middle of the transaction, which raises the question of how to sign the transaction before you have the signature. To avoid this problem, the scriptPubKey script is copied from the source transaction into the spending transaction (i.e. the transaction that is being signed) before computing the signature. Then the signature is turned into code in the Script language, creating the scriptSig script that is embedded in the transaction. It appears that using the previous transaction's scriptPubKey during signing is for historical reasons rather than any logical reason.[17] For transactions with multiple inputs, signing is even more complicated since each input requires a separate signature, but I won't go into the details.

One step that tripped me up is the hash type. Before signing, the transaction has a hash type constant temporarily appended. For a regular transaction, this is SIGHASH_ALL (0x00000001). After signing, this hash type is removed from the end of the transaction and appended to the scriptSig.

Another annoying thing about the Bitcoin protocol is that the signature and public key are both 512-bit elliptic curve values, but they are represented in totally different ways: the signature is encoded with DER encoding but the public key is represented as plain bytes. In addition, both values have an extra byte, but positioned inconsistently: SIGHASH_ALL is put after the signature, and type 04 is put before the public key.

Debugging the signature was made more difficult because the ECDSA algorithm uses a random number.[18] Thus, the signature is different every time you compute it, so it can't be compared with a known-good signature.

Update (Feb 2014): An important side-effect of the signature changing every time is that if you re-sign a transaction, the transaction's hash will change. This is known as Transaction Malleability. There are also ways that third parties can modify transactions in trivial ways that change the hash but not the meaning of the transaction. Although it has been known for years, malleability has recently caused big problems (Feb 2014) with MtGox (press release).

With these complications it took me a long time to get the signature to work. Eventually, though, I got all the bugs out of my signing code and succesfully signed a transaction. Here's the code snippet I used.

1

2

3

4

5

6

7

8

9

10

11

12

def makeSignedTransaction(privateKey, outputTransactionHash, sourceIndex, scriptPubKey, outputs):

myTxn_forSig = (makeRawTransaction(outputTransactionHash, sourceIndex, scriptPubKey, outputs)

+ "01000000") # hash code

s256 = hashlib.sha256(hashlib.sha256(myTxn_forSig.decode('hex')).digest()).digest()

sk = ecdsa.SigningKey.from_string(privateKey.decode('hex'), curve=ecdsa.SECP256k1)

sig = sk.sign_digest(s256, sigencode=ecdsa.util.sigencode_der) + '\01' # 01 is hashtype

pubKey = keyUtils.privateKeyToPublicKey(privateKey)

scriptSig = utils.varstr(sig).encode('hex') + utils.varstr(pubKey.decode('hex')).encode('hex')

signed_txn = makeRawTransaction(outputTransactionHash, sourceIndex, scriptSig, outputs)

verifyTxnSignature(signed_txn)

return signed_txn

txnUtils.py hosted with ❤ by GitHub

The final scriptSig contains the signature along with the public key for the source address (1MMMMSUb1piy2ufrSguNUdFmAcvqrQF8M5). This proves I am allowed to spend these bitcoins, making the transaction valid.

The final scriptPubKey contains the script that must succeed to spend the bitcoins. Note that this script is executed at some arbitrary time in the future when the bitcoins are spent. It contains the destination address (1KKKK6N21XKo48zWKuQKXdvSsCf95ibHFa) expressed in hex, not Base58Check. The effect is that only the owner of the private key for this address can spend the bitcoins, so that address is in effect the owner.

The final transaction

Once all the necessary methods are in place, the final transaction can be assembled.

1

2

3

4

5

6

7

8

9

10

11

12

privateKey = keyUtils.wifToPrivateKey("5HusYj2b2x4nroApgfvaSfKYZhRbKFH41bVyPooymbC6KfgSXdD") #1MMMM

signed_txn = txnUtils.makeSignedTransaction(privateKey,

"81b4c832d70cb56ff957589752eb4125a4cab78a25a8fc52d6a09e5bd4404d48", # output (prev) transaction hash

0, # sourceIndex

keyUtils.addrHashToScriptPubKey("1MMMMSUb1piy2ufrSguNUdFmAcvqrQF8M5"),

[[91234, #satoshis

keyUtils.addrHashToScriptPubKey("1KKKK6N21XKo48zWKuQKXdvSsCf95ibHFa")]]

)

txnUtils.verifyTxnSignature(signed_txn)

print 'SIGNED TXN', signed_txn

makeTransaction.py hosted with ❤ by GitHub

The final transaction is shown below. This combines the scriptSig and scriptPubKey above with the unsigned transaction described earlier.

A tangent: understanding elliptic curves

Bitcoin uses elliptic curves as part of the signing algorithm. I had heard about elliptic curves before in the context of solving Fermat's Last Theorem, so I was curious about what they are. The mathematics of elliptic curves is interesting, so I'll take a detour and give a quick overview.

The name elliptic curve is confusing: elliptic curves are not ellipses, do not look anything like ellipses, and they have very little to do with ellipses. An elliptic curve is a curve satisfying the fairly simple equation y^2 = x^3 + ax + b. Bitcoin uses a specific elliptic curve called secp256k1 with the simple equation y^2=x^3+7. [25]

Elliptic curve formula used by Bitcoin.

An important property of elliptic curves is that you can define addition of points on the curve with a simple rule: if you draw a straight line through the curve and it hits three points A, B, and C, then addition is defined by A+B+C=0. Due to the special nature of elliptic curves, addition defined in this way works "normally" and forms a group. With addition defined, you can define integer multiplication: e.g. 4A = A+A+A+A.

What makes elliptic curves useful cryptographically is that it's fast to do integer multiplication, but division basically requires brute force. For example, you can compute a product such as 12345678*A = Q really quickly (by computing powers of 2), but if you only know A and Q solving n*A = Q is hard. In elliptic curve cryptography, the secret number 12345678 would be the private key and the point Q on the curve would be the public key.

In cryptography, instead of using real-valued points on the curve, the coordinates are integers modulo a prime.[19] One of the surprising properties of elliptic curves is the math works pretty much the same whether you use real numbers or modulo arithmetic. Because of this, Bitcoin's elliptic curve doesn't look like the picture above, but is a random-looking mess of 256-bit points (imagine a big gray square of points).

The Elliptic Curve Digital Signature Algorithm (ECDSA) takes a message hash, and then does some straightforward elliptic curve arithmetic using the message, the private key, and a random number[18] to generate a new point on the curve that gives a signature. Anyone who has the public key, the message, and the signature can do some simple elliptic curve arithmetic to verify that the signature is valid. Thus, only the person with the private key can sign a message, but anyone with the public key can verify the message.

For more on elliptic curves, see the references[20].

Sending my transaction into the peer-to-peer network

Leaving elliptic curves behind, at this point I've created a transaction and signed it. The next step is to send it into the peer-to-peer network, where it will be picked up by miners and incorporated into a block.

How to find peers

The first step in using the peer-to-peer network is finding a peer. The list of peers changes every few seconds, whenever someone runs a client. Once a node is connected to a peer node, they share new peers by exchanging addr messages whenever a new peer is discovered. Thus, new peers rapidly spread through the system.

There's a chicken-and-egg problem, though, of how to find the first peer. Bitcoin clients solve this problem with several methods. Several reliable peers are registered in DNS under the name bitseed.xf2.org. By doing a nslookup, a client gets the IP addresses of these peers, and hopefully one of them will work. If that doesn't work, a seed list of peers is hardcoded into the client. [26]

nslookup can be used to find Bitcoin peers.

Peers enter and leave the network when ordinary users start and stop Bitcoin clients, so there is a lot of turnover in clients. The clients I use are unlikely to be operational right now, so you'll need to find new peers if you want to do experiments. You may need to try a bunch to find one that works.

Talking to peers

Once I had the address of a working peer, the next step was to send my transaction into the peer-to-peer network.[8] Using the peer-to-peer protocol is pretty straightforward. I opened a TCP connection to an arbitrary peer on port 8333, started sending messages, and received messages in turn. The Bitcoin peer-to-peer protocol is pretty forgiving; peers would keep communicating even if I totally messed up requests.

Important note: as a few people pointed out, if you want to experiment you should use the Bitcoin Testnet, which lets you experiment with "fake" bitcoins, since it's easy to lose your valuable bitcoins if you mess up on the real network. (For example, if you forget the change address in a transaction, excess bitcoins will go to the miners as a fee.) But I figured I would use the real Bitcoin network and risk my $1.00 worth of bitcoins.

The protocol consists of about 24 different message types. Each message is a fairly straightforward binary blob containing an ASCII command name and a binary payload appropriate to the command. The protocol is well-documented on the Bitcoin wiki.

The first step when connecting to a peer is to establish the connection by exchanging version messages. First I send a version message with my protocol version number[21], address, and a few other things. The peer sends its version message back. After this, nodes are supposed to acknowledge the version message with a verack message. (As I mentioned, the protocol is forgiving - everything works fine even if I skip the verack.)

Generating the version message isn't totally trivial since it has a bunch of fields, but it can be created with a few lines of Python. makeMessage below builds an arbitrary peer-to-peer message from the magic number, command name, and payload. getVersionMessage creates the payload for a versionmessage by packing together the various fields.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

magic = 0xd9b4bef9

def makeMessage(magic, command, payload):

checksum = hashlib.sha256(hashlib.sha256(payload).digest()).digest()[0:4]

return struct.pack('L12sL4s', magic, command, len(payload), checksum) + payload

def getVersionMsg():

version = 60002

services = 1

timestamp = int(time.time())

addr_me = utils.netaddr(socket.inet_aton("127.0.0.1"), 8333)

addr_you = utils.netaddr(socket.inet_aton("127.0.0.1"), 8333)

nonce = random.getrandbits(64)

sub_version_num = utils.varstr('')

start_height = 0

payload = struct.pack('<LQQ26s26sQsL', version, services, timestamp, addr_me,

addr_you, nonce, sub_version_num, start_height)

return makeMessage(magic, 'version', payload)

msgUtils.py hosted with ❤ by GitHub

Sending a transaction: tx

I sent the transaction into the peer-to-peer network with the stripped-down Python script below. The script sends a version message, receives (and ignores) the peer's version and verack messages, and then sends the transaction as a tx message. The hex string is the transaction that I created earlier.

1

2

3

4

5

6

7

8

9

10

11

def getTxMsg(payload):

return makeMessage(magic, 'tx', payload)

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

sock.connect(("97.88.151.164", 8333))

sock.send(msgUtils.getVersionMsg())

sock.recv(1000) # receive version

sock.recv(1000) # receive verack

sock.send(msgUtils.getTxMsg("0100000001484d40d45b9ea0d652fca8258ab7caa42541eb52975857f96fb50cd732c8b481000000008a47304402202cb265bf10707bf49346c3515dd3d16fc454618c58ec0a0ff448a676c54ff71302206c6624d762a1fcef4618284ead8f08678ac05b13c84235f1654e6ad168233e8201410414e301b2328f17442c0b8310d787bf3d8a404cfbd0704f135b6ad4b2d3ee751310f981926e53a6e8c39bd7d3fefd576c543cce493cbac06388f2651d1aacbfcdffffffff0162640100000000001976a914c8e90996c7c6080ee06284600c684ed904d14c5c88ac00000000".decode('hex')))

minimalSendTxn.py hosted with ❤ by GitHub

The following screenshot shows how sending my transaction appears in the Wireshark network analysis program[22]. I wrote Python scripts to process Bitcoin network traffic, but to keep things simple I'll just use Wireshark here. The "tx" message type is visible in the ASCII dump, followed on the next line by the start of my transaction (01 00 ...).

A transaction uploaded to Bitcoin, as seen in Wireshark.

To monitor the progress of my transaction, I had a socket opened to another random peer. Five seconds after sending my transaction, the other peer sent me a tx message with the hash of the transaction I just sent. Thus, it took just a few seconds for my transaction to get passed around the peer-to-peer network, or at least part of it.

Victory: my transaction is mined

After sending my transaction into the peer-to-peer network, I needed to wait for it to be mined before I could claim victory. Ten minutes later my script received an inv message with a new block (see Wireshark trace below). Checking this block showed that it contained my transaction, proving my transaction worked. I could also verify the success of this transaction by looking in my Bitcoin wallet and by checking online. Thus, after a lot of effort, I had successfully created a transaction manually and had it accepted by the system. (Needless to say, my first few transaction attempts weren't successful - my faulty transactions vanished into the network, never to be seen again.[8])

A new block in Bitcoin, as seen in Wireshark.

My transaction was mined by the large GHash.IO mining pool, into block #279068 with hash 0000000000000001a27b1d6eb8c405410398ece796e742da3b3e35363c2219ee. (The hash is reversed in inv message above: ee19...) Note that the hash starts with a large number of zeros - finding such a literally one in a quintillion value is what makes mining so difficult. This particular block contains 462 transactions, of which my transaction is just one.

For mining this block, the miners received the reward of 25 bitcoins, and total fees of 0.104 bitcoins, approximately $19,000 and $80 respectively. I paid a fee of 0.0001 bitcoins, approximately 8 cents or 10% of my transaction. The mining process is very interesting, but I'll leave that for a future article.

Bitcoin mining normally uses special-purpose ASIC hardware, designed to compute hashes at high speed. Photo credit: Gastev, CC:by

Conclusion

Using the raw Bitcoin protocol turned out to be harder than I expected, but I learned a lot about bitcoins along the way, and I hope you did too. My code is purely for demonstration - if you actually want to use bitcoins through Python, use a real library[24] rather than my code.

Notes and references

[1] The original Bitcoin client is Bitcoin-qt. In case you're wondering why qt, the client uses the common Qt UI framework. Alternatively you can use wallet software that doesn't participate in the peer-to-peer network, such as Electrum or MultiBit. Or you can use an online wallet such as Blockchain.info.

[2] A couple good articles on Bitcoin are How it works and the very thorough How the Bitcoin protocol actually works.

[3] The original Bitcoin paper is Bitcoin: A Peer-to-Peer Electronic Cash System written by the pseudonymous Satoshi Nakamoto in 2008. The true identity of Satoshi Nakamoto is unknown, although there are many theories.

[4] You may have noticed that sometimes Bitcoin is capitalized and sometimes not. It's not a problem with my shift key - the "official" style is to capitalize Bitcoin when referring to the system, and lower-case bitcoins when referring to the currency units.

[5] In case you're wondering how the popular MtGox Bitcoin exchange got its name, it was originally a trading card exchange called "Magic: The Gathering Online Exchange" and later took the acronym as its name.

[6] For more information on what data is in the blockchain, see the very helpful article Bitcoin, litecoin, dogecoin: How to explore the block chain.

[7] I'm not the only one who finds the Bitcoin transaction format inconvenient. For a rant on how messed up it is, see Criticisms of Bitcoin's raw txn format.

[8] You can also generate transaction and send raw transactions into the Bitcoin network using the bitcoin-qt console. Type sendrawtransaction a1b2c3d4.... This has the advantage of providing information in the debug log if the transaction is rejected. If you just want to experiment with the Bitcoin network, this is much, much easier than my manual approach.

[9] Apparently there's no solid reason to use RIPEM-160 hashing to create the address and SHA-256 hashing elsewhere, beyond a vague sense that using a different hash algorithm helps security. See discussion. Using one round of SHA-256 is subject to a length extension attack, which explains why double-hashing is used.

[10] The Base58Check algorithm is documented on the Bitcoin wiki. It is similar to base 64 encoding, except it omits the O, 0, I, and l characters to avoid ambiguity in printed text. A 4-byte checksum guards against errors, since using an erroneous bitcoin address will cause the bitcoins to be lost forever.

[11] Some boilerplate has been removed from the code snippets. For the full Python code, see my repository shirriff/bitcoin-code on GitHub. You will also need the ecdsa cryptography library.

[12] You may wonder how I ended up with addresses with nonrandom prefixes such as 1MMMM. The answer is brute force - I ran the address generation script overnight and collected some good addresses. (These addresses made it much easier to recognize my transactions in my testing.) There are scriptsand websites that will generate these "vanity" addresses for you.

[13] For a summary of Bitcoin fees, see bitcoinfees.com. This recent Reddit discussion of fees is also interesting.

[14] The original Bitcoin paper has a similar figure showing how transactions are chained together. I find it very confusing though, since it doesn't distinguish between the address and the public key.

[15] For details on the different types of contracts that can be set up with Bitcoin, see Contracts. One interesting type is the 2-of-3 escrow transaction, where two out of three parties must sign the transaction to release the bitcoins. Bitrated is one site that provides these.

[16] Although Bitcoin's Script language is very flexible, the Bitcoin network only permits a few standard transaction types and non-standard transactionsare not propagated (details). Some miners will accept non-standard transactions directly, though.

[17] There isn't a security benefit from copying the scriptPubKey into the spending transaction before signing since the hash of the original transaction is included in the spending transaction. For discussion, see Why TxPrev.PkScript is inserted into TxCopy during signature check?

[18] The random number used in the elliptic curve signature algorithm is critical to the security of signing. Sony used a constant instead of a random number in the PlayStation 3, allowing the private key to be determined. In an incident related to Bitcoin, a weakness in the random number generatorallowed bitcoins to be stolen from Android clients.

[19] For Bitcoin, the coordinates on the elliptic curve are integers modulo the prime2^256 - 2^32 - 2^9 -2^8 - 2^7 - 2^6 -2^4 -1, which is very nearly 2^256. This is why the keys in Bitcoin are 256-bit keys.

[20] For information on the historical connection between elliptic curves and ellipses (the equation turns up when integrating to compute the arc length of an ellipse) see the interesting article Why Ellipses Are Not Elliptic Curves, Adrian Rice and Ezra Brown, Mathematics Magazine, vol. 85, 2012, pp. 163-176. For more introductory information on elliptic curve cryptography, see ECC tutorial or A (Relatively Easy To Understand) Primer on Elliptic Curve Cryptography. For more on the mathematics of elliptic curves, see An Introduction to the Theory of Elliptic Curves by Joseph H. Silverman. Three Fermat trails to elliptic curves includes a discussion of how Fermat's Last Theorem was solved with elliptic curves.

[21] There doesn't seem to be documentation on the different Bitcoin protocol versions other than the code. I'm using version 60002 somewhat arbitrarily.

[22] The Wireshark network analysis software can dump out most types of Bitcoin packets, but only if you download a recent "beta release - I'm using version 1.11.2.

[24] Several Bitcoin libraries in Python are bitcoin-python, pycoin, and python-bitcoinlib.

[25] The elliptic curve plot was generated from the Sage mathematics package:

var("x y") implicit_plot(y^2-x^3-7, (x,-10, 10), (y,-10, 10), figsize=3, title="y^2=x^3+7")

[26] The hardcoded peer list in the Bitcoin client is in chainparams.cpp in the array pnseed. For more information on finding Bitcoin peers, see How Bitcoin clients find each other or Satoshi client node discovery.

Bitcoin multisig the hard way: Understanding raw P2SH multisig transactions

20 DECEMBER 2014

Recently, inspired by Ken Shirriff's and Bryce Neal's low level looks at the Bitcoin protocol, I set about constructing Bitcoin's much talked about multisignature transactions from scratch to understand their capabilities and limitations. Specifically, I used Bitcoin's Pay-to-ScriptHash (P2SH) transaction type to create a M-of-N multisignature transaction. The code to do it all in Go is available as go-bitcoin-multsig on GitHub and I'd like to go through how all of this works at the Bitcoin protocol level. We'll also step through creating and spending a multisig transaction to make it all clearer.

In many ways, this is a follow up to Ken's amazing explanation of the Bitcoin protocol and constructing a Pay-to-PubKeyHash (P2PKH) transaction, so I won't cover things covered there in any great detail. Please check out his post out first if you're completely new to the Bitcoin protocol.

I'll be using go-bitcoin-multisig to generate keys and transactions along the way, explaining each step. If you'd like to follow along and create a multisig transaction yourself, you'll need to follow the simple build instructions for go-bitcoin-multisig.

What is a Pay-to-ScriptHash (P2SH) transaction?

A typical Bitcoin address that looks like 15Cytz9sHqeqtKCw2vnpEyNQ8teKtrTPjp is actually a specific type of Bitcoin address known as a Pay-to-PubKeyHash (P2PKH) address. To spend Bitcoin funds sent to this type of address, the recipient must use the private key associated with the public key hash specified in that address to create a digital signature, which is put into the scriptSig of a spending transaction, unlocking the funds.

A Pay-to-ScriptHash (P2SH) Bitcoin address looks and works quite differently. A typical P2SH address looks like 347N1Thc213QqfYCz3PZkjoJpNv5b14kBd. A P2SH address always begins with a '3', instead of a '1' as in P2PKH addresses. This is because P2SH addresses have a version byte prefix of 0x05, instead of the 0x00 prefix in P2PKH addresses, and these come out as a '3' and '1' after base58check encoding.

So what information is encoded in a P2SH address? A specific unspent Bitcoin can actually have a whole range of different spending conditions attached to it, the most common being a typical P2PKH which just requires the recipient to provide a signature matching the public key hash. The Bitcoin core developers realized that people were looking at the capabilities of Bitcoin's Script language and seeing a whole array of possibilities about what spending conditions you could attach to a Bitcoin output, to create much more elaborate transactions than just P2PKH transactions. The core developers decided that instead of letting senders put in long scripts into their scriptPubKey (where spending conditions usually go), they would let each sender put in a hash of their spending conditions instead. These spending conditions are known as the redeem script, and a P2SH funding transaction simply contains a hash of this redeem script in the scriptPubKey of the funding transaction.The redeem script itself is only revealed, checked against the redeem script hash, and evaluated during the spending transaction.

Source: https://bitcoin.org

This puts the responsibility of providing the full redeem script on to the recipient of the P2SH funds. This has a number of advantages:

    • The sender can fund any arbitrary redeem script without knowing what those spending conditions are. This makes sense because a sender largely does not care about how their funds will be spent in the future -- this is an issue for the recipient who cares about the conditions of further spending. In the case of multisig transactions, the sender can send funds without knowing the required public keys (belonging to the recipient) of a multisignature address, which are revealed only when the recipient is spending the funds. This increases security for the recipient.

    • The sender can use a short, 34-character address like the one above, instead of a long, unwieldy one containing details of a full redeem script. This lets a recipient put up just a short address on their payment page or message, reducing the chance of human errors in transcription.

    • It lowers the transaction fees for the sender of funds. Transaction fees are proportional to the size of a transaction, and a fixed length hash lets the sender send funds to any arbitrary redeem script without worrying about paying higher fees. It is the responsibility of the recipient who creates the redeem script to determine how large their spending transaction will be and how much it will cost. This is a small issue at the moment since transaction costs are quite small, but they may be more important in the future as block rewards get smaller in Bitcoin.

All of this will hopefully make more sense as we go ahead and craft a multisignature P2SH transaction. If you'd like to learn more, the Bitcoin developer guide has a full explanation of P2SH transactions.

Creating a 2-of-3 multisig P2SH address

We will create a 2-of-3 multisignature address, where 2 digital signatures of 3 possible public keys are required to spend funds sent to this address.

First we need the hex representations of 3 public keys. There are lots of private/public key pair generators out there, but here we will use the one built into go-bitcoin-multisig. These keys are cryptographically secure to the limits of Go's crypto/randpackage, which uses /dev/urandom/ on Unix-like systems and CryptGenRandom API on Windows:

go-bitcoin-multisig --count 3 --concise

Which outputs for us: (your generated keys will be different, of course)

-------------- KEY #1 Private key: 5JruagvxNLXTnkksyLMfgFgf3CagJ3Ekxu5oGxpTm5mPfTAPez3 Public key hex: 04a882d414e478039cd5b52a92ffb13dd5e6bd4515497439dffd691a0f12af9575fa349b5694ed3155b136f09e63975a1700c9f4d4df849323dac06cf3bd6458cd Public Bitcoin address: 1JzVFZSN1kxGLTHG41EVvY5gHxLAX7q1Rh ---------------------------- KEY #2 Private key: 5JX3qAwDEEaapvLXRfbXRMSiyRgRSW9WjgxeyJQWwBugbudCwsk Public key hex: 046ce31db9bdd543e72fe3039a1f1c047dab87037c36a669ff90e28da1848f640de68c2fe913d363a51154a0c62d7adea1b822d05035077418267b1a1379790187 Public Bitcoin address: 14JfSvgEq8A8S7qcvxeaSCxhn1u1L71vo4 ---------------------------- KEY #3 Private key: 5JjHVMwJdjPEPQhq34WMUhzLcEd4SD7HgZktEh8WHstWcCLRceV Public key hex: 0411ffd36c70776538d079fbae117dc38effafb33304af83ce4894589747aee1ef992f63280567f52f5ba870678b4ab4ff6c8ea600bd217870a8b4f1f09f3a8e83 Public Bitcoin address: 1Kyy7pxzSKG75L9HhahRZgYoer9FePZL4R --------------

So we have 3 public keys in hex ready to go:

Key A:

04a882d414e478039cd5b52a92ffb13dd5e6bd4515497439dffd691a0f12af9575fa349b5694ed3155b136f09e63975a1700c9f4d4df849323dac06cf3bd6458cd

Key B:

046ce31db9bdd543e72fe3039a1f1c047dab87037c36a669ff90e28da1848f640de68c2fe913d363a51154a0c62d7adea1b822d05035077418267b1a1379790187

Key C:

0411ffd36c70776538d079fbae117dc38effafb33304af83ce4894589747aee1ef992f63280567f52f5ba870678b4ab4ff6c8ea600bd217870a8b4f1f09f3a8e83

Now, we specify that we want a 2-of-3 address and provide our 3 public keys to generate our P2SH address:

go-bitcoin-multisig address --m 2 --n 3 --public-keys 04a882d414e478039cd5b52a92ffb13dd5e6bd4515497439dffd691a0f12af9575fa349b5694ed3155b136f09e63975a1700c9f4d4df849323dac06cf3bd6458cd,046ce31db9bdd543e72fe3039a1f1c047dab87037c36a669ff90e28da1848f640de68c2fe913d363a51154a0c62d7adea1b822d05035077418267b1a1379790187,0411ffd36c70776538d079fbae117dc38effafb33304af83ce4894589747aee1ef992f63280567f52f5ba870678b4ab4ff6c8ea600bd217870a8b4f1f09f3a8e83

Which outputs for us:

--------------------- Your *P2SH ADDRESS* is: 347N1Thc213QqfYCz3PZkjoJpNv5b14kBd Give this to sender funding multisig address with Bitcoin. ------------------------------------------ Your *REDEEM SCRIPT* is: 524104a882d414e478039cd5b52a92ffb13dd5e6bd4515497439dffd691a0f12af9575fa349b5694ed3155b136f09e63975a1700c9f4d4df849323dac06cf3bd6458cd41046ce31db9bdd543e72fe3039a1f1c047dab87037c36a669ff90e28da1848f640de68c2fe913d363a51154a0c62d7adea1b822d05035077418267b1a1379790187410411ffd36c70776538d079fbae117dc38effafb33304af83ce4894589747aee1ef992f63280567f52f5ba870678b4ab4ff6c8ea600bd217870a8b4f1f09f3a8e8353ae Keep private and provide this to redeem multisig balance later. ---------------------

Let's breakdown that redeem script since that is where all the magic happens. A valid multisignature redeem script, according to the Bitcoin protocol, looks like:

<OP_2> <A pubkey> <B pubkey> <C pubkey> <OP_3> <OP_CHECKMULTISIG>

And this is what our particular redeem script contains:

From this redeemScript, our P2SH address is generated with two more steps:

1. Double hash our redeemScript (in pseudocode to show specific hash functions):

redeemScriptHash = RIPEMD160(SHA256(redeemScript))

2. Base58check encode our redeemscriptHash with a prefix of 0x05

P2SHAddress := base58check.Encode("05", redeemScriptHash)

And that's how go-bitcoin-multisig gives us our P2SH address of 347N1Thc213QqfYCz3PZkjoJpNv5b14kBd. It contains a hashed redeem script with our chosen public keys and multisig script, but this will not be revealed publicly until the spending transaction, since it has been hashed. We would at this point pass this address to the sender who is funding our multisig address.

Funding our P2SH address

To fund our multisig address now, we need a funding source of Bitcoins. go-bitcoin-multisig will fund from a standard P2PKH output, and we will need the input transaction id (txid), its matching private key, the amount to send (with the remaining balance taken as fees) and the destination P2SH address (which we just generated):

go-bitcoin-multisig fund --input-tx 3ad337270ac0ba14fbce812291b7d95338c878709ea8123a4d88c3c29efbc6ac --private-key 5JJyqG4bb15zqi7fTA4b227aUxQhBo1Ux6qX69ngeXYLr7fk2hs --destination 347N1Thc213QqfYCz3PZkjoJpNv5b14kBd --amount 65600

Which outputs for us:

----------------------------------------------------------------------------------------------------------------------------------- Your raw funding transaction is: 0100000001acc6fb9ec2c3884d3a12a89e7078c83853d9b7912281cefb14bac00a2737d33a000000008a47304402204e63d034c6074f17e9c5f8766bc7b5468a0dce5b69578bd08554e8f21434c58e0220763c6966f47c39068c8dcd3f3dbd8e2a4ea13ac9e9c899ca1fbc00e2558cbb8b01410431393af9984375830971ab5d3094c6a7d02db3568b2b06212a7090094549701bbb9e84d9477451acc42638963635899ce91bacb451a1bb6da73ddfbcf596bddfffffffff01400001000000000017a9141a8b0026343166625c7475f01e48b5ede8c0252e8700000000 Broadcast this transaction to fund your P2SH address. -----------------------------------------------------------------------------------------------------------------------------------

Note that the generated transaction changes slightly each time because of the nonce in the digital signatures and this may change the total size of the transaction slightly each time. Everything else should remain the same.

Let's breakdown our funding transaction:

The key difference compared to a typical P2PKH transaction is the scriptPubKey. We now have a scriptPubKey of the form:

<OP_HASH160> <redeemScriptHash> <OP_EQUAL>

Remember that OP_HASH160 in Bitcoin Script is just a RIPEMD160(SHA256()) function. This is used to compare the redeem script provided in the spending transaction to the hash in the funding transaction. We'll see how the scriptPubKey here and the scriptSig of the spending transaction come together shortly.

At this point, you can broadcast your own funding transaction and have it actually confirmed on the network. Don't forget to include a transaction fee (maybe ~10000 satoshi) so miners choose to include it in their blocks. The Blockchain.info pushtx toolor any other broadcast tool will work fine. The transaction above was broadcast and confirmed as txid 02b082113e35d5386285094c2829e7e2963fa0b5369fb7f4b79c4c90877dcd3d.

Spending our multisig P2SH funds

Now we want to be able to spend our P2SH multisig funds. First let's generate another key pair to be our destination where we can send our multisig funds.

go-bitcoin-multisig keys --concise

Which outputs for us:

-------------- KEY #1 Private key: 5Jmnhuc5gPWtTNczYVfL9yTbM6RArzXe3QYdnE9nbV4SBfppLcx Public key hex: 04459b7e1711f31e64507061bccb89fb618e86b254140dc98a42093e449fef067f2ece0a9b11a63697a11c5176528c436570499a13aa22824be53ea2718173b45a Public Bitcoin address: 18tiB1yNTzJMCg6bQS1Eh29dvJngq8QTfx --------------

Now, we will need 2 of the 3 private keys of the public keys used to generate our P2SH address. We'll use our 1st and 3rd original generated private keys (any 2 of 3 would work, of course).

Now, this is important: the order of keys does matter. We can obviously skip keys when our M required keys is less than our N possible keys, but they must show up in our signed spending transaction in the same order that they were provided in the redeem script.[1] go-bitcoin-multisig will sign the spending transaction in the order of keys given.

To create our spending transaction, we need the input txid of the funding transaction, our amount (with the remaining balance going to transaction fees) and the destination. We must also provide the original redeem script. Remember, the destination P2SH address is a hash and doesn't reveal our redeem script. Only the recipient who created the P2SH address knows the full redeem script, and in this case, we are that recipient and can provide it:

go-bitcoin-multisig spend --input-tx 02b082113e35d5386285094c2829e7e2963fa0b5369fb7f4b79c4c90877dcd3d --amount 55600 --destination 18tiB1yNTzJMCg6bQS1Eh29dvJngq8QTfx --private-keys 5JruagvxNLXTnkksyLMfgFgf3CagJ3Ekxu5oGxpTm5mPfTAPez3,5JjHVMwJdjPEPQhq34WMUhzLcEd4SD7HgZktEh8WHstWcCLRceV --redeemScript 524104a882d414e478039cd5b52a92ffb13dd5e6bd4515497439dffd691a0f12af9575fa349b5694ed3155b136f09e63975a1700c9f4d4df849323dac06cf3bd6458cd41046ce31db9bdd543e72fe3039a1f1c047dab87037c36a669ff90e28da1848f640de68c2fe913d363a51154a0c62d7adea1b822d05035077418267b1a1379790187410411ffd36c70776538d079fbae117dc38effafb33304af83ce4894589747aee1ef992f63280567f52f5ba870678b4ab4ff6c8ea600bd217870a8b4f1f09f3a8e8353ae

Which outputs for us:

Your raw spending transaction is: 01000000013dcd7d87904c9cb7f4b79f36b5a03f96e2e729284c09856238d5353e1182b00200000000fd5d01004730440220762ce7bca626942975bfd5b130ed3470b9f538eb2ac120c2043b445709369628022051d73c80328b543f744aa64b7e9ebefa7ade3e5c716eab4a09b408d2c307ccd701483045022100abf740b58d79cab000f8b0d328c2fff7eb88933971d1b63f8b99e89ca3f2dae602203354770db3cc2623349c87dea7a50cee1f78753141a5052b2d58aeb592bcf50f014cc9524104a882d414e478039cd5b52a92ffb13dd5e6bd4515497439dffd691a0f12af9575fa349b5694ed3155b136f09e63975a1700c9f4d4df849323dac06cf3bd6458cd41046ce31db9bdd543e72fe3039a1f1c047dab87037c36a669ff90e28da1848f640de68c2fe913d363a51154a0c62d7adea1b822d05035077418267b1a1379790187410411ffd36c70776538d079fbae117dc38effafb33304af83ce4894589747aee1ef992f63280567f52f5ba870678b4ab4ff6c8ea600bd217870a8b4f1f09f3a8e8353aeffffffff0130d90000000000001976a914569076ba39fc4ff6a2291d9ea9196d8c08f9c7ab88ac00000000 Broadcast this transaction to spend your multisig P2SH funds.

Again, the transaction will look slightly different each time because of the changing nonce in the digital signature, but everything else should look the same.

Let's breakdown our raw spending transaction:

Let's look at how the Bitcoin protocol will run through the script here. Combining the spending transaction scriptSig and funding transaction scriptPubKey, we get:

<OP_0> <sig A> <sig C> <redeemScript> <OP_HASH160> <redeemScriptHash> <OP_EQUAL>

Stepping through this script:

    1. OP_0 and the two signatures are added to the stack, kept for later.

    2. The redeemScript is added to the stack.

    3. OP_HASH160 hashes our redeemScript.

    4. redeemScriptHash is added to the stack.

    5. OP_EQUAL will compare OP_HASH160(redeemScript) and redeemScriptHash and check for equality. This confirms that our spending transaction is providing the correct redeemScript.

    6. Now our redeemScript can be evaluated:

      1. <OP_2> <A pubkey> <B pubkey> <C pubkey> <OP_3> <OP_CHECKMULTISIG>

    7. OP_CHECKMULTISIG will look at the 3 public keys and 2 signatures in the stack, and compare them one by one. As stated earlier, the order of signatures matters here and must match the order that the public keys were provided in.[1].

    8. OP_0 is included only to deal with an off-by-one error in Bitcoin Core when using OP_CHECKMULTISIG.

A couple of important notes, especially for troubleshooting, on how this raw transaction is created:

    • Ken talks in his post about how there is a temporary scriptSig when signing the raw transaction, before a signature (and hence final scriptSig) is available. For a P2PKH, this temporary scriptSig is the scriptPubKey of the input transaction. For a P2SH, the temporary scriptSig is the redeemScript itself. I am yet to find this clearly documented in the protocol specifications anywhere, but I may have just not found it. The only way I figured it out (after much pain) was by reverse engineering bitcoinjs-lib.[2]

    • When pushing items to the stack in Bitcoin Script, the usual format is <size of item> <item>. However, if the length of the item is greater than 75 bytes, this length would start to look identical to OP codes 76 and up. Therefore, we use the special opcodes OP_PUSHDATA1, OP_PUSHDATA2 and OP_PUSHDATA4 (indicating that the next 1, 2 or 4 bytes, respectively, specify the size of item to be pushed to stack) in these cases, and this happens for our larger redeemScript.[3]

    • The scriptSig length is included in a transaction as a var_int type in the Bitcoin protocol. This means that it can take up more than the usual one byte length if needed. For any scriptSig longer than 253 bytes, we can use two bytes by writing 0xfd (253) followed by two bytes specifying the scriptSig length, in little endian format.[4] Be careful though, you can only use two bytes if and only if it is needed. If it is smaller than 253 bytes, use the usual one byte to store the scriptSig length. Otherwise your signature with an unnecessarily long var_int will be considered invalid. This was another painful lesson learned only through repeated tests and reverse engineering bitcoinjs-lib. See here for the relevant Go code to see exactly what I mean.

We can now broadcast this transaction to spend our multisig P2SH funds. You can see the above transaction confirmed as txid eeab3ef6cbea5f812b1bb8b8270a163b781eb7cde10ae5a7d8a3f452a57dca93.

Wrap-up

Voila! We've just generated an M-of-N multisig P2SH address, funded it from a Bitcoin output and spent those funds by providing M signatures. I hope all of that was helpful for anyone trying to understand the innards of the Bitcoin protocol or trying to build multisig applications on top of the raw Bitcoin protocol. If there are any issues or questions about any part of the process, feel free as always to reach out to me on Twitter @soroushjp or email at me_AT_soroushjp.com.

Happy Holidays and Happy Bitcoining!

Appendix

References

Helpful Tools