diff --git a/src/Data/TrustChain.hs b/src/Data/TrustChain.hs
--- a/src/Data/TrustChain.hs
+++ b/src/Data/TrustChain.hs
@@ -19,6 +19,7 @@
     -- * Claims
   , Claim (..)
   , claims
+  , claimants
     -- * Index and Merge
   , assignments 
     -- * Inconsistencies
@@ -109,13 +110,13 @@
 -- |
 -- A path through the trust chain.
 data Claim a = Claim [PublicKey] a
-  deriving (Eq, Ord, Typeable, Generic, Binary)
+  deriving (Eq, Ord, Show, Read, Typeable, Generic, Binary)
 
 -- |
 -- An inconsistency with the various accounts in the trust chain
 data Inconsistency e a =
     IncompatibleClaim e (Claim a) [Claim a]
-  deriving (Eq, Ord, Typeable, Generic, Binary)
+  deriving (Eq, Ord, Show, Read, Typeable, Generic, Binary)
 
 -- |
 -- Extract all of the claims from the trust chain.
@@ -123,6 +124,18 @@
 claims = \case
   Trustless a -> [Claim [] a]
   TrustProxy s -> (\(Claim ps a) -> Claim (signedBy s : ps) a) <$> foldMap claims (signed s)
+
+-- |
+-- Index the claimants by what they're claiming, using the given indexing function.
+--
+-- The mental model here should something like @k = PublicKey@ and @a = Person@. What
+-- we're doing is figuring out, for every different 'PublicKey' contained in the @Trustless@
+-- node in our 'TrustChain', all of the different variations and series of signatures which lead up to those variations (along with who assented to those accounts).
+--
+-- There is no 'Merge'ing here, in particular. This is the way to splay out all of the different realities and the sequences of
+-- 'PublicKey' which signed that particular variation (at one time or another).
+claimants :: (Ord k, Ord a) => (a -> k) -> [Claim a] -> Map k (Map a (Set [PublicKey]))
+claimants i cs = Map.fromListWith (Map.unionWith (<>)) [ (k, Map.singleton a (Set.singleton ps)) | Claim ps a <- cs, let k = i a ]
 
 -- | 
 -- Extract all of the assignments from the trust chain, unifying information contained
diff --git a/test/Test.hs b/test/Test.hs
--- a/test/Test.hs
+++ b/test/Test.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE TypeApplications #-}
 {-# LANGUAGE DeriveAnyClass #-}
 {-# LANGUAGE DeriveGeneric #-}
 {-# LANGUAGE OverloadedStrings #-}
@@ -21,6 +22,10 @@
 requires msg = mapM_ (uncurry go) . zip [1..] where
   go x y = if y then pure () else putStrLn (msg <> ": " <> show x) >> exitFailure
 
+eq :: (Eq a, Show a) => String -> [(a, a)] -> IO ()
+eq msg = mapM_ (uncurry go) . zip [1..] where
+  go x (a, b) = if a == b then pure () else putStrLn (msg <> ": " <> show x <> ": " <> show a <> " /= " <> show b) >> exitFailure
+
 main :: IO ()
 main = do
   privateKey0 <- generatePrivateKey KeySize256
@@ -28,21 +33,23 @@
   let trustChain0 :: TrustChain [] String = Trustless "Hello"
   trustChain1 <- mkTrustProxy privateKey0 [mkTrustless "Hi", trustChain0]
   trustChain2 <- mkTrustProxy privateKey1 [mkTrustless "Hey", trustChain1]
-  let roundTrip f g x = x == f (g x)
+  let roundTrip f g x = (x, f (g x))
   requires "validTrustChain"
     [ validTrustChain trustChain0
     , validTrustChain trustChain1
     , validTrustChain trustChain2
     ]
-  requires "claims"
-    [ claims trustChain0 == [Claim [] "Hello"]
-    , claims trustChain1 == [Claim [privateToPublic privateKey0] "Hi", Claim [privateToPublic privateKey0] "Hello"]
-    , claims trustChain2 == [Claim [privateToPublic privateKey1] "Hey", Claim [privateToPublic privateKey1, privateToPublic privateKey0] "Hi", Claim [privateToPublic privateKey1, privateToPublic privateKey0] "Hello"] 
+  eq "claimants"
+    [ (claimants id (claims trustChain0),  Map.fromList [("Hello", Map.fromList [("Hello", Set.singleton [])])]) ]
+  eq "claims"
+    [ (claims trustChain0, [Claim [] "Hello"])
+    , (claims trustChain1, [Claim [privateToPublic privateKey0] "Hi", Claim [privateToPublic privateKey0] "Hello"])
+    , (claims trustChain2, [Claim [privateToPublic privateKey1] "Hey", Claim [privateToPublic privateKey1, privateToPublic privateKey0] "Hi", Claim [privateToPublic privateKey1, privateToPublic privateKey0] "Hello"])
     ]
-  requires "assignments"
-    [ assignments id (required id .? ["bad id"]) (claims trustChain0) == Right (Map.fromList [("Hello", "Hello")])
+  eq "assignments"
+    [ (assignments id (required @[String] id .? ["bad id"]) (claims trustChain0), Right (Map.fromList [("Hello", "Hello")]))
     ]
-  requires "encode/decode" $ map (roundTrip decode encode) [trustChain0, trustChain1, trustChain2]
+  eq "encode/decode" $ map (roundTrip decode encode) [trustChain0, trustChain1, trustChain2]
   person
 
 type Time = Integer
@@ -53,7 +60,7 @@
   , emails :: Set Text
   , posts :: Set (Time, Text)
   }
-  deriving (Eq, Ord, Binary, Generic)
+  deriving (Eq, Ord, Binary, Generic, Show, Read)
 
 mergePerson :: Merge [String] Person Person
 mergePerson =
@@ -74,7 +81,7 @@
   tc1 <- mkTrustProxy privateKey1 [Trustless myfriend]
   tc0' <- mkTrustProxy privateKey0 [tc0, tc1]
   tc1' <- mkTrustProxy privateKey1 [tc0, tc1]
-  requires "person"
-    [ assignments pubKey mergePerson (claims tc1') == assignments pubKey mergePerson (claims tc0')
-    , assignments pubKey mergePerson (claims tc0') == Right (Map.fromList [(privateToPublic privateKey0, myself), (privateToPublic privateKey1, myfriend)])
+  eq "person"
+    [ (assignments pubKey mergePerson (claims tc1'), assignments pubKey mergePerson (claims tc0'))
+    , (assignments pubKey mergePerson (claims tc0'), Right (Map.fromList [(privateToPublic privateKey0, myself), (privateToPublic privateKey1, myfriend)]))
     ]
diff --git a/trust-chain.cabal b/trust-chain.cabal
--- a/trust-chain.cabal
+++ b/trust-chain.cabal
@@ -1,6 +1,6 @@
 cabal-version:      2.4
 name:               trust-chain
-version:            0.1.2.0
+version:            0.1.3.0
 category:           Cryptography, Crypto
 synopsis:           An implementation of a trust chain
 license:            MIT
