diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,13 @@
+Copyright 2016 BlockApps, Inc
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,8 @@
+
+module Main (main) where
+
+import Distribution.Simple
+
+main :: IO ()
+main = defaultMain
+
diff --git a/ethereum-analyzer-deps.cabal b/ethereum-analyzer-deps.cabal
new file mode 100644
--- /dev/null
+++ b/ethereum-analyzer-deps.cabal
@@ -0,0 +1,54 @@
+name: ethereum-analyzer-deps
+version: 0.0.1
+cabal-version: >=1.10
+build-type: Simple
+author: Jamshid
+license-file:  LICENSE
+maintainer:    k_@berkeley.edu
+synopsis: Stripped dependencies of ethereum-analyzer.
+category:            Ethereum, Static Analysis
+license: Apache-2.0
+description:  
+    Stripped dependencies of ethereum-analyzer.
+
+source-repository this
+  type:     git
+  location: https://github.com/zchn/ethereum-analyzer
+  branch:   master
+  tag:      v0.0.1
+
+library
+    default-language: Haskell98
+    build-depends: 
+                   base >= 4 && < 5
+                 , aeson
+                 , ansi-wl-pprint
+                 , base16-bytestring
+                 , binary
+                 , bytestring
+                 , containers
+                 , deepseq
+                 , fast-logger
+                 , global-lock
+                 , monad-logger
+                 , nibblestring
+                 , split
+                 , text
+    exposed-modules: Blockchain.Data.Code
+                   , Blockchain.Data.RLP
+                   , Blockchain.Data.Util
+                   , Blockchain.VM.Code
+                   , Blockchain.VM.Opcodes
+                   , Blockchain.ExtWord
+                   , Blockchain.Format
+                   , Blockchain.Util
+                   , Blockchain.Output
+                   , Blockchain.Colors
+                   , Legacy.Haskoin.V0102.Network.Haskoin.Crypto.BigWord
+                   , Legacy.Haskoin.V0102.Network.Haskoin.Crypto.Curve
+                   , Legacy.Haskoin.V0102.Network.Haskoin.Crypto.NumberTheory
+                   , Legacy.Haskoin.V0102.Network.Haskoin.Util
+    ghc-options: -Wall -O2
+    buildable: True
+    hs-source-dirs: src
+
diff --git a/src/Blockchain/Colors.hs b/src/Blockchain/Colors.hs
new file mode 100644
--- /dev/null
+++ b/src/Blockchain/Colors.hs
@@ -0,0 +1,33 @@
+{-# OPTIONS_GHC  -fno-warn-missing-signatures -fno-warn-type-defaults #-}
+
+module Blockchain.Colors (
+    red, green, yellow, blue,
+    magenta, cyan, white2, white, black,
+    bright, dim, underline, blink, Blockchain.Colors.reverse, hidden,
+    setTitle
+) where
+
+
+bright string = "\ESC[1m" ++ string ++ "\ESC[0m"
+dim string = "\ESC[2m" ++ string ++ "\ESC[0m"
+underline string = "\ESC[4m" ++ string ++ "\ESC[0m"
+blink string = "\ESC[5m" ++ string ++ "\ESC[0m"
+reverse string = "\ESC[7m" ++ string ++ "\ESC[0m"
+hidden string = "\ESC[8m" ++ string ++ "\ESC[0m"
+
+
+black string = "\ESC[30m" ++ string ++ "\ESC[0m"
+red string = "\ESC[31m" ++ string ++ "\ESC[0m"
+green string = "\ESC[32m" ++ string ++ "\ESC[0m"
+yellow string = "\ESC[33m" ++ string ++ "\ESC[0m"
+blue string = "\ESC[34m" ++ string ++ "\ESC[0m"
+magenta string = "\ESC[35m" ++ string ++ "\ESC[0m" --AKA purple
+cyan string = "\ESC[36m" ++ string ++ "\ESC[0m" --AKA aqua
+white string = "\ESC[37m" ++ string ++ "\ESC[0m"
+white2 string = "\ESC[38m" ++ string ++ "\ESC[0m"
+
+
+setTitle::String->IO()
+setTitle value = do
+  putStr $ "\ESC]0;" ++ value ++ "\007"
+          
diff --git a/src/Blockchain/Data/Code.hs b/src/Blockchain/Data/Code.hs
new file mode 100644
--- /dev/null
+++ b/src/Blockchain/Data/Code.hs
@@ -0,0 +1,20 @@
+{-# LANGUAGE DeriveGeneric #-}
+
+module Blockchain.Data.Code where
+
+import qualified Data.ByteString as B
+import GHC.Generics
+
+import Blockchain.Data.RLP
+
+data Code =
+  Code{codeBytes::B.ByteString}
+  | PrecompiledCode Int deriving (Show, Eq, Read, Ord, Generic)
+
+instance RLPSerializable Code where
+    rlpEncode (Code bytes) = rlpEncode bytes
+    rlpEncode (PrecompiledCode _) = error "Error in call to rlpEncode for Code: Precompiled contracts can not be serialized."
+    rlpDecode = Code . rlpDecode
+
+-- instance Format Code where
+--    format Code {codeBytes=c} = B.unpack c
diff --git a/src/Blockchain/Data/RLP.hs b/src/Blockchain/Data/RLP.hs
new file mode 100644
--- /dev/null
+++ b/src/Blockchain/Data/RLP.hs
@@ -0,0 +1,159 @@
+{-# LANGUAGE FlexibleInstances #-}
+
+-- | The RLP module provides a framework within which serializers can be built, described in the Ethereum Yellowpaper (<http://gavwood.com/paper.pdf>).
+--
+-- The 'RLPObject' is an intermediate data container, whose serialization rules are well defined.  By creating code that converts from a
+-- given type to an 'RLPObject', full serialization will be specified.  The 'RLPSerializable' class provides functions to do this conversion.
+
+module Blockchain.Data.RLP (
+  RLPObject(..),
+  formatRLPObject,
+  RLPSerializable(..),
+  rlpSplit,
+  rlpSerialize,
+  rlpDeserialize
+  ) where
+
+import Data.Bits
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Base16 as B16
+import qualified Data.ByteString.Char8 as BC
+import Data.ByteString.Internal
+import Data.Word
+import Text.PrettyPrint.ANSI.Leijen hiding ((<$>))
+import Numeric
+
+import Blockchain.Data.Util
+
+-- | An internal representation of generic data, with no type information.
+--
+-- End users will not need to directly create objects of this type (an 'RLPObject' can be created using 'rlpEncode'),
+-- however the designer of a new type will need to create conversion code by making their type an instance 
+-- of the RLPSerializable class. 
+data RLPObject = RLPScalar Word8 | RLPString B.ByteString | RLPArray [RLPObject] deriving (Show, Eq, Ord)
+
+-- | Converts objects to and from 'RLPObject's.
+class RLPSerializable a where
+  rlpDecode::RLPObject->a
+  rlpEncode::a->RLPObject
+
+
+instance Pretty RLPObject where
+  pretty (RLPArray objects) =
+    encloseSep (text "[") (text "]") (text ", ") $ pretty <$> objects
+  pretty (RLPScalar n) = text $ "0x" ++ showHex n ""
+  pretty (RLPString s) = text $ "0x" ++ BC.unpack (B16.encode s)
+
+formatRLPObject::RLPObject->String
+formatRLPObject = show . pretty
+
+splitAtWithError::Int->B.ByteString->(B.ByteString, B.ByteString)
+splitAtWithError i s | i > B.length s = error "splitAtWithError called with n > length arr"
+splitAtWithError i s = B.splitAt i s
+
+getLength::Int->B.ByteString->(Integer, B.ByteString)
+getLength sizeOfLength bytes =
+  (bytes2Integer $ B.unpack $ B.take sizeOfLength bytes, B.drop sizeOfLength bytes)
+
+rlpSplit::B.ByteString->(RLPObject, B.ByteString)
+rlpSplit input =
+  case B.head input of
+    x | x >= 192 && x <= 192+55 ->
+      let (arrayData, nextRest) =
+            splitAtWithError (fromIntegral x - 192) $ B.tail input
+      in (RLPArray $ getRLPObjects arrayData, nextRest)
+
+    x | x >= 0xF8 && x <= 0xFF ->
+      let 
+        (arrLength, restAfterLen) = getLength (fromIntegral x - 0xF7) $ B.tail input
+        (arrayData, nextRest) = splitAtWithError (fromIntegral arrLength) restAfterLen
+      in (RLPArray $ getRLPObjects arrayData, nextRest)
+
+    x | x >= 128 && x <= 128+55 ->
+      let
+        (strList, nextRest) = splitAtWithError (fromIntegral $ x - 128) $ B.tail input
+      in 
+       (RLPString strList, nextRest)
+
+    x | x >= 0xB8 && x <= 0xBF ->
+      let 
+        (strLength, restAfterLen) = getLength (fromIntegral x - 0xB7) $ B.tail input
+        (strList, nextRest) = splitAtWithError (fromIntegral strLength) restAfterLen
+      in
+       (RLPString strList, nextRest)
+
+    x | x < 128 -> (RLPScalar x, B.tail input)
+            
+    x -> error ("Missing case in rlpSplit: " ++ show x)
+
+    
+getRLPObjects::ByteString->[RLPObject]
+getRLPObjects x | B.null x = []
+getRLPObjects theData = obj:getRLPObjects rest
+  where
+    (obj, rest) = rlpSplit theData
+
+int2Bytes::Int->[Word8]
+int2Bytes val | val < 0x100 = map (fromIntegral . (val `shiftR`)) [0]
+int2Bytes val | val < 0x10000 = map (fromIntegral . (val `shiftR`)) [8, 0]
+int2Bytes val | val < 0x1000000 = map (fromIntegral . (val `shiftR`)) [16,  8, 0]
+int2Bytes val | val < 0x100000000 = map (fromIntegral . (val `shiftR`)) [24, 16..0]
+int2Bytes val | val < 0x10000000000 = map (fromIntegral . (val `shiftR`)) [32, 24..0]
+int2Bytes _ = error "int2Bytes not defined for val >= 0x10000000000."
+
+rlp2Bytes::RLPObject->[Word8]
+rlp2Bytes (RLPScalar val) = [fromIntegral val]
+rlp2Bytes (RLPString s) | B.length s <= 55 = 0x80 + fromIntegral (B.length s):B.unpack s
+rlp2Bytes (RLPString s) =
+  [0xB7 + fromIntegral (length lengthAsBytes)] ++ lengthAsBytes ++ B.unpack s
+  where
+    lengthAsBytes = int2Bytes $ B.length s
+rlp2Bytes (RLPArray innerObjects) =
+  if length innerBytes <= 55
+  then 0xC0 + fromIntegral (length innerBytes):innerBytes
+  else let lenBytes = int2Bytes $ length innerBytes
+       in [0xF7 + fromIntegral (length lenBytes)] ++ lenBytes ++ innerBytes
+  where
+    innerBytes = concat $ rlp2Bytes <$> innerObjects
+
+--TODO- Probably should just use Data.Binary's 'Binary' class for this
+
+-- | Converts bytes to 'RLPObject's.
+--
+-- Full deserialization of an object can be obtained using @rlpDecode . rlpDeserialize@.
+rlpDeserialize::B.ByteString->RLPObject
+rlpDeserialize s = 
+  case rlpSplit s of
+    (o, x) | B.null x -> o
+    _ -> error ("parse error converting ByteString to an RLP Object: " ++ show (B.unpack s))
+
+
+-- | Converts 'RLPObject's to bytes.
+--
+-- Full serialization of an object can be obtained using @rlpSerialize . rlpEncode@.
+rlpSerialize::RLPObject->B.ByteString
+rlpSerialize o = B.pack $ rlp2Bytes o
+
+
+instance RLPSerializable Integer where
+  rlpEncode 0 = RLPString B.empty
+  rlpEncode x | x < 128 = RLPScalar $ fromIntegral x
+  rlpEncode x = RLPString $ B.pack $ integer2Bytes x
+  rlpDecode (RLPScalar x) = fromIntegral x
+  rlpDecode (RLPString s) = byteString2Integer s
+  rlpDecode (RLPArray _) = error "rlpDecode called for Integer for array"
+
+instance RLPSerializable String where
+  rlpEncode s = rlpEncode $ BC.pack s
+
+  rlpDecode (RLPString s) = BC.unpack s
+  rlpDecode (RLPScalar n) = [w2c $ fromIntegral n]
+  rlpDecode (RLPArray x) = error $ "Malformed RLP in call to rlpDecode for String: RLPObject is an array: " ++ show (pretty x)
+
+instance RLPSerializable B.ByteString where
+    rlpEncode x | B.length x == 1 && B.head x < 128 = RLPScalar $ B.head x
+    rlpEncode s = RLPString s
+      
+    rlpDecode (RLPScalar x) = B.singleton x
+    rlpDecode (RLPString s) = s
+    rlpDecode x = error ("rlpDecode for ByteString not defined for: " ++ show x)
diff --git a/src/Blockchain/Data/Util.hs b/src/Blockchain/Data/Util.hs
new file mode 100644
--- /dev/null
+++ b/src/Blockchain/Data/Util.hs
@@ -0,0 +1,24 @@
+
+module Blockchain.Data.Util (
+  byteString2Integer,
+  bytes2Integer,
+  integer2Bytes
+  ) where
+
+import Data.Bits
+import qualified Data.ByteString as B
+import Data.Word
+
+--I hate this, it is an ugly way to create an Integer from its component bytes.
+--There should be an easier way....
+--See http://stackoverflow.com/questions/25854311/efficient-packing-bytes-into-integers
+byteString2Integer::B.ByteString->Integer
+byteString2Integer x = bytes2Integer $ B.unpack x
+
+bytes2Integer::[Word8]->Integer
+bytes2Integer [] = 0
+bytes2Integer (byte:rest) = fromIntegral byte `shift` (8 * length rest) + bytes2Integer rest
+
+integer2Bytes::Integer->[Word8]
+integer2Bytes 0 = []
+integer2Bytes x = integer2Bytes (x `shiftR` 8) ++ [fromInteger (x .&. 255)]
diff --git a/src/Blockchain/ExtWord.hs b/src/Blockchain/ExtWord.hs
new file mode 100644
--- /dev/null
+++ b/src/Blockchain/ExtWord.hs
@@ -0,0 +1,98 @@
+{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+
+module Blockchain.ExtWord (
+  Word128,
+  Word160,
+  Word256,
+  Word512,
+  word64ToBytes,
+  bytesToWord64,
+  word128ToBytes,
+  bytesToWord128,
+  word160ToBytes,
+  bytesToWord160,
+  word256ToBytes,
+  bytesToWord256
+  ) where
+
+import Data.Binary
+import Data.Bits
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Lazy as BL
+import Legacy.Haskoin.V0102.Network.Haskoin.Crypto.BigWord (Word128, Word160, Word256, Word512)
+
+import Data.Ix
+
+import Blockchain.Data.RLP
+
+
+instance Ix Word256 where
+    range (x, y) | x == y = [x]
+    range (x, y) = x:range (x+1, y)
+    index (x, y) z | z < x || z > y = error $ "Ix{Word256}.index: Index (" ++ show z ++ ") out of range ((" ++ show x ++ "," ++ show y ++ "))"
+    index (x, _) z = fromIntegral $ z - x
+    inRange (x, y) z | z >= x && z <= y = True
+    inRange _ _ = False
+
+instance RLPSerializable Word512 where
+    rlpEncode val = RLPString $ BL.toStrict $ encode val
+
+    rlpDecode (RLPString s) | B.length s == 64 = decode $ BL.fromStrict s
+    rlpDecode x = error ("Missing case in rlp2Word512: " ++ show x)
+
+word64ToBytes::Word64->[Word8]
+word64ToBytes word = map (fromIntegral . (word `shiftR`)) [64-8, 64-16..0]
+
+bytesToWord64::[Word8]->Word64
+bytesToWord64 bytes | length bytes == 8 =
+  sum $ map (\(shiftBits, byte) -> fromIntegral byte `shiftL` shiftBits) $ zip [64-8,64-16..0] bytes
+bytesToWord64 _ = error "bytesToWord64 was called with the wrong number of bytes"
+
+word128ToBytes::Word128->[Word8]
+word128ToBytes word = map (fromIntegral . (word `shiftR`)) [128-8, 128-16..0]
+
+bytesToWord128::[Word8]->Word128
+bytesToWord128 bytes | length bytes == 16 =
+  sum $ map (\(shiftBits, byte) -> fromIntegral byte `shiftL` shiftBits) $ zip [128-8,128-16..0] bytes
+bytesToWord128 _ = error "bytesToWord128 was called with the wrong number of bytes"
+
+word160ToBytes::Word160->[Word8]
+word160ToBytes word = map (fromIntegral . (word `shiftR`)) [160-8, 160-16..0]
+
+bytesToWord160::[Word8]->Word160
+bytesToWord160 bytes | length bytes == 20 =
+  sum $ map (\(shiftBits, byte) -> fromIntegral byte `shiftL` shiftBits) $ zip [160-8,160-16..0] bytes
+bytesToWord160 _ = error "bytesToWord128 was called with the wrong number of bytes"
+
+word256ToBytes::Word256->[Word8]
+word256ToBytes word = map (fromIntegral . (word `shiftR`)) [256-8, 256-16..0]
+
+instance RLPSerializable Word128 where
+    rlpEncode val = RLPString $ BL.toStrict $ encode val
+
+    rlpDecode (RLPString s) | B.null s = 0
+    rlpDecode (RLPString s) | B.length s <= 16 = decode $ BL.fromStrict s
+    rlpDecode x = error ("Missing case in rlp2Word128: " ++ show x)
+
+
+instance RLPSerializable Word32 where
+    rlpEncode val = RLPString $ BL.toStrict $ encode val
+
+    rlpDecode (RLPString s) | B.null s = 0
+    rlpDecode (RLPString s) | B.length s <= 4 = decode $ BL.fromStrict s
+    rlpDecode x = error ("Missing case in rlp2Word32: " ++ show x)
+
+instance RLPSerializable Word16 where
+    rlpEncode val = RLPString $ BL.toStrict $ encode val
+
+    rlpDecode (RLPString s) | B.null s = 0
+    rlpDecode (RLPString s) | B.length s <= 2 = decode $ BL.fromStrict s
+    rlpDecode x = error ("Missing case in rlp2Word16: " ++ show x)
+
+
+
+bytesToWord256::[Word8]->Word256
+bytesToWord256 bytes | length bytes == 32 =
+  sum $ map (\(shiftBits, byte) -> fromIntegral byte `shiftL` shiftBits) $ zip [256-8,256-16..0] bytes
+bytesToWord256 _ = error "bytesToWord256 was called with the wrong number of bytes"
diff --git a/src/Blockchain/Format.hs b/src/Blockchain/Format.hs
new file mode 100644
--- /dev/null
+++ b/src/Blockchain/Format.hs
@@ -0,0 +1,21 @@
+{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
+
+module Blockchain.Format (
+  Format(..)
+  ) where
+
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Char8 as BC
+import qualified Data.ByteString.Base16 as B16
+
+import Blockchain.ExtWord
+
+class Format a where
+  format::a->String
+
+instance Format B.ByteString where
+  format x = BC.unpack (B16.encode x)
+
+instance Format Word256 where
+  format x = BC.unpack $ B16.encode $ B.pack $ word256ToBytes x
+
diff --git a/src/Blockchain/Output.hs b/src/Blockchain/Output.hs
new file mode 100644
--- /dev/null
+++ b/src/Blockchain/Output.hs
@@ -0,0 +1,18 @@
+
+module Blockchain.Output where
+
+import Control.Monad.Logger
+import qualified Data.ByteString.Char8 as BC
+import System.GlobalLock
+import System.Log.FastLogger
+
+printLogMsg::Loc->LogSource->LogLevel->LogStr->IO ()
+--printLogMsg loc logSource level msg = do
+printLogMsg _ _ _ msg = do
+  lock $ putStrLn $ BC.unpack $ fromLogStr msg
+
+printToFile::FilePath->Loc->LogSource->LogLevel->LogStr->IO ()
+--printLogMsg loc logSource level msg = do
+printToFile path _ _ _ msg = do
+  lock $ appendFile path $ BC.unpack (fromLogStr msg) ++ "\n"
+
diff --git a/src/Blockchain/Util.hs b/src/Blockchain/Util.hs
new file mode 100644
--- /dev/null
+++ b/src/Blockchain/Util.hs
@@ -0,0 +1,88 @@
+
+module Blockchain.Util where
+
+import Data.Bits
+import qualified Data.ByteString as B
+import qualified Data.NibbleString as N
+import Data.ByteString.Internal
+import Data.Char
+import Data.List
+import Data.Word
+import Numeric
+
+import Blockchain.ExtWord
+
+showHex4::Word256->String
+showHex4 i = replicate (4 - length rawOutput) '0' ++ rawOutput
+    where rawOutput = showHex i ""
+
+showHexU::Integer->[Char]
+showHexU = map toUpper . flip showHex ""
+
+nibbleString2ByteString::N.NibbleString->B.ByteString
+nibbleString2ByteString (N.EvenNibbleString s) = s
+nibbleString2ByteString (N.OddNibbleString c s) = c `B.cons` s
+
+byteString2NibbleString::B.ByteString->N.NibbleString
+byteString2NibbleString = N.EvenNibbleString
+
+--I hate this, it is an ugly way to create an Integer from its component bytes.
+--There should be an easier way....
+--See http://stackoverflow.com/questions/25854311/efficient-packing-bytes-into-integers
+byteString2Integer::B.ByteString->Integer
+byteString2Integer x = bytes2Integer $ B.unpack x
+
+bytes2Integer::[Word8]->Integer
+bytes2Integer [] = 0
+bytes2Integer (byte:rest) = fromIntegral byte `shift` (8 * length rest) + bytes2Integer rest
+
+integer2Bytes::Integer->[Word8]
+integer2Bytes 0 = []
+integer2Bytes x = integer2Bytes (x `shiftR` 8) ++ [fromInteger (x .&. 255)]
+
+--integer2Bytes1 is integer2Bytes, but with the extra condition that the output be of length 1 or more.
+integer2Bytes1::Integer->[Word8]
+integer2Bytes1 0 = [0]
+integer2Bytes1 x = integer2Bytes x
+
+padZeros::Int->String->String
+padZeros n s = replicate (n - length s) '0' ++ s
+
+tab::String->String
+tab [] = []
+tab ('\n':rest) = '\n':' ':' ':' ':' ':tab rest
+tab (c:rest) = c:tab rest
+
+showWord8::Word8->Char
+showWord8 c | c >= 32 && c < 127 = w2c c
+showWord8 _ = '?'
+
+showMem::Int->[Word8]->String
+showMem _ x | length x > 1000 = " mem size greater than 1000 bytes"
+showMem _ [] = "" 
+showMem p (v1:v2:v3:v4:v5:v6:v7:v8:rest) = 
+    padZeros 4 (showHex p "") ++ " " 
+             ++ [showWord8 v1] ++ [showWord8 v2] ++ [showWord8 v3] ++ [showWord8 v4]
+             ++ [showWord8 v5] ++ [showWord8 v6] ++ [showWord8 v7] ++ [showWord8 v8] ++ " "
+             ++ padZeros 2 (showHex v1 "") ++ " " ++ padZeros 2 (showHex v2 "") ++ " " ++ padZeros 2 (showHex v3 "") ++ " " ++ padZeros 2 (showHex v4 "") ++ " "
+             ++ padZeros 2 (showHex v5 "") ++ " " ++ padZeros 2 (showHex v6 "") ++ " " ++ padZeros 2 (showHex v7 "") ++ " " ++ padZeros 2 (showHex v8 "") ++ "\n"
+             ++ showMem (p+8) rest
+showMem p x = padZeros 4 (showHex p "") ++ " " ++ (showWord8 <$> x) ++ " " ++ intercalate " " (padZeros 2 <$> flip showHex "" <$> x)
+
+
+safeTake::Word256->B.ByteString->B.ByteString
+safeTake i _ | i > 0x7fffffffffffffff = error "error in call to safeTake: string too long"
+safeTake i s | i > fromIntegral (B.length s) = s `B.append` B.replicate (fromIntegral i - B.length s) 0
+safeTake i s = B.take (fromIntegral i) s
+
+safeDrop::Word256->B.ByteString->B.ByteString
+safeDrop i s | i > fromIntegral (B.length s) = B.empty
+safeDrop i _ | i > 0x7fffffffffffffff = error "error in call to safeDrop: string too long"
+safeDrop i s = B.drop (fromIntegral i) s
+
+
+isContiguous::(Eq a, Num a)=>[a]->Bool
+isContiguous [] = True
+isContiguous [_] = True
+isContiguous (x:y:rest) | y == x + 1 = isContiguous $ y:rest
+isContiguous _ = False
diff --git a/src/Blockchain/VM/Code.hs b/src/Blockchain/VM/Code.hs
new file mode 100644
--- /dev/null
+++ b/src/Blockchain/VM/Code.hs
@@ -0,0 +1,52 @@
+module Blockchain.VM.Code where
+
+import qualified Data.ByteString as B
+-- import Legacy.Haskoin.V0102.Network.Haskoin.Internals
+import Numeric
+import Text.PrettyPrint.ANSI.Leijen
+
+import Blockchain.ExtWord
+import qualified Blockchain.Colors as CL
+import Blockchain.Data.Code
+import Blockchain.Format
+import Blockchain.Util
+import Blockchain.VM.Opcodes
+
+
+getOperationAt::Code->Word256->(Operation, Word256)
+getOperationAt (Code bytes) p = getOperationAt' bytes p
+getOperationAt (PrecompiledCode _) _ = error "getOperationAt called for precompilded code"
+
+getOperationAt'::B.ByteString->Word256->(Operation, Word256)
+getOperationAt' rom p = opCode2Op $ safeDrop p rom
+
+showCode::Word256->Code->String
+showCode _ (Code bytes) | B.null bytes = ""
+showCode _ (PrecompiledCode x) = CL.blue $ "<PrecompiledCode:" ++ show x ++">"
+showCode lineNumber c@(Code rom) = showHex lineNumber "" ++ " " ++ format (B.pack $ op2OpCode op) ++ " " ++ show (pretty op) ++ "\n" ++  showCode (lineNumber + nextP) (Code (safeDrop nextP rom))
+        where
+          (op, nextP) = getOperationAt c 0
+
+formatCode::Code->String
+formatCode = showCode 0
+
+getValidJUMPDESTs::Code->[Word256]
+getValidJUMPDESTs (Code bytes) =
+  map fst $ filter ((== JUMPDEST) . snd) $ getOps bytes 0
+  where
+    getOps::B.ByteString->Word256->[(Word256, Operation)]
+    getOps bytes' p | p > fromIntegral (B.length bytes') = []
+    getOps code p = (p, op):getOps code (p+len)
+      where
+        (op, len) = getOperationAt' code p
+getValidJUMPDESTs (PrecompiledCode _) = error "getValidJUMPDESTs called on precompiled code"
+
+
+codeLength::Code->Int
+codeLength (Code bytes) = B.length bytes
+codeLength (PrecompiledCode _) = error "codeLength called on precompiled code"
+
+compile::[Operation]->Code
+compile x = Code bytes
+  where
+    bytes = B.pack $ op2OpCode =<< x
diff --git a/src/Blockchain/VM/Opcodes.hs b/src/Blockchain/VM/Opcodes.hs
new file mode 100644
--- /dev/null
+++ b/src/Blockchain/VM/Opcodes.hs
@@ -0,0 +1,195 @@
+module Blockchain.VM.Opcodes where
+
+import Prelude hiding (LT, GT, EQ)
+
+import Data.Binary
+import qualified Data.ByteString as B
+import qualified Data.Map as M
+import Data.Maybe
+import Legacy.Haskoin.V0102.Network.Haskoin.Crypto.BigWord
+import Text.PrettyPrint.ANSI.Leijen hiding ((<$>))
+
+import Blockchain.Util
+
+--import Debug.Trace
+
+data Operation =
+    STOP | ADD | MUL | SUB | DIV | SDIV | MOD | SMOD | ADDMOD | MULMOD | EXP | SIGNEXTEND | NEG | LT | GT | SLT | SGT | EQ | ISZERO | NOT | AND | OR | XOR | BYTE | SHA3 |
+    ADDRESS | BALANCE | ORIGIN | CALLER | CALLVALUE | CALLDATALOAD | CALLDATASIZE | CALLDATACOPY | CODESIZE | CODECOPY | GASPRICE | EXTCODESIZE | EXTCODECOPY |
+    BLOCKHASH | COINBASE | TIMESTAMP | NUMBER | DIFFICULTY | GASLIMIT | POP | MLOAD | MSTORE | MSTORE8 | SLOAD | SSTORE |
+    JUMP | JUMPI | PC | MSIZE | GAS | JUMPDEST |
+    PUSH [Word8] |
+    DUP1 | DUP2 | DUP3 | DUP4 |
+    DUP5 | DUP6 | DUP7 | DUP8 |
+    DUP9 | DUP10 | DUP11 | DUP12 |
+    DUP13 | DUP14 | DUP15 | DUP16 |
+    SWAP1 | SWAP2 | SWAP3 | SWAP4 |
+    SWAP5 | SWAP6 | SWAP7 | SWAP8 |
+    SWAP9 | SWAP10 | SWAP11 | SWAP12 |
+    SWAP13 | SWAP14 | SWAP15 | SWAP16 |
+    LOG0 | LOG1 | LOG2 | LOG3 | LOG4 |
+    CREATE | CALL | CALLCODE | RETURN | DELEGATECALL | INVALID | SUICIDE |
+    --Pseudo Opcodes
+    LABEL String | PUSHLABEL String |
+    PUSHDIFF String String | DATA B.ByteString |
+    MalformedOpcode Word8 deriving (Show, Eq, Ord)
+
+instance Pretty Operation where
+  pretty x@JUMPDEST = text $ "------" ++ show x
+  pretty x@(PUSH vals) = text $ show x ++ " --" ++ show (bytes2Integer vals)
+  pretty x = text $ show x
+
+data OPData = OPData Word8 Operation Int Int String
+
+type EthCode = [Operation]
+
+singleOp::Operation->([Word8]->Operation, Int)
+singleOp o = (const o, 1)
+
+opDatas::[OPData]
+opDatas =
+  [
+    OPData 0x00 STOP 0 0 "Halts execution.",
+    OPData 0x01 ADD 2 1 "Addition operation.",
+    OPData 0x02 MUL 2 1 "Multiplication operation.",
+    OPData 0x03 SUB 2 1 "Subtraction operation.",
+    OPData 0x04 DIV 2 1 "Integer division operation.",
+    OPData 0x05 SDIV 2 1 "Signed integer division operation.",
+    OPData 0x06 MOD 2 1 "Modulo remainder operation.",
+    OPData 0x07 SMOD 2 1 "Signed modulo remainder operation.",
+    OPData 0x08 ADDMOD 2 1 "unsigned modular addition",
+    OPData 0x09 MULMOD 2 1 "unsigned modular multiplication",
+    OPData 0x0a EXP 2 1 "Exponential operation.",
+    OPData 0x0b SIGNEXTEND 2 1 "Extend length of two’s complement signed integer.",
+
+    OPData 0x10 LT 2 1 "Less-than comparision.",
+    OPData 0x11 GT 2 1 "Greater-than comparision.",
+    OPData 0x12 SLT 2 1 "Signed less-than comparision.",
+    OPData 0x13 SGT 2 1 "Signed greater-than comparision.",
+    OPData 0x14 EQ 2 1 "Equality comparision.",
+    OPData 0x15 ISZERO 1 1 "Simple not operator.",
+    OPData 0x16 AND 2 1 "Bitwise AND operation.",
+    OPData 0x17 OR 2 1 "Bitwise OR operation.",
+    OPData 0x18 XOR 2 1 "Bitwise XOR operation.",
+    OPData 0x19 NOT 1 1 "Bitwise not operator.",
+    OPData 0x1a BYTE 2 1 "Retrieve single byte from word.",
+
+    OPData 0x20 SHA3 2 1 "Compute SHA3-256 hash.",
+
+    OPData 0x30 ADDRESS 0 1 "Get address of currently executing account.",
+    OPData 0x31 BALANCE 1 1 "Get balance of the given account.",
+    OPData 0x32 ORIGIN 0 1 "Get execution origination address.",
+    OPData 0x33 CALLER 0 1 "Get caller address.",
+    OPData 0x34 CALLVALUE 0 1 "Get deposited value by the instruction/transaction responsible for this execution.",
+    OPData 0x35 CALLDATALOAD 1 1 "Get input data of current environment.",
+    OPData 0x36 CALLDATASIZE 0 1 "Get size of input data in current environment.",
+    OPData 0x37 CALLDATACOPY 3 0 "Copy input data in current environment to memory.",
+    OPData 0x38 CODESIZE 0 1 "Get size of code running in current environment.",
+    OPData 0x39 CODECOPY 3 0 "Copy code running in current environment to memory.",
+    OPData 0x3a GASPRICE 0 1 "Get price of gas in current environment.",
+    OPData 0x3b EXTCODESIZE 0 1 "Get size of an account's code.",
+    OPData 0x3c EXTCODECOPY 0 4 "Copy an account’s code to memory",
+
+    OPData 0x40 BLOCKHASH 0 1 "Get hash of most recent complete block.",
+    OPData 0x41 COINBASE 0 1 "Get the block’s coinbase address.",
+    OPData 0x42 TIMESTAMP 0 1 "Get the block’s timestamp.",
+    OPData 0x43 NUMBER 0 1 "Get the block’s number.",
+    OPData 0x44 DIFFICULTY 0 1 "Get the block’s difficulty.",
+    OPData 0x45 GASLIMIT 0 1 "Get the block’s gas limit.",
+
+    OPData 0x50 POP 1 0 "Remove item from stack.",
+    OPData 0x51 MLOAD 1 1 "Load word from memory.",
+    OPData 0x52 MSTORE 2 0 "Save word to memory.",
+    OPData 0x53 MSTORE8 2 0 "Save byte to memory.",
+    OPData 0x54 SLOAD 1 1 "Load word from storage.",
+    OPData 0x55 SSTORE 2 0 "Save word to storage.",
+    OPData 0x56 JUMP 1 0 "Alter the program counter.",
+    OPData 0x57 JUMPI 2 0 "Conditionally alter the program counter.",
+    OPData 0x58 PC 0 1 "Get the program counter.",
+    OPData 0x59 MSIZE 0 1 "Get the size of active memory in bytes.",
+    OPData 0x5a GAS 0 1 "Get the amount of available gas.",
+    OPData 0x5b JUMPDEST 0 0 "set a potential jump destination",
+
+    OPData 0x80 DUP1 1 2 "Duplicate 1st stack item.",
+    OPData 0x81 DUP2 2 3 "Duplicate 2nd stack item.",
+    OPData 0x82 DUP3 3 4 "Duplicate 3rd stack item.",
+    OPData 0x83 DUP4 4 5 "Duplicate 4th stack item.",
+    OPData 0x84 DUP5 5 6 "Duplicate 5th stack item.",
+    OPData 0x85 DUP6 6 7 "Duplicate 6th stack item.",
+    OPData 0x86 DUP7 7 8 "Duplicate 7th stack item.",
+    OPData 0x87 DUP8 8 9 "Duplicate 8th stack item.",
+    OPData 0x88 DUP9 9 10 "Duplicate 9th stack item.",
+    OPData 0x89 DUP10 10 11 "Duplicate 10th stack item.",
+    OPData 0x8a DUP11 11 12 "Duplicate 11th stack item.",
+    OPData 0x8b DUP12 12 13 "Duplicate 12th stack item.",
+    OPData 0x8c DUP13 13 14 "Duplicate 13th stack item.",
+    OPData 0x8d DUP14 14 15 "Duplicate 14th stack item.",
+    OPData 0x8e DUP15 15 16 "Duplicate 15th stack item.",
+    OPData 0x8f DUP16 16 17 "Duplicate 16th stack item.",
+
+    OPData 0x90 SWAP1 2 2 "Exchange 1st and 2nd stack items.",
+    OPData 0x91 SWAP2 3 3 "Exchange 1st and 3nd stack items.",
+    OPData 0x92 SWAP3 4 4 "Exchange 1st and 4nd stack items.",
+    OPData 0x93 SWAP4 5 5 "Exchange 1st and 5nd stack items.",
+    OPData 0x94 SWAP5 6 6 "Exchange 1st and 6nd stack items.",
+    OPData 0x95 SWAP6 7 7 "Exchange 1st and 7nd stack items.",
+    OPData 0x96 SWAP7 8 8 "Exchange 1st and 8nd stack items.",
+    OPData 0x97 SWAP8 9 9 "Exchange 1st and 9nd stack items.",
+    OPData 0x98 SWAP9 10 10 "Exchange 1st and 10nd stack items.",
+    OPData 0x99 SWAP10 11 11 "Exchange 1st and 11nd stack items.",
+    OPData 0x9a SWAP11 12 12 "Exchange 1st and 12nd stack items.",
+    OPData 0x9b SWAP12 13 13 "Exchange 1st and 13nd stack items.",
+    OPData 0x9c SWAP13 14 14 "Exchange 1st and 14nd stack items.",
+    OPData 0x9d SWAP14 15 15 "Exchange 1st and 15nd stack items.",
+    OPData 0x9e SWAP15 16 16 "Exchange 1st and 16nd stack items.",
+    OPData 0x9f SWAP16 17 17 "Exchange 1st and 17nd stack items.",
+
+    OPData 0xa0 LOG0 2 0 "Append log record with no topics.",
+    OPData 0xa1 LOG1 3 0 "Append log record with one topic.",
+    OPData 0xa2 LOG2 4 0 "Append log record with two topics.",
+    OPData 0xa3 LOG3 5 0 "Append log record with three topics.",
+    OPData 0xa4 LOG4 6 0 "Append log record with four topics.",
+
+    OPData 0xf0 CREATE 3 1 "Create a new account with associated code.",
+    OPData 0xf1 CALL 7 1 "Message-call into an account.",
+    OPData 0xf2 CALLCODE 7 1 "Message-call into this account with alternate account's code.",
+    OPData 0xf3 RETURN 2 0 "Halt execution returning output data.",
+    OPData 0xf4 DELEGATECALL 7 1 "Message-call into this account with an alternative account’s code, but persisting the current values for sender and value.",
+    OPData 0xfe INVALID 0 0 "Designated invalid instruction.",
+    OPData 0xff SUICIDE 1 0 "Halt execution and register account for later deletion."
+  ]
+
+
+op2CodeMap::M.Map Operation Word8
+op2CodeMap=M.fromList $ (\(OPData code op _ _ _) -> (op, code)) <$> opDatas
+
+code2OpMap::M.Map Word8 Operation
+code2OpMap=M.fromList $ (\(OPData opcode op _ _ _) -> (opcode, op)) <$> opDatas
+
+op2OpCode::Operation->[Word8]
+op2OpCode (PUSH theList) | length theList <= 32 && not (null theList) =
+  0x5F + fromIntegral (length theList):theList
+op2OpCode (PUSH []) = error "PUSH needs at least one word"
+op2OpCode (PUSH x) = error $ "PUSH can only take up to 32 words: " ++ show x
+op2OpCode (DATA bytes) = B.unpack bytes
+op2OpCode (MalformedOpcode byte) = [byte]
+op2OpCode op =
+  case M.lookup op op2CodeMap of
+    Just x -> [x]
+    Nothing -> error $ "op is missing in op2CodeMap: " ++ show op
+
+opLen::Operation->Int
+opLen (PUSH x) = 1 + length x
+opLen _ = 1
+
+opCode2Op::B.ByteString->(Operation, Word256)
+opCode2Op rom | B.null rom = (STOP, 1) --according to the yellowpaper, should return STOP if outside of the code bytestring
+opCode2Op rom =
+  let opcode = B.head rom in --head OK, null weeded out above
+  if opcode >= 0x60 && opcode <= 0x7f
+  then (PUSH $ B.unpack $ safeTake (fromIntegral $ opcode-0x5F) $ B.tail rom, fromIntegral $ opcode - 0x5E)
+  else
+--    let op = fromMaybe (error $ "code is missing in code2OpMap: 0x" ++ showHex (B.head rom) "")
+    let op = fromMaybe (MalformedOpcode opcode)
+             $ M.lookup opcode code2OpMap in
+    (op, 1)
diff --git a/src/Legacy/Haskoin/V0102/Network/Haskoin/Crypto/BigWord.hs b/src/Legacy/Haskoin/V0102/Network/Haskoin/Crypto/BigWord.hs
new file mode 100644
--- /dev/null
+++ b/src/Legacy/Haskoin/V0102/Network/Haskoin/Crypto/BigWord.hs
@@ -0,0 +1,377 @@
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE EmptyDataDecls #-}
+module Legacy.Haskoin.V0102.Network.Haskoin.Crypto.BigWord
+(
+-- Useful type aliases
+  TxHash
+  , BlockHash
+  , Word512
+, Word256
+, Word160
+, Word128
+, FieldP
+, FieldN
+
+-- Data types
+, BigWord(..)
+, BigWordMod(..)
+
+-- Functions
+, inverseP
+, inverseN
+, quadraticResidue
+, isIntegerValidKey
+, encodeTxHashLE
+, decodeTxHashLE
+, encodeBlockHashLE
+, decodeBlockHashLE
+) where
+
+import Data.Bits
+    ( Bits
+    , (.&.), (.|.), xor
+    , complement
+    , shift, shiftL, shiftR
+    , bit, testBit, bitSize
+    , popCount, isSigned
+    )
+import Data.Binary (Binary, get, put)
+import Data.Binary.Get
+    ( getWord64be
+    , getWord32be
+    , getWord8
+    , getByteString
+    , Get
+    )
+import Data.Binary.Put
+    ( putWord64be
+    , putWord32be
+    , putWord8
+    , putByteString
+    )
+import Data.Aeson
+    ( Value (String)
+    , FromJSON
+    , ToJSON
+    , parseJSON
+    , toJSON
+    , withText
+    )
+import Control.DeepSeq (NFData, rnf)
+import Control.Monad (unless, guard)
+import Control.Applicative ((<$>))
+import Data.Ratio (numerator, denominator)
+import qualified Data.ByteString as BS (head, length, reverse)
+import qualified Data.Text as T (pack, unpack)
+
+import Legacy.Haskoin.V0102.Network.Haskoin.Crypto.Curve
+import Legacy.Haskoin.V0102.Network.Haskoin.Crypto.NumberTheory
+import Legacy.Haskoin.V0102.Network.Haskoin.Util
+
+-- | Type representing a transaction hash.
+type TxHash  = BigWord Mod256Tx
+-- | Type representing a block hash.
+type BlockHash = BigWord Mod256Block
+-- | Data type representing a 512 bit unsigned integer.
+-- It is implemented as an Integer modulo 2^512.
+type Word512 = BigWord Mod512
+-- | Data type representing a 256 bit unsigned integer.
+-- It is implemented as an Integer modulo 2^256.
+type Word256 = BigWord Mod256
+-- | Data type representing a 160 bit unsigned integer.
+-- It is implemented as an Integer modulo 2^160.
+type Word160 = BigWord Mod160
+-- | Data type representing a 128 bit unsigned integer.
+-- It is implemented as an Integer modulo 2^128.
+type Word128 = BigWord Mod128
+-- | Data type representing an Integer modulo coordinate field order P.
+type FieldP  = BigWord ModP
+-- | Data type representing an Integer modulo curve order N.
+type FieldN  = BigWord ModN
+
+data Mod512
+data Mod256
+data Mod256Tx
+data Mod256Block
+data Mod160
+data Mod128
+data ModP
+data ModN
+
+newtype BigWord n = BigWord { getBigWordInteger :: Integer }
+    deriving (Eq, Ord, Read, Show)
+
+instance NFData (BigWord n) where
+    rnf (BigWord n) = rnf n
+
+inverseP :: FieldP -> FieldP
+inverseP (BigWord i) = fromInteger $ mulInverse i curveP
+
+inverseN :: FieldN -> FieldN
+inverseN (BigWord i) = fromInteger $ mulInverse i curveN
+
+class BigWordMod a where
+    rFromInteger :: Integer -> BigWord a
+    rBitSize     :: BigWord a -> Int
+
+instance BigWordMod Mod512 where
+    rFromInteger i = BigWord $ i `mod` 2 ^ (512 :: Int)
+    rBitSize     _ = 512
+
+instance BigWordMod Mod256 where
+    rFromInteger i = BigWord $ i `mod` 2 ^ (256 :: Int)
+    rBitSize     _ = 256
+
+instance BigWordMod Mod256Tx where
+    rFromInteger i = BigWord $ i `mod` 2 ^ (256 :: Int)
+    rBitSize     _ = 256
+
+instance BigWordMod Mod256Block where
+    rFromInteger i = BigWord $ i `mod` 2 ^ (256 :: Int)
+    rBitSize     _ = 256
+
+instance BigWordMod Mod160 where
+    rFromInteger i = BigWord $ i `mod` 2 ^ (160 :: Int)
+    rBitSize     _ = 160
+
+instance BigWordMod Mod128 where
+    rFromInteger i = BigWord $ i `mod` 2 ^ (128 :: Int)
+    rBitSize     _ = 128
+
+instance BigWordMod ModP where
+    rFromInteger i = BigWord $ i `mod` curveP
+    rBitSize     _ = 256
+
+instance BigWordMod ModN where
+    rFromInteger i = BigWord $ i `mod` curveN
+    rBitSize     _ = 256
+
+instance BigWordMod n => Num (BigWord n) where
+    fromInteger = rFromInteger
+    (BigWord i1) + (BigWord i2) = fromInteger $ i1 + i2
+    (BigWord i1) * (BigWord i2) = fromInteger $ i1 * i2
+    negate (BigWord i) = fromInteger $ negate i
+    abs r = r
+    signum (BigWord i) = fromInteger $ signum i
+
+instance BigWordMod n => Bits (BigWord n) where
+    (BigWord i1) .&. (BigWord i2) = fromInteger $ i1 .&. i2
+    (BigWord i1) .|. (BigWord i2) = fromInteger $ i1 .|. i2
+    (BigWord i1) `xor` (BigWord i2) = fromInteger $ i1 `xor` i2
+    complement (BigWord i) = fromInteger $ complement i
+    shift (BigWord i) j = fromInteger $ shift i j
+    bitSize = rBitSize
+    testBit (BigWord i) = testBit i
+    bit n = fromInteger $ bit n
+    popCount (BigWord i) = popCount i
+    isSigned _ = False
+
+instance BigWordMod n => Bounded (BigWord n) where
+    minBound = fromInteger 0
+    maxBound = fromInteger (-1)
+
+instance BigWordMod n => Real (BigWord n) where
+    toRational (BigWord i) = toRational i
+
+instance BigWordMod n => Enum (BigWord n) where
+    succ r@(BigWord i)
+        | r == maxBound = error "BigWord: tried to take succ of maxBound"
+        | otherwise = fromInteger $ succ i
+    pred r@(BigWord i)
+        | r == minBound = error "BigWord: tried to take pred of minBound"
+        | otherwise = fromInteger $ pred i
+    toEnum i
+        | toInteger i >= toInteger (minFrom r) &&
+          toInteger i <= toInteger (maxFrom r) = r
+        | otherwise = error "BigWord: toEnum is outside of bounds"
+      where
+        r = fromInteger $ toEnum i
+        minFrom :: BigWordMod a => BigWord a -> BigWord a
+        minFrom _ = minBound
+        maxFrom :: BigWordMod a => BigWord a -> BigWord a
+        maxFrom _ = maxBound
+    fromEnum (BigWord i) = fromEnum i
+
+instance BigWordMod n => Integral (BigWord n) where
+    (BigWord i1) `quot` (BigWord i2) = fromInteger $ i1 `quot` i2
+    (BigWord i1) `rem` (BigWord i2) = fromInteger $ i1 `rem` i2
+    (BigWord i1) `div` (BigWord i2) = fromInteger $ i1 `div` i2
+    (BigWord i1) `mod` (BigWord i2) = fromInteger $ i1 `mod` i2
+    (BigWord i1) `quotRem` (BigWord i2) = (fromInteger a, fromInteger b)
+      where
+        (a,b) = i1 `quotRem` i2
+    (BigWord i1) `divMod` (BigWord i2) = (fromInteger a, fromInteger b)
+      where
+        (a,b) = i1 `divMod` i2
+    toInteger (BigWord i) = i
+
+{- Fractional is only defined for prime orders -}
+
+instance Fractional (BigWord ModP) where
+    recip = inverseP
+    fromRational r = fromInteger (numerator r) / fromInteger (denominator r)
+
+instance Fractional (BigWord ModN) where
+    recip = inverseN
+    fromRational r = fromInteger (numerator r) / fromInteger (denominator r)
+
+{- Binary instances for serialization / deserialization -}
+
+instance Binary (BigWord Mod512) where
+    get = do
+        a <- fromIntegral <$> (get :: Get Word256)
+        b <- fromIntegral <$> (get :: Get Word256)
+        return $ (a `shiftL` 256) + b
+
+    put (BigWord i) = do
+        put $ (fromIntegral (i `shiftR` 256) :: Word256)
+        put $ (fromIntegral i :: Word256)
+
+instance Binary (BigWord Mod256) where
+    get = do
+        a <- fromIntegral <$> getWord64be
+        b <- fromIntegral <$> getWord64be
+        c <- fromIntegral <$> getWord64be
+        d <- fromIntegral <$> getWord64be
+        return $ (a `shiftL` 192) + (b `shiftL` 128) + (c `shiftL` 64) + d
+
+    put (BigWord i) = do
+        putWord64be $ fromIntegral (i `shiftR` 192)
+        putWord64be $ fromIntegral (i `shiftR` 128)
+        putWord64be $ fromIntegral (i `shiftR` 64)
+        putWord64be $ fromIntegral i
+
+instance Binary (BigWord Mod256Tx) where
+    get = do
+        a <- fromIntegral <$> getWord64be
+        b <- fromIntegral <$> getWord64be
+        c <- fromIntegral <$> getWord64be
+        d <- fromIntegral <$> getWord64be
+        return $ (a `shiftL` 192) + (b `shiftL` 128) + (c `shiftL` 64) + d
+
+    put (BigWord i) = do
+        putWord64be $ fromIntegral (i `shiftR` 192)
+        putWord64be $ fromIntegral (i `shiftR` 128)
+        putWord64be $ fromIntegral (i `shiftR` 64)
+        putWord64be $ fromIntegral i
+
+instance Binary (BigWord Mod256Block) where
+    get = do
+        a <- fromIntegral <$> getWord64be
+        b <- fromIntegral <$> getWord64be
+        c <- fromIntegral <$> getWord64be
+        d <- fromIntegral <$> getWord64be
+        return $ (a `shiftL` 192) + (b `shiftL` 128) + (c `shiftL` 64) + d
+
+    put (BigWord i) = do
+        putWord64be $ fromIntegral (i `shiftR` 192)
+        putWord64be $ fromIntegral (i `shiftR` 128)
+        putWord64be $ fromIntegral (i `shiftR` 64)
+        putWord64be $ fromIntegral i
+
+instance Binary (BigWord Mod160) where
+    get = do
+        a <- fromIntegral <$> getWord32be
+        b <- fromIntegral <$> getWord64be
+        c <- fromIntegral <$> getWord64be
+        return $ (a `shiftL` 128) + (b `shiftL` 64) + c
+
+    put (BigWord i) = do
+        putWord32be $ fromIntegral (i `shiftR` 128)
+        putWord64be $ fromIntegral (i `shiftR` 64)
+        putWord64be $ fromIntegral i
+
+instance Binary (BigWord Mod128) where
+    get = do
+        a <- fromIntegral <$> getWord64be
+        b <- fromIntegral <$> getWord64be
+        return $ (a `shiftL` 64) + b
+
+    put (BigWord i) = do
+        putWord64be $ fromIntegral (i `shiftR` 64)
+        putWord64be $ fromIntegral i
+
+-- DER encoding of a FieldN element as Integer
+-- http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
+instance Binary (BigWord ModN) where
+    get = do
+        t <- getWord8
+        unless (t == 0x02) (fail $
+            "Bad DER identifier byte " ++ (show t) ++ ". Expecting 0x02" )
+        l <- getWord8
+        i <- bsToInteger <$> getByteString (fromIntegral l)
+        unless (isIntegerValidKey i) $ fail $
+            "Invalid fieldN element: " ++ (show i)
+        return $ fromInteger i
+
+    put (BigWord 0) = error "0 is an invalid FieldN element to serialize"
+    put (BigWord i) = do
+        putWord8 0x02 -- Integer type
+        let b = integerToBS i
+            l = fromIntegral $ BS.length b
+        if BS.head b >= 0x80
+            then do
+                putWord8 (l + 1)
+                putWord8 0x00
+            else do
+                putWord8 l
+        putByteString b
+
+instance Binary (BigWord ModP) where
+
+    -- Section 2.3.6 http://www.secg.org/download/aid-780/sec1-v2.pdf
+    get = do
+        (BigWord i) <- get :: Get Word256
+        unless (i < curveP) (fail $ "Get: Integer not in FieldP: " ++ (show i))
+        return $ fromInteger i
+
+    -- Section 2.3.7 http://www.secg.org/download/aid-780/sec1-v2.pdf
+    put r = put (fromIntegral r :: Word256)
+
+instance ToJSON (BigWord Mod256Tx) where
+    toJSON = String . T.pack . encodeTxHashLE
+
+instance FromJSON (BigWord Mod256Tx) where
+    parseJSON = withText "TxHash not a string: " $ \a -> do
+        let s = T.unpack a
+        maybe (fail $ "Not a TxHash: " ++ s) return $ decodeTxHashLE s
+
+instance ToJSON (BigWord Mod256) where
+    toJSON = String . T.pack . bsToHex . encode'
+
+instance FromJSON (BigWord Mod256) where
+    parseJSON = withText "Word256 not a string: " $ \a -> do
+        let s = T.unpack a
+        maybe (fail $ "Not a Word256: " ++ s) return $
+            hexToBS s >>= decodeToMaybe
+
+-- curveP = 3 (mod 4), thus Lagrange solutions apply
+-- http://en.wikipedia.org/wiki/Quadratic_residue
+quadraticResidue :: FieldP -> [FieldP]
+quadraticResidue x = guard (y^(2 :: Int) == x) >> [y, (-y)]
+  where
+    q = (curveP + 1) `div` 4
+    y = x^q
+
+isIntegerValidKey :: Integer -> Bool
+isIntegerValidKey i = i > 0 && i < curveN
+
+-- | Encodes a 'TxHash' as little endian in HEX format. This is mostly used for
+-- displaying transaction ids. Internally, these ids are handled as big endian
+-- but are transformed to little endian when displaying them.
+encodeTxHashLE :: TxHash -> String
+encodeTxHashLE = bsToHex . BS.reverse .  encode'
+
+-- | Decodes a little endian 'TxHash' in HEX format.
+decodeTxHashLE :: String -> Maybe TxHash
+decodeTxHashLE = (decodeToMaybe . BS.reverse =<<) . hexToBS
+
+-- | Encodes a 'BlockHash' as little endian in HEX format. This is mostly used
+-- for displaying Block hash ids. Internally, these ids are handled as big
+-- endian but are transformed to little endian when displaying them.
+encodeBlockHashLE :: BlockHash -> String
+encodeBlockHashLE = bsToHex . BS.reverse .  encode'
+
+-- | Decodes a little endian 'BlockHash' in HEX format.
+decodeBlockHashLE :: String -> Maybe BlockHash
+decodeBlockHashLE = (decodeToMaybe . BS.reverse =<<) . hexToBS
diff --git a/src/Legacy/Haskoin/V0102/Network/Haskoin/Crypto/Curve.hs b/src/Legacy/Haskoin/V0102/Network/Haskoin/Crypto/Curve.hs
new file mode 100644
--- /dev/null
+++ b/src/Legacy/Haskoin/V0102/Network/Haskoin/Crypto/Curve.hs
@@ -0,0 +1,27 @@
+module Legacy.Haskoin.V0102.Network.Haskoin.Crypto.Curve
+(
+  pairG
+, curveP
+, curveN
+, integerB
+, integerA
+) where
+
+-- SECP256k1 curve parameters
+
+pairG :: (Integer, Integer)
+pairG = ( 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798
+        , 0X483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8
+        )
+
+curveP :: Integer
+curveP = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f
+
+curveN :: Integer
+curveN = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141
+
+integerB :: Integer
+integerB = 7
+
+integerA :: Integer
+integerA = 0
diff --git a/src/Legacy/Haskoin/V0102/Network/Haskoin/Crypto/NumberTheory.hs b/src/Legacy/Haskoin/V0102/Network/Haskoin/Crypto/NumberTheory.hs
new file mode 100644
--- /dev/null
+++ b/src/Legacy/Haskoin/V0102/Network/Haskoin/Crypto/NumberTheory.hs
@@ -0,0 +1,23 @@
+module Legacy.Haskoin.V0102.Network.Haskoin.Crypto.NumberTheory
+(
+  extendedModGCD
+, mulInverse
+) where
+
+-- Extended euclidean algorithm
+-- Calculates the multiplicative inverse modulo p
+extendedModGCD :: Integer -> Integer -> Integer -> (Integer, Integer)
+extendedModGCD a b p
+    | b == 0 = (1,0)
+    | otherwise = (t, (s - q*t) `mod` p)
+  where
+    (q,r) = quotRem a b
+    (s,t) = extendedModGCD b r p
+
+-- Find multiplicative inverse of a : a*s = 1 (mod p)
+mulInverse :: Integer -> Integer -> Integer
+mulInverse a p
+    | a*s `mod` p == 1 = s
+    | otherwise = error "No multiplicative inverse (mod p) for a"
+  where
+    (s,_) = extendedModGCD a p p
diff --git a/src/Legacy/Haskoin/V0102/Network/Haskoin/Util.hs b/src/Legacy/Haskoin/V0102/Network/Haskoin/Util.hs
new file mode 100644
--- /dev/null
+++ b/src/Legacy/Haskoin/V0102/Network/Haskoin/Util.hs
@@ -0,0 +1,309 @@
+{-|
+  This module defines various utility functions used across the
+  Network.Haskoin modules.
+-}
+module Legacy.Haskoin.V0102.Network.Haskoin.Util
+(
+--   -- * ByteString helpers
+  toStrictBS
+  , toLazyBS
+  , stringToBS
+  , bsToString
+, bsToInteger
+, integerToBS
+  , bsToHex
+  , hexToBS
+
+-- * Data.Binary helpers
+, encode'
+, decode'
+, runPut'
+, runGet'
+, decodeOrFail'
+, runGetOrFail'
+, fromDecode
+, fromRunGet
+, decodeToEither
+, decodeToMaybe
+, isolate
+
+--   -- * Maybe and Either monad helpers
+-- , isLeft
+-- , isRight
+-- , fromRight
+-- , fromLeft
+-- , eitherToMaybe
+-- , maybeToEither
+-- -- , liftEither
+-- -- , liftMaybe
+
+--   -- * Various helpers
+-- , updateIndex
+-- , matchTemplate
+
+--   -- Triples
+-- , fst3
+-- , snd3
+-- , lst3
+
+) where
+
+import Numeric (readHex)
+import Control.Applicative ((<$>))
+import Control.Monad (guard)
+-- -- import Control.Monad.Trans.Either (EitherT, hoistEither)
+
+import Data.Word (Word8)
+import Data.Bits ((.|.), shiftL, shiftR)
+import Data.List (unfoldr)
+import Data.List.Split (chunksOf)
+import Data.Binary.Put (Put, runPut)
+import Data.Binary
+    ( Binary
+    , encode
+    , decode
+    , decodeOrFail
+    )
+import Data.Binary.Get
+    ( Get
+    , runGetOrFail
+    , getByteString
+    , ByteOffset
+    , runGet
+    )
+
+import qualified Data.ByteString.Lazy as BL
+    ( ByteString
+    , toChunks
+    , fromChunks
+    )
+import qualified Data.ByteString as BS
+    ( ByteString
+    , concat
+    , pack, unpack
+    , null
+    )
+import qualified Data.ByteString.Builder as BSB
+    ( toLazyByteString
+    , byteStringHex
+    )
+import qualified Data.ByteString.Char8 as C
+    ( pack
+    , unpack
+    )
+
+-- ByteString helpers
+
+-- | Transforms a lazy bytestring into a strict bytestring
+toStrictBS :: BL.ByteString -> BS.ByteString
+toStrictBS = BS.concat . BL.toChunks
+
+-- | Transforms a strict bytestring into a lazy bytestring
+toLazyBS :: BS.ByteString -> BL.ByteString
+toLazyBS bs = BL.fromChunks [bs]
+
+-- | Transforms a string into a strict bytestring
+stringToBS :: String -> BS.ByteString
+stringToBS = C.pack
+
+-- | Transform a strict bytestring to a string
+bsToString :: BS.ByteString -> String
+bsToString = C.unpack
+
+-- | Decode a big endian Integer from a bytestring
+bsToInteger :: BS.ByteString -> Integer
+bsToInteger = (foldr f 0) . reverse . BS.unpack
+  where
+    f w n = (toInteger w) .|. shiftL n 8
+
+-- | Encode an Integer to a bytestring as big endian
+integerToBS :: Integer -> BS.ByteString
+integerToBS 0 = BS.pack [0]
+integerToBS i
+    | i > 0     = BS.pack $ reverse $ unfoldr f i
+    | otherwise = error "integerToBS not defined for negative values"
+  where
+    f 0 = Nothing
+    f x = Just $ (fromInteger x :: Word8, x `shiftR` 8)
+
+-- | Encode a bytestring to a base16 (HEX) representation
+bsToHex :: BS.ByteString -> String
+bsToHex = bsToString . toStrictBS . BSB.toLazyByteString . BSB.byteStringHex
+
+-- | Decode a base16 (HEX) string from a bytestring. This function can fail
+-- if the string contains invalid HEX characters
+hexToBS :: String -> Maybe BS.ByteString
+hexToBS xs = BS.pack <$> mapM hexWord (chunksOf 2 xs)
+  where
+    hexWord x = do
+        guard $ length x == 2
+        let hs = readHex x
+        guard $ not $ null hs
+        let [(w, s)] = hs
+        guard $ null s
+        return w
+
+-- Data.Binary helpers
+
+-- | Strict version of @Data.Binary.encode@
+encode' :: Binary a => a -> BS.ByteString
+encode' = toStrictBS . encode
+
+-- | Strict version of @Data.Binary.decode@
+decode' :: Binary a => BS.ByteString -> a
+decode' = decode . toLazyBS
+
+-- | Strict version of @Data.Binary.runGet@
+runGet' :: Binary a => Get a -> BS.ByteString -> a
+runGet' m = (runGet m) . toLazyBS
+
+-- | Strict version of @Data.Binary.runPut@
+runPut' :: Put -> BS.ByteString
+runPut' = toStrictBS . runPut
+
+-- | Strict version of @Data.Binary.decodeOrFail@
+decodeOrFail' ::
+    Binary a =>
+    BS.ByteString ->
+    Either (BS.ByteString, ByteOffset, String) (BS.ByteString, ByteOffset, a)
+decodeOrFail' bs = case decodeOrFail $ toLazyBS bs of
+    Left  (lbs,o,err) -> Left  (toStrictBS lbs,o,err)
+    Right (lbs,o,res) -> Right (toStrictBS lbs,o,res)
+
+-- | Strict version of @Data.Binary.runGetOrFail@
+runGetOrFail' ::
+    Binary a => Get a -> BS.ByteString ->
+    Either (BS.ByteString, ByteOffset, String) (BS.ByteString, ByteOffset, a)
+runGetOrFail' m bs = case runGetOrFail m $ toLazyBS bs of
+    Left  (lbs,o,err) -> Left  (toStrictBS lbs,o,err)
+    Right (lbs,o,res) -> Right (toStrictBS lbs,o,res)
+
+-- | Try to decode a Data.Binary value. If decoding succeeds, apply the function
+-- to the result. Otherwise, return the default value.
+fromDecode :: Binary a
+           => BS.ByteString -- ^ The bytestring to decode
+           -> b             -- ^ Default value to return when decoding fails
+           -> (a -> b)      -- ^ Function to apply when decoding succeeds
+           -> b             -- ^ Final result
+fromDecode bs def f = either (const def) (f . lst) $ decodeOrFail' bs
+  where
+    lst (_,_,c) = c
+
+-- | Try to run a Data.Binary.Get monad. If decoding succeeds, apply a function
+-- to the result. Otherwise, return the default value.
+fromRunGet :: Binary a
+           => Get a         -- ^ The Get monad to run
+           -> BS.ByteString -- ^ The bytestring to decode
+           -> b             -- ^ Default value to return when decoding fails
+           -> (a -> b)      -- ^ Function to apply when decoding succeeds
+           -> b             -- ^ Final result
+fromRunGet m bs def f = either (const def) (f . lst) $ runGetOrFail' m bs
+  where
+    lst (_,_,c) = c
+
+-- | Decode a Data.Binary value into the Either monad. A Right value is returned
+-- with the result upon success. Otherwise a Left value with the error message
+-- is returned.
+decodeToEither :: Binary a => BS.ByteString -> Either String a
+decodeToEither bs = case decodeOrFail' bs of
+    Left  (_,_,err) -> Left err
+    Right (_,_,res) -> Right res
+
+-- | Decode a Data.Binary value into the Maybe monad. A Just value is returned
+-- with the result upon success. Otherwise, Nothing is returned.
+decodeToMaybe :: Binary a => BS.ByteString -> Maybe a
+decodeToMaybe bs = fromDecode bs Nothing Just
+
+-- | Isolate a Data.Binary.Get monad for the next @Int@ bytes. Only the next
+-- @Int@ bytes of the input bytestring will be available for the Get monad to
+-- consume. This function will fail if the Get monad fails or some of the input
+-- is not consumed.
+isolate :: Binary a => Int -> Get a -> Get a
+isolate i g = do
+    bs <- getByteString i
+    case runGetOrFail' g bs of
+        Left (_, _, err) -> fail err
+        Right (unconsumed, _, res)
+            | BS.null unconsumed -> return res
+            | otherwise          -> fail "Isolate: unconsumed input"
+
+-- -- Maybe and Eithre monad helpers
+
+-- -- | Returns True if the Either value is Right
+-- isRight :: Either a b -> Bool
+-- isRight (Right _) = True
+-- isRight _         = False
+
+-- -- | Returns True if the Either value is Left
+-- isLeft :: Either a b -> Bool
+-- isLeft = not . isRight
+
+-- -- | Extract the Right value from an Either value. Fails if the value is Left
+-- fromRight :: Either a b -> b
+-- fromRight (Right b) = b
+-- fromRight _ = error "Either.fromRight: Left"
+
+-- -- | Extract the Left value from an Either value. Fails if the value is Right
+-- fromLeft :: Either a b -> a
+-- fromLeft (Left a) = a
+-- fromLeft _ = error "Either.fromLeft: Right"
+
+-- -- | Transforms an Either value into a Maybe value. Right is mapped to Just
+-- -- and Left is mapped to Nothing. The value inside Left is lost.
+-- eitherToMaybe :: Either a b -> Maybe b
+-- eitherToMaybe (Right b) = Just b
+-- eitherToMaybe _ = Nothing
+
+-- -- | Transforms a Maybe value into an Either value. Just is mapped to Right and
+-- -- Nothing is mapped to Left. You also pass in an error value in case Left is
+-- -- returned.
+-- maybeToEither :: b -> Maybe a -> Either b a
+-- maybeToEither err m = maybe (Left err) Right m
+
+-- -- -- | Lift a Either computation into the EitherT monad
+-- -- liftEither :: Monad m => Either b a -> EitherT b m a
+-- -- liftEither = hoistEither
+
+-- -- -- | Lift a Maybe computation into the EitherT monad
+-- -- liftMaybe :: Monad m => b -> Maybe a -> EitherT b m a
+-- -- liftMaybe err = liftEither . (maybeToEither err)
+
+-- -- Various helpers
+
+-- -- | Applies a function to only one element of a list defined by it's index.
+-- -- If the index is out of the bounds of the list, the original list is returned.
+-- updateIndex :: Int      -- ^ The index of the element to change
+--             -> [a]      -- ^ The list of elements
+--             -> (a -> a) -- ^ The function to apply
+--             -> [a]      -- ^ The result with one element changed
+-- updateIndex i xs f
+--     | i < 0 || i >= length xs = xs
+--     | otherwise = l ++ (f h : r)
+--   where
+--     (l,h:r) = splitAt i xs
+
+-- -- | Use the list [b] as a template and try to match the elements of [a]
+-- -- against it. For each element of [b] return the (first) matching element of
+-- -- [a], or Nothing. Output list has same size as [b] and contains results in
+-- -- same order. Elements of [a] can only appear once.
+-- matchTemplate :: [a]              -- ^ The input list
+--               -> [b]              -- ^ The list to serve as a template
+--               -> (a -> b -> Bool) -- ^ The comparison function
+--               -> [Maybe a]        -- ^ Results of the template matching
+-- matchTemplate [] bs _ = replicate (length bs) Nothing
+-- matchTemplate _  [] _ = []
+-- matchTemplate as (b:bs) f = case break (flip f b) as of
+--     (l,(r:rs)) -> (Just r) : matchTemplate (l ++ rs) bs f
+--     _          -> Nothing  : matchTemplate as bs f
+
+-- -- | Returns the first value of a triple.
+-- fst3 :: (a,b,c) -> a
+-- fst3 (a,_,_) = a
+
+-- -- | Returns the second value of a triple.
+-- snd3 :: (a,b,c) -> b
+-- snd3 (_,b,_) = b
+
+-- -- | Returns the last value of a triple.
+-- lst3 :: (a,b,c) -> c
+-- lst3 (_,_,c) = c
