⛼ tinychain

Putting the rough in "rough consensus"

Tinychain is a pocket-sized implementation of Bitcoin. Its goal is to be a compact, understandable, working incarnation of the Nakamoto consensus algorithm at the expense of advanced functionality, speed, and any real usefulness.

I wrote it primarily to understand Bitcoin better, but hopefully it can serve as a jumping-off point for programmers who are interested in (but don't have intimate familiarity with) Bitcoin or cryptocurrency. At the very least, it can be a piñata for protocol developers who actually know what they're doing.

 $ cloc --quiet tinychain.py

-------------------------------------------------------------------------------
Language                     files          blank        comment           code
-------------------------------------------------------------------------------
Python                           1            341            174            679
-------------------------------------------------------------------------------

Quick start

What is Bitcoin?

In brief terms that map to this code...

Bitcoin is a way of generating pseudo-anonymous, decentralized trust at the cost of electricity. The most commonly known (but not sole) application of this is as a currency or store of value. If that sounds abstruse, general, and mindblowing, that's because it is.

In Bitcoin, value is recorded using a Transaction, which assigns some number of coins to an identity (via TxOuts) given some cryptographically unlocked TxIns. TxIns must always refer to previously created but unspent TxOuts.

A Transaction is written into history by being included in a Block. Each Block contains a data structure called a Merkle Tree which generates a fingerprint unique to the set of Transactions being included. The root of that Merkle tree is included in the block "header" and hashed (Block.id) to permanently seal the existence and inclusion of each Transaction in the block.

Blocks are linked together in a chain (active_chain) by referring to the previous Block header hash. In order to add a Block to the chain, the contents of its header must hash to a number under some difficulty target, which is set based upon how quickly recent blocks have been discovered (get_next_work_required()). This attempts to normalize the time between block discovery.

When a block is discovered, it creates a subsidy for the discoverer in the form of newly minted coins. The discoverer also collects fees from transactions included in the block, which are the value of inputs minus outputs. The block reward subsidy decreases logarithmically over time. Eventually the subsidy goes to zero and miners are incentivized to continue mining purely by a fee market.

Nodes in the network are in a never-ending competition to mine and propagate the next block, and in doing so facilitate the recording of transaction history. Transactions are submitted to nodes and broadcast across the network, stored temporarily in mempool where they are queued for block inclusion.

For more comprehensive descriptions of Bitcoin, see

Notable differences from Bitcoin

Q&A

How does RPC work?

We use JSON for over-the-wire serialization. It's slow and unrealistic but human-readable and easy. We deserialize right into the .*Msg classes, each of which dictates how a particular RPC message is handled via .handle().

Why doesn't the client track coins we've spent but haven't confirmed yet?

Yeah I know, the client sucks. I'll take a PR.

How can I add another RPC command to reveal more data from a node?

Just add a NamedTuple subclass with a handle() method defined; it registers automatically. Mimic any existing *Msg class.

Why aren't my changes changing anything?

Remember to rebuild the Docker container image when you make changes

docker-compose build && docker-compose up

How do I run automated tests?

pip install -r requirements.test.txt
py.test --cov test_tinychain.py

Is this yet another cryptocurrency created solely to Get Rich Quick™?

A resounding Yes! (if you're dealing in the very illiquid currency of education)

Otherwise nah. This thing has 0 real-world value.

What's with the logo?

It's a shitty unicode Merkle tree. Give a guy a break here, this is freeware!

Where can I get more of you ranting?

@jamesob

Do you take tips to Get Rich Quick™?

Sure.

18ehgMUJBqKc2Eyi6WHiMwHFwA8kobYEhy

BTC: 18ehgMUJBqKc2Eyi6WHiMwHFwA8kobYEhy

Half of all tips will be donated to an organization providing aid to Syrian refugees.