-- | BlockChain data structures {-# LANGUAGE BangPatterns, DeriveFunctor, DeriveFoldable, DeriveTraversable #-} module Bitcoin.BlockChain.Base ( -- * the block header BlockHeader(..) -- * one-parameter blocks , Block(..) , BlockChain(..) -- * two-parameter blocks , Block2(..) , BlockChain2(..) , module Bitcoin.BlockChain.Tx ) where -------------------------------------------------------------------------------- import Prelude import Data.Int import Data.Word import Data.List ( mapAccumL ) import Control.Monad import Control.Applicative import Data.Foldable ( Foldable(..) ) import Data.Traversable ( Traversable(..) ) import qualified Data.ByteString as B import qualified Data.ByteString.Lazy as L import Data.Binary import Data.Binary.Get import Bitcoin.Misc.Bifunctor import Bitcoin.Misc.HexString import Bitcoin.Misc.UnixTime import Bitcoin.Protocol.Hash import Bitcoin.BlockChain.Tx -------------------------------------------------------------------------------- newtype BlockChain tx = BlockChain [Block tx] deriving (Functor,Foldable,Traversable) -------------------------------------------------------------------------------- data Block tx = Block { _blockHeader :: !BlockHeader , _blockTxs :: [tx] } deriving (Eq,Show,Functor,Foldable,Traversable) -------------------------------------------------------------------------------- -- | The header of a block data BlockHeader = BlockHeader { _blkBlockVersion :: {-# UNPACK #-} !Word32 -- ^ block version (currently 1 or 2) , _blkPrevBlock :: {-# UNPACK #-} !Hash256 -- ^ hash of the previous block , _blkMerkleRoot :: {-# UNPACK #-} !Hash256 -- ^ merkle root of the transaction tree , _blkTimeStamp :: {-# UNPACK #-} !UnixTimeStamp -- ^ timestamp of the block , _blkDifficulty :: {-# UNPACK #-} !Word32 -- ^ the difficulty (see "Bitcoin.Protocol.Difficulty") , _blkNonce :: {-# UNPACK #-} !Word32 -- ^ the nonce , _blkBlockHash :: Hash256 -- ^ the hash of /this/ block. Note: the hash is not actually stored in the blockchain; but it is computed when the block is loaded } deriving (Eq,Show) -------------------------------------------------------------------------------- -- | A two-parameter version of 'Block', with 'BiFunctor' etc instances. -- It is a newtype only so that we can provide these instances... newtype Block2 inscript outscript = Block2 { unBlock2 :: Block (Tx inscript outscript) } -- | A two-parameter version of 'BlockChain', with 'BiFunctor' etc instances. newtype BlockChain2 inscript outscript = BlockChain2 { unBlockChain2 :: [Block2 inscript outscript] } instance BiFunctor BlockChain2 where fmapFst f (BlockChain2 blocks) = BlockChain2 (map (fmapFst f ) blocks) fmapSnd g (BlockChain2 blocks) = BlockChain2 (map (fmapSnd g) blocks) fmapBoth f g (BlockChain2 blocks) = BlockChain2 (map (fmapBoth f g) blocks) instance BiFoldable BlockChain2 where bifoldl f g x0 (BlockChain2 blocks) = Prelude.foldl (bifoldl f g) x0 blocks bifoldr f g (BlockChain2 blocks) x0 = Prelude.foldr (bifoldr f g) x0 blocks instance BiFunctor Block2 where fmapFst f (Block2 blk) = Block2 $ fmap (fmapFst f ) blk fmapSnd g (Block2 blk) = Block2 $ fmap (fmapSnd g) blk fmapBoth f g (Block2 blk) = Block2 $ fmap (fmapBoth f g) blk instance BiFoldable Block2 where bifoldl f g x0 (Block2 blk) = Data.Foldable.foldl (bifoldl f g) x0 blk bifoldr f g (Block2 blk) x0 = Data.Foldable.foldr (bifoldr f g) x0 blk --------------------------------------------------------------------------------