commit cc26a14c9df241afa7f2775e2b38a0935f9af18a
parent e0493e2d7e0233020fbf05dbf5af7e25e0d1fb8e
Author: Jared Tobin <jared@jtobin.io>
Date: Sat, 10 Oct 2026 14:31:08 +0400
lib: table-driven CRC-32C
Halves the time of channel_update_checksum.
Diffstat:
1 file changed, 23 insertions(+), 8 deletions(-)
diff --git a/lib/Lightning/Protocol/BOLT7/CRC32C.hs b/lib/Lightning/Protocol/BOLT7/CRC32C.hs
@@ -13,22 +13,37 @@ module Lightning.Protocol.BOLT7.CRC32C (
crc32c
) where
-import Data.Bits (complement, shiftR, xor, (.&.))
+import Data.Bits (complement, shiftL, shiftR, xor, (.&.), (.|.))
import qualified Data.ByteString as BS
+import qualified Data.ByteString.Unsafe as BU
import Data.Word (Word8, Word32)
--- the Castagnoli polynomial 0x1EDC6F41, bit-reflected
-poly :: Word32
-poly = 0x82F63B78
-
-- | The CRC-32C of a byte string.
crc32c :: BS.ByteString -> Word32
crc32c = complement . BS.foldl' step 0xFFFFFFFF
+ where
+ step !c !b = (c `shiftR` 8) `xor` entry (fromIntegral c `xor` b)
{-# INLINE crc32c #-}
-step :: Word32 -> Word8 -> Word32
-step !crc !byte = go (8 :: Int) (crc `xor` fromIntegral byte)
+-- the table entry for a byte, read from 'table'
+entry :: Word8 -> Word32
+entry i =
+ let !o = 4 * fromIntegral i -- at most 1020, within the 1024-byte table
+ byte k = fromIntegral (BU.unsafeIndex table (o + k)) :: Word32
+ in byte 0 .|. (byte 1 `shiftL` 8) .|. (byte 2 `shiftL` 16)
+ .|. (byte 3 `shiftL` 24)
+{-# INLINE entry #-}
+
+-- the 256 table entries, little-endian
+table :: BS.ByteString
+table = fst (BS.unfoldrN 1024 byte 0)
where
+ byte :: Int -> Maybe (Word8, Int)
+ byte k = Just
+ (fromIntegral (go (8 :: Int) (fromIntegral (k `shiftR` 2))
+ `shiftR` (8 * (k .&. 3))), k + 1)
+ -- the Castagnoli polynomial 0x1EDC6F41, bit-reflected
+ poly = 0x82F63B78 :: Word32
go 0 !c = c
go n !c = go (n - 1) ((c `shiftR` 1) `xor` (poly .&. negate (c .&. 1)))
-{-# INLINE step #-}
+{-# NOINLINE table #-}