haskoin-core-0.14.1: test/Haskoin/NetworkSpec.hs
{-# LANGUAGE OverloadedStrings #-}
module Haskoin.NetworkSpec (spec) where
import Data.Maybe (fromJust)
import Data.Serialize as S
import Data.Text (Text)
import Data.Word (Word32)
import Haskoin.Address
import Haskoin.Constants
import Haskoin.Keys
import Haskoin.Network
import Haskoin.Transaction
import Haskoin.Util
import Haskoin.Util.Arbitrary
import Haskoin.UtilSpec (customCerealID)
import Test.Hspec
import Test.Hspec.QuickCheck
import Test.HUnit (Assertion, assertBool, assertEqual)
import Test.QuickCheck
serialVals :: [SerialBox]
serialVals =
[ SerialBox arbitraryVarInt
, SerialBox arbitraryVarString
, SerialBox arbitraryNetworkAddress
, SerialBox arbitraryInvType
, SerialBox arbitraryInvVector
, SerialBox arbitraryInv1
, SerialBox arbitraryVersion
, SerialBox arbitraryAddr1
, SerialBox arbitraryAlert
, SerialBox arbitraryReject
, SerialBox arbitraryRejectCode
, SerialBox arbitraryGetData
, SerialBox arbitraryNotFound
, SerialBox arbitraryPing
, SerialBox arbitraryPong
, SerialBox arbitraryMessageCommand
, SerialBox arbitraryMessageHeader
, SerialBox arbitraryBloomFlags
, SerialBox arbitraryBloomFilter
, SerialBox arbitraryFilterLoad
, SerialBox arbitraryFilterAdd
]
spec :: Spec
spec = do
testIdentity serialVals [] [] []
describe "Custom identity tests" $ do
prop "Data.Serialize Encoding for type Message" $
forAll arbitraryNetwork $ \net ->
forAll (arbitraryMessage net) $
customCerealID (getMessage net) (putMessage net)
describe "bloom filters" $ do
it "bloom filter vector 1" bloomFilter1
it "bloom filter vector 2" bloomFilter2
it "bloom filter vector 3" bloomFilter3
describe "relevant bloom filter update" $ do
it "Relevant Update" relevantOutputUpdated
it "Irrelevant Update" irrelevantOutputNotUpdated
bloomFilter :: Word32 -> Text -> Assertion
bloomFilter n x = do
assertBool "Bloom filter doesn't contain vector 1" $ bloomContains f1 v1
assertBool "Bloom filter contains something it should not" $
not $ bloomContains f1 v2
assertBool "Bloom filter doesn't contain vector 3" $ bloomContains f3 v3
assertBool "Bloom filter doesn't contain vector 4" $ bloomContains f4 v4
assertBool "Bloom filter serialization is incorrect" $
S.encode f4 == bs
where
f0 = bloomCreate 3 0.01 n BloomUpdateAll
f1 = bloomInsert f0 v1
f3 = bloomInsert f1 v3
f4 = bloomInsert f3 v4
v1 = fromJust $ decodeHex "99108ad8ed9bb6274d3980bab5a85c048f0950c8"
v2 = fromJust $ decodeHex "19108ad8ed9bb6274d3980bab5a85c048f0950c8"
v3 = fromJust $ decodeHex "b5a2c786d9ef4658287ced5914b37a1b4aa32eee"
v4 = fromJust $ decodeHex "b9300670b4c5366e95b2699e8b18bc75e5f729c5"
bs = fromJust $ decodeHex x
bloomFilter1 :: Assertion
bloomFilter1 = bloomFilter 0 "03614e9b050000000000000001"
bloomFilter2 :: Assertion
bloomFilter2 = bloomFilter 2147483649 "03ce4299050000000100008001"
bloomFilter3 :: Assertion
bloomFilter3 =
assertBool "Bloom filter serialization is incorrect" $
S.encode f2 == bs
where
f0 = bloomCreate 2 0.001 0 BloomUpdateAll
f1 = bloomInsert f0 $ S.encode p
f2 = bloomInsert f1 $ S.encode $ getAddrHash160 $ pubKeyAddr p
k = fromJust $ fromWif btc "5Kg1gnAjaLfKiwhhPpGS3QfRg2m6awQvaj98JCZBZQ5SuS2F15C"
p = derivePubKeyI k
bs = fromJust $ decodeHex "038fc16b080000000000000001"
relevantOutputUpdated :: Assertion
relevantOutputUpdated = assertBool "Bloom filter output updated" $
any (bloomContains bf2) spendTxInput
where
bf0 = bloomCreate 10 0.000001 0 BloomUpdateAll
relevantOutputHash = fromJust $ decodeHex"03f47604ea2736334151081e13265b4fe38e6fa8"
bf1 = bloomInsert bf0 relevantOutputHash
bf2 = fromJust $ bloomRelevantUpdate bf1 relevantTx
spendTxInput = encode .prevOutput <$> txIn spendRelevantTx
irrelevantOutputNotUpdated :: Assertion
irrelevantOutputNotUpdated = assertEqual "Bloom filter not updated" Nothing bf2
where
bf0 = bloomCreate 10 0.000001 0 BloomUpdateAll
relevantOutputHash = fromJust $ decodeHex"03f47604ea2736334151081e13265b4fe38e6fa8"
bf1 = bloomInsert bf0 relevantOutputHash
bf2 = bloomRelevantUpdate bf1 unrelatedTx
-- Random transaction (57dc904f32ad4daab7b321dd469e8791ad09df784cdd273a73985150a4f225e9)
relevantTx :: Tx
relevantTx = Tx
{ txVersion = 1
, txIn = [ TxIn
{ prevOutput = OutPoint "35fe9017b7e3af592920b56fa06ac02faf0c52cdb19dcb416129ac71c95d060e" 1
, scriptInput = fromJust $ decodeHex "473044022032fc8eef299b7e94b9a986a6aa2dcb9733ab804bef80df995e443b9c1f8c604202203335df7a2e2b4789451cdb4b2b05a786a81c51519eb6a567fd6fe8cd7b2d33fe014104272502dc63a512dad1473cb82a71be9baf4f4303abd1ff6028fc8a78e1f3aec1218907119dec14f07354850758ff0948e88a904fa411c4df7d5444414ec64ad6"
, txInSequence = 4294967295
} ]
, txOut =
[ TxOut { outValue = 100000000, scriptOutput = fromJust $ decodeHex "76a91403f47604ea2736334151081e13265b4fe38e6fa888ac" }
, TxOut { outValue = 107980000, scriptOutput = fromJust $ decodeHex "76a91481cc186a2f4a69f633ed4bf10ef4a78be13effdd88ac" }
]
, txWitness = []
, txLockTime = 0
}
-- Transaction that spends above (fd6e3b693b844aa431fad46765c1aa019a6b13aebfa9dae916b3ffa43283a300)
spendRelevantTx :: Tx
spendRelevantTx = Tx
{ txVersion = 1
, txIn = [ TxIn
{ prevOutput = OutPoint "57dc904f32ad4daab7b321dd469e8791ad09df784cdd273a73985150a4f225e9" 0
, scriptInput = fromJust $ decodeHex "483045022100ecc334821e4e94cc2fdc841d5ad147d5bb942b993ba81460cc446e0410afa811022015fcbc542b734dbb61a05ec06012095096de5839c50808fe56f2b315e877c20d012103fb64e5792fa586172339b776b7017d3d529358cb73be6406a1fc994228d14f88"
, txInSequence = 4294967295
}, TxIn
{ prevOutput = OutPoint "cfee6a8d6e68e8fd16df6fff010afffcd19d7e075aa7b707dd1bae6adc420042" 0
, scriptInput = fromJust $ decodeHex "47304402200e6bb95fa606f254d17089d83c4ceeb19c5d1699b4faddcd4f1f1568286e6b650220087fb8439f31e1b30e47710d095422405f601d6151f2f93e125e1a08a6e29ad4012103b49252e8fc6d5b49c8d14ee71fab45591df4a126a6c453c724f3d356e38f0cee"
, txInSequence = 4294967295
} ]
, txOut =
[ TxOut { outValue = 3851100, scriptOutput = fromJust $ decodeHex "76a914a297cae82a9a3b932bf023ae274fe2585295c9ca88ac" }
, TxOut { outValue = 111000000, scriptOutput = fromJust $ decodeHex "76a9148f952c38600a61385974acc30a64f74407f9801488ac" }
]
, txWitness = []
, txLockTime = 0
}
-- This random transaction is unrelated to the others
unrelatedTx :: Tx
unrelatedTx = Tx
{ txVersion = 1
, txIn = [ TxIn
{ prevOutput = OutPoint "3ec3a71431c68e5d978a5fb4a0a1081d8bee8384d8aa4c06b1fbaf9413e2214f" 20
, scriptInput = fromJust $ decodeHex "483045022100ec9c202c9d3140b973aca9d7f21a82138aa4cfa43fddc5419098ac5e26a6f152022010848fd688f290ae010fb5cb493410caa03145fc12445900ec1ad2bde33aecd9012102c7445e72d723f99a0064526c28269d07f47c8fd81531a94a8d3bf5ebd5e23ef1"
, txInSequence = 4294967295
}]
, txOut =
[ TxOut { outValue = 12600000, scriptOutput = fromJust $ decodeHex "76a9148fef3b7051de8cc44e966159e7ea37f4520187e888ac" }
]
, txWitness = []
, txLockTime = 0
}