Skip to content

Commit

Permalink
Expose the Bech32 character set in a way that is more convenient for …
Browse files Browse the repository at this point in the history
…test code to consume.
  • Loading branch information
jonathanknowles committed May 20, 2019
1 parent bb9323a commit dbdb4e3
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 16 deletions.
24 changes: 14 additions & 10 deletions lib/bech32/src/Codec/Binary/Bech32/Internal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ module Codec.Binary.Bech32.Internal

-- * Character Set Manipulation
, charset
, charsetMap
, word5ToChar
, charToWord5

) where

Expand Down Expand Up @@ -142,7 +143,7 @@ encode :: HumanReadablePart -> ByteString -> Either EncodingError ByteString
encode hrp@(HumanReadablePart hrpBytes) payload = do
let payload5 = toBase32 (BS.unpack payload)
let payload' = payload5 ++ bech32CreateChecksum hrp payload5
let rest = map (charset Arr.!) payload'
let rest = map (word5ToChar Arr.!) payload'
let output = B8.map toLower hrpBytes <> B8.pack "1" <> B8.pack rest
guardE (BS.length output <= encodedStringMaxLength) EncodedStringTooLong
return output
Expand Down Expand Up @@ -196,13 +197,13 @@ decode bech32 = do
-- supported character set, return the list of illegal character positions.
parseDataWithChecksumPart :: ByteString -> Either [CharPosition] [Word5]
parseDataWithChecksumPart dcpUnparsed =
case mapM charsetMap $ B8.unpack dcpUnparsed of
case mapM charToWord5 $ B8.unpack dcpUnparsed of
Nothing -> Left invalidCharPositions
Just dcp -> Right dcp
where
invalidCharPositions =
CharPosition . fst <$> filter (isNothing . snd)
([0 .. ] `zip` (charsetMap <$> B8.unpack dcpUnparsed))
([0 .. ] `zip` (charToWord5 <$> B8.unpack dcpUnparsed))

-- | Convert an error encountered while parsing a human-readable part into a
-- general decoding error.
Expand Down Expand Up @@ -262,14 +263,17 @@ encodedStringMinLength =
Character Manipulation
-------------------------------------------------------------------------------}

charset :: Array Word5 Char
charset =
charset :: String
charset = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"

word5ToChar :: Array Word5 Char
word5ToChar =
Arr.listArray
(Word5 0, Word5 31)
"qpzry9x8gf2tvdw0s3jn54khce6mua7l"
charset

charsetMap :: Char -> Maybe Word5
charsetMap c
charToWord5 :: Char -> Maybe Word5
charToWord5 c
| inRange (Arr.bounds inv) upperC = inv Arr.! upperC
| otherwise = Nothing
where
Expand All @@ -278,7 +282,7 @@ charsetMap c
inv =
Arr.listArray ('0', 'Z') (repeat Nothing)
Arr.//
(map swap (Arr.assocs charset))
(map swap (Arr.assocs word5ToChar))

-- | The zero-based position of a character in a string, counting from the left.
newtype CharPosition = CharPosition Int
Expand Down
13 changes: 7 additions & 6 deletions lib/bech32/test/Codec/Binary/Bech32Spec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -101,15 +101,17 @@ spec = do
isJust (Bech32.toBase256 ws) ==>
(Bech32.toBase32 <$> Bech32.toBase256 ws) === Just ws

describe "Roundtrip (charsetMap . charset)" $ do
describe "Roundtrip (charToWord5 . word5ToChar)" $ do
it "can perform roundtrip character set conversion (lower-case)" $
property $ \w ->
Bech32.charsetMap (toLower (Bech32.charset Arr.! w)) === Just w
Bech32.charToWord5 (toLower (Bech32.word5ToChar Arr.! w))
=== Just w

describe "Roundtrip (charsetMap . charset)" $ do
describe "Roundtrip (charToWord5 . word5ToChar)" $ do
it "can perform roundtrip character set conversion (upper-case)" $
property $ \w ->
Bech32.charsetMap (toUpper (Bech32.charset Arr.! w)) === Just w
Bech32.charToWord5 (toUpper (Bech32.word5ToChar Arr.! w))
=== Just w

describe "Conversion of word string from one word size to another" $ do

Expand Down Expand Up @@ -186,8 +188,7 @@ instance Arbitrary ByteString where
, BS.drop 1 bytes
]
arbitrary = do
let alphabet = B8.unpack "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
bytes <- choose (0, 10) >>= \n -> vectorOf n (elements alphabet)
bytes <- choose (0, 10) >>= \n -> vectorOf n (elements Bech32.charset)
return (B8.pack bytes)

instance Arbitrary Bech32.Word5 where
Expand Down

0 comments on commit dbdb4e3

Please sign in to comment.