diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,11 @@
 The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
 and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
 
+## 0.9.6
+### Added
+- `bloomRelevantUpdate` implementation for Bloom filters (thanks to @IlyasRidhuan).
+- Fix for Bech32 encoding (thanks to @pavel-main).
+
 ## 0.9.5
 ### Added
 - Expose functions added in 0.9.4.
diff --git a/haskoin-core.cabal b/haskoin-core.cabal
--- a/haskoin-core.cabal
+++ b/haskoin-core.cabal
@@ -4,10 +4,10 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: 5f5401cf4317b9dec2a9b9aa52cf78893d599e2b45dc74a8f2bce1653c8a83ad
+-- hash: 263bc514478d37e2471bbc351ea84b803c76e518c55d7143d1e7927cd5f49e68
 
 name:           haskoin-core
-version:        0.9.5
+version:        0.9.6
 synopsis:       Bitcoin & Bitcoin Cash library for Haskell
 description:    Haskoin Core is a complete Bitcoin and Bitcoin Cash library of functions and data types for Haskell developers.
 category:       Bitcoin, Finance, Network
diff --git a/src/Network/Haskoin/Address/Bech32.hs b/src/Network/Haskoin/Address/Bech32.hs
--- a/src/Network/Haskoin/Address/Bech32.hs
+++ b/src/Network/Haskoin/Address/Bech32.hs
@@ -131,7 +131,7 @@
 bech32Encode :: HRP -> [Word5] -> Maybe Bech32
 bech32Encode hrp dat = do
     guard $ checkHRP hrp
-    let dat' = dat ++ bech32CreateChecksum hrp dat
+    let dat' = dat ++ bech32CreateChecksum (T.toLower hrp) dat
         rest = map (charset !) dat'
         result = T.concat [T.toLower hrp, T.pack "1", T.pack rest]
     guard $ T.length result <= maxBech32Length
diff --git a/src/Network/Haskoin/Network/Bloom.hs b/src/Network/Haskoin/Network/Bloom.hs
--- a/src/Network/Haskoin/Network/Bloom.hs
+++ b/src/Network/Haskoin/Network/Bloom.hs
@@ -24,6 +24,7 @@
     , isBloomEmpty
     , isBloomFull
     , acceptsFilters
+    , bloomRelevantUpdate
     ) where
 
 import           Control.Monad                  (forM_, replicateM)
@@ -33,14 +34,16 @@
 import qualified Data.Foldable                  as F
 import           Data.Hash.Murmur               (murmur3)
 import qualified Data.Sequence                  as S
-import           Data.Serialize                 (Serialize, get, put)
+import           Data.Serialize                 (Serialize, get, put,encode)
 import           Data.Serialize.Get             (getByteString, getWord32le,
                                                  getWord8)
 import           Data.Serialize.Put             (putByteString, putWord32le,
                                                  putWord8)
 import           Data.Word
 import           Network.Haskoin.Network.Common
-
+import           Network.Haskoin.Script.Common
+import           Network.Haskoin.Transaction.Common
+import           Data.List                      (foldl')
 -- | 20,000 items with fp rate < 0.1% or 10,000 items and <0.0001%
 maxBloomSize :: Int
 maxBloomSize = 36000
@@ -193,8 +196,47 @@
     isSet i = S.index s (fromIntegral $ i `shiftR` 3)
           .&. (bitMask !! fromIntegral (7 .&. i)) /= 0
 
--- TODO: Write bloomRelevantUpdate
--- bloomRelevantUpdate :: BloomFilter -> Tx -> Hash256 -> Maybe BloomFilter
+-- | Checks if any of the outputs of a tx is in the current bloom filter.
+-- If it is, add the txid and vout as an outpoint (i.e. so that 
+-- a future tx that spends the output won't be missed).
+bloomRelevantUpdate :: BloomFilter       
+                    -- ^ Bloom filter
+                    -> Tx                
+                    -- ^ Tx that may (or may not) have relevant outputs
+                    -> Maybe BloomFilter 
+                    -- ^ Returns an updated bloom filter adding relevant output
+bloomRelevantUpdate bfilter tx
+    | isBloomFull bfilter || isBloomEmpty bfilter = Nothing
+    | bloomFlags bfilter == BloomUpdateNone = Nothing
+    | length matchOuts > 0 = Just $ foldl' (addRelevant) bfilter matchOuts
+    | otherwise = Nothing
+    where
+        -- TxHash if we end up inserting an outpoint
+        h = txHash tx
+        -- Decode the scriptOutpus and add vOuts in case we make them outpoints
+        decodedOutputScripts = traverse (decodeOutputBS . scriptOutput) $ txOut tx
+        err = error $ "Error Decoding output script"
+        idxOutputScripts = either (const err) (zip [0..]) decodedOutputScripts
+        -- Check if any txOuts were contained in the bloom filter
+        matchFilter = filter (\(_,op) -> bloomContains bfilter $ encodeScriptOut op)
+        matchOuts = matchFilter idxOutputScripts
+
+        addRelevant :: BloomFilter -> (Word32,ScriptOutput) -> BloomFilter
+        addRelevant bfilter (id,scriptOut) = case (bloomFlags bfilter,scriptType) of
+            -- We filtered out BloomUpdateNone so we insert any PayPk or PayMulSig
+            (_, True) -> bloomInsert bfilter outpoint
+            (BloomUpdateAll, _ ) -> bloomInsert bfilter outpoint
+            _ ->  error "Error Updating Bloom Filter with relevant outpoint"
+            where
+                outpoint = encode $ OutPoint{ outPointHash = h, outPointIndex = id}
+                scriptType = (\s -> isPayPK s ||isPayMulSig s) scriptOut
+
+        -- Encodes a scriptOutput so it can be checked agains the Bloom Filter
+        encodeScriptOut :: ScriptOutput -> ByteString
+        encodeScriptOut (PayMulSig outputMuSig _) = encode outputMuSig
+        encodeScriptOut (PayWitnessScriptHash scriptHash) = encode scriptHash
+        encodeScriptOut (DataCarrier getOutputData) = encode getOutputData
+        encodeScriptOut outputHash = (encode . getOutputHash) outputHash
 
 -- | Returns True if the filter is empty (all bytes set to 0x00)
 isBloomEmpty :: BloomFilter -> Bool
diff --git a/test/Network/Haskoin/Address/Bech32Spec.hs b/test/Network/Haskoin/Address/Bech32Spec.hs
--- a/test/Network/Haskoin/Address/Bech32Spec.hs
+++ b/test/Network/Haskoin/Address/Bech32Spec.hs
@@ -28,6 +28,8 @@
         it "should be a valid address" $ forM_ validAddresses testValidAddress
         it "should be an invalid address" $
             forM_ invalidAddresses testInvalidAddress
+        it "should be same for the input in different case" $
+            all (== Just "test12hrzfj") . map (flip bech32Encode []) $ hrpCaseVariants
     describe "more encoding/decoding cases" $ do
         it "length > 90" $
             assert $
@@ -141,3 +143,14 @@
     , "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3pjxtptv"
     , "bc1gmk9yu"
     ]
+
+hrpCaseVariants:: [Text]
+hrpCaseVariants = map T.pack hrpTestPermutations
+
+hrpTestPermutations :: [String]
+hrpTestPermutations = do
+    a <- ['t', 'T']
+    b <- ['e', 'E']
+    c <- ['s', 'S']
+    d <- ['t', 'T']
+    return [a, b, c, d]
diff --git a/test/Network/Haskoin/NetworkSpec.hs b/test/Network/Haskoin/NetworkSpec.hs
--- a/test/Network/Haskoin/NetworkSpec.hs
+++ b/test/Network/Haskoin/NetworkSpec.hs
@@ -11,8 +11,10 @@
 import           Network.Haskoin.Network
 import           Network.Haskoin.Test
 import           Network.Haskoin.Util
+import           Network.Haskoin.Transaction.Common
 import           Test.Hspec
-import           Test.HUnit                (Assertion, assertBool)
+import           Test.HUnit                (Assertion, assertBool,
+                                            assertEqual)
 import           Test.QuickCheck
 
 spec :: Spec
@@ -22,6 +24,9 @@
         it "bloom filter vector 1" bloomFilter1
         it "bloom filter vector 2" bloomFilter2
         it "bloom filter vector 3" bloomFilter3
+    describe "relevant bloom filter update" $ do
+        it "Relevant Update" relevantOutputUpdated
+        it "Irrelevant Update" irrelevantOutputNotUpdated
     describe "serialization of protocol types" $ do
         it "encodes and decodes varint" $
             property $ forAll arbitraryVarInt cerealID
@@ -107,3 +112,76 @@
 
 testPutGet :: Eq a => Get a -> Putter a -> a -> Bool
 testPutGet g p a = runGet g (runPut (p a)) == Right a
+
+relevantOutputUpdated :: Assertion
+relevantOutputUpdated = assertBool "Bloom filter output updated" $
+    any (bloomContains bf2) spendTxInput
+    where
+        bf0 = bloomCreate 10 0.000001 0 BloomUpdateAll
+        relevantOutputHash = fromJust $ decodeHex"03f47604ea2736334151081e13265b4fe38e6fa8"
+        bf1 = bloomInsert bf0 relevantOutputHash
+        bf2 = fromJust $ bloomRelevantUpdate bf1 relevantTx
+        spendTxInput = (encode .prevOutput) <$> txIn spendRelevantTx 
+
+irrelevantOutputNotUpdated :: Assertion
+irrelevantOutputNotUpdated = assertEqual "Bloom filter not updated" Nothing bf2 
+    where
+        bf0 = bloomCreate 10 0.000001 0 BloomUpdateAll
+        relevantOutputHash = fromJust $ decodeHex"03f47604ea2736334151081e13265b4fe38e6fa8"
+        bf1 = bloomInsert bf0 relevantOutputHash
+        bf2 = bloomRelevantUpdate bf1 unrelatedTx
+        spendTxInput = (encode .prevOutput) <$> txIn spendRelevantTx 
+
+-- Random transaction (57dc904f32ad4daab7b321dd469e8791ad09df784cdd273a73985150a4f225e9)
+relevantTx :: Tx
+relevantTx = Tx
+        { txVersion = 1
+        , txIn = [ TxIn
+            { prevOutput = OutPoint "35fe9017b7e3af592920b56fa06ac02faf0c52cdb19dcb416129ac71c95d060e" 1
+            , scriptInput = fromJust $ decodeHex "473044022032fc8eef299b7e94b9a986a6aa2dcb9733ab804bef80df995e443b9c1f8c604202203335df7a2e2b4789451cdb4b2b05a786a81c51519eb6a567fd6fe8cd7b2d33fe014104272502dc63a512dad1473cb82a71be9baf4f4303abd1ff6028fc8a78e1f3aec1218907119dec14f07354850758ff0948e88a904fa411c4df7d5444414ec64ad6"
+            , txInSequence = 4294967295
+            } ]
+        , txOut =
+            [ TxOut { outValue = 100000000, scriptOutput = fromJust $ decodeHex "76a91403f47604ea2736334151081e13265b4fe38e6fa888ac" }
+            , TxOut { outValue = 107980000, scriptOutput = fromJust $ decodeHex "76a91481cc186a2f4a69f633ed4bf10ef4a78be13effdd88ac" }
+            ]
+        , txWitness = []
+        , txLockTime = 0
+        }
+
+-- Transaction that spends above (fd6e3b693b844aa431fad46765c1aa019a6b13aebfa9dae916b3ffa43283a300)
+spendRelevantTx :: Tx
+spendRelevantTx = Tx
+        { txVersion = 1
+        , txIn = [ TxIn
+            { prevOutput = OutPoint "57dc904f32ad4daab7b321dd469e8791ad09df784cdd273a73985150a4f225e9" 0
+            , scriptInput = fromJust $ decodeHex "483045022100ecc334821e4e94cc2fdc841d5ad147d5bb942b993ba81460cc446e0410afa811022015fcbc542b734dbb61a05ec06012095096de5839c50808fe56f2b315e877c20d012103fb64e5792fa586172339b776b7017d3d529358cb73be6406a1fc994228d14f88"
+            , txInSequence = 4294967295
+            }, TxIn
+            { prevOutput = OutPoint "cfee6a8d6e68e8fd16df6fff010afffcd19d7e075aa7b707dd1bae6adc420042" 0
+            , scriptInput = fromJust $ decodeHex "47304402200e6bb95fa606f254d17089d83c4ceeb19c5d1699b4faddcd4f1f1568286e6b650220087fb8439f31e1b30e47710d095422405f601d6151f2f93e125e1a08a6e29ad4012103b49252e8fc6d5b49c8d14ee71fab45591df4a126a6c453c724f3d356e38f0cee"
+            , txInSequence = 4294967295
+            } ]
+        , txOut =
+            [ TxOut { outValue = 3851100, scriptOutput = fromJust $ decodeHex "76a914a297cae82a9a3b932bf023ae274fe2585295c9ca88ac" }
+            , TxOut { outValue = 111000000, scriptOutput = fromJust $ decodeHex "76a9148f952c38600a61385974acc30a64f74407f9801488ac" }
+            ]
+        , txWitness = []
+        , txLockTime = 0
+        }
+
+-- This random transaction is unrelated to the others
+unrelatedTx :: Tx
+unrelatedTx = Tx
+        { txVersion = 1
+        , txIn = [ TxIn
+            { prevOutput = OutPoint "3ec3a71431c68e5d978a5fb4a0a1081d8bee8384d8aa4c06b1fbaf9413e2214f" 20
+            , scriptInput = fromJust $ decodeHex "483045022100ec9c202c9d3140b973aca9d7f21a82138aa4cfa43fddc5419098ac5e26a6f152022010848fd688f290ae010fb5cb493410caa03145fc12445900ec1ad2bde33aecd9012102c7445e72d723f99a0064526c28269d07f47c8fd81531a94a8d3bf5ebd5e23ef1"
+            , txInSequence = 4294967295
+            }]
+        , txOut =
+            [ TxOut { outValue = 12600000, scriptOutput = fromJust $ decodeHex "76a9148fef3b7051de8cc44e966159e7ea37f4520187e888ac" }
+            ]
+        , txWitness = []
+        , txLockTime = 0
+        }
