diff --git a/Changelog.md b/Changelog.md
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,3 +1,13 @@
+# Version 0.2
+
+- Field indexes of any unset field (message/repeated/oneof) are ignored in serialized payload to make possible rolling upgrades **BREAKING CHANGE**
+
+- Fully qualified names are used in generated Signable class instances source code to prevent possible shadowing issues (bugfix)
+
+- Signable class instances source code is generated in eta-reduced form to prevent possible shadowing issues (bugfix)
+
+- Provided code for special cases where protobuf field is named as Haskell keyword like `data`, `class`, `instance` etc (bugfix)
+
 # Version 0.1
 
 - Initial version.
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,6 +1,7 @@
 # signable-haskell-protoc
 
-Signable instances protoc compiler plugin:
+Deterministic serialisation and signatures with proto-lens support.
+Generate Signable class instances with command:
 
 ```
 protoc \
diff --git a/signable-haskell-protoc.cabal b/signable-haskell-protoc.cabal
--- a/signable-haskell-protoc.cabal
+++ b/signable-haskell-protoc.cabal
@@ -5,8 +5,8 @@
 -- see: https://github.com/sol/hpack
 
 name:           signable-haskell-protoc
-version:        0.1
-synopsis:       Signable instances protoc compiler plugin.
+version:        0.2
+synopsis:       Deterministic serialisation and signatures with proto-lens support
 description:    You can find documentation at <https://hackage.haskell.org/package/signable-haskell-protoc hackage>
 category:       Data, Cryptography
 homepage:       https://github.com/coingaming/signable#readme
@@ -40,6 +40,7 @@
       base >=4.7 && <5
     , bytestring ==0.10.*
     , casing >=0.1 && <0.2
+    , containers >=0.5 && <0.7
     , ghc >=8.2 && <8.11
     , ghc-paths ==0.1.*
     , ghc-source-gen >=0.4 && <0.5
diff --git a/src/Main.hs b/src/Main.hs
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -13,6 +13,7 @@
 import Data.ProtoLens (decodeMessage, defMessage, encodeMessage)
 import Data.ProtoLens.Compiler.ModuleName (protoModuleName)
 import Data.ProtoLens.Labels ()
+import qualified Data.Set as Set
 import Data.String (fromString)
 import qualified Data.Text as T
 import Data.Text (Text, intercalate, pack, unpack)
@@ -31,6 +32,7 @@
   ( DescriptorProto,
     EnumDescriptorProto,
     FieldDescriptorProto,
+    FieldDescriptorProto'Label (FieldDescriptorProto'LABEL_REPEATED),
     FieldDescriptorProto'Type (FieldDescriptorProto'TYPE_MESSAGE),
     FileDescriptorProto,
   )
@@ -77,15 +79,18 @@
         <$> req ^. #protoFile
     imports :: [ImportDecl']
     imports =
-      [ import' "Universum",
-        import' "Data.Signable"
-      ]
-        <> ( protoMods
-               >>= ( \x ->
-                       let n = modName x
-                        in import' . fromString <$> [n, n <> "_Fields"]
+      qualified'
+        <$> ( [ import' "Universum",
+                import' "Data.Signable",
+                import' "GHC.List"
+              ]
+                <> ( protoMods
+                       >>= ( \x ->
+                               let n = modName x
+                                in import' . fromString <$> [n, n <> "_Fields"]
+                           )
                    )
-           )
+            )
     body :: Text
     body =
       pack . showPpr dflags $
@@ -100,7 +105,8 @@
         [ "{- This file was auto-generated by the "
             <> pack prog
             <> " program. -}",
-          "{-# OPTIONS_GHC -fno-warn-orphans #-}"
+          "{-# OPTIONS_GHC -fno-warn-orphans #-}",
+          "{-# LANGUAGE NoImplicitPrelude #-}"
         ]
 
 parseModName :: FileDescriptorProto -> String
@@ -134,72 +140,155 @@
 mkMsgImpl :: String -> String -> DescriptorProto -> HsDecl'
 mkMsgImpl m t d =
   instance'
-    (var "Signable" @@ var (fromString $ m <> "." <> t))
+    (var "Data.Signable.Signable" @@ var (fromString $ m <> "." <> t))
     [ funBind "toBinary" $
         match
-          [bvar "x"]
-          ( var "mconcat"
-              @@ ( list
-                     . (mkMsgChunk m <$>)
-                     . sortBy (\x y -> compare (x ^. #number) (y ^. #number))
-                     $ d ^. #field
-                 )
+          []
+          ( op
+              (var "Universum.mconcat")
+              compose
+              ( op
+                  ( var "Universum.<&>"
+                      @@ ( list
+                             . (mkMsgChunk m <$>)
+                             . sortBy
+                               ( \x y ->
+                                   compare
+                                     (x ^. #number)
+                                     (y ^. #number)
+                               )
+                             $ d ^. #field
+                         )
+                  )
+                  compose
+                  (var "Universum.&")
+              )
           )
     ]
 
 mkMsgChunk :: String -> FieldDescriptorProto -> HsExpr'
-mkMsgChunk m d =
-  if (d ^. #type' == FieldDescriptorProto'TYPE_MESSAGE)
-    || (isJust $ d ^. #maybe'oneofIndex)
-    then mExpr
-    else expr
+mkMsgChunk m d
+  | d ^. #label == FieldDescriptorProto'LABEL_REPEATED =
+    rExpr
+  | (d ^. #type' == FieldDescriptorProto'TYPE_MESSAGE)
+      || (isJust $ d ^. #maybe'oneofIndex) =
+    mExpr
+  | otherwise =
+    expr
   where
-    n0 = camel . unpack $ d ^. #name
+    n0 = unReserve . camel . unpack $ d ^. #name
     tag = case safeFromIntegral $ d ^. #number :: Maybe Int32 of
       Just v ->
-        var "toBinary"
-          @@ int (fromIntegral v :: Integer) @::@ var "Int32"
+        var "Data.Signable.toBinary"
+          @@ int (fromIntegral v :: Integer) @::@ var "Universum.Int32"
       Nothing -> error "TAG_OVERFLOW"
-    expr =
+    rExpr =
       op
-        tag
-        "<>"
-        ( var
-            "toBinary"
-            @@ par
-              (var "view" @@ var (fromString $ m <> "_Fields." <> n0) @@ var "x")
+        ( var "Data.Signable.ifThenElse"
+            @@ (var "GHC.List.null")
+            @@ (var "Universum.const" @@ var "Universum.mempty")
+            @@ ( op
+                   (var "Universum.<>" @@ tag)
+                   compose
+                   (var "Data.Signable.toBinary")
+               )
         )
+        compose
+        (var "Universum.view" @@ var (fromString $ m <> "_Fields." <> n0))
     mExpr =
-      case'
-        (var "view" @@ var (fromString $ m <> "_Fields.maybe'" <> n0) @@ var "x")
-        [ match
-            [conP "Just" [bvar "v"]]
-            (op tag "<>" (var "toBinary" @@ var "v")),
-          match
-            [conP_ "Nothing"]
-            tag
-        ]
+      op
+        ( var "Universum.maybe"
+            @@ (var "Universum.mempty")
+            @@ ( op
+                   (var "Universum.<>" @@ tag)
+                   compose
+                   (var "Data.Signable.toBinary")
+               )
+        )
+        compose
+        (var "Universum.view" @@ var (fromString $ m <> "_Fields.maybe'" <> n0))
+    expr =
+      op
+        (var "Universum.<>" @@ tag)
+        compose
+        ( op
+            (var "Data.Signable.toBinary")
+            compose
+            (var "Universum.view" @@ var (fromString $ m <> "_Fields." <> n0))
+        )
 
 mkEnumImpl :: String -> String -> HsDecl'
 mkEnumImpl m t =
   instance'
-    (var "Signable" @@ var (fromString $ m <> "." <> t))
+    (var "Data.Signable.Signable" @@ var (fromString $ m <> "." <> t))
     [ funBind "toBinary" $
         match
-          [bvar "x"]
-          ( case'
-              ( (var "safeFromIntegral" @@ par (var "fromEnum" @@ var "x"))
-                  @::@ par (var "Maybe" @@ var "Int32")
+          []
+          ( op
+              ( (var "Universum.maybe")
+                  @@ (var "Universum.error" @@ string "ENUM_OVERFLOW")
+                  @@ (var "Data.Signable.toBinary")
               )
-              [ match
-                  [conP "Just" [bvar "v"]]
-                  (var "toBinary" @@ var "v"),
-                match
-                  [conP_ "Nothing"]
-                  (var "error" @@ string "ENUM_OVERFLOW")
-              ]
+              compose
+              ( op
+                  ( (var "Data.Signable.safeFromIntegral")
+                      @::@ ( var "Universum.Int"
+                               --> var "Universum.Maybe"
+                               @@ var "Universum.Int32"
+                           )
+                  )
+                  compose
+                  (var "Universum.fromEnum")
+              )
           )
     ]
+
+compose :: RdrNameStr
+compose = "Universum.."
+
+unReserve :: String -> String
+unReserve x =
+  if x `Set.member` reservedKeywords
+    then x <> "'"
+    else x
+
+-- | A list of reserved keywords that aren't valid as variable names.
+reservedKeywords :: Set.Set String
+reservedKeywords =
+  Set.fromList $
+    -- Haskell2010 keywords:
+    -- https://www.haskell.org/onlinereport/haskell2010/haskellch2.html#x7-180002.4
+    -- We don't include keywords that are allowed to be variable names,
+    -- in particular: "as", "forall", and "hiding".
+    [ "case",
+      "class",
+      "data",
+      "default",
+      "deriving",
+      "do",
+      "else",
+      "foreign",
+      "if",
+      "import",
+      "in",
+      "infix",
+      "infixl",
+      "infixr",
+      "instance",
+      "let",
+      "module",
+      "newtype",
+      "of",
+      "then",
+      "type",
+      "where"
+    ]
+      ++ [ "mdo", -- Nonstandard extensions
+           -- RecursiveDo
+           "rec", -- Arrows, RecursiveDo
+           "pattern", -- PatternSynonyms
+           "proc" -- Arrows
+         ]
 
 safeFromIntegral ::
   forall a b. (Integral a, Integral b, Bounded b) => a -> Maybe b
