{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE TemplateHaskell #-} module Data.Bitcoin.Block.Types where import Data.Binary (Binary, get, put) import Data.Binary.Get (getByteString, getWord32le) import Data.Binary.Put (putByteString, putWord32le) import Control.Lens.TH (makeLenses) import Control.Monad (forM_, replicateM) import qualified Data.ByteString as BS import qualified Data.HexString as HS import Data.LargeWord (Word256) import Data.Word (Word32) import qualified Data.Bitcoin.Transaction as Btc (Coinbase, Transaction (..)) import Data.Bitcoin.Types (BlockHash, VarInt (..)) -- | Data type recording information on a 'Block'. The hash of a block is -- defined as the hash of this data structure. The block mining process -- involves finding a partial hash collision by varying the nonce in the -- 'BlockHeader' and/or additional randomness in the 'Btc.Coinbase' of this -- 'Block'. Variations in the 'Btc.Coinbase' will result in different merkle -- roots in the 'BlockHeader'. data BlockHeader = BlockHeader { -- | Block version information, based on the version of the -- software creating this block. _blockVersion :: Word32, -- | Hash of the previous block (parent) referenced by this -- block. _prevBlock :: BlockHash, -- | Root of the merkle tree of all transactions pertaining -- to this block. _merkleRoot :: Word256, -- | Unix timestamp recording when this block was created _blockTimestamp :: Word32, -- | The difficulty target being used for this block _blockBits :: Word32, -- | A random nonce used to generate this block. Additional -- randomness is included in the coinbase transaction of -- this block. _bhNonce :: Word32 } deriving (Eq, Show) makeLenses ''BlockHeader instance Binary BlockHeader where get = do v <- getWord32le p <- getByteString 32 -- A BlockHash is exactly 32 bytes m <- get bt <- getWord32le bb <- getWord32le n <- getWord32le return $ BlockHeader v ((HS.fromBytes . BS.reverse) p) m bt bb n put (BlockHeader v p m bt bb n) = do putWord32le v putByteString ((BS.reverse . HS.toBytes) p) put m putWord32le bt putWord32le bb putWord32le n -- | Data type describing a block in the bitcoin protocol. data Block = Block { -- | Header information for this block. _blockHeader :: BlockHeader, -- | Coinbase transaction of this block. _blockCoinbaseTx :: Btc.Coinbase, -- | List of transactions pertaining to this block. _blockTxns :: [Btc.Transaction] } deriving (Eq, Show) makeLenses ''Block instance Binary Block where get = do header <- get (VarInt c) <- get cb <- get txs <- replicateM (fromIntegral (c-1)) get return $ Block header cb txs put (Block h cb txs) = do put h put $ VarInt $ fromIntegral $ length txs + 1 put cb forM_ txs put