diff --git a/src/Tahoe/CHK.hs b/src/Tahoe/CHK.hs
index dc76da5a4387488c0da34eab2281bd970e59b783..edb85f20e93d6707bb00f3e4198560b2db2b620a 100644
--- a/src/Tahoe/CHK.hs
+++ b/src/Tahoe/CHK.hs
@@ -72,6 +72,7 @@ module Tahoe.CHK (
 
 import qualified Codec.FEC as ZFEC
 import Control.Applicative (Alternative (empty))
+import Control.Lens (view, _2)
 import Crypto.Cipher.AES128 (
     AESKey128,
  )
@@ -108,7 +109,7 @@ import Tahoe.CHK.Merkle (
     rootHash,
  )
 import Tahoe.CHK.SHA256d (Digest' (Digest'), zero)
-import Tahoe.CHK.Share (Share (..))
+import Tahoe.CHK.Share (Share (..), uriExtension)
 import Tahoe.CHK.Types (
     BlockHash,
     CrypttextHash,
@@ -119,6 +120,7 @@ import Tahoe.CHK.Types (
  )
 import Tahoe.CHK.URIExtension (
     URIExtension (..),
+    codecParams,
  )
 import Tahoe.CHK.Validate (matchingBlockHashRoot, shareValidBlocks, validFingerprint, validShareRootHash)
 import Tahoe.Netstring (
@@ -336,40 +338,40 @@ encode readKey initParams@(Parameters maximumSegmentSize total _ required) ciphe
                 shareTree' = makeShareTree . map makeTreePartial . transpose $ cpBlockHashes
 
             -- A bag of additional metadata about the share and encoded object.
-            uriExtension =
+            uriExt =
                 URIExtension
-                    { uriExtCodecName = "crs"
-                    , uriExtCodecParams = p -- trace ("Params: " <> show p) p
-                    , uriExtSize = fromIntegral $ LB.length ciphertext
-                    , uriExtSegmentSize = segmentSize
-                    , uriExtNeededShares = required
-                    , uriExtTotalShares = total
-                    , uriExtNumSegments = numSegments
-                    , uriExtTailCodecParams = tailParams p (LB.length ciphertext)
-                    , uriExtCrypttextHash = makeCrypttextHash cpCrypttextHash
-                    , uriExtCrypttextRootHash = makeCrypttextRootHash cpCrypttextHashes
-                    , uriExtShareRootHash = rootHash shareTree
+                    { _codecName = "crs"
+                    , _codecParams = p -- trace ("Params: " <> show p) p
+                    , _size = fromIntegral $ LB.length ciphertext
+                    , _segmentSize = segmentSize
+                    , _neededShares = required
+                    , _totalShares = total
+                    , _numSegments = numSegments
+                    , _tailCodecParams = tailParams p (LB.length ciphertext)
+                    , _crypttextHash = makeCrypttextHash cpCrypttextHash
+                    , _crypttextRootHash = makeCrypttextRootHash cpCrypttextHashes
+                    , _shareRootHash = rootHash shareTree
                     }
 
             -- The read capability for the encoded object.
             cap =
                 Cap.makeReader
                     readKey
-                    (uriExtensionHash uriExtension)
+                    (uriExtensionHash uriExt)
                     required
                     total
                     (fromIntegral $ LB.length ciphertext)
 
             toShare sharenum blocks blockHashes =
                 Share
-                    { shareBlockSize = shareBlockSize p
-                    , shareDataSize = fromIntegral $ LB.length ciphertext `ceilDiv` fromIntegral required
-                    , shareBlocks = blocks
-                    , sharePlaintextHashTree = plaintextHashTree
-                    , shareCrypttextHashTree = crypttextHashTree
-                    , shareBlockHashTree = makeTreePartial blockHashes
-                    , shareNeededHashes = sort . fmap (first fromIntegral) $ computeNeededHashes shareTree sharenum
-                    , shareURIExtension = uriExtension
+                    { _blockSize = shareBlockSize p
+                    , _dataSize = fromIntegral $ LB.length ciphertext `ceilDiv` fromIntegral required
+                    , _blocks = blocks
+                    , _plaintextHashTree = plaintextHashTree
+                    , _crypttextHashTree = crypttextHashTree
+                    , _blockHashTree = makeTreePartial blockHashes
+                    , _neededHashes = sort . fmap (first fromIntegral) $ computeNeededHashes shareTree sharenum
+                    , _uriExtension = uriExt
                     }
 
             -- The size in bytes of one erasure-encoded block of data.
@@ -422,10 +424,10 @@ decode ::
     -- shares if it is possible to recover it, or Left with information about
     -- why it is not.
     IO (Either DecodeError LB.ByteString)
-decode Cap.Reader{verifier = verifier@Cap.Verifier{required, total, size}} shares
-    | size > fromIntegral @Int64 @Integer maxBound = pure $ Left SizeOverflow
-    | length shares < fromIntegral required = pure $ Left NotEnoughShares
-    | length validShares < fromIntegral required = pure . Left . IntegrityError $ invalidShares
+decode reader shares
+    | size reader > fromIntegral @Int64 @Integer maxBound = pure $ Left SizeOverflow
+    | length shares < fromIntegral (required reader) = pure $ Left NotEnoughShares
+    | length validShares < fromIntegral (required reader) = pure . Left . IntegrityError $ invalidShares
     | otherwise = do
         let -- The ZFEC decoder takes as input a list of (share number, block
             -- bytes) tuples (and the encoding parameters).  It wants the list
@@ -466,7 +468,7 @@ decode Cap.Reader{verifier = verifier@Cap.Verifier{required, total, size}} share
             -- the data we cannot use and structure what's left so we can
             -- easily skip over those segments if desired.
             enoughBlocks :: [Maybe [(Int, LB.ByteString)]]
-            enoughBlocks = guarded ((fromIntegral required <=) . length) <$> validBlocks
+            enoughBlocks = guarded ((fromIntegral (required reader) <=) . length) <$> validBlocks
 
             -- Figure out how many bytes are expected to be in each segment.
             -- Depending on the ZFEC encoding parameters, it is possible that
@@ -475,18 +477,18 @@ decode Cap.Reader{verifier = verifier@Cap.Verifier{required, total, size}} share
             -- bytes in the result.  By knowing how many bytes were originally
             -- in our segments, we can recognize and discard these extra
             -- bytes.
-            segSize = fromIntegral . paramSegmentSize . uriExtCodecParams . shareURIExtension . snd . head $ shares
+            segSize = fromIntegral . paramSegmentSize . view (_2 . uriExtension . codecParams) $ head shares
 
             -- A helper that knows the correct parameters to do ZFEC decoding
             -- for us.
-            zunfec' = (LB.take segSize <$>) . zunfecLazy (fromIntegral required) (fromIntegral total)
+            zunfec' = (LB.take segSize <$>) . zunfecLazy (fromIntegral (required reader)) (fromIntegral (total reader))
 
             -- Get ready to decode the groups of blocks back to the original
             -- segments, where this is possible.  We might have even more than
             -- we need at this point so be sure to discard any extras so
             -- zunfec doesn't grow angry.
             getSegments :: [Maybe (IO LB.ByteString)]
-            getSegments = fmap (zunfec' . take (fromIntegral required) <$>) enoughBlocks
+            getSegments = fmap (zunfec' . take (fromIntegral (required reader)) <$>) enoughBlocks
 
         -- Actually do it
         maybeSegments <- traverse sequence getSegments :: IO [Maybe LB.ByteString]
@@ -506,10 +508,10 @@ decode Cap.Reader{verifier = verifier@Cap.Verifier{required, total, size}} share
                 -- careful to find the tail segment size for use with the tail segment
                 -- so there might still be some extra bytes in the `segments` list
                 -- here.  This additional truncation addresses that.
-                pure . Right . LB.take (fromIntegral size) . LB.concat $ segments
+                pure . Right . LB.take (fromIntegral (size reader)) . LB.concat $ segments
   where
     -- Separate the shares into those we can use and those we cannot.
-    (validShares, invalidShares) = partitionShares verifier shares
+    (validShares, invalidShares) = partitionShares (view Cap.verifier reader) shares
 
     -- Project the share number out across all of that share's blocks.  The
     -- result is something we can transpose into the correct form for ZFEC
@@ -517,6 +519,10 @@ decode Cap.Reader{verifier = verifier@Cap.Verifier{required, total, size}} share
     fixBlocks :: (Int, [a]) -> [(Int, a)]
     fixBlocks (sharenum, bs) = zip (repeat sharenum) bs
 
+    size = view (Cap.verifier . Cap.size)
+    required = view (Cap.verifier . Cap.required)
+    total = view (Cap.verifier . Cap.total)
+
 -- | Give a reason a share is considered invalid.
 data InvalidShare
     = -- | The fingerprint in the capability does not match the fingerprint of the share.
diff --git a/src/Tahoe/CHK/Capability.hs b/src/Tahoe/CHK/Capability.hs
index 625e931d7cafbeb0afe2705cfbf97259bbf6f943..b2fa06893d0c6186adaa42d5e54673c856db159d 100644
--- a/src/Tahoe/CHK/Capability.hs
+++ b/src/Tahoe/CHK/Capability.hs
@@ -1,11 +1,19 @@
 {-# LANGUAGE DeriveAnyClass #-}
 {-# LANGUAGE DeriveGeneric #-}
 {-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE TemplateHaskell #-}
 
 module Tahoe.CHK.Capability (
     CHK (..),
-    Reader (..),
-    Verifier (..),
+    Reader,
+    readKey,
+    verifier,
+    Verifier,
+    storageIndex,
+    fingerprint,
+    required,
+    total,
+    size,
     makeReader,
     pCapability,
     pVerifier,
@@ -13,6 +21,8 @@ module Tahoe.CHK.Capability (
     dangerRealShow,
 ) where
 
+import Control.Lens (view)
+import Control.Lens.TH (makeLenses)
 import Crypto.Cipher.AES128 (
     AESKey128,
  )
@@ -61,27 +71,29 @@ data Verifier = Verifier
       -- content-addressable storage system that is a storage server.  It can be
       -- used to ask storage servers for "shares" (ciphertext plus some
       -- metadata) to download.
-      storageIndex :: B.ByteString
+      _storageIndex :: B.ByteString
     , -- | The fingerprint (aka "UEB hash" aka "URI extension block hash") is a
       -- cryptographic hash that covers the URI extension block at the end of a
       -- CHK share.  The URI extension block itself contains various other
       -- cryptographic hashes.  Altogether this allows for integrity checking so
       -- shares downloaded from storage servers can be checked for validity (ie,
       -- that they are the same as what was uploaded) before they are processed.
-      fingerprint :: B.ByteString
+      _fingerprint :: B.ByteString
     , -- | The number of shares required to ZFEC decode the contents of the
       -- shares.  ZFEC calls this *K*.  It must be that 1 <= required <= 256 and
       -- required <= total.  ZFEC is not defined outside of these bounds.
-      required :: Word16
+      _required :: Word16
     , -- | The total number of shares produced by ZFEC encoding.  ZFEC calls
       -- this *n*.  It must be that 1 <= total <= 256 and required <= total.
-      total :: Word16
+      _total :: Word16
     , -- | The size (in bytes) of the plaintext encoded in the shares.  It must
       -- be that size >= 0 and in practice it is usually true that size >= 56.
-      size :: Integer
+      _size :: Integer
     }
     deriving (Ord, Eq, Generic, ToExpr)
 
+$(makeLenses ''Verifier)
+
 {- | Replace most of the tail of a string with a short placeholder.  If the
  string is not much longer than `n` then the result might not actually be
  shorter.
@@ -102,17 +114,17 @@ bounded :: (Ord n, Integral n) => n -> n -> Parser n
 bounded = Tahoe.CHK.Parsing.bounded decimal
 
 instance Show Verifier where
-    show Verifier{storageIndex, fingerprint, required, total, size} =
+    show v =
         T.unpack $
             T.intercalate
                 ":"
                 [ "URI"
                 , "CHK-Verifier"
-                , shorten 4 . showBase32 $ storageIndex
-                , shorten 4 . showBase32 $ fingerprint
-                , showT required
-                , showT total
-                , showT size
+                , shorten 4 . showBase32 $ view storageIndex v
+                , shorten 4 . showBase32 $ view fingerprint v
+                , showT $ view required v
+                , showT $ view total v
+                , showT $ view size v
                 ]
 
 {- | Represent a CHK "read" capability.  This capability type can be diminished
@@ -126,11 +138,13 @@ data Reader = Reader
       -- key to turn the original plaintext into ciphertext and back again.  The
       -- read key is also used to derive the verify key for the verify
       -- capability.  See ``storageIndexHash``.
-      readKey :: AESKey128
+      _readKey :: AESKey128
     , -- | The verify capability for this read capability.
-      verifier :: Verifier
+      _verifier :: Verifier
     }
 
+$(makeLenses ''Reader)
+
 -- AESKey128 has no Eq or Ord instances so derive these for Reader manually.
 -- We do include the AESKey128 in our comparison by encoding it to bytes
 -- first.
@@ -149,23 +163,23 @@ instance ToExpr Reader where
  secret key.
 -}
 instance Show Reader where
-    show Reader{readKey, verifier} =
+    show reader =
         T.unpack $
             T.intercalate
                 ":"
                 [ "URI"
                 , "CHK"
-                , shorten 4 . showBase32 . encode $ readKey
-                , shorten 4 . showBase32 . fingerprint $ verifier
-                , showT . required $ verifier
-                , showT . total $ verifier
-                , showT . size $ verifier
+                , shorten 4 . showBase32 . encode $ view readKey reader
+                , shorten 4 . showBase32 $ view (verifier . fingerprint) reader
+                , showT $ view (verifier . required) reader
+                , showT $ view (verifier . total) reader
+                , showT $ view (verifier . size) reader
                 ]
 
 -- Construct a key with Eq and Ord instances for the Reader Eq and Ord
 -- instances.
 readerKey :: Reader -> (B.ByteString, Verifier)
-readerKey r = (encode . readKey $ r, verifier r)
+readerKey r = (encode $ view readKey r, view verifier r)
 
 {- | A "Content-Hash-Key" (CHK) capability is small value that can be used to
  perform some operation on a (usually) larger value that may be stored
@@ -185,27 +199,27 @@ data CHK = CHKVerifier Verifier | CHKReader Reader deriving (Ord, Eq)
  implementation of Tahoe-LAFS.
 -}
 dangerRealShow :: CHK -> T.Text
-dangerRealShow (CHKVerifier (Verifier{storageIndex, fingerprint, required, total, size})) =
+dangerRealShow (CHKVerifier v) =
     T.intercalate
         ":"
         [ "URI"
         , "CHK-Verifier"
-        , showBase32 storageIndex
-        , showBase32 fingerprint
-        , showT required
-        , showT total
-        , showT size
+        , showBase32 $ view storageIndex v
+        , showBase32 $ view fingerprint v
+        , showT $ view required v
+        , showT $ view total v
+        , showT $ view size v
         ]
-dangerRealShow (CHKReader (Reader{readKey, verifier})) =
+dangerRealShow (CHKReader r) =
     T.intercalate
         ":"
         [ "URI"
         , "CHK"
-        , showBase32 . encode $ readKey
-        , showBase32 . fingerprint $ verifier
-        , showT . required $ verifier
-        , showT . total $ verifier
-        , showT . size $ verifier
+        , showBase32 . encode $ view readKey r
+        , showBase32 $ view (verifier . fingerprint) r
+        , showT $ view (verifier . required) r
+        , showT $ view (verifier . total) r
+        , showT $ view (verifier . size) r
         ]
 
 {- | A parser combinator for parsing either a verify or read CHK capability
@@ -249,8 +263,8 @@ pReader =
  correct derivation of the corresponding CHK verify capability.
 -}
 makeReader :: AESKey128 -> B.ByteString -> Word16 -> Word16 -> Integer -> Reader
-makeReader readKey fingerprint required total size =
-    Reader readKey (deriveVerifier readKey fingerprint required total size)
+makeReader readKey' fingerprint' required' total' size' =
+    Reader readKey' (deriveVerifier readKey' fingerprint' required' total' size')
 
 {- | Given all of the fields of a CHK read capability, derive and return the
  corresponding CHK verify capability.
diff --git a/src/Tahoe/CHK/Share.hs b/src/Tahoe/CHK/Share.hs
index 10576c1688de98289943403d14d0f31c53329c49..8caef4d1e2ea126d8df0b72b7bb19289b051c82f 100644
--- a/src/Tahoe/CHK/Share.hs
+++ b/src/Tahoe/CHK/Share.hs
@@ -3,6 +3,7 @@
 {-# LANGUAGE NamedFieldPuns #-}
 {-# LANGUAGE RecordWildCards #-}
 {-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TemplateHaskell #-}
 
 -- To read all the plaintext of a CHK share which you have enough shares for:
 
@@ -42,6 +43,7 @@ with an encoder to and decoder from the canonical serialized representation.
 module Tahoe.CHK.Share where
 
 import Control.Exception (Exception, throw)
+import Control.Lens (makeLenses)
 import Crypto.Hash (HashAlgorithm (hashDigestSize), digestFromByteString)
 import Data.Bifunctor (Bifunctor (bimap))
 import Data.Binary (
@@ -84,24 +86,26 @@ import Text.Megaparsec (parse)
 -- | Structured representation of a single CHK share.
 data Share = Share
     { -- | The ZFEC block size.  Legacy value.  Unused.
-      shareBlockSize :: Word64
+      _blockSize :: Word64
     , -- | The share data length.  Legacy value.  Unused.
-      shareDataSize :: Word64
+      _dataSize :: Word64
     , -- | The ZFEC encoded ciphertext blocks.
-      shareBlocks :: [LBS.ByteString]
+      _blocks :: [LBS.ByteString]
     , -- | A merkle tree of plaintext segment hashes.  Unimplemented.
-      sharePlaintextHashTree :: MerkleTree BS.ByteString SHA256d
+      _plaintextHashTree :: MerkleTree BS.ByteString SHA256d
     , -- | A merkle tree of ciphertext segment hashes.
-      shareCrypttextHashTree :: MerkleTree BS.ByteString SHA256d
+      _crypttextHashTree :: MerkleTree BS.ByteString SHA256d
     , -- | A merkle tree of hashes of `shareBlocks`.
-      shareBlockHashTree :: MerkleTree BS.ByteString SHA256d
+      _blockHashTree :: MerkleTree BS.ByteString SHA256d
     , -- | The information needed to complete a merkle proof for this share.
-      shareNeededHashes :: [(ShareNum, Digest' SHA256d)]
+      _neededHashes :: [(ShareNum, Digest' SHA256d)]
     , -- | Additional metadata about this share.
-      shareURIExtension :: URIExtension
+      _uriExtension :: URIExtension
     }
     deriving (Eq, Ord, Show, Generic, ToExpr)
 
+$(makeLenses ''Share)
+
 getWord32 :: Get Word64
 getWord32 = do
     word32 <- get :: Get Word32
@@ -126,16 +130,7 @@ instance Binary Share where
     -- Serialize a share to its canonical byte representation.  This replaces
     -- much of allmydata.immutable.layout.
     put
-        Share
-            { shareBlockSize
-            , shareDataSize
-            , shareBlocks
-            , sharePlaintextHashTree
-            , shareCrypttextHashTree
-            , shareBlockHashTree
-            , shareNeededHashes
-            , shareURIExtension
-            } =
+        Share{..} =
             let -- shareDataSize is supposedly unused.  Avoid making any
                 -- calculations based on its value.  We'll serialize it into
                 -- the output but otherwise we should ignore it.  Instead,
@@ -143,7 +138,7 @@ instance Binary Share where
                 -- rest of our data.
                 --
                 -- CRSEncoder.set_params
-                realSize = sumOn' LBS.length shareBlocks
+                realSize = sumOn' LBS.length _blocks
 
                 -- Pick a share format version based on the size of our data,
                 -- along with helpers to encoding our fields for that format
@@ -155,13 +150,13 @@ instance Binary Share where
                 --
                 -- Tahoe also checks blockSize < 2 ^ 32 but I don't see how it is
                 -- possible for blockSize to be greater than dataSize.
-                (version, encodeWord, putWord) = chooseVersion $ max shareDataSize (int64ToWord64 realSize)
+                (version, encodeWord, putWord) = chooseVersion $ max _dataSize (int64ToWord64 realSize)
 
                 -- This excludes the version but otherwise has all of the integer
                 -- header fields we need to write.
                 header =
-                    [ shareBlockSize
-                    , shareDataSize
+                    [ _blockSize
+                    , _dataSize
                     , (fromIntegral :: Int -> Word64) headerSize
                     ]
                         <> trailerFieldOffsets
@@ -192,26 +187,26 @@ instance Binary Share where
                 -- trailer field which has an offset recorded in the header.
                 -- That code will produce an incorrect header if this
                 -- assumption is violated.
-                ueb = uriExtensionToBytes shareURIExtension
+                ueb = uriExtensionToBytes _uriExtension
                 trailerFields =
-                    [ encode sharePlaintextHashTree
-                    , encode shareCrypttextHashTree
-                    , encode shareBlockHashTree
-                    , LBS.fromStrict $ serializeNeededShares shareNeededHashes
+                    [ encode _plaintextHashTree
+                    , encode _crypttextHashTree
+                    , encode _blockHashTree
+                    , LBS.fromStrict $ serializeNeededShares _neededHashes
                     , LBS.fromStrict $ encodeWord (intToWord64 $ BS.length ueb) <> ueb
                     ]
              in do
                     put (fromIntegral version :: Word32)
                     mapM_ putWord header
-                    mapM_ putLazyByteString shareBlocks
+                    mapM_ putLazyByteString _blocks
                     mapM_ putLazyByteString trailerFields
 
     get = do
         -- Read the version marker to determine the size of certain following
         -- fields.
         (_version, getWord) <- getVersion -- 0, 1
-        shareBlockSize <- getWord -- 4, 1
-        shareDataSize <- getWord -- 8, 1
+        _blockSize <- getWord -- 4, 1
+        _dataSize <- getWord -- 8, 1
 
         -- These offsets are all relative to the beginning of the share.
         dataOffset <- getWord -- 12, 36
@@ -228,19 +223,19 @@ instance Binary Share where
         -- we'll fail to load the share but at least we won't apply an invalid
         -- interpretation to any of the data.
         allShareBlocks <- getLazyByteStringInBoundsFrom "share blocks" dataOffset plaintextHashTreeOffset -- 36, <1 byte>
-        sharePlaintextHashTree <- isolateBetween "plaintext hash tree" plaintextHashTreeOffset crypttextHashTreeOffset get -- 37, <69 - 37 == 32 bytes>
-        shareCrypttextHashTree <- isolateBetween "crypttext hash tree" crypttextHashTreeOffset blockHashesOffset get -- 69, <101 - 69 == 32 bytes>
-        shareBlockHashTree <- isolateBetween "block hash tree" blockHashesOffset shareHashesOffset get -- 101, <133 - 101 == 32 bytes>
-        shareNeededHashes <- fromMaybe (fail "Could not parse `needed hashes`") . unserializeNeededShares . LBS.toStrict <$> getLazyByteStringInBoundsFrom "needed shares" shareHashesOffset uriExtensionLengthOffset -- 133, <167 - 133 == 34 bytes>
+        _plaintextHashTree <- isolateBetween "plaintext hash tree" plaintextHashTreeOffset crypttextHashTreeOffset get -- 37, <69 - 37 == 32 bytes>
+        _crypttextHashTree <- isolateBetween "crypttext hash tree" crypttextHashTreeOffset blockHashesOffset get -- 69, <101 - 69 == 32 bytes>
+        _blockHashTree <- isolateBetween "block hash tree" blockHashesOffset shareHashesOffset get -- 101, <133 - 101 == 32 bytes>
+        _neededHashes <- fromMaybe (fail "Could not parse `needed hashes`") . unserializeNeededShares . LBS.toStrict <$> getLazyByteStringInBoundsFrom "needed shares" shareHashesOffset uriExtensionLengthOffset -- 133, <167 - 133 == 34 bytes>
         uriExtensionLength <- getWord >>= getInt64FromWord64 "URI extension length" -- 167,
         uriExtensionBytes <- getLazyByteString uriExtensionLength
-        shareURIExtension <-
+        _uriExtension <-
             either
                 (fail . show)
                 pure
                 (parse pURIExtension "URI extension" $ LBS.toStrict uriExtensionBytes)
 
-        let shareBlocks = segmentLazyBytes (fromIntegral shareBlockSize) allShareBlocks
+        let _blocks = segmentLazyBytes (fromIntegral _blockSize) allShareBlocks
 
         pure $ Share{..}
 
diff --git a/src/Tahoe/CHK/URIExtension.hs b/src/Tahoe/CHK/URIExtension.hs
index 16cb0f226844ed3fc81a2ec4d3d40cf7baa16234..41b4f9441c92fd8c3ccad21f10ea9896bf7a3187 100644
--- a/src/Tahoe/CHK/URIExtension.hs
+++ b/src/Tahoe/CHK/URIExtension.hs
@@ -2,9 +2,21 @@
 {-# LANGUAGE DeriveGeneric #-}
 {-# LANGUAGE NamedFieldPuns #-}
 {-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE TemplateHaskell #-}
 
 module Tahoe.CHK.URIExtension (
     URIExtension (..),
+    codecName,
+    codecParams,
+    tailCodecParams,
+    size,
+    segmentSize,
+    numSegments,
+    neededShares,
+    totalShares,
+    crypttextHash,
+    crypttextRootHash,
+    shareRootHash,
     uriExtensionToBytes,
     showBytes,
     pURIExtension,
@@ -12,6 +24,8 @@ module Tahoe.CHK.URIExtension (
 
 import Control.Applicative.Combinators (count)
 import Control.Applicative.Permutations (runPermutation, toPermutation)
+import Control.Lens (view)
+import Control.Lens.TH (makeLenses)
 import Control.Monad (join, void, (>=>))
 import Crypto.Hash (HashAlgorithm, digestFromByteString)
 import Data.TreeDiff.Class (ToExpr)
@@ -58,37 +72,39 @@ import Tahoe.Netstring (
 -- | Represent additional metadata that appears at the end of each share.
 data URIExtension = URIExtension
     { -- | The name of the encoding function.  Only "zfec" is implemented.
-      uriExtCodecName :: B.ByteString
+      _codecName :: B.ByteString
     , -- | The parameters for the encoding function for all except the final
       -- segment.
-      uriExtCodecParams :: Parameters
+      _codecParams :: Parameters
     , -- | The parameters for the encoding function for the final segment.
-      uriExtTailCodecParams :: Parameters
+      _tailCodecParams :: Parameters
     , -- | The application data size in bytes.
-      uriExtSize :: Size
+      _size :: Size
     , -- | The individual segment size in bytes.
-      uriExtSegmentSize :: Size
+      _segmentSize :: Size
     , -- | The number of segments of application data.  Note the last segment
       -- may be short so it is not necessarily the case that uriExtSize ==
       -- uriExtSegmentSize * uriExtNumSegments.
-      uriExtNumSegments :: SegmentNum
+      _numSegments :: SegmentNum
     , -- | The required (K) parameter to the encoding function.  This is a
       -- duplicate of the values in uriExtCodecParams and uriExtTailCodecParams.
-      uriExtNeededShares :: Required
+      _neededShares :: Required
     , -- | The total (N) parameter to the encoding function.  This too is a
       -- duplicate.
-      uriExtTotalShares :: Total
+      _totalShares :: Total
     , -- | A tagged sha256d hash of the complete ciphertext.
-      uriExtCrypttextHash :: CrypttextHash SHA256d
+      _crypttextHash :: CrypttextHash SHA256d
     , -- | The root hash of a merkle tree where the leaf hashes are of segments of ciphertext.
-      uriExtCrypttextRootHash :: CrypttextHash SHA256d
+      _crypttextRootHash :: CrypttextHash SHA256d
     , -- | The root hash of a merkle tree where leaf hashes are the root hashes of all of the block hash trees.
-      uriExtShareRootHash :: CrypttextHash SHA256d
+      _shareRootHash :: CrypttextHash SHA256d
     }
     deriving (Eq, Ord, Generic, ToExpr)
 
+$(makeLenses ''URIExtension)
+
 instance Show URIExtension where
-    show (URIExtension name params tailParams size segSize numSegs needed total hash1 hash2 hash3) =
+    show (URIExtension name params tailParams sz segSize numSegs needed total hash1 hash2 hash3) =
         T.unpack . T.concat $
             [ "URIExtension { "
             , "codec = "
@@ -98,7 +114,7 @@ instance Show URIExtension where
             , "; tail-codec-params = "
             , showText tailParams
             , "; size = "
-            , showText size
+            , showText sz
             , "; segment-size = "
             , showText segSize
             , "; num-segments = "
@@ -125,17 +141,17 @@ uriExtensionToBytes :: URIExtension -> B.ByteString
 uriExtensionToBytes =
     toWeirdString
         -- all of the below values are authenticated by the capability you get when you store data in Tahoe
-        [ ("codec_name", uriExtCodecName)
-        , ("codec_params", paramsToBytes . uriExtCodecParams)
-        , ("tail_codec_params", paramsToBytes . uriExtTailCodecParams)
-        , ("size", showBytes . uriExtSize)
-        , ("segment_size", showBytes . uriExtSegmentSize)
-        , ("num_segments", showBytes . uriExtNumSegments)
-        , ("needed_shares", showBytes . uriExtNeededShares)
-        , ("total_shares", showBytes . uriExtTotalShares)
-        , ("crypttext_hash", toBytes . uriExtCrypttextHash) -- hash of the *entire* cipher text
-        , ("crypttext_root_hash", toBytes . uriExtCrypttextRootHash) -- root hash of the *cipher text* merkle tree
-        , ("share_root_hash", toBytes . uriExtShareRootHash) -- root hash of the *share* merkle tree
+        [ ("codec_name", view codecName)
+        , ("codec_params", paramsToBytes . view codecParams)
+        , ("tail_codec_params", paramsToBytes . view tailCodecParams)
+        , ("size", showBytes . view size)
+        , ("segment_size", showBytes . view segmentSize)
+        , ("num_segments", showBytes . view numSegments)
+        , ("needed_shares", showBytes . view neededShares)
+        , ("total_shares", showBytes . view totalShares)
+        , ("crypttext_hash", toBytes . view crypttextHash) -- hash of the *entire* cipher text
+        , ("crypttext_root_hash", toBytes . view crypttextRootHash) -- root hash of the *cipher text* merkle tree
+        , ("share_root_hash", toBytes . view shareRootHash) -- root hash of the *share* merkle tree
         ]
 
 type Parser = Parsec Void B.ByteString
diff --git a/src/Tahoe/CHK/Validate.hs b/src/Tahoe/CHK/Validate.hs
index d8ba0beab517274923f0ee732f652ddcaf40bc1c..a7e3dec2aec442e6b59c2750f42fb9724bb3a452 100644
--- a/src/Tahoe/CHK/Validate.hs
+++ b/src/Tahoe/CHK/Validate.hs
@@ -1,53 +1,51 @@
-{-# LANGUAGE NamedFieldPuns #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 
 module Tahoe.CHK.Validate where
 
+import Control.Lens (view)
 import Crypto.Hash (HashAlgorithm)
 import Data.Bifunctor (Bifunctor (first))
 import qualified Data.ByteString.Lazy as LB
-import Tahoe.CHK.Capability (Verifier (fingerprint))
+import Tahoe.CHK.Capability (Verifier, fingerprint)
 import Tahoe.CHK.Crypto (blockHash', uriExtensionHash)
 import Tahoe.CHK.Merkle (checkMerkleProof, heightForLeafCount, leafHashes, rootHash)
 import Tahoe.CHK.SHA256d (Digest', SHA256d)
-import Tahoe.CHK.Share (Share (..))
-import Tahoe.CHK.URIExtension (URIExtension (URIExtension, uriExtShareRootHash, uriExtTotalShares))
+import Tahoe.CHK.Share (Share (..), blockHashTree, blocks, neededHashes, uriExtension)
+import Tahoe.CHK.URIExtension (shareRootHash, totalShares)
 
 {- | Determine the validity of the given share's fingerprint as defined by the
  given capability.
 -}
 validFingerprint :: Verifier -> Share -> Bool
-validFingerprint cap = (== fingerprint cap) . uriExtensionHash . shareURIExtension
+validFingerprint cap = (== view fingerprint cap) . uriExtensionHash . _uriExtension
 
 {- | True if the share's own hash in the `shareNeededHashes` list equals the
  root of the share's block hash merkle tree, False otherwise.
 -}
 matchingBlockHashRoot :: Int -> Share -> Bool
-matchingBlockHashRoot
-    shareNum
-    Share{shareNeededHashes, shareBlockHashTree, shareURIExtension = URIExtension{uriExtTotalShares}} =
-        -- We should find exactly one element with a share number matching our
-        -- share number and the associated hash should match our hash.  If we find
-        -- none or more than one then the share is mis-encoded and we should fail
-        -- validation (though maybe we should do so with a distinct error value).
-        isMatching
-      where
-        isMatching =
-            checkMatch
-                . findOwnHash
-                $ shareNeededHashes
+matchingBlockHashRoot shareNum share =
+    -- We should find exactly one element with a share number matching our
+    -- share number and the associated hash should match our hash.  If we find
+    -- none or more than one then the share is mis-encoded and we should fail
+    -- validation (though maybe we should do so with a distinct error value).
+    isMatching
+  where
+    isMatching =
+        checkMatch
+            . findOwnHash
+            $ view neededHashes share
 
-        checkMatch = ([rootHash shareBlockHashTree] ==) . map snd
+    checkMatch = ([rootHash (view blockHashTree share)] ==) . map snd
 
-        -- Note that shareNeededHashes contains "node numbers" while our
-        -- shareNum is a "leaf number".  So, convert.
-        findOwnHash = filter ((== nodeNumber) . fst)
+    -- Note that shareNeededHashes contains "node numbers" while our
+    -- shareNum is a "leaf number".  So, convert.
+    findOwnHash = filter ((== nodeNumber) . fst)
 
-        nodeNumber :: Int
-        nodeNumber = toNodeNumber shareNum
+    nodeNumber :: Int
+    nodeNumber = toNodeNumber shareNum
 
-        toNodeNumber num = num + (2 ^ treeHeight) - 1
-        treeHeight = heightForLeafCount uriExtTotalShares
+    toNodeNumber num = num + (2 ^ treeHeight) - 1
+    treeHeight = heightForLeafCount . view (uriExtension . totalShares) $ share
 
 {- | Determine the validity of each of the given shares' "share root hash"
  values with respect to the other shares in the list.
@@ -63,19 +61,19 @@ validShareRootHash shares@((_, aShare) : _) =
     -- hash from the UEB has also been validated and we can use it.  The UEB
     -- is the same for all shares so we can pull this value from an arbitrary
     -- share.
-    expected = uriExtShareRootHash . shareURIExtension $ aShare
+    expected = view (uriExtension . shareRootHash) aShare
 
     -- Extract the proof for each share in the given list.
     proofs = uncurry oneProof <$> shares
 
     -- Also extract each share's leaf hash to supply to the proof checker.
-    leafs = rootHash . shareBlockHashTree . snd <$> shares
+    leafs = rootHash . view blockHashTree . snd <$> shares
 
     oneProof :: Int -> Share -> [(Int, Digest' SHA256d)]
-    oneProof shareNum Share{shareNeededHashes} = fmap (first (+ 1)) proof
+    oneProof shareNum share = fmap (first (+ 1)) proof
       where
         -- The length of the proof equals the height of the tree.
-        treeHeight = length shareNeededHashes
+        treeHeight = length (view neededHashes share)
 
         -- Since inclusion of our block tree root hash is what the proof is
         -- proving we don't want it.  We need to take it out to use our proof
@@ -90,7 +88,7 @@ validShareRootHash shares@((_, aShare) : _) =
 
         -- The proof is all of the needed hashes except for this share's own
         -- hash which we will feed into the proof checker separately.
-        proof = filter ((/= nodeNum) . fst) (first fromIntegral <$> shareNeededHashes)
+        proof = filter ((/= nodeNum) . fst) (first fromIntegral <$> view neededHashes share)
 
 showHashes :: (Show a, Show b) => [(a, b)] -> String
 showHashes = unwords . fmap showHash
@@ -102,8 +100,8 @@ showHash (n, bs) = unwords [show n, show bs]
  the values in the Share's "block hash tree".
 -}
 shareValidBlocks :: Share -> [Maybe LB.ByteString]
-shareValidBlocks Share{shareBlocks, shareBlockHashTree} =
-    zipWith checkHash shareBlocks (leafHashes shareBlockHashTree)
+shareValidBlocks share =
+    zipWith checkHash (view blocks share) (leafHashes (view blockHashTree share))
   where
     checkHash :: forall hash. HashAlgorithm hash => LB.ByteString -> Digest' hash -> Maybe LB.ByteString
     checkHash bs expected
diff --git a/tahoe-chk.cabal b/tahoe-chk.cabal
index 44a0c47324a3aec5d30eb9a3c013411e2ad62081..570d1785376ae3693009c7a2b005564239f3ddad 100644
--- a/tahoe-chk.cabal
+++ b/tahoe-chk.cabal
@@ -68,6 +68,7 @@ library
     , extra               >=1.7.7    && <1.8
     , fec                 >=0.1.1    && <0.2
     , filepath            >=1.4.2    && <1.5
+    , lens                >=5.0      && <5.3
     , megaparsec          >=8.0      && <9.3
     , memory              >=0.15     && <0.17
     , monad-loops         >=0.4.3    && <0.5
@@ -135,6 +136,7 @@ test-suite tahoe-chk-tests
     , fec                >=0.1.1    && <0.2
     , filepath           >=1.4.2    && <1.5
     , hedgehog           >=1.0.3    && <1.1
+    , lens               >=5.0      && <5.3
     , megaparsec         >=8.0      && <9.3
     , memory             >=0.15     && <0.17
     , scientific         >=0.3.6.2  && <0.4
diff --git a/test/Generators.hs b/test/Generators.hs
index 87c0e07d2f6852def2f791eda6be08b445f5b7b9..78bdc83e4704a2a17bb1a851938026aed2a06a61 100644
--- a/test/Generators.hs
+++ b/test/Generators.hs
@@ -4,6 +4,8 @@
 
 module Generators where
 
+import Control.Lens (over, view)
+import Control.Lens.Tuple (_2)
 import Control.Monad (zipWithM)
 import Crypto.Hash (
     HashAlgorithm,
@@ -13,7 +15,7 @@ import Crypto.Hash (
 import Crypto.Hash.Algorithms (
     SHA256 (SHA256),
  )
-import Data.Bifunctor (Bifunctor (first, second))
+import Data.Bifunctor (Bifunctor (first))
 import Data.ByteArray (xor)
 import qualified Data.ByteString as BS
 import Data.ByteString.Base32 (encodeBase32Unpadded)
@@ -24,12 +26,12 @@ import qualified Data.Text as T
 import Hedgehog (MonadGen)
 import qualified Hedgehog.Gen as Gen
 import qualified Hedgehog.Range as Range
-import Tahoe.CHK.Capability (Reader (..), Verifier (..))
+import Tahoe.CHK.Capability (Reader, fingerprint, verifier)
 import Tahoe.CHK.Crypto (storageIndexLength)
 import Tahoe.CHK.Merkle (MerkleTree, makeTreePartial)
 import Tahoe.CHK.SHA256d (Digest' (..), SHA256d, toBytes)
 import Tahoe.CHK.Server (StorageServerAnnouncement (StorageServerAnnouncement))
-import Tahoe.CHK.Share (Share (..))
+import Tahoe.CHK.Share (Share (..), blocks, neededHashes)
 import Tahoe.CHK.Types (Parameters (..), Required, ShareNum, StorageIndex, Total)
 import Tahoe.CHK.URIExtension (URIExtension (URIExtension))
 
@@ -88,7 +90,7 @@ shares = do
     -- memory (and even if they didn't, they would be constrained by disk
     -- space and speed) and maxBound :: Int64 is a lot of bytes...
     let maxSize = 65536
-    shareBlockSize <- Gen.integral (Range.exponential 1 maxSize)
+    _blockSize <- Gen.integral (Range.exponential 1 maxSize)
     numBlocks <- Gen.integral (Range.exponential 1 32)
 
     -- We don't make shareDataSize agree with the rest of the share data
@@ -97,21 +99,21 @@ shares = do
     --
     -- We can go all the way up to an unreasonable maximum here because this
     -- doesn't influence how many bytes are actually in the share.
-    shareDataSize <- fromIntegral <$> Gen.integral (Range.linear 1 maxInt64)
+    _dataSize <- fromIntegral <$> Gen.integral (Range.linear 1 maxInt64)
 
-    shareBlocks <- Gen.list (Range.singleton numBlocks) (LBS.fromStrict <$> Gen.bytes (Range.singleton $ fromIntegral shareBlockSize))
+    _blocks <- Gen.list (Range.singleton numBlocks) (LBS.fromStrict <$> Gen.bytes (Range.singleton $ fromIntegral _blockSize))
 
     -- XXX These merkle trees and the "needed hashes" list all have a size
     -- that really needs to be dictated by the encoding parameters (k and n).
-    sharePlaintextHashTree <- merkleTrees (Range.exponential 1 256)
-    shareCrypttextHashTree <- merkleTrees (Range.exponential 1 256)
-    shareBlockHashTree <- merkleTrees (Range.exponential 1 256)
-    shareNeededHashes <- Gen.list (Range.exponential 1 100) ((,) <$> Gen.integral (Range.exponential 1 255) <*> digests)
+    _plaintextHashTree <- merkleTrees (Range.exponential 1 256)
+    _crypttextHashTree <- merkleTrees (Range.exponential 1 256)
+    _blockHashTree <- merkleTrees (Range.exponential 1 256)
+    _neededHashes <- Gen.list (Range.exponential 1 100) ((,) <$> Gen.integral (Range.exponential 1 255) <*> digests)
 
     -- XXX A valid share will have a URI extension that agrees with some of
     -- the other fields we've just generated, which we're not even trying to
     -- do here.
-    shareURIExtension <- genURIExtension
+    _uriExtension <- genURIExtension
 
     pure $ Share{..}
 
@@ -172,28 +174,32 @@ data ShareBitFlips
  capability.
 -}
 fingerprintBitFlipper :: MonadGen m => Reader -> m ShareBitFlips
-fingerprintBitFlipper (Reader{verifier = Verifier{fingerprint}}) = do
-    FingerprintBitFlips <$> (Gen.bytes . Range.singleton . BS.length) fingerprint
+fingerprintBitFlipper reader = do
+    FingerprintBitFlips <$> (Gen.bytes . Range.singleton . BS.length) (view (verifier . fingerprint) reader)
 
 -- | Choose a function to run on a value based on a boolean.
 conditionally :: (a -> b) -> (a -> b) -> Bool -> a -> b
 conditionally f g p x = if p then f x else g x
 
 -- | Generate instructions for flipping some bits in some blocks.
-blockBitFlipper :: MonadGen m => Parameters -> [Share] -> m ShareBitFlips
+blockBitFlipper :: forall m. MonadGen m => Parameters -> [Share] -> m ShareBitFlips
 blockBitFlipper Parameters{paramRequiredShares, paramTotalShares} shares' = do
     -- Pick the shares the blocks of which will be modified.
     whichShares <- enoughModifiedShares paramRequiredShares paramTotalShares
 
     -- Make up some masks to do the block modification.
-    masks <- zipWithM (conditionally maskForShare zerosForShare) whichShares shares'
+    masks <- zipWithM (conditionally maskForShare (pure . zerosForShare)) whichShares shares'
     pure $ BlockBitFlips masks
   where
-    zerosForShare Share{shareBlocks = []} = pure []
-    zerosForShare Share{shareBlocks = blocks@(block : _)} = pure $ replicate (length blocks) (BS.replicate (fromIntegral @Int64 @Int $ LBS.length block) 0)
+    -- Replace all the Word8s in the share blocks with 0s.
+    zerosForShare :: Share -> [BS.ByteString]
+    zerosForShare = (LBS.toStrict <$>) . (LBS.map (const 0) <$>) . view blocks
 
-    maskForShare Share{shareBlocks = []} = pure []
-    maskForShare Share{shareBlocks = blocks@(block : _)} = Gen.list (Range.singleton (length blocks)) (nonZeroBytes (Range.singleton (fromIntegral @Int64 @Int $ LBS.length block)))
+    maskForShare :: Share -> m [BS.ByteString]
+    maskForShare = go . view blocks
+      where
+        go :: [LBS.ByteString] -> m [BS.ByteString]
+        go = mapM (nonZeroBytes . Range.singleton . fromIntegral @Int64 @Int . LBS.length)
 
 {- | Generate flags indicating which shares should be modified in order to
  make the whole set unusable.
@@ -214,20 +220,18 @@ enoughModifiedShares required total = do
 
 -- | Execute the ShareTreeLeafBitFlips instruction on a list of shares.
 applyShareBitFlips :: ShareBitFlips -> ([Share], Reader) -> ([Share], Reader)
-applyShareBitFlips (FingerprintBitFlips flips) = second flipFingerprint
-  where
-    flipFingerprint cap@(Reader{verifier = v@(Verifier{fingerprint})}) = cap{verifier = v{fingerprint = xor flips fingerprint}}
+applyShareBitFlips (FingerprintBitFlips flips) = over (_2 . verifier . fingerprint) (xor flips)
 applyShareBitFlips (ShareTreeLeafBitFlips shareFlips) = first (zipWith flipLeaves shareFlips)
   where
     flipLeaves :: [BS.ByteString] -> Share -> Share
-    flipLeaves leafFlips share = share{shareNeededHashes = zipWith flipBits (shareNeededHashes share) leafFlips}
+    flipLeaves leafFlips share = share{_neededHashes = zipWith flipBits (view neededHashes share) leafFlips}
 
     flipBits :: forall hash a. HashAlgorithm hash => (a, Digest' hash) -> BS.ByteString -> (a, Digest' hash)
     flipBits (a, x) y = (a, Digest' . fromJust . digestFromByteString @hash $ xor @BS.ByteString @BS.ByteString @BS.ByteString (toBytes x) y)
 applyShareBitFlips (BlockBitFlips blockFlips) = first (zipWith flipBlocks blockFlips)
   where
     flipBlocks :: [BS.ByteString] -> Share -> Share
-    flipBlocks masks s@Share{shareBlocks} = s{shareBlocks = LBS.fromStrict <$> zipWith xor (LBS.toStrict <$> shareBlocks) masks}
+    flipBlocks masks s@Share{_blocks} = s{_blocks = LBS.fromStrict <$> zipWith xor (LBS.toStrict <$> _blocks) masks}
 
 {- | Generate lists of shares like the one given but with some bits in the
      hashes needed to validate the merkle path to each share's "share root
@@ -246,17 +250,17 @@ shareTreeLeafBitFlipper Parameters{paramRequiredShares, paramTotalShares} shares
     zeroMask = BS.replicate bytesInMask 0
 
     modifiedShare :: MonadGen m => Bool -> Share -> m [BS.ByteString]
-    modifiedShare False Share{shareNeededHashes} = pure $ replicate (length shareNeededHashes) zeroMask
-    modifiedShare True Share{shareNeededHashes} = do
+    modifiedShare False Share{_neededHashes} = pure $ replicate (length _neededHashes) zeroMask
+    modifiedShare True Share{_neededHashes} = do
         let -- We have to change *something*
             minHashesToModify = 1
             -- We might change everything
-            maxHashesToModify = length shareNeededHashes
+            maxHashesToModify = length _neededHashes
 
         -- Now choose how many we will change.
         numHashesToModify <- Gen.integral $ Range.linear minHashesToModify (maxHashesToModify - 1)
         -- And which ones
-        modifyHash <- Gen.shuffle $ (< numHashesToModify) <$> [0 .. length shareNeededHashes - 1]
+        modifyHash <- Gen.shuffle $ (< numHashesToModify) <$> [0 .. length _neededHashes - 1]
 
         mapM modifiedHash modifyHash
 
diff --git a/test/SpecCHK.hs b/test/SpecCHK.hs
index 24ddaac2ec6d902e1e6e2dc95c742484376133ce..8fa8fe50416bf05dadf26933cd9b98b98e85a3fe 100644
--- a/test/SpecCHK.hs
+++ b/test/SpecCHK.hs
@@ -9,6 +9,7 @@ module SpecCHK (
 import Control.Arrow (
     (&&&),
  )
+import Control.Lens (view)
 import Control.Monad.IO.Class (MonadIO (liftIO))
 import Crypto.Cipher.AES128 (
     AESKey128,
@@ -50,19 +51,19 @@ import qualified Hedgehog.Gen as Gen
 import qualified Hedgehog.Range as Range
 import Tahoe.CHK (padCiphertext)
 import qualified Tahoe.CHK (decode, encode, segmentCiphertext)
-import Tahoe.CHK.Capability (Reader (verifier), dangerRealShow, pCapability, pReader)
+import Tahoe.CHK.Capability (Reader, dangerRealShow, pCapability, pReader, verifier)
 import Tahoe.CHK.Crypto (convergenceSecretLength)
 import Tahoe.CHK.Encrypt (encrypt)
 import Tahoe.CHK.Share (
     Share (
-        shareBlockSize,
-        shareURIExtension
+        _blockSize
     ),
+    uriExtension,
  )
 import Tahoe.CHK.Types (
     Parameters (..),
  )
-import Tahoe.CHK.URIExtension (uriExtCodecParams)
+import Tahoe.CHK.URIExtension (codecParams)
 import Tahoe.CHK.Upload (
     UploadResult (..),
     Uploadable (..),
@@ -189,10 +190,10 @@ testSizes =
     testCase "the maximum segment size encoded in the UEB equals the actual segment size" $ do
         uploadable <- memoryUploadableWithConvergence (B.replicate 32 0x00) (fromIntegral $ BL.length ciphertext) ciphertext params
         (shares', _cap) <- Tahoe.CHK.encode (uploadableKey uploadable) params ciphertext
-        mapM_ (assertEqual "The shareBlockSize reflects the parameters and real ciphertext size" (fromIntegral $ BL.length ciphertext `div` 2) . shareBlockSize) shares'
+        mapM_ (assertEqual "The shareBlockSize reflects the parameters and real ciphertext size" (fromIntegral $ BL.length ciphertext `div` 2) . _blockSize) shares'
         mapM_ (assertEqual "The segment size is reduced to the ciphertext size" (fromIntegral $ BL.length ciphertext) . getSegmentSize) shares'
   where
-    getSegmentSize = paramSegmentSize . uriExtCodecParams . shareURIExtension
+    getSegmentSize = paramSegmentSize . view (uriExtension . codecParams)
     params =
         Parameters
             { paramSegmentSize = 100000
@@ -246,7 +247,7 @@ wellKnownCase WellKnown{..} =
         assertEqual' expectedShares shares'
         assertEqual' wellKnownShares encodedShares
         assertEqual "The cap matches" cap wellKnownCapability
-        assertEqual "The fingerprint matches" allValid ((validFingerprint . verifier $ wellKnownCapability) <$> expectedShares)
+        assertEqual "The fingerprint matches" allValid ((validFingerprint . view verifier $ wellKnownCapability) <$> expectedShares)
         assertEqual "The block tree root hash matches the proof" allValid (zipWith matchingBlockHashRoot [0 ..] expectedShares)
         assertEqual "The share tree root hash is consistent" allValid (validShareRootHash $ zip [0 ..] expectedShares)
         pure ()