CeroCoinClient (version 1.9.0, 2018-March-20) |
CeroCoinClient.py
Version: 1.9.0
Author: Avinash Kak (kak@purdue.edu)
Date: 2018-March-20
Download Version 1.9.0:
gztar
bztar
View version 1.9.0 code in browser
Switch to Version 1.9.1
CONTENTS:
CHANGES
INTRODUCTION
WHAT TO DO AFTER YOU HAVE INSTALLED THIS MODULE
CeroCoinClient --- A MULTITHREADED IMPLEMENTATION
THE CeroCoin CLASS
THE COIN MINER THREAD
THE TRANSACTION MAKER THREAD
THE BLOCK MAKER THREAD
USING YOUR SMARTPHONE WiFi HOTSPOT FOR PORTABLE CeroCoin DEMOS
USAGE
CONSTRUCTOR PARAMETERS
INSTALLATION
BUGS
FUTURE PLANS
ABOUT THE AUTHOR
COPYRIGHT
CHANGES:
Version 1.9.0
This version includes improved inter-thread coordination among the miner
thread, the transaction maker thread, and the block maker thread. While
this version uses boolean flags for thread coordination, I am planning to
use Event based logic for doing the same in a future version of this module.
INTRODUCTION:
The purpose of this educational module is to serve as a platform for
explaining the following three key notions of crypto currencies: (1) What it
means to mine a coin; (2) How the ownership of a coin is transferred from
one client to another in a network; and (3) How the notion of blockchain is
used to prevent "double-spending".
The presentation on crypto currencies is a part of Lecture 15 in my class on
computer and network security at Purdue University. The idea is for the
students to learn about crypto currencies after they have become proficient
with public-key cryptography and hashing functions.
By its very definition, a crypto currency (CC) requires for its existence a
network of hosts that (1) compete in discovering new coins at a prescribed
level of proof-or-work difficulty; (2) that allow for coin ownership to be
transferred through the notion of a transaction that requires the buyer to
send its public key to the seller; and (3) that allows for all the prior
transactions that were accepted by the network to be embedded in the next
transaction through the magic of hashing.
This solely network-based existence of CC makes it challenging to present
the ideas involved in a classroom setting. It is to address this challenge
that I created the CeroCoinClient module.
The simplest classroom presentation with this module involves two networked
laptops that you can take with you to class. I will refer to the two laptops
(which can obviously be any two digital devices capable of executing Python)
as two CeroCoin clients. In one client, you execute this module with a
relatively low level of proof-of-work (PoW) difficulty and, in the the other
client, with a much higher PoW difficulty level. This makes it highly
likely that the client with the lower PoW difficulty will be the producer of
new coins and the other laptop would serve as the "buyer" of those coins.
By connecting the coin producing client to the overhead screen, you can
demonstrate (1) the production of coins; (2) the making of a transaction,
which requires the buyer to supply its public-key to the coin miner, and for
the seller to sign off on the coin to which was appended the buyer's public
key; and, finally, (3) the making of a block that is a packaging of a
certain number of transactions.
But note that PoW you assign to a client is just for getting started. After
the network has accepted a block, the client would have no choice but to
make its PoW value consistent with what is in the received block.
In any case, the two-laptop based presentation I have described above allows
you to demonstrate in a classroom setting how a CeroCoin client abandons its
current search for a new coin when it receives a block with a longer
blockchain length and/or with a PoW difficulty level that exceeds the level
being used in the current search.
This demonstration of how a CeroCoin client abandons its current search for
a new coin when it receives a block of transactions with a longer blockchain
length, or, for a given blockchain length, a higher level of PoW difficulty
is made visually compelling by the fact that the students can see for
themselves the change in the name of the coin miner thread in the display
you project on the overhead screen.
You can create even more interesting classroom demonstrations with more than
two laptops, with all laptops running
the CeroCoinClient module at a
prescribed level of PoW difficulty that changes as blocks are received from
the network. You can demonstrate the blocks being transferred between the
laptops and ongoing coin search in the individual laptops being replaced by
new search upon receipt of blocks with longer blockchain lengths and/or
blocks with higher levels of PoW difficulty.
The best venue for giving multi-laptop demonstrations is a computer network
lab where you can simultaneously project the outputs from the different
laptops on different overhead screens.
WHAT TO DO AFTER YOU HAVE INSTALLED THIS MODULE:
The easiest thing to do after you have installed the module is to execute
the script:
that you will find in the Examples directory of the distribution. For
obvious reasons, you must execute this script in each of the clients you are
using for your demo. It is a good idea to use different values for the
constructor parameters starting_pow_difficulty and num_transactions_in_block
in the different clients. That gives you a gentler start for the demo ---
although eventually all the clients will change their proof-of-work
difficulty level in order for this parameter to be consistent across the
network. By gentler start for the demo, I mean you showing the formation of the
coins, the formation of the transactions, and the construction of blocks without
becoming overwhelmed by the blocks going back and forth in the network.
CeroCoinClient --- A MULTITHREADED IMPLEMENTATION:
A working demonstration of the principles that underlie CC requires an
implementation that must either be multithreaded or one that is based on
multiprocessing. There are two important reasons for that: (1) The search
for a new coin is a completely random process in which the time taken to
discover the next coin cannot be predicted in advance. And (2) The ongoing
search for a new coin must be abandoned immediately when a block of
transactions is received from another client in the network if the received
block has a blockchain length that is longer than what is being used in the
current search, or, for a given blockchain length, if the received block has
a PoW difficultly level that is higher than what is being used in the
current search.
That implies that, at the least, you must execute the coin mining code and
the code that is in charge of receiving and validating incoming blocks in
two separate threads or processes. Since a client can construct a new block
using mixture of transactions some of which are based on the coins
discovered by the client, while others are based on the coins acquired from
other clients, you are going to have to also run the block construction code
in a separate thread or a process of its own.
I have chosen a multithreaded implementation for CeroCoinClient that launches
the following six different threads when you fire up the code in the
CeroCoinClient module: (1) A server thread that monitors the server port
6404 for requests for connection from other CeroCoinClient hosts in a
network; (2) When the request for a connection is accepted by the server
socket running in the server thread, it hands over the connection to a
client connection thread that maintains that connection going forward; (3) A
network scanner thread that establishes connections with the other CeroCoin
hosts in the network; (4) A coin miner thread that is constantly searching
for a new coin at a specified level of PoW difficulty; (5) A transaction
maker thread that springs into action when a client discovers a new coin,
offering the coin to the list of
CeroCoin clients discovered by the scanner
thread after this list is randomized; and, finally, (6) A block maker thread
that springs into action when it sees a certain minimum number of
transactions for packaging into a block.
In what follows, I will first present the CeroCoin class whose instances
represent the new coins that are discovered by the coin mining process, and
then present what is accomplished in several of the threads listed above in
an order that reflects how central a thread is to the overall demonstration
of how the coins are discovered, validated, and traded in a CeroCoin
network.
THE CeroCoin CLASS:
A coin must contain all the information necessary for establishing its
authenticity by the other CeroCoin clients in a network. The coin must show
the genesis string and the nonce whose combination led to the hash value
that met the proof-of-work condition. For obvious reasons, the coin
definition must also include the PoW difficulty level used for discovering
the coin. In the definition of CeroCoin, I have also included the identity
of the miner, which is the SHA256 hash of the miner's public key. Finally,
the miner must sign the coin that was discovered. Shown below is what a
coin looks like before it is embedded in a transaction.
COIN_ID=e8e95b71
COIN_MINER=7048aeaf64a9581e7937b73743984033ffbc71798b0e0f563508044fd5b4f566
MINER_PUB_KEY=CEROCOIN_PUBKEY,mod=bf7945e8da95c52f509fa3357a3c7f415faead2a4e8b36856
c06c9282da2838634d5c79cb64328a4e52b16ad39e0f877d9215c545f9e479244989638cd70db87,e=10001
GENESIS_STRING=6629f94e11003069b3433b6d7acaf239aaf1007c06a99aa5668cce2a05110821884b
0fb5996026f33e578e83300642ae20aa5bc07d1f6911a9e952871fe06c7efbadbae3391d562343
dea79920b44e7d4eb1c861dc96dad5d47e60b91a7c7e748b7bc349fc17d4694ddf81c6c8ca14c8
e14b89f9c38591dd874653cf6f657ae2
NONCE=fbadbae3391d562343dea79920b44e7d4eb1c861dc96dad5d47e60b91a7c7e748b7bc349fc17d4
694ddf81c6c8ca14c8e14b89f9c38591dd874653cf6f657ae2
POW_DIFFICULTY=252 TIMESTAMP=1521231331.09
HASHVAL=0347908fe169610afa4512b3b3cec9f1a7c12d6cb2359158d31f30ecea354528
SELLER_SIGNATURE=5d2333fad828291b237f0c8668c52e77dbedeca3a78b6d9c53c7b8c5df4de9ace38
db4486d18e8b682467ab3a60e82362f6e64b39b4cc8fd8f529783cf13a79d
CEROCOIN_END
The display shown above has placed each field of the coin in a new line.
That is just for ease of visualizing the structure of a coin. The internal
representation used for a coin does not include any newline characters.
Note, too, that every coin has associated with it a 32-bit randomly
generated ID as shown by the eight hex characters for the COIN_ID field.
THE COIN MINER THREAD:
The job assigned to the miner thread is to compute a hash of a string that
is a combination of what I referred to as a genesis string and a nonce. For
the very first coin in a network, the genesis string is a pseudorandomly
generally bit vector of length 256. However, after the clients start
broadcasting blocks, a client would have no choice but to use the latest
accepted block for creating the genesis string in its miner thread.
Obviously, every CeroCoin client has the freedom to start at ground zero
with a pseudorandomly generated genesis string. However, after a block is
accepted by the network, such a coin would not be accepted by the network
because the length of the blockchain incorporated in it would be shorter
than what is in the block that was accepted. The nonce is always generated
pseudorandomly.
The goal of the miner thread is keep on trying different possible values for
the nonce until a hash value is discovered that corresponds to the current
proof-of-value (PoW) difficulty level. The PoW difficulty level is
expressed as the acceptable upperbound for the hash value. Since this
module uses the SHA256 for hashing, the hash values produced are 256 bit
wide. Setting PoW to, say, 240 means that we would want the hash value to be
less than 2^240 in order to be acceptable for the discovery of a new
coin. So the smaller the value of PoW difficulty, the the greater the
challenge in discovering a new coin. Since a 256-bit hash implies 2^256
different possible values for the hash, a PoW difficulty of K would
translate into the ratio (2^K / 2^256) as the probability associated with
coin discovery. This probability can be made arbitrarily small by choosing
a sufficiently small value for K.
The miner thread presents the following sort of output as it searches for a
new coin:
Thread-3 -- Try 2 -- hashval: 4a46e047e4c4c5efcc51202275216617dcea433b424d0b5c091a23aa126b51be
Thread-3 -- Try 3 -- hashval: 1366538d6213c2abf951fdeed5838f417c64bd704c9cd5613ff8937ccaa70062
Thread-3 -- Try 4 -- hashval: 9542a932a80bb761869ad4c4c1919447205d5c21f4e991bee558ffdc7505c047
Thread-3 -- Try 5 -- hashval: b776f4d8d35302504196a2c738c9bfb07c60535b00ba57979b03ea6afd8b96a1
Thread-3 -- Try 6 -- hashval: 67ec79c047c41fdb5ed2ad598a9f364fde601f3b0c6925300f97775c45b656a1
Thread-3 -- Try 7 -- hashval: a0b6e4dda5a0ef40e12cc247fab09bf05ebf8ea0c7dc1b57f69c83ecdf83ee2c
Thread-3 -- Try 8 -- hashval: a7c267f63a34e381bc66a777b515eef215b3d8eaba63109e7f6388a9b1411372
...
...
...
It is important to note the name of the thread, "Thread-3" in the display
shown above, in which the miner is running. As mentioned earlier, when a
client receives a new block that incorporates a blockchain length that
exceeds the blockchain length in the genesis string being used currently, it
must abandon the ongoing work at mining and start over with a new genesis
string based on the new block. This can be seen by the change in the name
of the miner thread. When such an event takes place, you will see the
following sort of output in the terminal screen of the client that is
abandoning the present coin search and starting over:
========> self.blockchain_length: 8
========> received_block_pow_difficulty: 251
========> self.pow_difficulty: 251
========> WILL ASK THE CURRENT MINER THREAD TO STOP
>>>>>>>>> CURRENT MINER THREAD TERMINATED SUCCESSFULLY <<<<<<<<<<<<
========> STARTING A NEW COIN MINER THREAD WITH POW DIFFICULTY OF 251 AND BLOCKCHAIN LENGTH OF 12
THE TRANSACTION MAKER THREAD:
In the code, I have abbreviated the name of this thread to "transactor"
thread. (Sorry if you find the word "transactor" ugly.)
The job assigned to the transactor thread is to find another client in the
network who wants to acquire a coin. This other client must express its
willingness for becoming new owner of the coin by supplying its public key
to the transactor. The transactor thread appends the new owner's public key
to the coin being traded, places a timestamp on the coin thus augmented, and
digitally signs the resulting string. The output of these steps is referred
to as a transaction. Shown below is an example of such a transaction:
TRANSACTION_ID=c64a8969
CEROCOIN_BEGIN
COIN_ID=e8e95b71
COIN_MINER=7048aeaf64a9581e7937b73743984033ffbc71798b0e0f563508044fd5b4f566
MINER_PUB_KEY=CEROCOIN_PUBKEY,mod=bf7945e8da95c52f509fa3357a3c7f415faead2a4e8b36856
c06c9282da2838634d5c79cb64328a4e52b16ad39e0f877d9215c545f9e479244989638cd70db87,e=10001
GENESIS_STRING=6629f94e11003069b3433b6d7acaf239aaf1007c06a99aa5668cce2a05110821884b0
fb5996026f33e578e83300642ae20aa5bc07d1f6911a9e952871fe06c7efbadbae3391d562
343dea79920b44e7d4eb1c861dc96dad5d47e60b91a7c7e748b7bc349fc17d4694ddf81c6c
8ca14c8e14b89f9c38591dd874653cf6f657ae2
NONCE=fbadbae3391d562343dea79920b44e7d4eb1c861dc96dad5d47e60b91a7c7e748b7bc349fc17d46
94ddf81c6c8ca14c8e14b89f9c38591dd874653cf6f657ae2
POW_DIFFICULTY=252 TIMESTAMP=1521231331.09
HASHVAL=0347908fe169610afa4512b3b3cec9f1a7c12d6cb2359158d31f30ecea354528
SELLER_SIGNATURE=5d2333fad828291b237f0c8668c52e77dbedeca3a78b6d9c53c7b8c5df4de9ace38db
4486d18e8b682467ab3a60e82362f6e64b39b4cc8fd8f529783cf13a79d
CEROCOIN_END
SELLER=7048aeaf64a9581e7937b73743984033ffbc71798b0e0f563508044fd5b4f566
SELLER_PUB_KEY=CEROCOIN_PUBKEY,mod=bf7945e8da95c52f509fa3357a3c7f415faead2a4e8b36856c0
6c9282da2838634d5c79cb64328a4e52b16ad39e0f877d9215c545f9e479244989638cd70db87,e=10001
BUYER_PUB_KEY=CEROCOIN_PUBKEY,mod=bf7945e8da95c52f509fa3357a3c7f415faead2a4e8b36856c06c
9282da2838634d5c79cb64328a4e52b16ad39e0f877d9215c545f9e479244989638cd70db87,e=10001
TIMESTAMP=1521231336.11
SELLER_TRANX_SIGNATURE=27b55110b47dad71378f5747d815e4ad5bc6ca130c45f871ed4b83d43c94a4f38
52e0eab033645c7287865d9a32eeb0009b04e6fb899c75d40f1220f31fb5c7e
CEROCOIN_TRANSACTION_END---
Note again that the newlines in the display shown above are just to make it
easier for the reader to see the different fields. The internal
representation of a transaction is just one continuous string without any
newline characters in it.
THE BLOCK MAKER THREAD:
The job assigned to the block maker thread is to (1) package the generated
transactions into a block; (2) extend the blockchain length from the value
used in the previous block whose hash is incorporated in the new block, the
length being extended by the number of transactions in the current block;
(3) incorporate a timestamp in the new block; (4) digitally sign the block
with the private key of the client; and, finally, (5) broadcast the block
the CeroCoin network.
Note that a generated transaction cannot be treated on par with a received
transaction for the purpose of constructing a block. As mentioned earlier,
a transaction has a particular structure that, at least at the beginning,
indicates who produced the coin in the first place and to whom was the coin
ownership transferred subsequently. More generally, though, a transaction
indicates the change in ownership of a coin from a previous owner to its new
owner. For a block maker to create a block from both the self discovered
coins and the coins acquired from other clients, it would first need to
extract the coins from the received transactions. Subsequently, such coins
could be treated in the same way as the self-generated coins. This logic
does not yet exist in the CeroCoinClient module. I plan to include it in
a later version.
USING YOUR SMARTPHONE WiFi HOTSPOT FOR PORTABLE CeroCoin DEMOS:
As mentioned earlier, a crypto currency has no existence outside a network.
What that implies is that you cannot demonstrate the workings of crypto
currency algorithms with a single digital device. (This statement of mine
does not apply if you can create multiple virtual machines on a laptop. A
network of VMs would obviously allow you to demonstrate all of the key
concepts mentioned so far with a single laptop.)
If you want to give demos with CeroCoinClient in different networking
environments, you'd need to manually enter the IP addresses of all the
digital devices you plan to use in your demo in the constructor call for the
CeroCoinClient class.
This can get to be tiring after a while.
The easiest solution to the problem is to use the WiFi hotspot on your
personal smartphone as a means to network all the digital devices you wish
to use in your demo. Let's say you create a demo involving 2 or 3 laptops
at home, with all the laptops connected through your smartphone based
WiFi hotspot. The first time you do this, you will have to manually
enter the IP addresses of the different laptops in the value
of the CeroCoinClient constructor parameter cerocoin_network. Subsequenly,
if you use the same WiFi hotspot in your classroom for networking
the laptops, you won't have to change a thing in the IP addresses previously
entered in the CeroCoinClient constructor call. This works because when
connecting with a WiFi access point a digital device's first preference is to
ask for the same IP address as it had the last time. If that address got
assigned to some other client, your laptop would get a different IP address.
So just make sure that you connect your demo laptops to your smartphone AP
before you invite any of your students to join in through their own laptops.
USAGE:
To create a CeroCoinClient node in a network, all you have to do is to
execute the following constructor call:
M = choose a value for the RSA modulus
N = choose a value for proof-of-work difficulty level
K = choose a value for how many transactions to pack into a block
ceronode = CeroCoinClient.CeroCoinClient(
cerocoin_network = network,
modulus_size = M,
starting_pow_difficulty = N,
num_transactions_in_block = K,
max_iterations_debug_mode = 200,
)
ceronode.initialize_node_and_run()
The next section elaborates on the four constructor parameters shown in
the constructor call.
CONSTRUCTOR PARAMETERS:
cerocoin_network:
The IP addresses I have shown in the 'network' variable are typical of
what I get for the hosts with my Android phone based WiFi hotspot.
As I mentioned earlier in this doc page, using your own smartphone WiFi
hotspot would make it much easier to create a portable demo with the
CeroCoinClient module since it would save you the bother of having to
manually enter the IP addresses in the cerocoin_network list each time
you run the demo (especially if the demos are meant to be run in
different network environments) with the same set of laptops.
modulus_size:
This is for the modulus to be used by a client in the RSA algorithm for
generating its public/private key pair.
For a classroom demonstration, you are better off using a small value
like 512 for the modulus since that keeps the size of the keys small enough
so that you can conveniently display a transaction as a part of the demo
(recall that a transaction must contain the public key of the buyer of
the coin). Obviously, using a small value like 512 for the modulus
gives you no security at all in this day and age. But that's okay for
for just the demos.
starting_pow_difficulty:
This constructor parameter sets the proof-of-work difficulty level when
a client first starts searching for a coin. The smaller this integer,
the greater the difficulty of finding an acceptable combination of the
genesis string and a nonce whose hash value would not exceed 2^N. This
is just the starting value for PoW. After the first block produced by
any node in the CeroCoin network has been accepted by the network
(including by the client in question), the client will change its PoW
difficulty level in order to be consistent with that block.
If you are giving a demo involving just two networked clients, my
recommendation would be to set starting_pow_difficulty to something like
252 in one client and to something like 240 in the other client. This
will make it highly likely that, at least at the beginning, the client
with pow_difficulty set to 252 will generate enough coins to demonstrate
the important crypto currency concepts during the limited time available
in a classroom demonstration. The client with pow_difficulty set to 240
will act mostly as the "buyer" of the coins generated by the other
client. Obviously, after the latter client has accepted a block from
the former client on account of blockchain length consideration, the
former client will alter its own PoW difficulty level to what is found
in the block. Subsequently, both clients will start exchanging blocks
on an equal basis as they discover new coins.
The beginning phase of this interaction between the two clients will
make it easier for you to demonstrate what is meant by a transaction and
how the client that receives a block from the other client abandons its
ongoing search for a coin and starts a fresh search using a new genesis
string that is based on the received block.
If you are giving a demo involving three clients, I'd recommend using
starting_pow_difficulty levels for 252, 251, and 240 in the clients.
This would allow the the clients running with starting_pow_difficulty
levels of 252 and 251 to exchange transactions and blocks right from the
beginning and the remaining client to act mostly as a receiver of the
transactions and blocks (before it accepts a block from either of the
other two clients). Now you can illustrate how the first two clients
set and reset their coin searches as each receives a new block from the
other and so on.
num_transactions_in_block:
A client uses this value to decide when to pack the generated
transactions into a block. By using different values for this parameter
in the different clients in a classroom demo, you can control the rate
at which each client broadcasts its blocks to the rest of the network
for a smoother explanation of the interaction between the clients.
max_iterations_debug_mode:
It is good to set some upper bound for this parameter especially if you
are tinkering with the code. Recall that a CeroCoinClient works through
half a dozen different threads and several of the operations are carried
out inside try-except clauses. So it is possible for the coin miner
thread to keep on working even when you have run into problems in some
other thread.
INSTALLATION:
The CeroCoinClient class was packaged using setuptools. For installation,
execute the following command-line in the source directory (this is the
directory that contains the setup.py file after you have downloaded and
uncompressed the package):
On Linux distributions, this will install the module file at a location that
looks like
If you do not have root access, you have the option of working directly off
the directory in which you downloaded the software by simply placing the
following statements at the top of your scripts that use the CeroCoinClient
class:
sys.path.append( "pathname_to_CeroCoinClient_directory" )
To uninstall the module, simply delete the source directory, locate where
the CeroCoinClient module was installed with "locate CeroCoinClient" and
delete those files. As mentioned above, the full pathname to the installed
version is likely to look like
/usr/local/lib/python2.7/dist-packages/CeroCoinClient*
If you want to carry out a non-standard install of the CeroCoinClient
module, look up the on-line information on Disutils by pointing your browser
to
http://docs.python.org/dist/dist.html
BUGS:
Please notify the author if you encounter any bugs. When sending email,
please place the string 'CeroCoin' in the subject line.
FUTURE PLANS:
You will soon see a version of the module that will work with both Python 2
and 3 (as is the case with all of my other Python modules). Additionally, I
am also planning to replace the inter-thread coordination logic with one
based on events.
ABOUT THE AUTHOR:
The author, Avinash Kak, recently finished a 17-year long "Objects Trilogy
Project" with the publication of the book "Designing with Objects" by
John-Wiley. If interested, visit his web page at Purdue to find out what
this project was all about. You might like "Designing with Objects"
especially if you enjoyed reading Harry Potter as a kid (or even as an
adult, for that matter).
For all issues related to this module, contact the author at kak@purdue.edu
If you send email, please place the string "CeroCoin" in your subject line
to get past the author's spam filter.
COPYRIGHT:
Python Software Foundation License
Copyright 2018 Avinash Kak
@endofdocs
Modules | ||||||
|
Classes | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Functions | ||
|
Data | ||
__author__ = 'Avinash Kak (kak@purdue.edu)' __copyright__ = '(C) 2018 Avinash Kak. Python Software Foundation.' __date__ = '2018-March-20' __url__ = 'https://engineering.purdue.edu/kak/distCeroCoin/CeroCoinClient-1-9.0.html' __version__ = '1.9.0' lock = <thread.lock object> |
Author | ||
Avinash Kak (kak@purdue.edu) |