{-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} {-# OPTIONS_GHC -fno-warn-orphans #-} module Cardano.Address.DerivationSpec ( spec ) where import Prelude import Cardano.Address.Derivation ( Depth (..) , DerivationType (..) , Index (..) , XPrv , indexFromWord32 , nextIndex , sign , toXPub , verify , xprvChainCode , xprvFromBytes , xprvToBytes , xpubChainCode , xpubFromBytes , xpubToBytes ) import Data.ByteArray ( ScrubbedBytes ) import Data.ByteString ( ByteString ) import Data.String ( IsString (..) ) import Test.Hspec ( Spec, describe, it, shouldBe ) import Test.Hspec.QuickCheck ( prop ) import Test.QuickCheck ( Arbitrary (..), Property, property, (===) ) import Test.Arbitrary () spec :: Spec spec = describe "Checking auxiliary address derivations types" $ do describe "Bounded / Indexed relationship" $ do it "nextIndex maxBound for Hardened indices should result in failure" $ nextIndex (maxBound @(Index 'Hardened _)) `shouldBe` Nothing it "nextIndex maxBound for Soft indices should result in failure" $ nextIndex (maxBound @(Index 'Soft _)) `shouldBe` Nothing describe "Indexed Roundtrip" $ do it "Index @'Hardened _" (property prop_roundtripIndexedHard) it "Index @'Soft _" (property prop_roundtripIndexedSoft) describe "XPub / XPrv properties" $ do prop "roundtripping: xpubToBytes . xpubFromBytes" $ prop_roundtripBytes xpubToBytes xpubFromBytes prop "roundtripping: xprvToBytes . xprvFromBytes" $ prop_roundtripBytes xprvToBytes xprvFromBytes prop "forall xprv. xprvChainCode xprv == xpubChainCode (toXPub xprv)" prop_chainCodeInvariance prop "forall xprv msg. 'verify' ('toXPub' xprv) msg ('sign' xprv msg) == 'True'" prop_publicKeySignature {------------------------------------------------------------------------------- Properties -------------------------------------------------------------------------------} prop_publicKeySignature :: XPrv -> ScrubbedBytes -> Property prop_publicKeySignature xprv msg = verify (toXPub xprv) msg (sign xprv msg) === True prop_chainCodeInvariance :: XPrv -> Property prop_chainCodeInvariance xprv = xprvChainCode xprv === xpubChainCode (toXPub xprv) prop_roundtripBytes :: (Eq a, Show a) => (a -> ByteString) -> (ByteString -> Maybe a) -> a -> Property prop_roundtripBytes encode decode a = decode (encode a) === pure a prop_roundtripIndexedHard :: Index 'WholeDomain 'AccountK -> Property prop_roundtripIndexedHard ix = (indexFromWord32 . indexToWord32) ix === Just ix prop_roundtripIndexedSoft :: Index 'Soft 'PaymentK -> Property prop_roundtripIndexedSoft ix = (indexFromWord32 . indexToWord32) ix === Just ix {------------------------------------------------------------------------------- Arbitrary Instances -------------------------------------------------------------------------------} instance Arbitrary ScrubbedBytes where arbitrary = fromString <$> arbitrary