diff --git a/bitcoin-compact-filters.cabal b/bitcoin-compact-filters.cabal
--- a/bitcoin-compact-filters.cabal
+++ b/bitcoin-compact-filters.cabal
@@ -1,6 +1,6 @@
 cabal-version:       2.2
 name:                bitcoin-compact-filters
-version:             0.1.0.2
+version:             0.1.1
 synopsis:            BIP 158 compact block filters
 
 copyright:           2020 Bitnomial, Inc.
@@ -15,19 +15,20 @@
     examples/*.json
 
 tested-with:
-    GHC == 8.10.4
-  , GHC == 8.10.5
-  , GHC == 9.0.1
+    GHC == 8.10.7
+  , GHC == 9.0.2
+  , GHC == 9.2.7
+  , GHC == 9.4.4
 
 common core
   default-language: Haskell2010
   ghc-options:      -Wall
   build-depends:
-      base >=4.12 && <4.16
+      base >=4.12 && <4.19
     , bytestring >=0.10 && <0.12
     , cereal ^>=0.5
-    , haskoin-core >=0.17.1 && <0.21
-    , text ^>=1.2
+    , haskoin-core >=0.17.1 && <0.22
+    , text >=1.2 && <2.1
 
      
 library
@@ -38,9 +39,8 @@
     Bitcoin.CompactFilter
 
   build-depends:
-      bitstream ^>=0.3.0.1
-    , transformers ^>=0.5
-    , memory >=0.15 && <0.17
+      transformers >=0.5 && <0.7
+    , memory >=0.15 && <0.19
 
 
 test-suite bitcoin-cf-tests
@@ -61,7 +61,7 @@
     Paths_bitcoin_compact_filters
 
   build-depends:
-      aeson >=1.0 && <1.6
+      aeson >=1.0 && <2.2
     , bitcoin-compact-filters
     , tasty >=1.0 && <1.5
     , tasty-hunit >=0.9 && <0.11
diff --git a/src/Bitcoin/CompactFilter.hs b/src/Bitcoin/CompactFilter.hs
--- a/src/Bitcoin/CompactFilter.hs
+++ b/src/Bitcoin/CompactFilter.hs
@@ -19,9 +19,7 @@
 import Control.Monad.Trans.Class (lift)
 import Control.Monad.Trans.State.Strict (StateT, evalStateT)
 import qualified Control.Monad.Trans.State.Strict as St
-import Data.Bits (shiftL, shiftR, testBit)
-import Data.Bitstream (Bitstream, Right)
-import qualified Data.Bitstream as BiS
+import Data.Bits (clearBit, setBit, shiftL, shiftR, testBit)
 import Data.Bool (bool)
 import Data.ByteArray.Hash (
     SipHash (..),
@@ -30,6 +28,7 @@
  )
 import Data.ByteString (ByteString)
 import qualified Data.ByteString as BS
+import qualified Data.ByteString.Lazy as BSL
 import Data.Foldable (foldl')
 import Data.List (sort)
 import Data.Serialize (
@@ -72,8 +71,8 @@
 
 -- | Hashes of scripts in the block
 newtype BlockFilter = BlockFilter
-    { -- | Get the list of hashes in increasing order
-      blockFilter :: [Word64]
+    { blockFilter :: [Word64]
+    -- ^ Get the list of hashes in increasing order
     }
     deriving (Eq, Show)
 
@@ -221,6 +220,36 @@
             | otherwise -> x0 : dedup xs
         xs -> xs
 
+{- | Golomb coded sets are not naturally expressed in bytes, but rather as a bit
+ stream
+-}
+data Bitstream
+    = Bitstream
+        BSL.ByteString
+        -- ^ Complete bytes written so far, in reverse order
+        {-# UNPACK #-} !Word8
+        -- ^ The current work byte
+        {-# UNPACK #-} !Int
+        -- ^ Pointer to the first open bit
+
+emptyB :: Bitstream
+emptyB = Bitstream mempty 0 7
+
+appendBit :: Bool -> Bitstream -> Bitstream
+appendBit b (Bitstream bytes inFlight cursor)
+    | cursor == 0 = Bitstream (BSL.cons nextInFlight bytes) 0 7
+    | otherwise = Bitstream bytes nextInFlight (cursor - 1)
+  where
+    nextInFlight = bool clearBit setBit b inFlight cursor
+
+asByteString :: Bitstream -> ByteString
+asByteString (Bitstream bytes inFlight cursor) =
+    BSL.toStrict $ BSL.reverse paddedBytes
+  where
+    paddedBytes
+        | cursor == 7 = bytes
+        | otherwise = BSL.cons inFlight bytes
+
 constructGCS ::
     -- | modulus
     Int ->
@@ -228,8 +257,8 @@
     [Word64] ->
     ByteString
 constructGCS p =
-    BiS.toByteString
-        . foldMap (golombRiceEncode p)
+    asByteString
+        . foldl' (golombRiceEncode p) emptyB
         . diffs
 
 diffs :: Num a => [a] -> [a]
@@ -239,12 +268,12 @@
 unDiffs (x : xs) = scanl (+) x xs
 unDiffs [] = []
 
-golombRiceEncode :: Int -> Word64 -> Bitstream Right
-golombRiceEncode p v = x <> BiS.singleton False <> y
+golombRiceEncode :: Int -> Bitstream -> Word64 -> Bitstream
+golombRiceEncode p b v = foldl' (flip nextBit) prefix [p - i | i <- [1 .. p]]
   where
     q = fromIntegral $ v `shiftR` p
-    x = BiS.replicate q True
-    y = BiS.fromNBits p v
+    prefix = appendBit False $ iterate (appendBit True) b !! q
+    nextBit = appendBit . testBit v
 
 fromBits :: Num a => [Bool] -> a
 fromBits = foldl' onBit 0
