bech32

Pure Haskell bech32, bech32m encoding/decoding (docs.ppad.tech/bech32).
git clone git://git.ppad.tech/bech32.git
Log | Files | Refs | README | LICENSE

commit ac53d4ef9aebd4ce0687d108d4e365bc689175fa
parent 5b396bdc0d4700cc1b27f5b58ac2e28802c3f9db
Author: Jared Tobin <jared@jtobin.io>
Date:   Tue, 10 Jun 2025 19:01:05 +0400

lib: make total

Diffstat:
Mlib/Data/ByteString/Bech32.hs | 3++-
Mlib/Data/ByteString/Bech32/Internal.hs | 24+++++++++++++++---------
Mlib/Data/ByteString/Bech32m.hs | 3++-
3 files changed, 19 insertions(+), 11 deletions(-)

diff --git a/lib/Data/ByteString/Bech32.hs b/lib/Data/ByteString/Bech32.hs @@ -50,7 +50,8 @@ encode -> Maybe BS.ByteString -- ^ bech32-encoded bytestring encode (B8.map C.toLower -> hrp) (B32.encode -> dat) = do guard (BI.valid_hrp hrp) - let check = create_checksum hrp (BI.as_word5 dat) + ws <- BI.as_word5 dat + let check = create_checksum hrp ws res = toStrict $ BSB.byteString hrp <> BSB.word8 49 -- 1 diff --git a/lib/Data/ByteString/Bech32/Internal.hs b/lib/Data/ByteString/Bech32/Internal.hs @@ -77,11 +77,13 @@ word5 = \case {-# INLINE word5 #-} -- base32 -> word5 -as_word5 :: BS.ByteString -> BS.ByteString -as_word5 = BS.map f where - f b = case word5 (fi b) of - Nothing -> error "ppad-bech32 (as_word5): input not bech32-encoded" - Just w -> fi w +as_word5 :: BS.ByteString -> Maybe BS.ByteString +as_word5 = go mempty where + go acc bs = case BS.uncons bs of + Nothing -> pure (toStrict acc) + Just (h, t) -> do + w5 <- word5 (fi h) + go (acc <> BSB.word8 w5) t -- word5 -> base32 as_base32 :: BS.ByteString -> BS.ByteString @@ -144,8 +146,12 @@ verify enc b32 = case BS.elemIndexEnd 0x31 b32 of Nothing -> False Just idx -> let (hrp, BU.unsafeDrop 1 -> dat) = BS.splitAt idx b32 - bs = hrp_expand hrp <> as_word5 dat - in polymod bs == case enc of - Bech32 -> 1 - Bech32m -> _BECH32M_CONST + w5s = as_word5 dat + in case w5s of + Nothing -> False + Just ws -> + let bs = hrp_expand hrp <> ws + in polymod bs == case enc of + Bech32 -> 1 + Bech32m -> _BECH32M_CONST diff --git a/lib/Data/ByteString/Bech32m.hs b/lib/Data/ByteString/Bech32m.hs @@ -51,7 +51,8 @@ encode -> Maybe BS.ByteString -- ^ bech32m-encoded bytestring encode (B8.map C.toLower -> hrp) (B32.encode -> dat) = do guard (BI.valid_hrp hrp) - let check = create_checksum hrp (BI.as_word5 dat) + ws <- BI.as_word5 dat + let check = create_checksum hrp ws res = toStrict $ BSB.byteString hrp <> BSB.word8 49 -- 1