{-# OPTIONS_GHC -fno-cse -fno-full-laziness #-} {-| Network specific constants -} module Network.Haskoin.Constants ( -- ** Data Network(..) -- ** Functions , switchToTestnet3 , setNetwork , getNetwork -- ** Network parameters , networkName , addrPrefix , scriptPrefix , secretPrefix , extPubKeyPrefix , extSecretPrefix , networkMagic , genesisHeader , maxBlockSize , maxSatoshi , haskoinUserAgent , defaultPort , allowMinDifficultyBlocks , powLimit , targetTimespan , targetSpacing , checkpoints ) where import Data.Bits (shiftR) import Data.ByteString (ByteString) import Data.IORef (IORef, newIORef, readIORef, writeIORef) import Data.Word (Word8, Word32, Word64) import Data.LargeWord (Word256) import Network.Haskoin.Block.Types import System.IO.Unsafe (unsafePerformIO) data Network = Network { getNetworkName :: !String , getAddrPrefix :: !Word8 , getScriptPrefix :: !Word8 , getSecretPrefix :: !Word8 , getExtPubKeyPrefix :: !Word32 , getExtSecretPrefix :: !Word32 , getNetworkMagic :: !Word32 , getGenesisHeader :: !BlockHeader , getMaxBlockSize :: !Int , getMaxSatoshi :: !Word64 , getHaskoinUserAgent :: !ByteString , getDefaultPort :: !Int , getAllowMinDifficultyBlocks :: !Bool , getPowLimit :: !Integer , getTargetTimespan :: !Word32 , getTargetSpacing :: !Word32 , getCheckpoints :: ![(Int, BlockHash)] } deriving (Eq, Show, Read) -- | Switch to Testnet3. Do at start of program. switchToTestnet3 :: IO () switchToTestnet3 = setNetwork testnet3 -- | Change network constants manually. If switching to Testnet3, use -- switchToTestnet3 instead. setNetwork :: Network -> IO () setNetwork = writeIORef networkRef {-# NOINLINE networkRef #-} -- | Use this if you want to change constants to something other than Testnet3. networkRef :: IORef Network networkRef = unsafePerformIO $ newIORef prodnet {-# NOINLINE getNetwork #-} -- | Read current network constants record getNetwork :: Network getNetwork = unsafePerformIO $ readIORef networkRef -- | Name of the bitcoin network networkName :: String networkName = getNetworkName getNetwork -- | Prefix for base58 PubKey hash address addrPrefix :: Word8 addrPrefix = getAddrPrefix getNetwork -- | Prefix for base58 script hash address scriptPrefix :: Word8 scriptPrefix = getScriptPrefix getNetwork -- | Prefix for private key WIF format secretPrefix :: Word8 secretPrefix = getSecretPrefix getNetwork -- | Prefix for extended public keys (BIP32) extPubKeyPrefix :: Word32 extPubKeyPrefix = getExtPubKeyPrefix getNetwork -- | Prefix for extended private keys (BIP32) extSecretPrefix :: Word32 extSecretPrefix = getExtSecretPrefix getNetwork -- | Network magic bytes networkMagic :: Word32 networkMagic = getNetworkMagic getNetwork -- | Genesis block header information genesisHeader :: BlockHeader genesisHeader = getGenesisHeader getNetwork -- | Maximum size of a block in bytes maxBlockSize :: Int maxBlockSize = getMaxBlockSize getNetwork -- | Maximum number of satoshi maxSatoshi :: Word64 maxSatoshi = getMaxSatoshi getNetwork -- | User agent string haskoinUserAgent :: ByteString haskoinUserAgent = getHaskoinUserAgent getNetwork -- | Default port defaultPort :: Int defaultPort = getDefaultPort getNetwork -- | Allow relaxed difficulty transition rules allowMinDifficultyBlocks :: Bool allowMinDifficultyBlocks = getAllowMinDifficultyBlocks getNetwork -- | Lower bound for the proof of work difficulty powLimit :: Integer powLimit = getPowLimit getNetwork -- | Time between difficulty cycles (2 weeks on average) targetTimespan :: Word32 targetTimespan = getTargetTimespan getNetwork -- | Time between blocks (10 minutes per block) targetSpacing :: Word32 targetSpacing = getTargetSpacing getNetwork -- | Checkpoints to enfore checkpoints :: [(Int, BlockHash)] checkpoints = getCheckpoints getNetwork prodnet :: Network prodnet = Network { getNetworkName = "prodnet" , getAddrPrefix = 0 , getScriptPrefix = 5 , getSecretPrefix = 128 , getExtPubKeyPrefix = 0x0488b21e , getExtSecretPrefix = 0x0488ade4 , getNetworkMagic = 0xf9beb4d9 , getGenesisHeader = BlockHeader -- Hash 000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f { blockVersion = 0x01 , prevBlock = "0000000000000000000000000000000000000000000000000000000000000000" , merkleRoot = "3ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a" , blockTimestamp = 1231006505 , blockBits = 486604799 , bhNonce = 2083236893 } , getMaxBlockSize = 1000000 , getMaxSatoshi = 2100000000000000 , getHaskoinUserAgent = "/haskoin:0.3.0/" , getDefaultPort = 8333 , getAllowMinDifficultyBlocks = False , getPowLimit = fromIntegral (maxBound `shiftR` 32 :: Word256) , getTargetTimespan = 14 * 24 * 60 * 60 , getTargetSpacing = 10 * 60 , getCheckpoints = [ ( 11111 , "0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d" ) , ( 33333 , "000000002dd5588a74784eaa7ab0507a18ad16a236e7b1ce69f00d7ddfb5d0a6" ) , ( 74000 , "0000000000573993a3c9e41ce34471c079dcf5f52a0e824a81e7f953b8661a20" ) , ( 105000 , "00000000000291ce28027faea320c8d2b054b2e0fe44a773f3eefb151d6bdc97" ) , ( 134444 , "00000000000005b12ffd4cd315cd34ffd4a594f430ac814c91184a0d42d2b0fe" ) , ( 168000 , "000000000000099e61ea72015e79632f216fe6cb33d7899acb35b75c8303b763" ) , ( 193000 , "000000000000059f452a5f7340de6682a977387c17010ff6e6c3bd83ca8b1317" ) , ( 210000 , "000000000000048b95347e83192f69cf0366076336c639f9b7228e9ba171342e" ) , ( 216116 , "00000000000001b4f4b433e81ee46494af945cf96014816a4e2370f11b23df4e" ) , ( 225430 , "00000000000001c108384350f74090433e7fcf79a606b8e797f065b130575932" ) , ( 250000 , "000000000000003887df1f29024b06fc2200b55f8af8f35453d7be294df2d214" ) , ( 279000 , "0000000000000001ae8c72a0b0c301f67e3afca10e819efa9041e458e9bd7e40" ) ] } testnet3 :: Network testnet3 = Network { getNetworkName = "testnet" , getAddrPrefix = 111 , getScriptPrefix = 196 , getSecretPrefix = 239 , getExtPubKeyPrefix = 0x043587cf , getExtSecretPrefix = 0x04358394 , getNetworkMagic = 0x0b110907 , getGenesisHeader = BlockHeader -- Hash 000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943 { blockVersion = 0x01 , prevBlock = "0000000000000000000000000000000000000000000000000000000000000000" , merkleRoot = "3ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a" , blockTimestamp = 1296688602 , blockBits = 486604799 , bhNonce = 414098458 } , getMaxBlockSize = 1000000 , getMaxSatoshi = 2100000000000000 , getHaskoinUserAgent = "/haskoin-testnet:0.3.0/" , getDefaultPort = 18333 , getAllowMinDifficultyBlocks = True , getPowLimit = fromIntegral (maxBound `shiftR` 32 :: Word256) , getTargetTimespan = 14 * 24 * 60 * 60 , getTargetSpacing = 10 * 60 , getCheckpoints = [ ( 546 , "000000002a936ca763904c3c35fce2f3556c559c0214345d31b1bcebf76acb70" ) ] }