Dependencies
-
Redis running on port 6379
-
flask
-
redis-py
-
python-ecdsa
-
jsonpickle
Running
Providing all dependencies are correctly installed with pip and Redis from apt-get
, first run the server with ./run_server.py
and then see a demo transaction by Alice with ./demo.py
.
Explanation
This implementation was intended as a simplified blockchain + currency implementation that was simple enough for any intelligent person to understand in brief, yet implemented in an abstract enough manner and close enough to the real implementation that Bitcoin could be seen as having many conceptually straightforward enhancements upon this implementation.
On startup, the server creates a genesis block, introducing some amount of coins (currently 50) into the economy. The server also generates itself a public and private key. The only transaction in the first block is the payment from the server to its public key. It is expected that the protocol will enforce the requirement of a signing of a transaction request by the server's private key before any of the 50 coins can be distributed, but at the moment, this centralized server can do whatever it wants (more on that later).
Currently, any user can request a distribution of funds by making a request to the server's free_money
endpoint, providing their public key and their requested amount. The server will then verify the amount requested remains unspent (unimplemented) and will append a block to the blockchain with a transaction ledger that some amount of coins have been distributed to the requester. If the transaction does not add up to the exact amount of unspent coins on the server, the transaction will be split so that X coins go to the requester and total - X go back to the public key of the server. This allows us to efficiently calculate the amount of available coins remaining on the server instead of having to go back to the genesis block each time and determine how many have been spent.
Although currently unimplemented, an endpoint send_money
would accept a destination public key, the transaction details, the requestor's public key, and a signature of the request that comes from signing the request with the requestor's private key and, based upon the difficulty of the Elliptic Curve crypographic algorithm, cannot be generated by another user with realistic odds. The server would then verify with the requestor's public key that the signature is, in fact, valid, guaranteeing the validity of the send money request. Then, the server would verify the amount of money available to spend and append the new transactions in the form of a new block, onto the blockchain similar to the server distributing coin as described above. Given the current scale of the platform, this could be done instantly, but in the larger scale, this could take a considerate amount of time and should include an incentive to the server for processing this transaction (more on that later).
A single block in this system appears as follows:
+---------------------------------------+
|hash_to_previous_block |
+---------------------------------------+
|Transaction list: |
|[(public_key_of_recipient, # of coins sent),|
| ...] |
| |
| |
| |
| |
+---------------------------------------+
Differences from Bitcoin
When comparing this blockchain and coin implementation to Bitcoin, I will assume all features have been completed. Following is a brief overview of some of the key features that could be added to this implementation to make it more similar to the full Bitcoin implementation.
Centralization
The current implementation is very similar to ScroogeCoin as described in Bitcoin and Cryptocurrency Technologies and is missing one of the most central appeals of Bitcoin: decentralization.
Currently, the server controls everything, including the security, the number of coins, and so forth. It would be easy for the server to manufacture infinite amounts of coins or to decide to never process other transactions.
Bitcoin avoids this dangerous centralization of control via distributed consensus. Anyone on the network has a say in the transactions and the creation of coins. One of the most conceptually challenging concepts of Bitcoin is the fact that this crowd literally controls every aspect of the currency, and it is only by the incentives to implement the protocol properly that all transactions are treated equally (instead of some being favored or some being denied entirely) and the coins have stable inflation. You can imagine the Bitcoin ecosystem like a class, and there was always that one moment that never panned out where someone said 'If we all refuse to take the final, the professor will have to give us all an A!'. But if the professor says, 'You can try, but I won't hesitate to give you all Fs,' then the vast majority of the class will fall in line and drop their protests.
Proof of work
A person's vote in the distributed Bitcoin system is determined by their computing power, a factor that, so far, has been an effective deterrent to system takeover. In the construct_block
method, the server generates a new block and appends the transactions to them, setting the hash_to_previous_block
to a sha256
hash of the block. In the full implementation, the hashing of this block would be done by the network, and they would have to factor in a repeatedly-generated, random nonce
into the hashing. The only valid hash_to_previous_block
accepted by the distributed network is one under a given target value called the difficulty
. This value is computed to make it probabilistically impossible to repeatedly generate hashes in a short amount of time, say, fewer than 10 minutes. This distributes the votes across the network, preventing one user from controlling a chain of records in the blockchain. It also allows a distribution of incentives, small portions of coin paid to the miners that provide proof of work.
Block space savings via Merkle trees
The current block uses a great deal of space by listing out each transaction in each block, requiring linear iteration to find a transaction. Through a Merkle tree, a block can store a hash value representing the root of a tree, and without storing any further data, the hash of any transaction in the tree can be determined in logarithmic time, thus achieving a win-win savings of both time and space.
And more
Understanding the centralized implementation is a great first step. Then, understanding the transition from centralization to decentralization encompasses many of the most critical pieces of the puzzle. However, there are many more moving parts that can be explored through the references below.
References
Bitcoin and Cryptocurrency Technologies
Bitcoin: Peer-to-Peer Electronic Cash