blockchain-0.0.2: test/Data/Blockchain/Core/Builder/TransactionSpec.hs
module Data.Blockchain.Core.Builder.TransactionSpec (spec) where
import TestUtil
import qualified Data.List.NonEmpty as NonEmpty
import Data.Blockchain.Core.Blockchain
import Data.Blockchain.Core.Builder
import Data.Blockchain.Core.Crypto
import Data.Blockchain.Core.Types
blockchainItems :: IO (Blockchain Validated, KeyPair)
blockchainItems = do
blockchain <- blockchain1Block
block <- block1A
privateKey <- block1ACoinbasePrivateKey
return (blockchain, KeyPair (coinbasePublicKey block) privateKey)
coinbasePublicKey :: Block -> PublicKey
coinbasePublicKey = signaturePubKey . NonEmpty.head . coinbaseTransactionOut . coinbaseTransaction
spec :: Spec
spec = describe "Data.Blockchain.Core.Builder.Transaction" $
describe "createSimpleTransaction" $ do
propNumTests 5 "should create a valid transaction" $
\(Small value) (Small fee) targetPublicKey -> value + fee < 100 ==> ioProperty $ do
(blockchain, keyPair) <- blockchainItems
(Transaction txIn txOut) <- throwLeft <$>
createSimpleTransaction keyPair targetPublicKey value fee blockchain
return $
length txIn == 1 &&
txOut == NonEmpty.fromList
[ TransactionOut (100 - value - fee) (publicKey keyPair)
, TransactionOut value targetPublicKey
]
propNumTests 5 "should not issue a refund if entire balance is spent" $
\(Small value) targetPublicKey -> value < 100 ==> ioProperty $ do
(blockchain, keyPair) <- blockchainItems
let fee = 100 - value
(Transaction txIn txOut) <- throwLeft <$>
createSimpleTransaction keyPair targetPublicKey value fee blockchain
return $
length txIn == 1 &&
txOut == NonEmpty.fromList [ TransactionOut value targetPublicKey ]
propNumTests 5 "should reject transactions attempting to spend from empty address" $
\(Small value) (Small fee) publicKey targetPublicKey -> value + fee < 100 ==> ioProperty $ do
(blockchain, KeyPair _ privKey) <- blockchainItems
let keyPair = KeyPair publicKey privKey
res <- createSimpleTransaction keyPair targetPublicKey value fee blockchain
return $ res === Left SourceAddressEmpty
propNumTests 5 "should reject transactions attempting to spend more than is available in the address" $
\(MediumWord value) (MediumWord fee) targetPublicKey -> value + fee > 100 ==> ioProperty $ do
(blockchain, keyPair) <- blockchainItems
res <- createSimpleTransaction keyPair targetPublicKey value fee blockchain
return $ res === Left SourceAddressInsufficientFunds
propNumTests 5 "should reject transactions with invalid private key" $
\(Small value) (Small fee) privateKey targetPublicKey -> value + fee < 100 ==> ioProperty $ do
(blockchain, KeyPair pubKey _) <- blockchainItems
let keyPair = KeyPair pubKey privateKey
res <- createSimpleTransaction keyPair targetPublicKey value fee blockchain
return $ res === Left InvalidPrivateKey