Skip to content

Commit

Permalink
Introduce constants checksumLength and maxEncodedStringLength.
Browse files Browse the repository at this point in the history
Use these constants to avoid repeatedly hardcoding the same values
within functions.
  • Loading branch information
jonathanknowles committed May 15, 2019
1 parent 9d0c225 commit 7e66795
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 8 deletions.
22 changes: 17 additions & 5 deletions lib/bech32/src/Codec/Binary/Bech32.hs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@

module Codec.Binary.Bech32
(
-- * Encoder & Decoder
-- * Encoding & Decoding
encode
, decode
, checksumLength
, maxEncodedStringLength

-- * Human-Readable Part
, HumanReadablePart
Expand Down Expand Up @@ -95,21 +97,31 @@ encode hrp@(HumanReadablePart hrpBytes) payload = do
let payload' = payload5 ++ bech32CreateChecksum hrp payload5
let rest = map (charset Arr.!) payload'
let output = B8.map toLower hrpBytes <> B8.pack "1" <> B8.pack rest
guard (BS.length output <= 90)
guard (BS.length output <= maxEncodedStringLength)
return output

decode :: ByteString -> Maybe (HumanReadablePart, ByteString)
decode bech32 = do
guard $ BS.length bech32 <= 90
guard $ BS.length bech32 <= maxEncodedStringLength
guard $ B8.map toUpper bech32 == bech32 || B8.map toLower bech32 == bech32
let (hrp, dat) = B8.breakEnd (== '1') $ B8.map toLower bech32
guard $ BS.length dat >= 6
guard $ BS.length dat >= checksumLength
hrp' <- B8.stripSuffix (B8.pack "1") hrp >>= mkHumanReadablePart
dat' <- mapM charsetMap $ B8.unpack dat
guard $ bech32VerifyChecksum hrp' dat'
result <- toBase256 (take (BS.length dat - 6) dat')
result <- toBase256 (take (BS.length dat - checksumLength) dat')
return (hrp', BS.pack result)

-- | The length of the checksum portion of an encoded string, in bytes.
checksumLength :: Int
checksumLength = 6

-- | The maximum length of an encoded string, in bytes. This length includes the
-- human-readable part, the separator character, the encoded data portion,
-- and the checksum.
maxEncodedStringLength :: Int
maxEncodedStringLength = 90

{-------------------------------------------------------------------------------
Internal
-------------------------------------------------------------------------------}
Expand Down
13 changes: 10 additions & 3 deletions lib/bech32/test/Codec/Binary/Bech32Spec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,17 @@ spec = do
Bech32.decode checksum `shouldSatisfy` isNothing

describe "More Encoding/Decoding Cases" $ do
it "length > 90" $ do
let (Just hrp) = mkHumanReadablePart (B8.pack "ca")
Bech32.encode hrp (BS.pack (replicate 82 1))
it "length > maximum" $ do
let hrpUnpacked = "ca"
let hrpLength = length hrpUnpacked
let (Just hrp) = mkHumanReadablePart (B8.pack hrpUnpacked)
let separatorLength = 1
let maxDataLength =
Bech32.maxEncodedStringLength
- Bech32.checksumLength - separatorLength - hrpLength
Bech32.encode hrp (BS.pack (replicate (maxDataLength + 1) 1))
`shouldSatisfy` isNothing

it "hrp lowercased" $ do
let (Just hrp) = mkHumanReadablePart (B8.pack "HRP")
Bech32.encode hrp mempty
Expand Down

0 comments on commit 7e66795

Please sign in to comment.