haskoin-0.0.2: tests/Network/Haskoin/Crypto/BigWord/Tests.hs
module Network.Haskoin.Crypto.BigWord.Tests (tests) where
import Test.QuickCheck.Property (Property, (==>))
import Test.Framework (Test, testGroup)
import Test.Framework.Providers.QuickCheck2 (testProperty)
import Data.Bits
( isSigned
, bit
, testBit
, shift
, bitSize
, popCount
, (.&.), (.|.)
, xor, complement
)
import Data.Word (Word8, Word32)
import qualified Data.ByteString as BS (length, index)
import Network.Haskoin.Crypto.Arbitrary
import Network.Haskoin.Crypto.BigWord
import Network.Haskoin.Crypto.NumberTheory
import Network.Haskoin.Crypto.Curve
import Network.Haskoin.Util
tests :: [Test]
tests =
[ testGroup "Number Theory"
[ testProperty "a * inv(a) = 1 (mod p)" inverseMod
, testProperty "a * inv(a) = 1 (mod p) in FieldP" inverseModP
, testProperty "a * inv(a) = 1 (mod n) in FieldN" inverseModN
, testProperty "sqrt( a^2 ) = a (mod p)" sqrtP
],
testGroup "BigWord Numeric"
[ testProperty "BigWord fromInteger" ringFromInteger
, testProperty "BigWord addition" ringAddition
, testProperty "BigWord multiplication" ringMult
, testProperty "BigWord negation" ringNegate
, testProperty "BigWord abs" ringAbs
, testProperty "BigWord signum" ringSignum
],
testGroup "BigWord Bits"
[ testProperty "BigWord AND" ringAnd
, testProperty "BigWord OR" ringOr
, testProperty "BigWord XOR" ringXor
, testProperty "BigWord Complement" ringComplement
, testProperty "BigWord Shift" ringShift
, testProperty "BigWord Bitsize" ringBitsize
, testProperty "BigWord Testbit" ringTestbit
, testProperty "BigWord Bit" ringBit
, testProperty "BigWord PopCount" ringPopCount
, testProperty "BigWord IsSigned" ringIsSigned
],
testGroup "BigWord Bounded"
[ testProperty "BigWord minBound" ringMinBound
, testProperty "BigWord maxBound" ringMaxBound
],
testGroup "BigWord Enum"
[ testProperty "BigWord succ" ringSucc
, testProperty "BigWord pred" ringPred
, testProperty "BigWord toEnum" ringToEnum
, testProperty "BigWord fromEnum" ringFromEnum
],
testGroup "BigWord Integral"
[ testProperty "BigWord Quot" ringQuot
, testProperty "BigWord Rem" ringRem
, testProperty "BigWord Div" ringDiv
, testProperty "BigWord Mod" ringMod
, testProperty "BigWord QuotRem" ringQuotRem
, testProperty "BigWord DivMod" ringDivMod
, testProperty "BigWord toInteger" ringToInteger
],
testGroup "BigWord Binary"
[ testProperty "get( put(Word512) ) = Word512" getPutWord512
, testProperty "get( put(Word256) ) = Word256" getPutWord256
, testProperty "get( put(Word160) ) = Word160" getPutWord160
, testProperty "get( put(Word128) ) = Word128" getPutWord128
, testProperty "get( put(FieldP) ) = FieldP" getPutModP
, testProperty "size( put(FieldP) ) = 32" putModPSize
, testProperty "get( put(FieldN) ) = FieldN" getPutModN
, testProperty "Verify DER of put(FieldN)" putModNSize
],
testGroup "BigWord Read Show"
[ testProperty "read( show(Word512) ) = Word512" readShowWord512
, testProperty "read( show(Word256) ) = Word256" readShowWord256
, testProperty "read( show(Word160) ) = Word160" readShowWord160
, testProperty "read( show(Word128) ) = Word128" readShowWord128
, testProperty "read( show(FieldP) ) = FieldP" readShowModP
, testProperty "read( show(FieldN) ) = FieldN" readShowModN
]
]
{- Number Theory -}
inverseMod :: Integer -> Property
inverseMod i = p > 0 ==> (p * (mulInverse p curveP)) `mod` curveP == 1
where
p = abs i
inverseModP :: FieldP -> Property
inverseModP r = r > 0 ==> r/r == 1
inverseModN :: FieldN -> Property
inverseModN r = r > 0 ==> r/r == 1
sqrtP :: FieldP -> Bool
sqrtP x = (a == x && b == (-x)) || (a == (-x) && b == x)
where
(a:b:_) = quadraticResidue (x^(2 :: Int))
{- BigWord Numeric -}
ringFromInteger :: Integer -> Bool
ringFromInteger i = getBigWordInteger ring == fromIntegral model
where
model = fromInteger i :: Word32
ring = fromInteger i :: Test32
ringAddition :: Integer -> Integer -> Bool
ringAddition i1 i2 = getBigWordInteger ring == fromIntegral model
where
model = (fromInteger i1) + (fromInteger i2) :: Word32
ring = (fromInteger i1) + (fromInteger i2) :: Test32
ringMult :: Integer -> Integer -> Bool
ringMult i1 i2 = getBigWordInteger ring == fromIntegral model
where
model = (fromInteger i1) * (fromInteger i2) :: Word32
ring = (fromInteger i1) * (fromInteger i2) :: Test32
ringNegate :: Integer -> Bool
ringNegate i = getBigWordInteger ring == fromIntegral model
where
model = negate (fromInteger i) :: Word32
ring = negate (fromInteger i) :: Test32
ringAbs :: Integer -> Bool
ringAbs i = getBigWordInteger ring == fromIntegral model
where
model = abs (fromInteger i) :: Word32
ring = abs (fromInteger i) :: Test32
ringSignum :: Integer -> Bool
ringSignum i = getBigWordInteger ring == fromIntegral model
where
model = signum (fromInteger i) :: Word32
ring = signum (fromInteger i) :: Test32
{- BigWord Bits -}
ringAnd :: Integer -> Integer -> Bool
ringAnd i1 i2 = getBigWordInteger ring == fromIntegral model
where
model = (fromInteger i1) .&. (fromInteger i2) :: Word32
ring = (fromInteger i1) .&. (fromInteger i2) :: Test32
ringOr :: Integer -> Integer -> Bool
ringOr i1 i2 = getBigWordInteger ring == fromIntegral model
where
model = (fromInteger i1) .|. (fromInteger i2) :: Word32
ring = (fromInteger i1) .|. (fromInteger i2) :: Test32
ringXor :: Integer -> Integer -> Bool
ringXor i1 i2 = getBigWordInteger ring == fromIntegral model
where
model = (fromInteger i1) `xor` (fromInteger i2) :: Word32
ring = (fromInteger i1) `xor` (fromInteger i2) :: Test32
ringComplement :: Integer -> Bool
ringComplement i = getBigWordInteger ring == fromIntegral model
where
model = complement (fromInteger i) :: Word32
ring = complement (fromInteger i) :: Test32
ringShift :: Integer -> Word8 -> Bool
ringShift i j = getBigWordInteger ring == fromIntegral model
where
model = shift (fromInteger i) (fromIntegral j) :: Word32
ring = shift (fromInteger i) (fromIntegral j) :: Test32
ringBitsize :: Integer -> Bool
ringBitsize i = ring == model
where
model = bitSize ((fromInteger i) :: Word32)
ring = bitSize ((fromInteger i) :: Test32)
ringTestbit :: Integer -> Word8 -> Bool
ringTestbit i j = ring == model
where
model = testBit ((fromInteger i) :: Word32) (fromIntegral j)
ring = testBit ((fromInteger i) :: Test32) (fromIntegral j)
ringBit :: Word8 -> Bool
ringBit i = getBigWordInteger ring == fromIntegral model
where
model = bit (fromIntegral i) :: Word32
ring = bit (fromIntegral i) :: Test32
ringPopCount :: Integer -> Bool
ringPopCount i = ring == model
where
model = popCount ((fromInteger i) :: Word32)
ring = popCount ((fromInteger i) :: Test32)
ringIsSigned :: Integer -> Bool
ringIsSigned i = ring == model
where
model = isSigned ((fromInteger i) :: Word32)
ring = isSigned ((fromInteger i) :: Test32)
{- BigWord Bounded -}
ringMinBound :: Test32 -> Bool
ringMinBound _ = (minBound :: Test32) - 1 == (maxBound :: Test32)
ringMaxBound :: Test32 -> Bool
ringMaxBound _ = (maxBound :: Test32) + 1 == (minBound :: Test32)
{- BigWord Enum -}
ringSucc :: Integer -> Property
ringSucc i = (fromIntegral i) /= maxB ==>
getBigWordInteger ring == fromIntegral model
where
model = succ (fromInteger i) :: Word32
ring = succ (fromInteger i) :: Test32
maxB = maxBound :: Word32
ringPred :: Integer -> Property
ringPred i = (fromIntegral i) /= minB ==>
getBigWordInteger ring == fromIntegral model
where
model = pred (fromInteger i) :: Word32
ring = pred (fromInteger i) :: Test32
minB = minBound :: Word32
ringToEnum :: Word32 -> Bool
ringToEnum w = getBigWordInteger ring == fromIntegral model
where
model = toEnum (fromIntegral w) :: Word32
ring = toEnum (fromIntegral w) :: Test32
ringFromEnum :: Integer -> Bool
ringFromEnum i = model == ring
where
model = fromEnum ((fromInteger i) :: Word32)
ring = fromEnum ((fromInteger i) :: Test32)
{- BigWord Integral -}
ringQuot :: Integer -> Integer -> Property
ringQuot i1 i2 = i2 /= 0 ==> getBigWordInteger ring == fromIntegral model
where
model = (fromInteger i1) `quot` (fromInteger i2) :: Word32
ring = (fromInteger i1) `quot` (fromInteger i2) :: Test32
ringRem :: Integer -> Integer -> Property
ringRem i1 i2 = i2 /= 0 ==> getBigWordInteger ring == fromIntegral model
where
model = (fromInteger i1) `rem` (fromInteger i2) :: Word32
ring = (fromInteger i1) `rem` (fromInteger i2) :: Test32
ringDiv :: Integer -> Integer -> Property
ringDiv i1 i2 = i2 /= 0 ==> getBigWordInteger ring == fromIntegral model
where
model = (fromInteger i1) `div` (fromInteger i2) :: Word32
ring = (fromInteger i1) `div` (fromInteger i2) :: Test32
ringMod :: Integer -> Integer -> Property
ringMod i1 i2 = i2 /= 0 ==> getBigWordInteger ring == fromIntegral model
where
model = (fromInteger i1) `mod` (fromInteger i2) :: Word32
ring = (fromInteger i1) `mod` (fromInteger i2) :: Test32
ringQuotRem :: Integer -> Integer -> Property
ringQuotRem i1 i2 = i2 /= 0 ==>
(getBigWordInteger r1 == fromIntegral m1) &&
(getBigWordInteger r2 == fromIntegral m2)
where
(m1,m2) = (fromInteger i1) `quotRem` (fromInteger i2) :: (Word32, Word32)
(r1,r2) = (fromInteger i1) `quotRem` (fromInteger i2) :: (Test32, Test32)
ringDivMod :: Integer -> Integer -> Property
ringDivMod i1 i2 = i2 /= 0 ==>
(getBigWordInteger r1 == fromIntegral m1) &&
(getBigWordInteger r2 == fromIntegral m2)
where
(m1,m2) = (fromInteger i1) `divMod` (fromInteger i2) :: (Word32, Word32)
(r1,r2) = (fromInteger i1) `divMod` (fromInteger i2) :: (Test32, Test32)
ringToInteger :: Test32 -> Bool
ringToInteger r@(BigWord i) = toInteger r == i
{- BigWord Binary -}
getPutWord512 :: Word512 -> Bool
getPutWord512 r = r == (decode' $ encode' r)
getPutWord256 :: Word256 -> Bool
getPutWord256 r = r == (decode' $ encode' r)
getPutWord160 :: Word160 -> Bool
getPutWord160 r = r == (decode' $ encode' r)
getPutWord128 :: Word128 -> Bool
getPutWord128 r = r == (decode' $ encode' r)
getPutModP :: FieldP -> Bool
getPutModP r = r == (decode' $ encode' r)
putModPSize :: FieldP -> Bool
putModPSize r = BS.length (encode' r) == 32
getPutModN :: FieldN -> Property
getPutModN r = r > 0 ==> r == (decode' $ encode' r)
putModNSize :: FieldN -> Property
putModNSize r = r > 0 ==>
( a == 0x02 -- DER type is Integer
&& b <= 33 -- Can't be bigger than 32 + 0x00 padding
&& l == fromIntegral (b + 2) -- Advertised length matches
&& c < 0x80 -- High byte is never 1
)
where
bs = encode' r
a = BS.index bs 0
b = BS.index bs 1
c = BS.index bs 2
l = BS.length bs
{- BigWord Read Show -}
readShowWord512 :: Word512 -> Bool
readShowWord512 r = r == (read $ show r)
readShowWord256 :: Word256 -> Bool
readShowWord256 r = r == (read $ show r)
readShowWord160 :: Word160 -> Bool
readShowWord160 r = r == (read $ show r)
readShowWord128 :: Word128 -> Bool
readShowWord128 r = r == (read $ show r)
readShowModP :: FieldP -> Bool
readShowModP r = r == (read $ show r)
readShowModN :: FieldN -> Property
readShowModN r = r > 0 ==> r == (read $ show r)