CRC32C.hs (1581B)
1 {-# OPTIONS_HADDOCK hide #-} 2 {-# LANGUAGE BangPatterns #-} 3 4 -- | 5 -- Module: Lightning.Protocol.BOLT7.CRC32C 6 -- Copyright: (c) 2025 Jared Tobin 7 -- License: MIT 8 -- Maintainer: Jared Tobin <jared@ppad.tech> 9 -- 10 -- CRC-32C (Castagnoli), per RFC 3720, for @channel_update@ checksums. 11 12 module Lightning.Protocol.BOLT7.CRC32C ( 13 crc32c 14 ) where 15 16 import Data.Bits (complement, shiftL, shiftR, xor, (.&.), (.|.)) 17 import qualified Data.ByteString as BS 18 import qualified Data.ByteString.Unsafe as BU 19 import Data.Word (Word8, Word32) 20 21 -- | The CRC-32C of a byte string. 22 crc32c :: BS.ByteString -> Word32 23 crc32c = complement . BS.foldl' step 0xFFFFFFFF 24 where 25 step !c !b = (c `shiftR` 8) `xor` entry (fromIntegral c `xor` b) 26 {-# INLINE crc32c #-} 27 28 -- the table entry for a byte, read from 'table' 29 entry :: Word8 -> Word32 30 entry i = 31 let !o = 4 * fromIntegral i -- at most 1020, within the 1024-byte table 32 byte k = fromIntegral (BU.unsafeIndex table (o + k)) :: Word32 33 in byte 0 .|. (byte 1 `shiftL` 8) .|. (byte 2 `shiftL` 16) 34 .|. (byte 3 `shiftL` 24) 35 {-# INLINE entry #-} 36 37 -- the 256 table entries, little-endian 38 table :: BS.ByteString 39 table = fst (BS.unfoldrN 1024 byte 0) 40 where 41 byte :: Int -> Maybe (Word8, Int) 42 byte k = Just 43 (fromIntegral (go (8 :: Int) (fromIntegral (k `shiftR` 2)) 44 `shiftR` (8 * (k .&. 3))), k + 1) 45 -- the Castagnoli polynomial 0x1EDC6F41, bit-reflected 46 poly = 0x82F63B78 :: Word32 47 go 0 !c = c 48 go n !c = go (n - 1) ((c `shiftR` 1) `xor` (poly .&. negate (c .&. 1))) 49 {-# NOINLINE table #-}