easy-bitcoin-0.0.0.2: Network/EasyBitcoin/Internal/Base58.hs
{-# LANGUAGE OverloadedStrings #-}
module Network.EasyBitcoin.Internal.Base58
( encodeBase58
, decodeBase58
, addRedundancy
, liftRedundacy
)
where
import qualified Data.ByteString as BS
import Data.Char (ord, chr)
import Data.Word (Word8)
import Data.Maybe (fromJust, isJust, listToMaybe)
import Numeric (showIntAtBase, readInt)
import Data.String (fromString)
import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as B8
import qualified Data.Text as T
import Control.Applicative
import Data.Bits
import Data.List(unfoldr)
import Numeric (showIntAtBase, readInt)
import Network.EasyBitcoin.Internal.HashFunctions
import Network.EasyBitcoin.Internal.ByteString
-------------------------------------------------------------------------------
-----------------------------------------------------
addRedundancy :: BS.ByteString -> BS.ByteString
addRedundancy bs = BS.append bs (encode' $ chksum32 bs)
liftRedundacy :: BS.ByteString -> Maybe BS.ByteString
liftRedundacy bs = let (original,extra) = BS.splitAt (BS.length bs - 4) bs
in if encode' (chksum32 original) == extra
then Just original
else Nothing
encodeBase58::BS.ByteString -> String
encodeBase58 bs = l++r
where
(z,b) = BS.span (== 0) bs
l = replicate (BS.length z) '1' -- preserve leading 0's
r | BS.null b = ""
| otherwise = encodeBase58I $ bsToInteger b
decodeBase58::String -> Maybe BS.ByteString
decodeBase58 str = r >>= return . (BS.append prefix)
where
(z,b) = span (== '1') $ str
prefix = BS.replicate (length z) 0 -- preserve leading 1's
r | null b = Just BS.empty
| otherwise = integerToBS <$> decodeBase58I b
---------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------
b58Data :: BS.ByteString
b58Data = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
b58 :: Word8 -> Word8
b58 i = BS.index b58Data (fromIntegral i)
b58' :: Word8 -> Maybe Word8
b58' w = fromIntegral <$> BS.elemIndex w b58Data
encodeBase58I :: Integer -> String
encodeBase58I i = showIntAtBase (58 :: Integer) f (fromIntegral i) ""
where
f = chr . fromIntegral . b58 . fromIntegral
decodeBase58I :: String -> Maybe Integer
decodeBase58I s = case listToMaybe $ readInt 58 p f s of
Just (r,[]) -> Just r
_ -> Nothing
where
c = b58' . fromIntegral . ord
p = isJust . c
f = fromIntegral . fromJust . c
------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------
-- | Transforms a string into a strict bytestring
stringToBS :: String -> BS.ByteString
stringToBS = B8.pack
-- | Transform a strict bytestring to a string
bsToString :: BS.ByteString -> String
bsToString = B8.unpack