Typical e-currencies before BitCoin were based on securities - there is a central system of distribution and every user of such currency is dependent on that. On the other hand BitCoin, as well as any other cryptocurrency, is simply a huge ledger including every transaction ever made. That approach allows BitCoin to forget about one, central administrator and emitter of the currency. Everyone using BitCoin has a history of all the transactions and can verify it.
A BitCoin transaction is just a document telling what amount of currency has been transferred between which accounts.
(more about transactions: https://en.bitcoin.it/wiki/Transaction)
An account (wallet) is defined by the account ID only. The account ID is a public key in Eliptic Curves Cryptography. To generate such key you can use
openssl (please note that it cannot be a valid BitCoin wallet - this is only an example of how the cryptocurrency like BitCoin can be implemented):
$ openssl ecparam -name secp256k1 -genkey -noout -out private_key.pem $ openssl ec -in private_key.pem -pubout -out public_key.pem
The private key has to be stored in secret - this is the only way to get access to the BitCoin money! The public keys are acting like transaction addresses. The private keys are used to sign every transaction:
$ openssl dgst -sha256 -sign private_key.pem -out file.txt.sig file.txt
The transaction is being signed by a payor. That makes the transaction confident, because everyone can prove that transaction has been done by payor by verifying the signature:
$ openssl dgst -sha256 -verify public_key.pem -signature file.txt.sig file.txt
The amount of bitcoins that belong to an account is being calculated by iterating over all transactions made with this account - a summary of all incomes and outcomes.
After creating and signing a transaction, BitCoin client sends it via P2P to any other BitCoin client. This works very similar to torrent data propagation.
Blocks of transactions
While the transactions are being collected they form a structure called a Block of transactions. The blocks contains a transaction table in certain order. To make sure the data is ordered properly, BitCoin client makes a Merkle tree structure. Let me illustrate it by example:
Let's say that we have three transactions: a, b and c. In the first place, we need to calculate the hash of every transaction:
d1 = sha(a) d2 = sha(b) d3 = sha(c)
We collected the three transactions, but we need the transactions quantity to be the power of two. To fill the missing spot, we will take the
d4 = sha(c)
The second step is to calculate the hash for pairs of hashes from the previous step. The pair is defined here as a concatenation of the hashes:
d5 = sha(d1 concat d2) d6 = sha(d3 concat d4)
We will repeat the same steps until we end up with only one hash:
d7 = sha(d5 concat d6)
d7 is called the root of the Merkle tree.
Instead of simple SHA256 method, BitCoin client uses a double SHA256 as a hashing function:
# transactions single SHA256 hash $ echo -n hello | openssl dgst -sha2562cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824 # double SHA256 hash (SHA256D) $ echo -n hello | openssl dgst -sha256 -binary | openssl dgst -sha2569595c9df90075148eb06860365df33584b75bff782a510c6cd4883a419833d50
(more about Merkle trees: https://en.bitcoin.it/wiki/Protocol_documentation#Merkle_Trees)
The BitCoin has the following block structure:
Of course, it is a simplified model (see: https://en.bitcoin.it/wiki/Block)
Validating the block
The block has to have a certain structure, as well as proper values set in its fields. The verification of the block is the heart of the BitCoin algorithms.
First, the transactions have to be valid. Invalid transactions should not be included in the block.
- Every transaction should be verified (by validating the digital signature).
- Every transaction should be possible due to the payer account balance.
timefield value of the block should be greater than a previous block
previous block hashshould be a hash of the existing block in the blockchain.
- All transactions attached to the block should be valid due to merkle root of the block (content of transaction matters as well as transactions order).
Calculating target difficulty
To verify block we need to know the target difficulty. Difficulty is a value calculated form
bits field in a block. For instance, if we have
bits = 0x19015f53, then we can calculate exponent and mantissa:
# expontent $ echo "16 i 19015F53 A i 2 24 ^ / 16 o p" | dc19 # mantissa $ echo "16 i 19015F53 19015F53 A i 2 24 ^ / 2 24 ^ * - 16 o p" | dc15f53 # current target $ echo "16 i 2 19 3 - 8 * ^ 15F53 * 10 o p" | dc15F5300000000000000000000000000000000000000000000
The block is valid when it has set some values in the
nonce field (it could be any value) with one primary condition: the block hash has to be lower than or equal to calculated target!
The calculation of such value is a hard task for a client. The value in the
nonce is the proof of work.
Difficulty and changes in current target
The value in
bits is not random - it has to fulfill some assumption: it needs to keep the difficulty on such level that the block is being added to blockchain every 10 minutes. This assumption allows the BitCoin system to "approve" transaction every 10 minutes.
The current target is calculated with the help of the
difficulty feature. Current difficulty is:
difficulty = difficulty_1_target / current_target
0x1d00ffff (it is a constant) in compact format what is
0x00000000ffff0000000000000000000000000000000000000000000000000000 in hexadecimal.
To check if the difficulty is on the right level we need to check the hashrate of last 2016 blocks. The number 2016, assuming a cycle of 10 minutes, gives exactly two weeks. This time is compared with actual time that has been spent on calculating those 2016 blocks (basing on
time field) and the difficulty is being adjusted due to that comparison. When the difficulty is too high, then we need to reduce it by increasing the current
target, otherwise, we need to decrease current
next_difficulty = prev_difficulty * (2016 * 10 * 60) / time_between_last_2016_blocks
BitCoin mining and bitcoin distribution
Once the client generates a block it can be attached to the blockchain and propagated over P2P network. To remain in the blockchain, the block has to be the first generated. If there are several blocks generated, then the longest chain wins.
Every client that generates the block (i.e. finds the proper
nonce value) is rewarded with a
coinbase transaction. The number of bitcoins generated per block starts at 50 and is halved every 210,000 blocks (about four years).
To be certain that our transaction will be added to the blockchain quickly we can set a fee. The fee is a small amount of bitcoins. BitCoin clients are trying to put in their newly generated block transactions where the sum of fees is the biggest.
All the fees from transactions sum up to the bonus reward for a client that generated the winning block.
In the future, when the
coinbase transaction will consist of a very small amount, the fees will be the only reward for a block owner.
The algorithm behind BitCoin is quite simple and provides a good security base to store our money, but not only! Solutions provided by proof-of-work and blockchains allows to store any data that needs verification of ownership. There are several concepts like Proof of existence or BitCoin Notary to provide a simple way of verification of the documents/files/etc. ownership.