bitcoin-h
This simple project aims to implement the bitcoin system as a proof-of-concept.
Depends heavily on the Servant library to provide RESTful APIs for node/node, node/server communication
The Design
Since a bitcoin-h node must maintain a running state of the whole blockchain, the ReaderT pattern is mainly applied in the node codes.
Several important bitcoin concepts are not implemented here, including:
- bitcoin fork
- pay-to-public-key-hash, as well as other transaction validation methods
- mining incentives
Implemented concepts:
- Server/Node communication via web services
- Node register, block chain requesting
- transaction mining, new block broadcasting
- Merkel tree generation and validation
- a static computation difficulty
- other related stuff
Usage
For mocking bitcoin-h server, run
$ cabal new-build
$ cabal new-run
For mocking bitcoin-h nodes, run
$ cabal new-repl
*Server> import Node
*Server Node> forkIO $ runNode 19901
*Server Node> forkIO $ runNode 19902
...
APIs
API | Method | Endpoints | Parameters | Return |
---|---|---|---|---|
Server | GET | /nodes | [Nodes] | |
Server | POST | /register | Node | Status |
Server | POST | /newTransaction | Transaction | Status |
Node | GET | /blocks | [Blocks] | |
Node | POST | /updateNodes | Node | Status |
Node | POST | /updateBlocks | Block | Status |
Node | POST | /newServerTransaction | Transaction | Status |
Examples
Supposing that server is running on port 19900, two nodes on ports 19901/19902
List all the nodes
$ curl --header "Content-Type: application/json" --request POST --data '{"mkInputs":[{"mkInAddr":"Shanghai","mkInAmount":40}],"mkOutputs":[{"mkOutAddr":"Guangzhou","mkOutAmount":10}, {"mkOutAddr":"Shanghai","mkOutAmount":30}]}' http://localhost:19900/newTransaction
"RequestSuccess"%
Show the GenesisBlock
$ curl --header "Content-Type: application/json" --request GET http://localhost:19901/blocks
[{"mkHeader":{"mkNonce":9675,"tag":"ChainedBlockHeader","mkPrevHeader":{"tag":"Genesis"},"mkMerkelRoot":7694568972639932276},"mkMerkelTree":{"tag":"MerkelLeaf","contents":7694568972639932276},"mkTransactions":[{"mkOutputs":[{"mkOutAmount":100,"mkOutAddr":"Guangzhou"},{"mkOutAmount":100,"mkOutAddr":"shanghai"},{"mkOutAmount":100,"mkOutAddr":"Beijing"}],"mkInputs":[]}]}]%
New Transaction
$ curl --header "Content-Type: application/json" --request POST --data '{"mkInputs":[{"mkInAddr":"Guangzhou","mkInAmount":100}],"mkOutputs":[{"mkOutAddr":"Guangzhou","mkOutAmount":50}, {"mkOutAddr":"Shanghai","mkOutAmount":40}]}' http://localhost:19900/newTransaction
"RequestSuccess"%
Show the mined blocks
$ curl --header "Content-Type: application/json" --request GET http://localhost:19902/blocks
[{"mkHeader":{"mkNonce":9675,"tag":"ChainedBlockHeader","mkPrevHeader":{"tag":"Genesis"},"mkMerkelRoot":7694568972639932276},"mkMerkelTree":{"tag":"MerkelLeaf","contents":7694568972639932276},"mkTransactions":[{"mkOutputs":[{"mkOutAmount":100,"mkOutAddr":"Guangzhou"},{"mkOutAmount":100,"mkOutAddr":"shanghai"},{"mkOutAmount":100,"mkOutAddr":"Beijing"}],"mkInputs":[]}]},{"mkHeader":{"mkNonce":748,"tag":"ChainedBlockHeader","mkPrevHeader":{"mkNonce":9675,"tag":"ChainedBlockHeader","mkPrevHeader":{"tag":"Genesis"},"mkMerkelRoot":7694568972639932276},"mkMerkelRoot":894334348103117156},"mkMerkelTree":{"tag":"MerkelLeaf","contents":894334348103117156},"mkTransactions":[{"mkOutputs":[{"mkOutAmount":50,"mkOutAddr":"Guangzhou"},{"mkOutAmount":40,"mkOutAddr":"Shanghai"}],"mkInputs":[{"mkInAddr":"Guangzhou","mkInAmount":100}]}]}]%