- snip -
Danny, thank you, you've been more than helpful with my questions over the past few weeks. I've been trying to get a more in-depth understanding of how everything is working under the hood of this beast. May I ask who you are quoting "encumbers an output with a requirement to supply a signature with a key that hashes to a given hash value"
In this circumstance, what is the given hash value's relation to the destination address? The signature you speak of is derived from the private key of the origin of the output, correct?
The pay-to-pub-key-hash makes reference to the pub key hash, but not the public key itself? I guess that is the point of the pkh?
Is there any resource you can suggest to me that covers this kind of thing all the way through?
Thanks
Shorena has done a pretty good job of answering you at a high level with generally used terms.
However, your questions are starting to get into some rather complicated details of the bitcoin protocol such that understanding how it actually works is going to require you to unlearn some things that most people believe about bitcoin.
The first thing to understand is that a "bitcoin address" is an abstraction that only exists at the human interface level. We use "addresses" to make it easier to discuss the transfer of control of value with those that aren't really interested in what is actually happening. There are no addresses in transactions or in the blockchain. The data that is stored there is just typically converted to an address representation when it is shown to humans.
The next thing to understand is that bitcoins aren't "sent" anywhere. They certainly aren't sent to an address (since as I just stated, addresses don't even exist at the protocol level). As a matter of fact, the concept of "bitcoins" as a thing that can be sent is just an abstraction that only exists at the human interface level. We use the concept of "a bitcoin", and "fractions of bitcoins" to make it easier to discuss transfer of control of value with those that aren't really interested in what is actually happening. There is nothing that can be called "a bitcoin" or "a satoshi" in transactions or in the blockchain. The value that is associated with an output is just typically referred to as a quantity of bitcoins when it is shown to humans. Perhaps we'll save this idea that bitcoins are just an abstraction and don't actually exist for another conversation, for now it's sufficient to understand that transactions are broadcast to peers on the bitcoin network, those peers verify that the transaction is valid and then relay it to their peers, eventually it gets to miners (or mining pools) which verify it is valid and include the transaction in a block, they perform a proof-of-work on the block and the block is then broadcast to all peers to be relayed and added to everyone's blockchain. So in the end, what you have are transactions registered in a shared blockchain, not bitcoins being removed from a wallet and sent anywhere.
What actually exists in transactions are output scripts. In every case other than the generation transaction, transactions are supplied value with inputs that are nothing more than unspent outputs from previous transactions (generation transactions get there value from another mechanism that isn't important for this discussion). All transactions then assign some, or all, of their value to new unspent outputs. Each output has a script that must be satisfied with some data in any input that tries to spend it. If the input does not supply data that allows the output script to be successfully executed, then the transaction is not valid.
There are opcode (operation code) bytes that are used to build the script. You can see the opcode list here:
https://en.bitcoin.it/wiki/ScriptOne possible output script is:
<OP_DUP> <OP_HASH160> 0x14 <
the 20 byte RIPEMD160 hash of a public key> <OP_EQUALVERIFY> <OP_CHECKSIG>
When this output is referenced as an input to a transaction, the data supplied by transaction input is pushed onto the stack. The script is then processed. The data that this script is expecting to be supplied by the transaction input is an ECDSA signature of the transaction that is spending this output and then a public key.
So the stack consists of a signature on the bottom, and then a public key on top of that.
The OP_DUP says to duplicate whatever element is on the top of the processing stack (the most thing most recently added, which in this case is the public key), and push the result on top of the stack.
So the stack now consists of a signature on the bottom, then a public key on top of that, then a duplicate of that public key on top of that.
OP_HASH160 says to remove the top element off the stack, use the RIPEMD160 algorithm to hash the data that was just removed, and push the result back on top of the stack.
So now the stack now consists of a signature on the bottom, then a public key on top of that, then a RIPEMD160 hash of that public key on top of that.
0x14 is a hex representation of the number 20. It says to push the next 20 bytes of the script onto the stack. This is the 20 byte RIPEMD160 hash from the output that is being spent.
So now the stack now consists of a signature on the bottom, then a public key on top of that, then a RIPEMD160 hash of that public key on top of that, then the RIPEMD160 hash from the output that is being spent on top of that.
OP_EQUALVERIFY says to remove the top two elements from the stack and verify that they are equal to each other. If they are not equal, then the transaction is invalid and we can stop processing. This verifies that the public key that was supplied by the person spending the output hashes to the same value as the RIPEMD160 hash that the output was encumbered with in its script. It is the public key that the output script was expecting.
So, as long as the two hashes were equal, the stack now consists of a signature on the bottom, then a public key on top of that.
OP_CHECKSIG says to remove the element on top of the stack and consider it to be an ECDSA public key, then remove the next element from the top of the stack and consider it to be a signature of the transaction that is attempting to spend the output. Then use ECDSA with the public key to verify that the signature is a valid signature of the transaction. We already determined with OP_EQUALVERIFY that this is the expected public key, so now we are making sure that the spender has control of the private key (since without the private key, they wouldn't have been able to generate a valid signature). If the signature is not valid, then the transaction is not valid and we can stop processing. If the signature is valid, then there is nothing left on the stack, there is nothing left of the script to process, and we have not encountered anything that reported as invalid, so the input is valid and will be accepted by all nodes running the bitcoin protocol.
This is a pay-to-pub-key-hash script. As you can probably see, this would be complicated and messy to have to write out every time you want someone to use this script in an output of a transaction that they are creating. Also, everything except the hash value in that script is constant. So, when creating wallets, we can all agree to call this script a "version 1" script. Then I could just give you the hash value and tell you to use the version 1 script.
Of course, I'd still have to give you the 160 bit hash value somehow, and there is a chance that you could make a typing error and put the wrong hash in there! Then nobody will be able to spend the output you create (unless someone else is lucky enough to have the key that hashes to whatever value you entered. So, I can create a 4 byte checksum on that 160 bit value, and give you that as well. Now there is only a 1 in 4294967295 chance that any typing error that you make in either the hash or the checksum will still result in a hash that matches the checksum.
Now I just need an easy way to give you the script version, the hash, and the checksum. If I send it to you in binary (and a use a full byte to represent the version), then I've got to send you a stream of 200 ones and zeros! Base58 representation of a number uses almost all of the english alphabetical characters as well as nearly all of the base 10 digits. It leaves out a few that are difficult to distinguish from other similarly shaped symbols (0,O,I,l) (zero, capital Oh, capital eye, lowercase el). So if we start with the 8 bit version, append the 160 bit hash value, append the 32 bit checksum, and then convert the resulting 200 bit number into base58, we'll get a much shorter alpha-numeric string (typically about 34 characters). We call this 34 character string a "bitcoin address".
So now, all we have to do is have all wallet creators agree that when they receive one of these "addresses" they will verify the checksum to prevent typing errors, and then recognize which script to create based on the version number.
Once we have such a system of creating "addresses" from standard scripts with some variable data, it becomes possible to come up with a new standard script and assign it a version number. Wallet creators can then add the new scripts to their wallets and all the users need to know to make use of the new script is what the new "address" looks like.
So, you can hopefully see here that output scripts encumber the output with a condition that must be met with input data in order for the output to be used to supply value to a transaction. Notice that the transactions don't actually send bitcoins anywhere. They just encumber outputs with conditions. Users that want to spend those outputs then satisfy those conditions with input data, and create new outputs that are encumbered with new conditions.
If you haven't already done so, I suggest that you read the bitcoin whitepaper that Satoshi Nakamoto wrote:
https://bitcoin.org/bitcoin.pdfThere are some generalizations in there, and there are some implementation details that were later improved upon, so it doesn't describe exactly how bitcoin works, but it gives a good high level overview of the general concepts.
As for some of these other details, You can learn a lot from exploring the bitcoin wiki. I'd suggest you start with the following if you are looking for details on the stuff I just described:
https://en.bitcoin.it/wiki/Base58Check_encodinghttps://en.bitcoin.it/wiki/Addresshttps://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresseshttps://en.bitcoin.it/wiki/List_of_address_prefixeshttps://en.bitcoin.it/wiki/Scripthttps://en.bitcoin.it/wiki/Transaction