blockchain
Generic blockchain implementation in Haskell. Heavily inspired by Bitcoin blockchain, but does not fully comply to the Bitcoin blockchain spec. Should be suitable for creating arbitrary Bitcoin-like blockchains with various configurations.
Build
$ stack build
Test
$ stack test -- run unit tests
$ ./scripts/test_mining <num-miners> -- run test mining network
$ ./scripts/test_stats <file-path> -- print blockchain stats
notable differences from Bitcoin blockchain
- Merkle root computed with extra leaves at end of tree (compared to extra leaves duplicated in bitcoin)
- Entities serialized as json
- Blockchain config is encoded in blockchain
- Blocks include a dedicated coinbase transaction field to simplify special case handling
- Block headers include an additional field for coinbase transaction hash
- A "transaction in" must declare its previous transaction hash as either a coinbase transaction or a normal transaction
design goals
- Enforce invariants in types whenever possible (non-empty transactions, genesis block, coinbase transactions, etc.)
- Make it simple to create blockchains with arbitrary configurations
- Make construction of unverified blockchains easy, but provide assurance any validated blockchain instance conforms to expected rules
- Blocks & transactions are never presumed to be a valid part of a blockchain unless present in a validated blockchain
- Adding new blocks to a validated blockchain can assume validity of prior parts of the blockchain
- Inspecting unspent transaction outputs of a validated blockchain can assume validity of all transactions
- Blockchain should be readily serializable
docs
A blockchain is a config and a tree of blocks with each node having a potentially infinite set of branches. A Blockchain
also includes a tag to note whether is has been verified to meet all the expected conditions -- Blockchain Validated
or Blockchain Unvalidated
.
data Blockchain a = Blockchain
{ _config :: BlockchainConfig
, _node :: BlockchainNode
}
data BlockchainNode = BlockchainNode
{ nodeBlock :: Block
, nodeNodes :: [BlockchainNode]
}
Blockchain construction revolves around three basic functions. Note: the BlockchainNode
constructor is exported, while the top level Blockchain
constructor is not.
-- build an unvalidated blockchain from a config and node
construct :: BlockchainConfig -> BlockchainNode -> Blockchain Unvalidated
-- validate the blockchain
validate :: Blockchain Unvalidated -> Either ValidationException (Blockchain Validated)
-- add a block
addBlock :: Block -> Blockchain Validated -> Either BlockException (Blockchain Validated)
Finally, blocks are created by mining. This is a process of finding a Block
with a certain shape so that it satisfies the expected difficulty, as defined in the blockchain config. Blocks are mined with the coinbase reward going to the provided public key. Note: this function may take a long time to finish executing. Most realistic use cases should run this in a separate thread that can be canceled.
mineBlock :: PublicKey -> [Transaction] -> Blockchain Validated -> IO (Either MineBlockException Block)
todo
- Test attempts to double spend address funds -- particularly within the same transaction
- Implement
createTransaction
(currently onlycreateSimpleTransaction
) - Function that validates transactions -- outside of create transaction logic
- Implement max transaction count per block
- Cache block header hash on block (and maybe transactions) for more efficient operations
- Maybe cache on the blockchain itself, and
validate
computes/checks hashes?
- Maybe cache on the blockchain itself, and
- Run lint in CI
references
- http://www.stephendiehl.com/posts/smart_contracts.html
- http://kadena.io/docs/Kadena-PactWhitepaper.pdf
- http://davidederosa.com/basic-blockchain-programming/
- https://en.bitcoin.it/wiki/Transaction
- https://en.bitcoin.it/wiki/Block
- https://en.bitcoin.it/wiki/Block_hashing_algorithm
- https://en.bitcoin.it/wiki/Hashcash
- https://en.bitcoin.it/wiki/Genesis_block
- https://en.bitcoin.it/wiki/Protocol_rules#.22tx.22_messages