bolt7

Routing gossip protocol, per BOLT #7 (docs.ppad.tech/bolt7).
git clone git://git.ppad.tech/bolt7.git
Log | Files | Refs | README | LICENSE

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 #-}