Giter Club home page Giter Club logo

coincoin's Introduction

coincoin

Build Status

coincoin is a cryptocurrency proof-of-concept implemented in Elixir. It's an umbrella project that focuses on the 2 main components of (most of) the existing cryptocurrencies: the blockchain and digital transactions.

It's goal is to be as simple as possible but complete enough to technically understand what's going on behind Bitcoin or Ethereum for example.

Setup

Blockchains are P2P softwares. To start using coincoin, we need to setup multiple nodes and connect them together.

You need Elixir installed. Clone this repository and go to the root of the project.

Then pull the dependencies using mix deps.get

To setup a 3 nodes blockchain, spawn 3 tabs in your terminal (node1, node2 and node3) and run:

  • node1: iex -S mix phx.server (defaults: PORT=4000 P2P_PORT=5000)
  • node2: PORT=4001 P2P_PORT=5001 iex -S mix phx.server
  • node3: PORT=4002 P2P_PORT=5002 iex -S mix phx.server

Then connect the nodes to create a P2P network:

$node2> Blockchain.connect("localhost:5000") # connect node2 to node1

$node3> Blockchain.connect("localhost:5001") # connect node3 to node2

This will setup a simple network:

node1 <--> node2 <--> node3

You can also use the robinmonjo/coincoin docker image available on the docker hub:

docker run -it robinmonjo/coincoin

If you use Docker, in the Blockchain.connect/1 call make sure to pass your container IP address and that this address is reachable.

Notes:

  • if you don't want to interact with the REST API, you can skip the PORT env var and use iex -S mix instead of iex -S mix phx.server
  • Blockchain.connect(5000) is equivalent to Blockchain.connect("localhost:5000")
  • for releases use make release

Usage

When started, coincoin will start 3 apps:

  • blockchain: a minimal blockchain
  • token: a minimal cryptocurrency implemented on top of the blockchain
  • blockchain_web: a web interface to manage nodes of the blockchain

To manipulate the blockchain and store random data in it using the iex console checkout the blockchain app. To do the same using a REST API, checkout the blockchain_web app. And finally to play with a cryptocurrency and use the blockchain as a distributed ledger, checkout the token app.

Why coincoin ?

Lately I heard a lot about:

  1. how Elixir is awesome and is the future of complex system / web development
  2. how blockchain technology will be the next big thing

So what about building a cryptocurrency proof-of-concept in Elixir ?

As I'm sure about 1, I still have some doubts about 2 eventough technologies behind cryptocurrencies are exciting.

Also "coin-coin" in french is the noise of a duck (hence Scrooge McDuck)

Final words

Issues, suggestions and pull requests are very welcome ๐Ÿ˜Š

coincoin's People

Contributors

robinmonjo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

coincoin's Issues

Pluggable proof-of-*

from @yorgis in a comment of this PR #7

What would happen if we want to support something like PoW + PoT together, IF I am not mistaking Dash coin does that, it split it up into 50% 50% work.

Also, let say tomorrow I want to create ProofOfSharing (PoSH) how would that look like?

When I told you to move it into some module I was actually thinking on create some config with the module (not called proof_of_work because defeat the idea ๐Ÿ˜„ ) where we can setup either a list or just a module and you will call the compute function on it, which is why I told you about the protocol.

So that way you can have as many implementations of how you reward or do any computation of this kind.

Something like

config :blockchain,
  some_better_name_key: [ProofOfWork, ProofOfStake, ProofOfShares]

# or

config :blockchain,
  some_better_name_key: [
    pow: ProofOfWork, # <- for the sack of the demo whatever key value pair
    pos: ProofOfStake,
    posh: ProofOfShares
  ]

the last example could be useful when you want to control that you HAVE to use specific module for X reason. I would even stick with the array for now ๐Ÿ˜„ we need study what other coins do differently and more important where the crypto world is moving to

Nonce typo

nounce should be spelled nonce. Unfortunately it's not only in the documentation but also in the code base as part of the Blockchain.Difficulty and Blockchain.Block structs. I can put a PR renaming it but wanted to open an issue first.

Make the blockchain available for external usage

The goal is to provide the blockchain part as an hex package so people can reuse it in their own project.

To achieve this we must:

  1. define an API that could work for "every use cases"
  2. document high level API + usage
  3. find a name for the package
  4. namespace the blockchain app with this name
  5. follow this guide to publish the app

@yordis the first part I think is to think about an API. For now, the Blockchain app exposes:

A protocol that data we want to store on the chain must follow:

defprotocol Blockchain.BlockData do
  @spec hash(t) :: String.t()
  def hash(data) 

  @spec verify(t, [Blockchain.Block.t()]) :: :ok | {:error, String.t()}
  def verify(data, chain)
end

A set of functions to interact with the blockchain

@yordis you have a use case in mind, this is perfect to define what APIs you will need. We can then include them in the project. Then we must find a name for the package and namespace it. Waiting for suggestions ๐Ÿ˜Š

Improve polimorphism in the blockchain

coincoin makes a strong distinction between the blockchain and the transactions stored on it.

The blockchain only requires that data stored in each block implements this simple protocol:

defprotocol Blockchain.Data do
  def hash(data)
  def verify(data, chain)
end

This is ok so far but the problem is that when data are sent through the network, they are JSON encode / decoded. So for example, when I send a Token.Transaction to the blockchain, I send it as a raw Map (because even if I don't once decoded data will be seen as a raw Map by other peers), so I had to implement the Blockchain.Data protocol for Map. This is not ok, Map is way to generic, that makes the code not reusable at all !

The only way I can think of to improve this is to store somewhere the type of the data in the blockchain. So when blocks get decoded the data field is not a Map but the user defined type.

Reward miners

How does it works in Bitcoin

In the Bitcoin blockchain, a block is mined every ~10 minutes. This block can contains from 0 to N transactions. The only limit is that at the end, the block is no more than 1Mb. What's interesting here is that even if there is no transaction a block will still be mined and a "coinbase" transaction (a transaction that generates bitcoin) get generated every ~10 minutes.

Miners also collect transactions fees, and that's a way for people to ensure their transactions will be incorporated into the blockchain quickly if they set a high transaction fee

What's going on with coincoin ?

Currently coincoin has a really naive approach to mining:

  1. A transaction comes in
  2. Miner compete to mine the block
  3. First miner to come up with the proof-of-work add the block to the chain

Miners do not have any rewards and the only way to inject tokens into the blockchain is to use the Token.free_tokens/1 API.

How to reward miners in coincoin ?

For simplicity reasons, I will ignore transaction fees:

  • miners always spend their time mining the next block even if no transactions are in their pool
  • when they start mining a new block:
    1. they generate a new coinbase transaction for themselves
    2. compute the merkle root of all the transactions in their pool (+ the coinbase transaction)
    3. start to compute the nonce

Implications

  • a block no longer contains only one transaction, and will contains 1 coinbase transaction + 0 or N transactions
  • a block contains a merkle_root field which is used to compute the block hash
  • The Token.Ledger module must change to loop over transactions (no more one transaction per block)
  • coinbase transactions must be validated (amount ...)
  • difficulty must be a full part of the protocol and not just a config. Ideally, coincoin will be configured with an average time to mine a block and a block mining reward amount, and miners will re-adapt the difficulty based on this and the time it took to mine X blocks

make release error && cannot run

$ make release
cd apps/blockchain_web && MIX_ENV=prod mix phx.digest
** (Mix.Config.LoadError) could not load config config/prod.secret.exs
    ** (File.Error) could not read file "/home/den/projects/coincoin/apps/blockchain_web/config/prod.secret.exs": no such file or directory
    (elixir) lib/file.ex:272: File.read!/1
    (mix) lib/mix/config.ex:180: Mix.Config.read!/2
    (mix) lib/mix/config.ex:217: anonymous fn/3 in Mix.Config.read_wildcard!/2
    (elixir) lib/enum.ex:1811: Enum."-reduce/3-lists^foldl/2-0-"/3
    (stdlib) erl_eval.erl:670: :erl_eval.do_apply/6
    (stdlib) erl_eval.erl:878: :erl_eval.expr_list/6
    (stdlib) erl_eval.erl:404: :erl_eval.expr/5
Makefile:9: recipe for target 'shared' failed
make: *** [shared] Error 1

I'm doing exactly as it said in README, but make release fails. Error came from blockchain_web.

I've removed mention of secrets from prod.exs and trying to run release.

First node starts, but then I've got an error:

PORT=4001 P2P_PORT=5001 _build/prod/rel/coincoin/bin/coincoin.run console
Protocol 'inet_tcp': the name [email protected] seems to be in use by another Erlang node

Add spec types to all functions

@robinmonjo before you keep going man it is really important to add the type spec of the functions. You dont need to write that much documentation but at least with the type spec I know what the function specs and what it returns.

I wish I could do it myself but I have to track down all the code in each function to know about it.

Persistent wallet

Wallet (public and private keys) are in memory only. Even worst, they are generated on init of the Token.MyWallet gen_server. This is really bad because if/when the gen_server crashes, new keys are generated and all coins are lost !

  • So we should first generate a wallet in the application.ex module and pass it to the gen_server from here. This would prevent a crash to generate a new wallet
  • we want to persist public keys and private keys in a file ~/.coincoin_keys. On startup if this file exist and keys can be read from it, we use these keys, otherwise we generate the keys and create this file. This must be implemented at the MyWallet module level and not the Wallet module level.
  • document key persistence and how to make it work with docker

Move all error to atom

Hey, I notice you are sending so errors like human readable, that is good but it doesn't scale that well because at the moment you need to know which error happened you will need to go back and use some atom or something descriptive or you will have to do some string pattern matching which is really bad.

I suggest to use atoms for identifier particular error and have some module with the mapping to human message.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.