• Stars
    star
    1,448
  • Rank 32,489 (Top 0.7 %)
  • Language
    Python
  • License
    MIT License
  • Created over 7 years ago
  • Updated over 3 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A pocket-sized implementation of Bitcoin

⛼ 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

  • Install Docker & docker-compose
  • Clone this repo: git clone [email protected]:jamesob/tinychain.git
  • Make sure you're in a Python3.6 environment: virtualenv --python=python3.6 venv && . venv/bin/activate
  • Grab Python dependencies locally: pip install -r requirements.txt
  • Run docker-compose up. This will spawn two tinychain nodes.
  • In another window, run ./bin/sync_wallets. This brings the wallet data from the Docker containers onto your host.
    $ ./bin/sync_wallets
    
    Synced node1's wallet:
    [2017-08-05 12:59:34,423][tinychain:1075] INFO your address is 1898KEjkziq9uRCzaVUUoBwzhURt4nrbP8
     0.0 ⛼
    
    Synced node2's wallet:
    [2017-08-05 12:59:35,876][tinychain:1075] INFO your address is 15YxFVo4EuqvDJH8ey2bY352MVRVpH1yFD
    0.0 ⛼
    
  • Try running ./client.py balance -w wallet1.dat; try it with the other wallet file.
    $ ./client.py balance -w wallet2.dat
    
    [2017-08-05 13:00:37,317][tinychain:1075] INFO your address is 15YxFVo4EuqvDJH8ey2bY352MVRVpH1yFD
    0.0 ⛼
    
  • Once you see a few blocks go by, try sending some money between the wallets
    $ ./client.py send -w wallet2.dat 1898KEjkziq9uRCzaVUUoBwzhURt4nrbP8 1337
    
    [2017-08-05 13:08:08,251][tinychain:1077] INFO your address is 1Q2fBbg8XnnPiv1UHe44f2x9vf54YKXh7C
    [2017-08-05 13:08:08,361][client:105] INFO built txn Transaction(...)
    [2017-08-05 13:08:08,362][client:106] INFO broadcasting txn 2aa89204456207384851a4bbf8bde155eca7fcf30b833495d5b0541f84931919
    
  • Check on the status of the transaction
     $ ./client.py status e8f63eeeca32f9df28a3a62a366f63e8595cf70efb94710d43626ff4c0918a8a
    
     [2017-08-05 13:09:21,489][tinychain:1077] INFO your address is 1898KEjkziq9uRCzaVUUoBwzhURt4nrbP8
     Mined in 0000000726752f82af3d0f271fd61337035256051a9a1e5881e82d93d8e42d66 at height 5
    

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

  • Byte-level representation and endianness are very important when serializing a data structure to be hashed in Bitcoin and are not reproduced faithfully here. In fact, serialization of any kind here is very dumbed down and based entirely on raw strings or JSON.

  • Transaction types are limited to pay-to-public-key-hash (P2PKH), which facilitate the bare minimum of "sending money." More exotic transaction types which allow m-of-n key signatures and Script-based unlocking are not implemented.

  • Initial Block Download is at best a simplified version of the old "blocks-first" scheme. It eschews getdata and instead returns block payloads directly in inv.

  • The longest, valid chain is determined simply by chain length (number of blocks) vs. chainwork.

  • Peer "discovery" is done through environment variable hardcoding. In bitcoin core, this is done with DNS seeds.

  • Replace by fee is absent.

  • Memory usage is egregious. Networking is a hack.

  • Satoshis are instead called Belushis because, well...

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

More Repositories

1

desk

A lightweight workspace manager for the shell
Shell
2,514
star
2

coldcore

Trust-minimized Bitcoin wallet
Python
133
star
3

docker-bitcoind

A configurable docker image for bitcoind
Python
87
star
4

Miser

Programmatic budgeting
Python
58
star
5

clii

Python 3.7+ function annotations -> CLI
Python
43
star
6

simple-ctv-vault

A simple vault structure using OP_CTV
Python
42
star
7

mempool.work

Summary of mempool design, challenges, and proposals (re: fees)
41
star
8

assumeutxo-docs

Documentation for Bitcoin's assumeutxo proposal
16
star
9

bitcoin-github-scrape

Haphazard scripts for scraping bitcoin/bitcoin data from GitHub
8
star
10

txture

The 30 second blog engine for (Clojure) hackers
Clojure
7
star
11

verystable

A python toolkit for unstable bitcoin things
Python
6
star
12

opvault-demo

An example wallet using OP_VAULT
Python
6
star
13

omgwebapp

A minimal flask/react/webpack boilerplate internet starter kit thing
JavaScript
6
star
14

delving-bitcoin-archive

A public archive of delvingbitcoin.org
4
star
15

create.clj

A driver for the iRobot Create, written in Clojure. Not complete, by any means.
C
3
star
16

discourse-archive

Provides a simple archive of Discourse content
Python
3
star
17

whatup.sh

Get a quick overview of what's happening on a Unix system
Shell
3
star
18

ackr

Haphazard tool for reviewing Bitcoin Core PRs
Python
3
star
19

biketrip

The source code to a Jekyll site about our bike trip to SF.
JavaScript
3
star
20

bashwords

BASH integrated vocabulary training.
Python
2
star
21

id3renamer

Rename MP3s based on ID3 with Python.
Python
2
star
22

prom-exporter-basic

A Prometheus exporter for basic system metrics with no dependencies
Python
2
star
23

pwdy

A command-line password manager.
Python
2
star
24

mnty

A small utility for managing sshfs mount profiles.
Python
2
star
25

sicp

Completed exercises from Sussman-Abelson's Structure and Interpretation of Computer Programs
Scheme
2
star
26

exploring-git

I explore the git source, take notes
1
star
27

uncertainties

making experimental physics a little less horrible
Python
1
star
28

kali

A horrifying build tool for LAMPDrupal stacks.
Python
1
star
29

icpc-problems

A collection of ACM ICPC problems I've completed
Java
1
star
30

deltaT

My txture blog
Clojure
1
star
31

jrni

An over-under-engineered flat journal management system in rust
Rust
1
star
32

droid-arch-tethering

A script to set up Droid tethering for clients running Arch Linux.
Python
1
star
33

weekend-hackups

An excuse to make some shit.
1
star
34

transcraper

Scrape your information from financial institutions
Python
1
star
35

clibrarian

Your CLI history over HTTP
CoffeeScript
1
star
36

jamesob.github.io

CSS
1
star
37

gandi-ddns

Declarative dynamic DNS with gandi.net
Python
1
star
38

cryptopals-solutions

Cryptopals solutions in Rust
Rust
1
star
39

jamesob.github.com

JavaScript
1
star