haskoin-core-0.13.2: test/Haskoin/AddressSpec.hs
{-# LANGUAGE OverloadedStrings #-}
module Haskoin.AddressSpec (spec) where
import Data.Aeson
import Data.Aeson.Types
import Data.ByteString (ByteString)
import qualified Data.ByteString as BS (append, empty, pack)
import Data.Either (isRight)
import Data.Maybe (fromJust, isJust)
import qualified Data.Serialize as S
import Data.Text (Text)
import Haskoin.Address
import Haskoin.Address.Base58
import Haskoin.Constants
import Haskoin.Keys (derivePubKeyI)
import Haskoin.Test
import Test.Hspec
import Test.HUnit (Assertion, assertBool, assertEqual)
import Test.QuickCheck
spec :: Spec
spec = do
let net = btc
describe "btc address" . it "base58 encodings" $ mapM_ runVector vectors
describe "btc-test address" $ props btcTest
describe "bch address" $ props bch
describe "bch-test address" $ props bchTest
describe "bch-regtest address" $ props bchRegTest
describe "json serialization" . it "encodes and decodes address" $
forAll arbitraryAddress (testCustom (addrFromJSON net) (addrToJSON net))
describe "witness address vectors" . it "p2sh(pwpkh)" $
mapM_ testCompatWitness compatWitnessVectors
props :: Network -> Spec
props net = do
it "encodes and decodes base58 bytestring" $
property $
forAll arbitraryBS $ \bs -> decodeBase58 (encodeBase58 bs) == Just bs
it "encodes and decodes base58 bytestring with checksum" $
property $
forAll arbitraryBS $ \bs ->
decodeBase58Check (encodeBase58Check bs) == Just bs
it "encodes and decodes address" $
property $
forAll arbitraryAddress $ \a ->
(stringToAddr net =<< addrToString net a) == Just a
it "shows and reads address" $
property $ forAll arbitraryAddress $ \a -> read (show a) == a
runVector :: (ByteString, Text, Text) -> Assertion
runVector (bs, e, chk) = do
assertEqual "encodeBase58" e b58
assertEqual "encodeBase58Check" chk b58Chk
assertEqual "decodeBase58" (Just bs) (decodeBase58 b58)
assertEqual "decodeBase58Check" (Just bs) (decodeBase58Check b58Chk)
where
b58 = encodeBase58 bs
b58Chk = encodeBase58Check bs
vectors :: [(ByteString, Text, Text)]
vectors =
[ ( BS.empty, "", "3QJmnh" )
, ( BS.pack [0], "1", "1Wh4bh" )
, ( BS.pack [0,0,0,0], "1111", "11114bdQda" )
, ( BS.pack [0,0,1,0,0], "11LUw", "113CUwsFVuo" )
, ( BS.pack [255], "5Q", "VrZDWwe" )
, ( BS.pack [0,0,0,0] `BS.append` BS.pack [1..255]
, "1111cWB5HCBdLjAuqGGReWE3R3CguuwSjw6RHn39s2yuDRTS5NsBgNiFpWgAnEx6VQi8csexkgYw3mdYrMHr8x9i7aEwP8kZ7vccXWqKDvGv3u1GxFKPuAkn8JCPPGDMf3vMMnbzm6Nh9zh1gcNsMvH3ZNLmP5fSG6DGbbi2tuwMWPthr4boWwCxf7ewSgNQeacyozhKDDQQ1qL5fQFUW52QKUZDZ5fw3KXNQJMcNTcaB723LchjeKun7MuGW5qyCBZYzA1KjofN1gYBV3NqyhQJ3Ns746GNuf9N2pQPmHz4xpnSrrfCvy6TVVz5d4PdrjeshsWQwpZsZGzvbdAdN8MKV5QsBDY"
, "111151KWPPBRzdWPr1ASeu172gVgLf1YfUp6VJyk6K9t4cLqYtFHcMa2iX8S3NJEprUcW7W5LvaPRpz7UG7puBj5STE3nKhCGt5eckYq7mMn5nT7oTTic2BAX6zDdqrmGCnkszQkzkz8e5QLGDjf7KeQgtEDm4UER6DMSdBjFQVa6cHrrJn9myVyyhUrsVnfUk2WmNFZvkWv3Tnvzo2cJ1xW62XDfUgYz1pd97eUGGPuXvDFfLsBVd1dfdUhPwxW7pMPgdWHTmg5uqKGFF6vE4xXpAqZTbTxRZjCDdTn68c2wrcxApm8hq3JX65Hix7VtcD13FF8b7BzBtwjXq1ze6NMjKgUcqpJTN9vt"
)
]
testCustom :: Eq a => (Value -> Parser a) -> (a -> Value) -> a -> Bool
testCustom f g x = parseMaybe f (g x) == Just x
compatWitnessVectors :: [(Network, Text, Text)]
compatWitnessVectors =
[ ( btcTest
, "cNUnpYpMsJXYCERYBciJnsWBpcYEFjdcbq6dxj4SskGhs7uHuJ7Q"
, "2N6PDTueBHvXzW61B4oe5SW1D3v2Z3Vpbvw")
]
testCompatWitness :: (Network, Text, Text) -> Assertion
testCompatWitness (net, seckey, addr) = do
let seckeyM = fromWif net seckey
assertBool "decode seckey" (isJust seckeyM)
let pubkey = derivePubKeyI (fromJust seckeyM)
let addrM = addrToString btcTest (pubKeyCompatWitnessAddr pubkey)
assertBool "address can be encoded" (isJust addrM)
assertEqual "witness address matches" addr (fromJust addrM)