roomanidzee / haskelchain

Simple Blockchain System Implementation in Haskell

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

haskelchain

Simple implementation of a Blockchain system

Haskell CI

Prerequisites

This project relies on the Haskell Stack tool.

It is recommended that you follow the instructions on how to install Haskell with Stack on Haskell's official Downloads page.

Build

To build this project simply run

stack build

This will install all dependencies, including a proper version of GHC (which should be there already if you have Haskell Platform 8.6.5).

Run

This project has one executable that you can run with

stack exec haskelchain-exe

During development it is recommended a combination of build and exec:

stack build && stack exec haskelchain-exe

Alternatively, you can run

stack build file-watch

For continuous builds in the background.

Interpreter

You can run GHCi (GHC interpreter) for the whole project with

stack ghci

or

stack repl

During development it might be beneficial to work using an interpreter for quick reloads, interacting with various parts of code and trying out things.

Note that you can run executable from GHCi by invoking main.

GHCi commands

There are some useful commands in GHCi that might help you with the development process:

  • :t or :type — show the type of an expression:
>>> :t map (+1)
map (+1) :: Num b => [b] -> [b]
  • :l or :load — load file or module:
>>> :load src/MyProject.hs
[1 of 1] Compiling MyProject        ( src/MyProject.hs, interpreted )
Ok, one module loaded.
  • :set and :unset — turn an option on/off:
>>> :set -XOverloadedStrings
>>> :set -Wall -fno-warn-type-defaults

ghcid

For faster feedback from the compiler it is recommended to use ghcid (GHCi deamon).

Install ghcid with stack:

stack install ghcid

Now you can run ghcid with Stack using

ghcid -c "stack repl"

This will run GHCi with the entire project loaded and will quickly reload all modules when you modify them to tell you if you have any errors or warnings.

Note: you can also run ghcid without parameters and it will detect Stack project, but you'll have to use system-wide .ghci. See ndmitchell/ghcid#72 for more details.

How to work with blockchain

You can work with by two methods:

  • from GHCI:
import Mining()
import Types()
import Control.Comonad.Cofree (Cofree (..))
import Crypto.Hash
import qualified Data.ByteString as B
import qualified Data.Text as T
import Data.Text.Encoding (encodeUtf8)
import qualified Data.Vector as V
import System.IO.Unsafe (unsafePerformIO)
import Data.Time.Clock.POSIX

packStr'' :: String -> B.ByteString
packStr'' = encodeUtf8 . T.pack

let testTransaction = Transaction 300 500 100

let testBlock = Block (V.fromList [testTransaction, testTransaction])

let testGenesisBlock = Block (V.fromList [])

let genesisChain = testGenesisBlock :< Genesis

let newBlock = Block (V.fromList [testTransaction])

let testString = "test_hash"

let testBlockHeader =
     BlockHeader
        { _miner = 1,
          _parentHash = hash (packStr'' testString),
          _nonce = 100,
          _minedAt = unsafePerformIO getPOSIXTime
        }

let testChain = testBlock :< Node testBlockHeader genesisChain

let newChain = addBlock newBlock testBlockHeader testChain

show (headers newChain)

show (balances newChain)

let blockChains = chains newChain
length(blockChain)

show(blockTimeAverage newChain)

show(desiredDifficulty newChain)

show(difficulty newChain)

transactionsPool = return [Transaction 300 500 100, Transaction 300 400 100]
let testAccount = 1
let minedChain = unsafePerformIO (mineOn transactionsPool testAccount newChain)

show(headers newChain)
show(headers minedChain)

-- ================================================================

import BlockchainService()
import System.IO.Unsafe (unsafePerformIO)
import Mining()
import Types()

unsafePerformIO (createEmptyChainFile "genesis_chain_file")
let genesisChainNew = makeGenesis
let existedChain = unsafePerformIO (loadOrCreateFileChain "genesis_chain_file" genesisChainNew)
show(headers existedChain)

let testMineAccount = "5"
let fileName = "mined_file"
show (unsafePerformIO(mineAndSaveBlock fileName testMineAccount)::String)

show (unsafePerformIO(listBalances "mined_file"))

  • from HTTP API:

GET localhost:8081/createChainFileRoute?file_name=genesis_chain1_file 
  return string with creation result

GET localhost:8081/listBalancesRoute?file_name=genesis_chain_file
  return balances from input file chain path

GET localhost:8081/mineBlocksRoute?file_name=genesis_chain_file&account_value=1
  performs mining process and return status string about process

About

Simple Blockchain System Implementation in Haskell


Languages

Language:Haskell 100.0%