{-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} {-# OPTIONS_GHC -fno-warn-orphans #-} {-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-} module Cardano.Address.Style.ShelleySpec ( spec ) where import Prelude import Cardano.Address ( Address , ChainPointer (..) , HasNetworkDiscriminant (..) , bech32 , bech32With , fromBech32 , unAddress , unsafeMkAddress ) import Cardano.Address.Derivation ( Depth (..) , DerivationType (..) , GenMasterKey (..) , HardDerivation (..) , Index (..) , Pub , SoftDerivation (..) , XPrv , XPub , hashCredential , indexFromWord32 , pubFromBytes , pubToBytes , toXPub , unsafeMkIndex , xprvPrivateKey , xprvToBytes , xpubFromBytes , xpubToBytes , xpubToPub ) import Cardano.Address.KeyHash ( GovernanceType (..), KeyHash (..), KeyRole (..), keyHashToText ) import Cardano.Address.Script ( Script (..), ScriptHash (..), toScriptHash ) import Cardano.Address.Style.Shelley ( Credential (..) , Role (..) , Shelley (..) , delegationAddress , deriveCCColdPrivateKey , deriveCCHotPrivateKey , deriveDRepPrivateKey , deriveDelegationPrivateKey , liftPub , liftXPub , mkNetworkDiscriminant , paymentAddress , pointerAddress , roleFromIndex , roleToIndex ) import Cardano.Mnemonic ( SomeMnemonic, mkSomeMnemonic ) import Codec.Binary.Encoding ( AbstractEncoding (..), encode, fromBase16 ) import Control.Monad ( (<=<) ) import Crypto.Hash ( hashWith ) import Crypto.Hash.Algorithms ( SHA3_256 (SHA3_256) ) import Data.Aeson ( ToJSON, Value (..) ) import Data.ByteArray ( ByteArrayAccess, ScrubbedBytes ) import Data.ByteString ( ByteString ) import Data.Either ( rights ) import Data.Function ( (&) ) import Data.Maybe ( fromMaybe, isNothing ) import Data.Text ( Text ) import Data.Word ( Word32 ) import GHC.Generics ( Generic ) import Test.Arbitrary () import Test.Hspec ( Spec, SpecWith, describe, it, shouldBe ) import Test.Hspec.Golden ( Golden (..) ) import Test.Hspec.QuickCheck ( prop ) import Test.QuickCheck ( Arbitrary (..) , Property , choose , counterexample , label , property , vector , (===) ) import Text.Pretty.Simple ( defaultOutputOptionsNoColor, pShowOpt ) import qualified Cardano.Address.Style.Shelley as Shelley import qualified Cardano.Codec.Bech32.Prefixes as CIP5 import qualified Data.Aeson.Encode.Pretty as Aeson import qualified Data.ByteArray as BA import qualified Data.ByteArray.Encoding as BAE import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy as BL import qualified Data.Char as Char import qualified Data.Text as T import qualified Data.Text.Encoding as T import qualified Data.Text.Lazy as TL import qualified Data.Text.Lazy.Encoding as TLE import qualified Data.Text.Lazy.IO as TL spec :: Spec spec = do describe "BIP-0044 Derivation Properties" $ do it "deriveAccountPrivateKey works for various indexes" $ property prop_accountKeyDerivation it "N(CKDpriv((kpar, cpar), i)) === CKDpub(N(kpar, cpar), i) for any key" $ property prop_publicChildKeyDerivation describe "Role indices" $ do it "Calling indexFromWord32 for invalid value fails)" $ property prop_fromWord32Role it "Roundtrip index" $ property prop_roundtripIndexRole describe "Proper pointer addresses construction" $ do it "Using different numbers in DelegationPointerAddress does not fail" (property prop_pointerAddressConstruction) describe "Text Encoding Roundtrips" $ do prop "bech32 . fromBech32 - Shelley - payment address" $ prop_roundtripTextEncoding bech32 fromBech32 prop "bech32 . fromBech32 - Shelley - delegation address" $ prop_roundtripTextEncodingDelegation bech32 fromBech32 prop "bech32 . fromBech32 - Shelley - pointer address" $ prop_roundtripTextEncodingPointer bech32 fromBech32 describe "Golden tests" $ do goldenTestPointerAddress GoldenTestPointerAddress { verKey = "1a2a3a4a5a6a7a8a" , stakePtr = ChainPointer 128 2 3 , netTag = 0 , expectedAddr = "408a4d111f71a79169c50bcbc27e1e20b6e13e87ff8f33edc3cab419d481000203" } goldenTestPointerAddress GoldenTestPointerAddress { verKey = "1a2a3a4a5a6a7a8a" , stakePtr = ChainPointer 128 2 3 , netTag = 1 , expectedAddr = "418a4d111f71a79169c50bcbc27e1e20b6e13e87ff8f33edc3cab419d481000203" } goldenTestEnterpriseAddress GoldenTestEnterpriseAddress { verKey = "1a2a3a4a5a6a7a8a" , netTag = 0 , expectedAddr = "608a4d111f71a79169c50bcbc27e1e20b6e13e87ff8f33edc3cab419d4" } goldenTestEnterpriseAddress GoldenTestEnterpriseAddress { verKey = "1a2a3a4a5a6a7a8a" , netTag = 1 , expectedAddr = "618a4d111f71a79169c50bcbc27e1e20b6e13e87ff8f33edc3cab419d4" } goldenTestEnterpriseAddressKeyHash GoldenTestEnterpriseAddress { verKey = "1a2a3a4a5a6a7a8a" , netTag = 0 , expectedAddr = "608a4d111f71a79169c50bcbc27e1e20b6e13e87ff8f33edc3cab419d4" } goldenTestEnterpriseAddressKeyHash GoldenTestEnterpriseAddress { verKey = "1a2a3a4a5a6a7a8a" , netTag = 1 , expectedAddr = "618a4d111f71a79169c50bcbc27e1e20b6e13e87ff8f33edc3cab419d4" } goldenTestBaseAddressPayFromXPub GoldenTestBaseAddress { verKeyPayment = "1a2a3a4a5a6a7a8a" , verKeyStake = "1c2c3c4c5c6c7c8c" , netTag = 0 , expectedAddr = "008a4d111f71a79169c50bcbc27e1e20b6e13e87ff8f33edc3cab419d408b2d658668c2e341ee5bda4477b63c5aca7ec7ae4e3d196163556a4" } goldenTestBaseAddressPayFromXPub GoldenTestBaseAddress { verKeyPayment = "1a2a3a4a5a6a7a8a" , verKeyStake = "1c2c3c4c5c6c7c8c" , netTag = 1 , expectedAddr = "018a4d111f71a79169c50bcbc27e1e20b6e13e87ff8f33edc3cab419d408b2d658668c2e341ee5bda4477b63c5aca7ec7ae4e3d196163556a4" } goldenTestBaseAddressPayFromPub GoldenTestBaseAddress { verKeyPayment = "1a2a3a4a5a6a7a8a" , verKeyStake = "1c2c3c4c5c6c7c8c" , netTag = 0 , expectedAddr = "008a4d111f71a79169c50bcbc27e1e20b6e13e87ff8f33edc3cab419d408b2d658668c2e341ee5bda4477b63c5aca7ec7ae4e3d196163556a4" } goldenTestBaseAddressPayFromPub GoldenTestBaseAddress { verKeyPayment = "1a2a3a4a5a6a7a8a" , verKeyStake = "1c2c3c4c5c6c7c8c" , netTag = 1 , expectedAddr = "018a4d111f71a79169c50bcbc27e1e20b6e13e87ff8f33edc3cab419d408b2d658668c2e341ee5bda4477b63c5aca7ec7ae4e3d196163556a4" } goldenTestBaseAddressPayFromKeyHash GoldenTestBaseAddress { verKeyPayment = "1a2a3a4a5a6a7a8a" , verKeyStake = "1c2c3c4c5c6c7c8c" , netTag = 0 , expectedAddr = "008a4d111f71a79169c50bcbc27e1e20b6e13e87ff8f33edc3cab419d408b2d658668c2e341ee5bda4477b63c5aca7ec7ae4e3d196163556a4" } goldenTestBaseAddressPayFromKeyHash GoldenTestBaseAddress { verKeyPayment = "1a2a3a4a5a6a7a8a" , verKeyStake = "1c2c3c4c5c6c7c8c" , netTag = 1 , expectedAddr = "018a4d111f71a79169c50bcbc27e1e20b6e13e87ff8f33edc3cab419d408b2d658668c2e341ee5bda4477b63c5aca7ec7ae4e3d196163556a4" } goldenTestBaseAddressStakeFromKeyHash GoldenTestBaseAddress { verKeyPayment = "1a2a3a4a5a6a7a8a" , verKeyStake = "1c2c3c4c5c6c7c8c" , netTag = 0 , expectedAddr = "008a4d111f71a79169c50bcbc27e1e20b6e13e87ff8f33edc3cab419d408b2d658668c2e341ee5bda4477b63c5aca7ec7ae4e3d196163556a4" } goldenTestBaseAddressStakeFromKeyHash GoldenTestBaseAddress { verKeyPayment = "1a2a3a4a5a6a7a8a" , verKeyStake = "1c2c3c4c5c6c7c8c" , netTag = 1 , expectedAddr = "018a4d111f71a79169c50bcbc27e1e20b6e13e87ff8f33edc3cab419d408b2d658668c2e341ee5bda4477b63c5aca7ec7ae4e3d196163556a4" } goldenTestBaseAddressStakeFromPub GoldenTestBaseAddress { verKeyPayment = "1a2a3a4a5a6a7a8a" , verKeyStake = "1c2c3c4c5c6c7c8c" , netTag = 0 , expectedAddr = "008a4d111f71a79169c50bcbc27e1e20b6e13e87ff8f33edc3cab419d408b2d658668c2e341ee5bda4477b63c5aca7ec7ae4e3d196163556a4" } goldenTestBaseAddressStakeFromPub GoldenTestBaseAddress { verKeyPayment = "1a2a3a4a5a6a7a8a" , verKeyStake = "1c2c3c4c5c6c7c8c" , netTag = 1 , expectedAddr = "018a4d111f71a79169c50bcbc27e1e20b6e13e87ff8f33edc3cab419d408b2d658668c2e341ee5bda4477b63c5aca7ec7ae4e3d196163556a4" } goldenTestBaseAddressBothFromKeyHash GoldenTestBaseAddress { verKeyPayment = "1a2a3a4a5a6a7a8a" , verKeyStake = "1c2c3c4c5c6c7c8c" , netTag = 0 , expectedAddr = "008a4d111f71a79169c50bcbc27e1e20b6e13e87ff8f33edc3cab419d408b2d658668c2e341ee5bda4477b63c5aca7ec7ae4e3d196163556a4" } goldenTestBaseAddressBothFromKeyHash GoldenTestBaseAddress { verKeyPayment = "1a2a3a4a5a6a7a8a" , verKeyStake = "1c2c3c4c5c6c7c8c" , netTag = 1 , expectedAddr = "018a4d111f71a79169c50bcbc27e1e20b6e13e87ff8f33edc3cab419d408b2d658668c2e341ee5bda4477b63c5aca7ec7ae4e3d196163556a4" } goldenTestBaseAddressBothFromPub GoldenTestBaseAddress { verKeyPayment = "1a2a3a4a5a6a7a8a" , verKeyStake = "1c2c3c4c5c6c7c8c" , netTag = 0 , expectedAddr = "008a4d111f71a79169c50bcbc27e1e20b6e13e87ff8f33edc3cab419d408b2d658668c2e341ee5bda4477b63c5aca7ec7ae4e3d196163556a4" } goldenTestBaseAddressBothFromPub GoldenTestBaseAddress { verKeyPayment = "1a2a3a4a5a6a7a8a" , verKeyStake = "1c2c3c4c5c6c7c8c" , netTag = 1 , expectedAddr = "018a4d111f71a79169c50bcbc27e1e20b6e13e87ff8f33edc3cab419d408b2d658668c2e341ee5bda4477b63c5aca7ec7ae4e3d196163556a4" } goldenTestGovernance GoldenTestGovernance { mnemonic = [ "test", "walk", "nut", "penalty", "hip", "pave", "soap", "entry", "language", "right", "filter", "choice" ] , accountIx = 0x80000000 , expectedKeysHashes = KeysHashes { drepXsk = "drep_xsk14rjh4rs2dzm6k5xxe5f73cypzuv02pknfl9xwnsjws8a7ulp530xztarpdlyh05csw2cmnekths7dstq0se3wtza84m4fueffezsjfgassgs9xtfzgehrn0fn7c82uc0rkj06s0w0t80hflzz8cwyry3eg9066uj" , drepXskHex = "a8e57a8e0a68b7ab50c6cd13e8e0811718f506d34fca674e12740fdf73e1a45e612fa30b7e4bbe9883958dcf365de1e6c1607c33172c5d3d7754f3294e4509251d8411029969123371cde99fb075730f1da4fd41ee7acefba7e211f0e20c91ca" , drepSk = "drep_sk14rjh4rs2dzm6k5xxe5f73cypzuv02pknfl9xwnsjws8a7ulp530xztarpdlyh05csw2cmnekths7dstq0se3wtza84m4fueffezsjfglsqmad" , drepSkHex = "a8e57a8e0a68b7ab50c6cd13e8e0811718f506d34fca674e12740fdf73e1a45e612fa30b7e4bbe9883958dcf365de1e6c1607c33172c5d3d7754f3294e450925" , drepXvk = "drep_xvk17axh4sc9zwkpsft3tlgpjemfwc0u5mnld80r85zw7zdqcst6w543mpq3q2vkjy3nw8x7n8asw4es78dyl4q7u7kwlwn7yy0sugxfrjs6z25qe" , drepXvkHex = "f74d7ac30513ac1825715fd0196769761fca6e7f69de33d04ef09a0c417a752b1d8411029969123371cde99fb075730f1da4fd41ee7acefba7e211f0e20c91ca" , drepVk = "drep_vk17axh4sc9zwkpsft3tlgpjemfwc0u5mnld80r85zw7zdqcst6w54sdv4a4e" , drepVkHex = "f74d7ac30513ac1825715fd0196769761fca6e7f69de33d04ef09a0c417a752b" , drep = "drep1y2jmg4g450lced7q9n34rq6d5vjwkm0ugx6h0894u6ur92s9txn3a" , drepHex = "a5b45515a3ff8cb7c02ce351834da324eb6dfc41b5779cb5e6b832aa" , drepScript1 = "drep16pjhzfkm7rqntfezfkgu5p50t0mkntmdruwlp089zu8v22aculf" , drepScript1Hex = "d0657126dbf0c135a7224d91ca068f5bf769af6d1f1df0bce5170ec5" , drepScript2 = "drep14edv7pg3y4wkglyykvvy5t2j906ld3dhdwvf7jda8qaa670f745" , drepScript2Hex = "ae5acf0511255d647c84b3184a2d522bf5f6c5b76b989f49bd383bdd" , ccColdXsk = "cc_cold_xsk1dp84kjq9qa647wr70e2yedzt8e27kwugh8mfw675re0hgm8p530z3d9230cjjzyyzlq04hn94x9q2m9um2tvp2y8fn7tau9l2wfj5ykxqxtgua0lxpf0lfn44md2afyl7dktyvpkmug9u28p6v452flxeuca0v7w" , ccColdXskHex = "684f5b480507755f387e7e544cb44b3e55eb3b88b9f6976bd41e5f746ce1a45e28b4aa8bf129088417c0fade65a98a056cbcda96c0a8874cfcbef0bf53932a12c601968e75ff3052ffa675aedaaea49ff36cb23036df105e28e1d32b4527e6cf" , ccColdSk = "cc_cold_sk1dp84kjq9qa647wr70e2yedzt8e27kwugh8mfw675re0hgm8p530z3d9230cjjzyyzlq04hn94x9q2m9um2tvp2y8fn7tau9l2wfj5yslmdl88" , ccColdSkHex = "684f5b480507755f387e7e544cb44b3e55eb3b88b9f6976bd41e5f746ce1a45e28b4aa8bf129088417c0fade65a98a056cbcda96c0a8874cfcbef0bf53932a12" , ccColdXvk = "cc_cold_xvk149up407pvp9p36lldlp4qckqqzn6vm7u5yerwy8d8rqalse3t04vvqvk3e6l7vzjl7n8ttk646jflumvkgcrdhcstc5wr5etg5n7dnc8nqv5d" , ccColdXvkHex = "a9781abfc1604a18ebff6fc35062c000a7a66fdca1323710ed38c1dfc3315beac601968e75ff3052ffa675aedaaea49ff36cb23036df105e28e1d32b4527e6cf" , ccColdVk = "cc_cold_vk149up407pvp9p36lldlp4qckqqzn6vm7u5yerwy8d8rqalse3t04q7qsvwl" , ccColdVkHex = "a9781abfc1604a18ebff6fc35062c000a7a66fdca1323710ed38c1dfc3315bea" , ccCold = "cc_cold1ztl0h9vka4ns45kfj7xh3ljwkd46yn9m5znzlfxd6rpdeagw6p59q" , ccColdHex = "fefb9596ed670ad2c9978d78fe4eb36ba24cbba0a62fa4cdd0c2dcf5" , ccColdScript1 = "cc_cold14ehj5f64f40xju0086fnunctulkh46mq7munm7upe4hpc434cg3" , ccColdScript1Hex = "ae6f2a27554d5e6971ef3e933e4f0be7ed7aeb60f6f93dfb81cd6e1c" , ccColdScript2 = "cc_cold1zxwzpnk0ah7m5ptjjtmkhvgs4736k3e0ns66shd0fy33vkd39j0" , ccColdScript2Hex = "119c20cecfedfdba057292f76bb110afa3ab472f9c35a85daf492316" , ccHotXsk = "cc_hot_xsk1mpt30ys7v2ykqms4c83wuednh4hvy3lr27yfhgtp0rhdka8p5300j4d2z77sq2t3kp082qzgkanwkm05mp2u2nwja3ad3pgw9l34a0j5sl5yd6d8pze8dqwksd069kkfdqggk0yytcmet96fre45w64qkgyxl0dt" , ccHotXskHex = "d85717921e6289606e15c1e2ee65b3bd6ec247e357889ba16178eedb74e1a45ef955aa17bd002971b05e750048b766eb6df4d855c54dd2ec7ad8850e2fe35ebe5487e846e9a708b27681d6835fa2dac968108b3c845e379597491e6b476aa0b2" , ccHotSk = "cc_hot_sk1mpt30ys7v2ykqms4c83wuednh4hvy3lr27yfhgtp0rhdka8p5300j4d2z77sq2t3kp082qzgkanwkm05mp2u2nwja3ad3pgw9l34a0sdh7u7e" , ccHotSkHex = "d85717921e6289606e15c1e2ee65b3bd6ec247e357889ba16178eedb74e1a45ef955aa17bd002971b05e750048b766eb6df4d855c54dd2ec7ad8850e2fe35ebe" , ccHotXvk = "cc_hot_xvk10y48lq72hypxraew74lwjjn9e2dscuwphckglh2nrrpkgweqk5h4fplggm56wz9jw6qadq6l5tdvj6qs3v7ggh3hjkt5j8ntga42pvs5rvh0a" , ccHotXvkHex = "792a7f83cab90261f72ef57ee94a65ca9b0c71c1be2c8fdd5318c3643b20b52f5487e846e9a708b27681d6835fa2dac968108b3c845e379597491e6b476aa0b2" , ccHotVk = "cc_hot_vk10y48lq72hypxraew74lwjjn9e2dscuwphckglh2nrrpkgweqk5hschnzv5" , ccHotVkHex = "792a7f83cab90261f72ef57ee94a65ca9b0c71c1be2c8fdd5318c3643b20b52f" , ccHot = "cc_hot1qtmd98q0w9jdxasse0m8kyn2nya7kf9qwmgx20cl5p543rcdtr4dz" , ccHotHex = "f6d29c0f7164d37610cbf67b126a993beb24a076d0653f1fa069588f" , ccHotScript1 = "cc_hot16fayy2wf9myfvxmtl5e2suuqmnhy5zx80vxkezen7xqws04z0n8" , ccHotScript1Hex = "d27a4229c92ec8961b6bfd32a87380dcee4a08c77b0d6c8b33f180e8" , ccHotScript2 = "cc_hot1vts8nrrsxmlntp3v7sh5u7k6qmmlkkmyv5uspq4xjxlpgr6svrf" , ccHotScript2Hex = "62e0798c7036ff35862cf42f4e7ada06f7fb5b6465390082a691be14" } } goldenTestGovernance GoldenTestGovernance { mnemonic = [ "test", "walk", "nut", "penalty", "hip", "pave", "soap", "entry", "language", "right", "filter", "choice" ] , accountIx = 0x80000100 , expectedKeysHashes = KeysHashes { drepXsk = "drep_xsk1zracgd4mqt32f5cj0ps0wudf78u6lumz7gprgm3j8zec5ahp530weq4z9ayj6jzj33lpj86jkk2gnt0ns0d5sywteexxehvva7gugz99ydmpemzpsfnj49vjvw88q9a2s2hxc9ggxal5q6xsqz5vaat2xqsha72w" , drepXskHex = "10fb8436bb02e2a4d3127860f771a9f1f9aff362f202346e3238b38a76e1a45eec82a22f492d48528c7e191f52b59489adf383db4811cbce4c6cdd8cef91c408a523761cec4182672a9592638e7017aa82ae6c1508377f4068d000a8cef56a30" , drepSk = "drep_sk1zracgd4mqt32f5cj0ps0wudf78u6lumz7gprgm3j8zec5ahp530weq4z9ayj6jzj33lpj86jkk2gnt0ns0d5sywteexxehvva7gugzqjur0zk" , drepSkHex = "10fb8436bb02e2a4d3127860f771a9f1f9aff362f202346e3238b38a76e1a45eec82a22f492d48528c7e191f52b59489adf383db4811cbce4c6cdd8cef91c408" , drepXvk = "drep_xvk1wq6ylcpjnwavhveey855tkhdrqdav6yfxvltw0emky9d3erxn9m22gmkrnkyrqn8922eycuwwqt64q4wds2ssdmlgp5dqq9gem6k5vq23ph3c" , drepXvkHex = "70344fe0329bbacbb33921e945daed181bd66889333eb73f3bb10ad8e4669976a523761cec4182672a9592638e7017aa82ae6c1508377f4068d000a8cef56a30" , drepVk = "drep_vk1wq6ylcpjnwavhveey855tkhdrqdav6yfxvltw0emky9d3erxn9mqdrlerg" , drepVkHex = "70344fe0329bbacbb33921e945daed181bd66889333eb73f3bb10ad8e4669976" , drep = "drep1yg0dx99005ll3lxnyrrnadv9ynthfj3cwvlwqr4u4qdavwshx0yl0" , drepHex = "1ed314af7d3ff8fcd320c73eb58524d774ca38733ee00ebca81bd63a" , drepScript1 = "drep18cgl8kdnjculhww4n3h0a3ahc85ahjcsg53u0f93jnz9cqnvdpd" , drepScript1Hex = "3e11f3d9b39639fbb9d59c6efec7b7c1e9dbcb104523c7a4b194c45c" , drepScript2 = "drep1hwj9yuvzxc623w5lmwvp44md7qkdywz2fcd583qmyu62jrsw2xy" , drepScript2Hex = "bba45271823634a8ba9fdb981ad76df02cd2384a4e1b43c41b2734a9" , ccColdXsk = "cc_cold_xsk1dppxrjspxrjj5e5xrmh6yaw6w30arsl5lqcsp09ynyzwwulp530q4tlvug79xx6ja3u32fu9jyy84p6erjmza6twrackm9kfsdpc3ap7uxpempqjftx74qwxnmn7d6pg8pl9zpnc0rese26pfmzl9cmtgg8xsxvu" , ccColdXskHex = "684261ca0130e52a66861eefa275da745fd1c3f4f83100bca49904e773e1a45e0aafece23c531b52ec7915278591087a87591cb62ee96e1f716d96c9834388f43ee1839d84124acdea81c69ee7e6e828387e51067878f30cab414ec5f2e36b42" , ccColdSk = "cc_cold_sk1dppxrjspxrjj5e5xrmh6yaw6w30arsl5lqcsp09ynyzwwulp530q4tlvug79xx6ja3u32fu9jyy84p6erjmza6twrackm9kfsdpc3aqr79jja" , ccColdSkHex = "684261ca0130e52a66861eefa275da745fd1c3f4f83100bca49904e773e1a45e0aafece23c531b52ec7915278591087a87591cb62ee96e1f716d96c9834388f4" , ccColdXvk = "cc_cold_xvk1e2mquwugpwnykfftjs4mv3w4uk80f4hjgd2zls5vusz3zuqhr7gnacvrnkzpyjkda2qud8h8um5zswr72yr8s78npj45znk97t3kkssryhkyv" , ccColdXvkHex = "cab60e3b880ba64b252b942bb645d5e58ef4d6f243542fc28ce4051170171f913ee1839d84124acdea81c69ee7e6e828387e51067878f30cab414ec5f2e36b42" , ccColdVk = "cc_cold_vk1e2mquwugpwnykfftjs4mv3w4uk80f4hjgd2zls5vusz3zuqhr7gs3qg4hr" , ccColdVkHex = "cab60e3b880ba64b252b942bb645d5e58ef4d6f243542fc28ce4051170171f91" , ccCold = "cc_cold1zt5nwd86uuvwjxalghyxlrxcreledplxellyeygd6xjvxcqy66a7t" , ccColdHex = "e93734fae718e91bbf45c86f8cd81e7f9687e6cffe4c910dd1a4c360" , ccColdScript1 = "cc_cold1prtcxdlu75dz48lf8hh86gt8ng7z39yvmyqcg92sgze7gpt2gga" , ccColdScript1Hex = "08d78337fcf51a2a9fe93dee7d21679a3c28948cd90184155040b3e4" , ccColdScript2 = "cc_cold1969h0m92nuqrj7x74pj3tnhxh97lfhl4y2vwvqvc6kecwkq6xe5" , ccColdScript2Hex = "2e8b77ecaa9f003978dea86515cee6b97df4dff52298e60198d5b387" , ccHotXsk = "cc_hot_xsk15pt89wppyhr9eqgm5nnu7tna3dfmqxa2u45e4g7krzp9u78p530pez36k8k9n0gw08hn6drxlwxxsgc4jsejv6hvcnkd7gd3zxhstpe3vzde6e98zql6n2cmekklm63dydnt80szdr0h768dexeklrfspc5lznuz" , ccHotXskHex = "a05672b82125c65c811ba4e7cf2e7d8b53b01baae5699aa3d618825e78e1a45e1c8a3ab1ec59bd0e79ef3d3466fb8c6823159433266aecc4ecdf21b111af058731609b9d64a7103fa9ab1bcdadfdea2d2366b3be0268df7f68edc9b36f8d300e" , ccHotSk = "cc_hot_sk15pt89wppyhr9eqgm5nnu7tna3dfmqxa2u45e4g7krzp9u78p530pez36k8k9n0gw08hn6drxlwxxsgc4jsejv6hvcnkd7gd3zxhstpc7gujxf" , ccHotSkHex = "a05672b82125c65c811ba4e7cf2e7d8b53b01baae5699aa3d618825e78e1a45e1c8a3ab1ec59bd0e79ef3d3466fb8c6823159433266aecc4ecdf21b111af0587" , ccHotXvk = "cc_hot_xvk10qawpxlz7eytt9yr4xlwtjkw345v0ehzsxdlkks6qralyp975phrzcymn4j2wypl4x43hnddlh4z6gmxkwlqy6xl0a5wmjdnd7xnqrsvak8ry" , ccHotXvkHex = "783ae09be2f648b59483a9bee5cace8d68c7e6e2819bfb5a1a00fbf204bea06e31609b9d64a7103fa9ab1bcdadfdea2d2366b3be0268df7f68edc9b36f8d300e" , ccHotVk = "cc_hot_vk10qawpxlz7eytt9yr4xlwtjkw345v0ehzsxdlkks6qralyp975phqx538xn" , ccHotVkHex = "783ae09be2f648b59483a9bee5cace8d68c7e6e2819bfb5a1a00fbf204bea06e" , ccHot = "cc_hot1qtgaf67mr95fa90qj7gehkr3y3q73x6pasmdu3algq6ylpgfamj02" , ccHotHex = "d1d4ebdb19689e95e097919bd8712441e89b41ec36de47bf40344f85" , ccHotScript1 = "cc_hot1hheftszv4jw83f5megrvhrevl7lwwmtnjav7srkqngr92348jvr" , ccHotScript1Hex = "bdf295c04cac9c78a69bca06cb8f2cffbee76d739759e80ec09a0655" , ccHotScript2 = "cc_hot1dg9jdwlsxzakctywv2cw7a7ggj2dwu0gz5tueu2rf40zv05atgs" , ccHotScript2Hex = "6a0b26bbf030bb6c2c8e62b0ef77c84494d771e81517ccf1434d5e26" } } goldenTestGovernance GoldenTestGovernance { mnemonic = [ "excess", "behave", "track", "soul", "table", "wear", "ocean", "cash", "stay", "nature", "item", "turtle", "palm", "soccer", "lunch", "horror", "start", "stumble", "month", "panic", "right", "must", "lock", "dress" ] , accountIx = 0x80000000 , expectedKeysHashes = KeysHashes { drepXsk = "drep_xsk17pwn6d7pu0d6sfzysyk5taux99f5tdqsct7zzthgljyd5zs33azej0tm5ny7ksunthqu84tqg832md6vs3hm392agwx3auhvyjtzxr2l6c0dj47k6zedl4kgugneu04j64fc5uueayydmufdrdaled9k4qllaka6" , drepXskHex = "f05d3d37c1e3dba82444812d45f786295345b410c2fc212ee8fc88da0a118f45993d7ba4c9eb43935dc1c3d56041e2adb74c846fb8955d438d1ef2ec2496230d5fd61ed957d6d0b2dfd6c8e2279e3eb2d5538a7399e908ddf12d1b7bfcb4b6a8" , drepSk = "drep_sk17pwn6d7pu0d6sfzysyk5taux99f5tdqsct7zzthgljyd5zs33azej0tm5ny7ksunthqu84tqg832md6vs3hm392agwx3auhvyjtzxrgwyexuy" , drepSkHex = "f05d3d37c1e3dba82444812d45f786295345b410c2fc212ee8fc88da0a118f45993d7ba4c9eb43935dc1c3d56041e2adb74c846fb8955d438d1ef2ec2496230d" , drepXvk = "drep_xvk15j30gk0uex88lc9vh6sfda93lv6zede65mzp7ck56m9pgeqhnht9l4s7m9tad59jmltv3c38nclt942n3feen6ggmhcj6xmmlj6td2qu4ce82" , drepXvkHex = "a4a2f459fcc98e7fe0acbea096f4b1fb342cb73aa6c41f62d4d6ca1464179dd65fd61ed957d6d0b2dfd6c8e2279e3eb2d5538a7399e908ddf12d1b7bfcb4b6a8" , drepVk = "drep_vk15j30gk0uex88lc9vh6sfda93lv6zede65mzp7ck56m9pgeqhnhtqvs6j8t" , drepVkHex = "a4a2f459fcc98e7fe0acbea096f4b1fb342cb73aa6c41f62d4d6ca1464179dd6" , drep = "drep1yge7tpltrazw286rqlhw6lk7vxgq30zdrsevrqye6cm8x2gf38vlv" , drepHex = "33e587eb1f44e51f4307eeed7ede619008bc4d1c32c18099d6367329" , drepScript1 = "drep17fql6ztxyk63taryk2e4mh47jw3wdchv9e7u4jxg4edrxg8enef" , drepScript1Hex = "f241fd096625b515f464b2b35ddebe93a2e6e2ec2e7dcac8c8ae5a33" , drepScript2 = "drep10qp23w0gppuvc7chc3g7saudlmhj9jmm9ssrrzzm3qwksrn4cul" , drepScript2Hex = "7802a8b9e80878cc7b17c451e8778dfeef22cb7b2c2031885b881d68" , ccColdXsk = "cc_cold_xsk1hqtevrzlhtcglwvt5pmgct8ssqx37vjjf3wuydpd6flyqrg33azacap5w5mclacmuycx3xgrtstxgrpzcncf6l840t0klmywc69ryd9zf95taaaseka98yakuj2048slnuekw22qm58majt8alhs438eecehquu0" , ccColdXskHex = "b817960c5fbaf08fb98ba0768c2cf0800d1f32524c5dc2342dd27e400d118f45dc743475378ff71be1306899035c16640c22c4f09d7cf57adf6fec8ec68a3234a24968bef7b0cdba5393b6e494fa9e1f9f33672940dd0fbec967efef0ac4f9ce" , ccColdSk = "cc_cold_sk1hqtevrzlhtcglwvt5pmgct8ssqx37vjjf3wuydpd6flyqrg33azacap5w5mclacmuycx3xgrtstxgrpzcncf6l840t0klmywc69rydqvncuyc" , ccColdSkHex = "b817960c5fbaf08fb98ba0768c2cf0800d1f32524c5dc2342dd27e400d118f45dc743475378ff71be1306899035c16640c22c4f09d7cf57adf6fec8ec68a3234" , ccColdXvk = "cc_cold_xvk13wc4cvvr266t4rxm9wyel4deeqxyylvjzjdk5w74lva2xm0dhxt6yjtghmmmpnd62wfmdey5l20pl8envu55phg0hmyk0ml0ptz0nns9cqjlk" , ccColdXvkHex = "8bb15c318356b4ba8cdb2b899fd5b9c80c427d92149b6a3bd5fb3aa36dedb997a24968bef7b0cdba5393b6e494fa9e1f9f33672940dd0fbec967efef0ac4f9ce" , ccColdVk = "cc_cold_vk13wc4cvvr266t4rxm9wyel4deeqxyylvjzjdk5w74lva2xm0dhxtsfpa2qu" , ccColdVkHex = "8bb15c318356b4ba8cdb2b899fd5b9c80c427d92149b6a3bd5fb3aa36dedb997" , ccCold = "cc_cold1ztc2kq7xa0vdrdz3tg7umg724srnw6yac0zschqdl0rerushdm3cm" , ccColdHex = "f0ab03c6ebd8d1b4515a3dcda3caac0737689dc3c50c5c0dfbc791f2" , ccColdScript1 = "cc_cold15z7ynn7fuqu55hh850962vrrg7tcdncl8spnjtrxjjm06lpsfgc" , ccColdScript1Hex = "a0bc49cfc9e0394a5ee7a3cba53063479786cf1f3c03392c6694b6fd" , ccColdScript2 = "cc_cold1ahw3qh3ledhxp0frga9aawfkxpu0qstte9nmem0phqqegzf9lp3" , ccColdScript2Hex = "eddd105e3fcb6e60bd23474bdeb9363078f0416bc967bcede1b80194" , ccHotXsk = "cc_hot_xsk1wzamzchtj7m79mjfpg3c02m534ugej5ac0p3s2sresr7vys33azktmjva6flctprqu6m4k4w459x9qkfsz2ahgy5ganjn23djhhkg5e5eyhu7fjxl6tpxtmzh7e2ftuj4qgmawsmcl7sqesn8e0pmh97zs3c3fqj" , ccHotXskHex = "70bbb162eb97b7e2ee490a2387ab748d788cca9dc3c3182a03cc07e612118f4565ee4cee93fc2c230735badaaead0a6282c98095dba094476729aa2d95ef645334c92fcf2646fe96132f62bfb2a4af92a811beba1bc7fd0066133e5e1ddcbe14" , ccHotSk = "cc_hot_sk1wzamzchtj7m79mjfpg3c02m534ugej5ac0p3s2sresr7vys33azktmjva6flctprqu6m4k4w459x9qkfsz2ahgy5ganjn23djhhkg5cmwegml" , ccHotSkHex = "70bbb162eb97b7e2ee490a2387ab748d788cca9dc3c3182a03cc07e612118f4565ee4cee93fc2c230735badaaead0a6282c98095dba094476729aa2d95ef6453" , ccHotXvk = "cc_hot_xvk1tazd6lvnf2c9j8m58h6xy56uuyhkee526jgxj2ylaextl0xamd4nfjf0eunydl5kzvhk90aj5jhe92q3h6aph3laqpnpx0j7rhwtu9qe7dhsc" , ccHotXvkHex = "5f44dd7d934ab0591f743df462535ce12f6ce68ad49069289fee4cbfbcdddb6b34c92fcf2646fe96132f62bfb2a4af92a811beba1bc7fd0066133e5e1ddcbe14" , ccHotVk = "cc_hot_vk1tazd6lvnf2c9j8m58h6xy56uuyhkee526jgxj2ylaextl0xamd4swmuygc" , ccHotVkHex = "5f44dd7d934ab0591f743df462535ce12f6ce68ad49069289fee4cbfbcdddb6b" , ccHot = "cc_hot1qtp2wn5mef3ypk2872d7kl0djczfwsqkmgk53ca8cdjye3qehdsy0" , ccHotHex = "c2a74e9bca6240d947f29beb7ded9604974016da2d48e3a7c3644cc4" , ccHotScript1 = "cc_hot1tmwlec0twwvl29h6pgvew5mf4recsxtktev9g07xm37fvvupdmd" , ccHotScript1Hex = "5eddfce1eb7399f516fa0a19975369a8f38819765e58543fc6dc7c96" , ccHotScript2 = "cc_hot1c77thg5lrahy0he4q6glsk8vgsp45gt75k3pq09d02u8gvktfzw" , ccHotScript2Hex = "c7bcbba29f1f6e47df350691f858ec44035a217ea5a2103cad7ab874" } } goldenTestGovernance GoldenTestGovernance { mnemonic = [ "excess", "behave", "track", "soul", "table", "wear", "ocean", "cash", "stay", "nature", "item", "turtle", "palm", "soccer", "lunch", "horror", "start", "stumble", "month", "panic", "right", "must", "lock", "dress" ] , accountIx = 0x80000100 , expectedKeysHashes = KeysHashes { drepXsk = "drep_xsk14z6a7nd2q5r03s4gxsrujc59sg757vqqcwxeuc5s874c2rq33az37lwkxpxvh5s4a94sncxp6y7m73pxsuknt7gvethhue5jk5vc5n2hrg95mynhw7mtrshxr5mpku4v8x6lpm05nznrqej70u0fllgfkusexdkv" , drepXskHex = "a8b5df4daa0506f8c2a83407c96285823d4f3000c38d9e62903fab850c118f451f7dd6304ccbd215e96b09e0c1d13dbf4426872d35f90ccaef7e6692b5198a4d571a0b4d927777b6b1c2e61d361b72ac39b5f0edf498a630665e7f1e9ffd09b7" , drepSk = "drep_sk14z6a7nd2q5r03s4gxsrujc59sg757vqqcwxeuc5s874c2rq33az37lwkxpxvh5s4a94sncxp6y7m73pxsuknt7gvethhue5jk5vc5ngl9zhrx" , drepSkHex = "a8b5df4daa0506f8c2a83407c96285823d4f3000c38d9e62903fab850c118f451f7dd6304ccbd215e96b09e0c1d13dbf4426872d35f90ccaef7e6692b5198a4d" , drepXvk = "drep_xvk14dwjrplj73qeggdsg4lh4j9tp495asyq9t6augwaue8kqvjg5wq4wxstfkf8waakk8pwv8fkrde2cwd47rklfx9xxpn9ulc7nl7sndcvdjh2m" , drepXvkHex = "ab5d2187f2f4419421b0457f7ac8ab0d4b4ec0802af5de21dde64f603248a381571a0b4d927777b6b1c2e61d361b72ac39b5f0edf498a630665e7f1e9ffd09b7" , drepVk = "drep_vk14dwjrplj73qeggdsg4lh4j9tp495asyq9t6augwaue8kqvjg5wqskrq5yn" , drepVkHex = "ab5d2187f2f4419421b0457f7ac8ab0d4b4ec0802af5de21dde64f603248a381" , drep = "drep1ytq6xshsm7uzhy729e45q6avkpyq9a74d2va3726sz5td3gqrgcll" , drepHex = "c1a342f0dfb82b93ca2e6b406bacb04802f7d56a99d8f95a80a8b6c5" , drepScript1 = "drep1ckr4x9293myuyz5379wndh4ag00c787htnzwzxxmpfnfzaqtayp" , drepScript1Hex = "c5875315458ec9c20a91f15d36debd43df8f1fd75cc4e118db0a6691" , drepScript2 = "drep1wgly5zd539aam7yxr7trxy48dhupswmwusutm4q40dwkc07n3y8" , drepScript2Hex = "723e4a09b4897bddf8861f963312a76df8183b6ee438bdd4157b5d6c" , ccColdXsk = "cc_cold_xsk1hqe5kcsq59mx4t9nxrctmth0ppz9gda0gnppyll3h9rxcyq33az4uy3u6qhzuhjsstzca9awgsx27j07hxhrkrk6487nvywp0ag669m4v6lj3knq7e6pxaujy98akn5exhgk44ftruepkte0hdm74dd8zceqnk2h" , ccColdXskHex = "b8334b6200a1766aacb330f0bdaeef08445437af44c2127ff1b9466c10118f455e123cd02e2e5e5082c58e97ae440caf49feb9ae3b0edaa9fd3611c17f51ad177566bf28da60f674137792214fdb4e9935d16ad52b1f321b2f2fbb77eab5a716" , ccColdSk = "cc_cold_sk1hqe5kcsq59mx4t9nxrctmth0ppz9gda0gnppyll3h9rxcyq33az4uy3u6qhzuhjsstzca9awgsx27j07hxhrkrk6487nvywp0ag669c5qtm3p" , ccColdSkHex = "b8334b6200a1766aacb330f0bdaeef08445437af44c2127ff1b9466c10118f455e123cd02e2e5e5082c58e97ae440caf49feb9ae3b0edaa9fd3611c17f51ad17" , ccColdXvk = "cc_cold_xvk1lmqejccjpxsd9cl4uavxj0jryjlfk5r8wemr0d8saal49lttp2482e4l9rdxpan5zdmeyg20md8fjdw3dt2jk8ejrvhjlwmha266w9syf55nr" , ccColdXvkHex = "fec199631209a0d2e3f5e758693e4324be9b5067767637b4f0ef7f52fd6b0aaa7566bf28da60f674137792214fdb4e9935d16ad52b1f321b2f2fbb77eab5a716" , ccColdVk = "cc_cold_vk1lmqejccjpxsd9cl4uavxj0jryjlfk5r8wemr0d8saal49lttp24q6lw08l" , ccColdVkHex = "fec199631209a0d2e3f5e758693e4324be9b5067767637b4f0ef7f52fd6b0aaa" , ccCold = "cc_cold1zfxtx2h8qhanhw3u4jt5ydtgsry39gm2ff7v5ax5j4k87sgmkas3l" , ccColdHex = "4cb32ae705fb3bba3cac9742356880c912a36a4a7cca74d4956c7f41" , ccColdScript1 = "cc_cold1qlk7rgkd5n6ga8enwk08vwtmlklhzfnmjtjlzlwed62tulgk75f" , ccColdScript1Hex = "07ede1a2cda4f48e9f33759e76397bfdbf71267b92e5f17dd96e94be" , ccColdScript2 = "cc_cold1a4qmd5d3dqppxtq5wcuuaa3xfe868vyn46afvktz5ucxzauy6tg" , ccColdScript2Hex = "ed41b6d1b16802132c147639cef6264e4fa3b093aeba965962a73061" , ccHotXsk = "cc_hot_xsk14rzh5lvtdhvum6vjfvkwp73mz9gl426cj04xfavnjgmdxrq33azugz0k9sekf2eg70lr34rg5aclr54v30za77xn945kncdm0le6lutxlr5ar355u5awqt2hkmdurv4qv64cmpg39zq2ahjxqken8vk62qunx4hl" , ccHotXskHex = "a8c57a7d8b6dd9cde9924b2ce0fa3b1151faab5893ea64f5939236d30c118f45c409f62c3364ab28f3fe38d468a771f1d2ac8bc5df78d32d6969e1bb7ff3aff166f8e9d1c694e53ae02d57b6dbc1b2a066ab8d85112880aede4605b333b2da50" , ccHotSk = "cc_hot_sk14rzh5lvtdhvum6vjfvkwp73mz9gl426cj04xfavnjgmdxrq33azugz0k9sekf2eg70lr34rg5aclr54v30za77xn945kncdm0le6lugud8v57" , ccHotSkHex = "a8c57a7d8b6dd9cde9924b2ce0fa3b1151faab5893ea64f5939236d30c118f45c409f62c3364ab28f3fe38d468a771f1d2ac8bc5df78d32d6969e1bb7ff3aff1" , ccHotXvk = "cc_hot_xvk1g2925ntunmthw66sr8t7v3qe7fls4575wput3936cguzk7m6w4fkd78f68rffef6uqk40dkmcxe2qe4t3kz3z2yq4m0yvpdnxwed55q798msd" , ccHotXvkHex = "428aaa4d7c9ed7776b5019d7e64419f27f0ad3d47078b8963ac2382b7b7a755366f8e9d1c694e53ae02d57b6dbc1b2a066ab8d85112880aede4605b333b2da50" , ccHotVk = "cc_hot_vk1g2925ntunmthw66sr8t7v3qe7fls4575wput3936cguzk7m6w4fs0zjxf8" , ccHotVkHex = "428aaa4d7c9ed7776b5019d7e64419f27f0ad3d47078b8963ac2382b7b7a7553" , ccHot = "cc_hot1q257k3xs4gww24vm0s3zwzkz850xr0ewz9xa3edyfmf622g5zjp8w" , ccHotHex = "a9eb44d0aa1ce5559b7c22270ac23d1e61bf2e114dd8e5a44ed3a529" , ccHotScript1 = "cc_hot1n42mr24e22eyspa7m0y6lq5rk8tesq35xt6gfgkezcxluez2snm" , ccHotScript1Hex = "9d55b1aab952b24807bedbc9af8283b1d798023432f484a2d9160dfe" , ccHotScript2 = "cc_hot1gfqmx4g0czk2nz2m2rfawg4me283jl7wz4wfssup03av2aynvs9" , ccHotScript2Hex = "4241b3550fc0aca9895b50d3d722bbca8f197fce155c9843817c7ac5" } } describe "Test vectors" $ do testVectors [ "test", "child", "burst", "immense", "armed", "parrot" , "company", "walk", "dog" ] testVectors [ "test", "walk", "nut", "penalty", "hip", "pave", "soap", "entry", "language", "right", "filter", "choice" ] testVectors [ "art", "forum", "devote", "street", "sure", "rather", "head", "chuckle", "guard", "poverty", "release", "quote", "oak", "craft", "enemy"] testVectors [ "churn", "shaft", "spoon", "second", "erode", "useless", "thrive", "burst", "group", "seed", "element", "sign", "scrub", "buffalo", "jelly", "grace", "neck", "useless" ] testVectors [ "draft", "ability", "female", "child", "jump", "maid", "roof", "hurt", "below", "live", "topple", "paper", "exclude", "ordinary", "coach", "churn", "sunset", "emerge", "blame", "ketchup", "much" ] testVectors [ "excess", "behave", "track", "soul", "table", "wear", "ocean", "cash", "stay", "nature", "item", "turtle", "palm", "soccer", "lunch", "horror", "start", "stumble", "month", "panic", "right", "must", "lock", "dress" ] {------------------------------------------------------------------------------- Properties -------------------------------------------------------------------------------} prop_publicChildKeyDerivation :: (SomeMnemonic, SndFactor) -> Role -> Index 'Soft 'PaymentK -> Property prop_publicChildKeyDerivation (mw, (SndFactor sndFactor)) cc ix = addrXPub1 === addrXPub2 where rootXPrv = genMasterKeyFromMnemonic mw sndFactor :: Shelley 'RootK XPrv accXPrv = deriveAccountPrivateKey rootXPrv minBound addrXPub1 = toXPub <$> deriveAddressPrivateKey accXPrv cc ix addrXPub2 = deriveAddressPublicKey (toXPub <$> accXPrv) cc ix prop_accountKeyDerivation :: (SomeMnemonic, SndFactor) -> Index 'Hardened 'AccountK -> Property prop_accountKeyDerivation (mw, (SndFactor sndFactor)) ix = accXPrv `seq` property () where rootXPrv = genMasterKeyFromMnemonic mw sndFactor :: Shelley 'RootK XPrv accXPrv = deriveAccountPrivateKey rootXPrv ix prop_fromWord32Role :: Int -> Property prop_fromWord32Role n = isNothing (toRole n) === (n > fromRole maxBound || n < fromRole minBound) where fromRole = fromIntegral . indexToWord32 . roleToIndex toRole = roleFromIndex . unsafeMkIndex . fromIntegral prop_roundtripIndexRole :: Role -> Property prop_roundtripIndexRole ix = (roleFromIndex . roleToIndex) ix === Just ix prop_pointerAddressConstruction :: (SomeMnemonic, SndFactor) -> Role -> Index 'Soft 'PaymentK -> NetworkDiscriminant Shelley -> ChainPointer -> Property prop_pointerAddressConstruction (mw, (SndFactor sndFactor)) cc ix net ptr = pointerAddr `seq` property () where rootXPrv = genMasterKeyFromMnemonic mw sndFactor :: Shelley 'RootK XPrv accXPrv = deriveAccountPrivateKey rootXPrv minBound addrXPub = toXPub <$> deriveAddressPrivateKey accXPrv cc ix pointerAddr = pointerAddress net (PaymentFromExtendedKey addrXPub) ptr {------------------------------------------------------------------------------- Golden tests -------------------------------------------------------------------------------} -- | Definitions: Let's assume we have private key < xprv | pub | cc > -- Then, extended private key should be understood as < xprv | | cc > -- extended public key should be understood as < | pub | cc > -- verification public key should be understood as < | pub | > data GoldenTestPointerAddress = GoldenTestPointerAddress { -- | The verification public key as string to be encoded into base16 form -- After that it should have 32-byte length verKey :: Text -- | Location of stake cerificate in the blockchain , stakePtr :: ChainPointer -- | Network tag , netTag :: Integer -- | Expected address as encoded into base16 form , expectedAddr :: Text } goldenTestPointerAddress :: GoldenTestPointerAddress -> SpecWith () goldenTestPointerAddress GoldenTestPointerAddress{..} = it ("pointer address for networkId " <> show netTag) $ do let (Just xPub) = xpubFromBytes $ b16encode $ T.append verKey verKey let addrXPub = liftXPub xPub :: Shelley 'PaymentK XPub let (Right tag) = mkNetworkDiscriminant netTag let ptrAddr = pointerAddress tag (PaymentFromExtendedKey addrXPub) stakePtr let (Right bytes) = b16decode expectedAddr ptrAddr `shouldBe` unsafeMkAddress bytes data GoldenTestEnterpriseAddress = GoldenTestEnterpriseAddress { -- | The verification public key as string to be encoded into base16 form -- After that it should have 32-byte length verKey :: Text -- | Network tag , netTag :: Integer -- | Expected address as encoded into base16 form , expectedAddr :: Text } goldenTestEnterpriseAddress :: GoldenTestEnterpriseAddress -> SpecWith () goldenTestEnterpriseAddress GoldenTestEnterpriseAddress{..} = it ("enterprise address for networkId " <> show netTag) $ do let (Just xPub) = xpubFromBytes $ b16encode $ T.append verKey verKey let addrXPub = liftXPub xPub :: Shelley 'PaymentK XPub let (Right tag) = mkNetworkDiscriminant netTag let enterpriseAddr = Shelley.paymentAddress tag (PaymentFromExtendedKey addrXPub) let (Right bytes) = b16decode expectedAddr enterpriseAddr `shouldBe` unsafeMkAddress bytes goldenTestEnterpriseAddressKeyHash :: GoldenTestEnterpriseAddress -> SpecWith () goldenTestEnterpriseAddressKeyHash GoldenTestEnterpriseAddress{..} = it ("enterprise address for networkId " <> show netTag) $ do let bs = b16encode $ T.append verKey verKey let (Just xPub) = xpubFromBytes bs let addrXPub = liftXPub xPub :: Shelley 'PaymentK XPub let (Right tag) = mkNetworkDiscriminant netTag let enterpriseAddrFromKey = Shelley.paymentAddress tag (PaymentFromExtendedKey addrXPub) let keyHashDigest = hashCredential $ BS.take 32 bs let keyHash = KeyHash Payment keyHashDigest let enterpriseAddrFromKeyHash = Shelley.paymentAddress tag (PaymentFromKeyHash keyHash) enterpriseAddrFromKey `shouldBe` enterpriseAddrFromKeyHash data GoldenTestBaseAddress = GoldenTestBaseAddress { -- | The verification public key as string to be encoded into base16 form -- After that it should have 32-byte length verKeyPayment :: Text -- | The verification public key as string to be encoded into base16 form -- After that it should have 32-byte length , verKeyStake :: Text -- | Network tag , netTag :: Integer -- | Expected address as encoded into base16 form , expectedAddr :: Text } goldenTestBaseAddressPayFromXPub :: GoldenTestBaseAddress -> SpecWith () goldenTestBaseAddressPayFromXPub GoldenTestBaseAddress{..} = it ("base address for networkId " <> show netTag) $ do let (Just xPub1) = xpubFromBytes $ b16encode $ T.append verKeyPayment verKeyPayment let addrXPub = liftXPub xPub1 :: Shelley 'PaymentK XPub let (Just xPub2) = xpubFromBytes $ b16encode $ T.append verKeyStake verKeyStake let stakeXPub = liftXPub xPub2 :: Shelley 'DelegationK XPub let (Right tag) = mkNetworkDiscriminant netTag let baseAddr = delegationAddress tag (PaymentFromExtendedKey addrXPub) (DelegationFromExtendedKey stakeXPub) let (Right bytes) = b16decode expectedAddr baseAddr `shouldBe` unsafeMkAddress bytes goldenTestBaseAddressPayFromPub :: GoldenTestBaseAddress -> SpecWith () goldenTestBaseAddressPayFromPub GoldenTestBaseAddress{..} = it ("base address for networkId " <> show netTag) $ do let (Just pub1) = pubFromBytes $ b16encode verKeyPayment let addrPub = liftPub pub1 :: Shelley 'PaymentK Pub let (Just xPub2) = xpubFromBytes $ b16encode $ T.append verKeyStake verKeyStake let stakeXPub = liftXPub xPub2 :: Shelley 'DelegationK XPub let (Right tag) = mkNetworkDiscriminant netTag let baseAddr = delegationAddress tag (PaymentFromKey addrPub) (DelegationFromExtendedKey stakeXPub) let (Right bytes) = b16decode expectedAddr baseAddr `shouldBe` unsafeMkAddress bytes goldenTestBaseAddressPayFromKeyHash :: GoldenTestBaseAddress -> SpecWith () goldenTestBaseAddressPayFromKeyHash GoldenTestBaseAddress{..} = it ("base address for networkId " <> show netTag) $ do let paymentBs = b16encode $ T.append verKeyPayment verKeyPayment let (Just xPub1) = xpubFromBytes paymentBs let addrXPub = liftXPub xPub1 :: Shelley 'PaymentK XPub let (Just xPub2) = xpubFromBytes $ b16encode $ T.append verKeyStake verKeyStake let stakeXPub = liftXPub xPub2 :: Shelley 'DelegationK XPub let (Right tag) = mkNetworkDiscriminant netTag let baseAddrPayFromKey = delegationAddress tag (PaymentFromExtendedKey addrXPub) (DelegationFromExtendedKey stakeXPub) let keyHashDigest = hashCredential $ BS.take 32 paymentBs let keyHash = KeyHash Payment keyHashDigest let baseAddrPayFromKeyHash = delegationAddress tag (PaymentFromKeyHash keyHash) (DelegationFromExtendedKey stakeXPub) baseAddrPayFromKey `shouldBe` baseAddrPayFromKeyHash goldenTestBaseAddressStakeFromKeyHash :: GoldenTestBaseAddress -> SpecWith () goldenTestBaseAddressStakeFromKeyHash GoldenTestBaseAddress{..} = it ("base address for networkId " <> show netTag) $ do let paymentBs = b16encode $ T.append verKeyPayment verKeyPayment let (Just xPub1) = xpubFromBytes paymentBs let addrXPub = liftXPub xPub1 :: Shelley 'PaymentK XPub let stakeBs = b16encode $ T.append verKeyStake verKeyStake let (Just xPub2) = xpubFromBytes stakeBs let stakeXPub = liftXPub xPub2 :: Shelley 'DelegationK XPub let (Right tag) = mkNetworkDiscriminant netTag let baseAddrStakeFromKey = delegationAddress tag (PaymentFromExtendedKey addrXPub) (DelegationFromExtendedKey stakeXPub) let keyHashDigest = hashCredential $ BS.take 32 stakeBs let keyHash = KeyHash Delegation keyHashDigest let baseAddrStakeFromKeyHash = delegationAddress tag (PaymentFromExtendedKey addrXPub) (DelegationFromKeyHash keyHash) baseAddrStakeFromKey `shouldBe` baseAddrStakeFromKeyHash goldenTestBaseAddressStakeFromPub :: GoldenTestBaseAddress -> SpecWith () goldenTestBaseAddressStakeFromPub GoldenTestBaseAddress{..} = it ("base address for networkId " <> show netTag) $ do let paymentBs = b16encode $ T.append verKeyPayment verKeyPayment let (Just xPub1) = xpubFromBytes paymentBs let addrXPub = liftXPub xPub1 :: Shelley 'PaymentK XPub let stakeBs = b16encode $ T.append verKeyStake verKeyStake let (Just xPub2) = xpubFromBytes stakeBs let stakeXPub = liftXPub xPub2 :: Shelley 'DelegationK XPub let (Right tag) = mkNetworkDiscriminant netTag let baseAddrStakeFromExtendedKey = delegationAddress tag (PaymentFromExtendedKey addrXPub) (DelegationFromExtendedKey stakeXPub) let stakeBs1 = b16encode verKeyStake let (Just pub2) = pubFromBytes stakeBs1 let stakePub = liftPub pub2 :: Shelley 'DelegationK Pub let baseAddrStakeFromKey = delegationAddress tag (PaymentFromExtendedKey addrXPub) (DelegationFromKey stakePub) baseAddrStakeFromExtendedKey `shouldBe` baseAddrStakeFromKey goldenTestBaseAddressBothFromKeyHash :: GoldenTestBaseAddress -> SpecWith () goldenTestBaseAddressBothFromKeyHash GoldenTestBaseAddress{..} = it ("base address for networkId " <> show netTag) $ do let paymentBs = b16encode $ T.append verKeyPayment verKeyPayment let (Just xPub1) = xpubFromBytes paymentBs let addrXPub = liftXPub xPub1 :: Shelley 'PaymentK XPub let stakeBs = b16encode $ T.append verKeyStake verKeyStake let (Just xPub2) = xpubFromBytes stakeBs let stakeXPub = liftXPub xPub2 :: Shelley 'DelegationK XPub let (Right tag) = mkNetworkDiscriminant netTag let baseAddrBothFromKey = delegationAddress tag (PaymentFromExtendedKey addrXPub) (DelegationFromExtendedKey stakeXPub) let paymentKeyHashDigest = hashCredential $ BS.take 32 paymentBs let paymentKeyHash = KeyHash Payment paymentKeyHashDigest let stakeKeyHashDigest = hashCredential $ BS.take 32 stakeBs let stakeKeyHash = KeyHash Delegation stakeKeyHashDigest let baseAddrBothFromKeyHash = delegationAddress tag (PaymentFromKeyHash paymentKeyHash) (DelegationFromKeyHash stakeKeyHash) baseAddrBothFromKey `shouldBe` baseAddrBothFromKeyHash goldenTestBaseAddressBothFromPub :: GoldenTestBaseAddress -> SpecWith () goldenTestBaseAddressBothFromPub GoldenTestBaseAddress{..} = it ("base address for networkId " <> show netTag) $ do let paymentBs = b16encode $ T.append verKeyPayment verKeyPayment let (Just xPub1) = xpubFromBytes paymentBs let addrXPub = liftXPub xPub1 :: Shelley 'PaymentK XPub let stakeBs = b16encode $ T.append verKeyStake verKeyStake let (Just xPub2) = xpubFromBytes stakeBs let stakeXPub = liftXPub xPub2 :: Shelley 'DelegationK XPub let (Right tag) = mkNetworkDiscriminant netTag let baseAddrBothFromKey = delegationAddress tag (PaymentFromExtendedKey addrXPub) (DelegationFromExtendedKey stakeXPub) let paymentBs1 = b16encode verKeyPayment let (Just pub1) = pubFromBytes paymentBs1 let addrPub = liftPub pub1 :: Shelley 'PaymentK Pub let stakeBs1 = b16encode verKeyStake let (Just pub2) = pubFromBytes stakeBs1 let stakePub = liftPub pub2 :: Shelley 'DelegationK Pub let baseAddrBothFromPub = delegationAddress tag (PaymentFromKey addrPub) (DelegationFromKey stakePub) baseAddrBothFromKey `shouldBe` baseAddrBothFromPub data KeysHashes = KeysHashes { -- | CIP-1852’s DRep extended signing key (Ed25519-bip32 extended private key), bech32 encoded prefixed with 'drep_xsk' drepXsk :: Text -- | CIP-1852’s DRep extended signing key (Ed25519-bip32 extended private key), base16 encoded , drepXskHex :: Text -- | CIP-1852’s DRep signing key (Ed25519-bip32 non-extended private key), bech32 encoded prefixed with 'drep_sk' , drepSk :: Text -- | CIP-1852’s DRep signing key (Ed25519-bip32 non-extended private key), base16 encoded , drepSkHex :: Text -- | CIP-1852’s DRep extended verification key (Ed25519 public key with chain code), bech32 encoded prefixed with 'drep_xvk' , drepXvk :: Text -- | CIP-1852’s DRep extended verification key (Ed25519 public key with chain code), base16 encoded , drepXvkHex :: Text -- | CIP-1852’s DRep verification key (Ed25519 public key), bech32 encoded prefixed with 'drep_vk' , drepVk :: Text -- | CIP-1852’s DRep verification key (Ed25519 public key), base16 encoded , drepVkHex :: Text -- | Delegate representative verification key hash (DRep ID) (blake2b_224 digest of a delegate representative verification key), bech32 encoded prefixed with 'drep' , drep :: Text -- | Delegate representative verification key hash (DRep ID) (blake2b_224 digest of a delegate representative verification key), base16 encoded , drepHex :: Text -- | Delegate representative script hash (DRep ID) (blake2b_224 digest of a serialized delegate representative script prepended with 00100011 byte), bech32 encoded prefixed with 'drep' -- script: all [drep, active_from 5001] , drepScript1 :: Text -- | Delegate representative script hash (DRep ID) (blake2b_224 digest of a serialized delegate representative script), base16 encoded -- script: all [drep, active_from 5001] , drepScript1Hex :: Text -- | Delegate representative script hash (DRep ID) (blake2b_224 digest of a serialized delegate representative script prepended with 00100011 byte), bech32 encoded prefixed with 'drep' -- script: any [drep, all [active_from 5001, active_until 6001]] , drepScript2 :: Text -- | Delegate representative script hash (DRep ID) (blake2b_224 digest of a serialized delegate representative script), base16 encoded -- script: any [drep, all [active_from 5001, active_until 6001]] , drepScript2Hex :: Text -- | CIP-1852’s constitutional committee cold extended signing key (Ed25519-bip32 extended private key), bech32 encoded prefixed with 'cc_cold_xsk' , ccColdXsk :: Text -- | CIP-1852’s constitutional committee cold extended signing key (Ed25519-bip32 extended private key), base16 encoded , ccColdXskHex :: Text -- | CIP-1852’s constitutional committee cold signing key (Ed25519-bip32 non-extended private key), bech32 encoded prefixed with 'cc_cold_sk' , ccColdSk :: Text -- | CIP-1852’s constitutional committee cold signing key (Ed25519-bip32 non-extended private key), base16 encoded , ccColdSkHex :: Text -- | CIP-1852’s constitutional committee extended cold verification signing key (Ed25519 public key with chain code), bech32 encoded prefixed with 'cc_cold_xvk' , ccColdXvk :: Text -- | CIP-1852’s constitutional committee extended cold verification signing key (Ed25519 public key with chain code), base16 encoded , ccColdXvkHex :: Text -- | CIP-1852’s constitutional committee cold verification signing key (Ed25519 private key), bech32 encoded prefixed with 'cc_cold_vk' , ccColdVk :: Text -- | CIP-1852’s constitutional committee cold verification signing key (Ed25519 private key), base16 encoded , ccColdVkHex :: Text -- | Constitutional committee cold verification key hash (cold credential) (blake2b_224 digest of a consitutional committee cold verification key), bech32 encoded prefixed with 'cc_cold' , ccCold :: Text -- | Constitutional committee cold verification key hash (cold credential) (blake2b_224 digest of a consitutional committee cold verification key), base16 encoded , ccColdHex :: Text -- | Constitutional committee cold script hash (cold credential) (blake2b_224 digest of a serialized constitutional committee cold script prepended with 00010011 byte), bech32 encoded prefixed with 'cc_cold' -- script: all [ccCold, active_from 5001] , ccColdScript1 :: Text -- | Constitutional committee cold script hash (cold credential) (blake2b_224 digest of a serialized constitutional committee cold script), base16 encoded -- script: all [ccCold, active_from 5001] , ccColdScript1Hex :: Text -- | Constitutional committee cold script hash (cold credential) (blake2b_224 digest of a serialized constitutional committee cold script prepended with 00010011 byte), bech32 encoded prefixed with 'cc_cold' -- script: any [ccCold, all [active_from 5001, active_until 6001]] , ccColdScript2 :: Text -- | Constitutional committee cold script hash (cold credential) (blake2b_224 digest of a serialized constitutional committee cold script), base16 encoded -- script: any [ccCold, all [active_from 5001, active_until 6001]] , ccColdScript2Hex :: Text -- | CIP-1852’s constitutional committee hot extended signing key (Ed25519-bip32 extended private key), bech32 encoded prefixed with 'cc_hot_xsk' , ccHotXsk :: Text -- | CIP-1852’s constitutional committee hot extended signing key (Ed25519-bip32 extended private key), base16 encoded , ccHotXskHex :: Text -- | CIP-1852’s constitutional committee hot signing key (Ed25519-bip32 non-extended private key), bech32 encoded prefixed with 'cc_hot_sk' , ccHotSk :: Text -- | CIP-1852’s constitutional committee hot signing key (Ed25519-bip32 non-extended private key), base16 encoded , ccHotSkHex :: Text -- | CIP-1852’s constitutional committee extended hot verification signing key (Ed25519 public key with chain code), bech32 encoded prefixed with 'cc_hot_xvk' , ccHotXvk :: Text -- | CIP-1852’s constitutional committee extended hot verification signing key (Ed25519 public key with chain code), base16 encoded , ccHotXvkHex :: Text -- | CIP-1852’s constitutional committee hot verification signing key (Ed25519 private key), bech32 encoded prefixed with 'cc_hot_vk' , ccHotVk :: Text -- | CIP-1852’s constitutional committee hot verification signing key (Ed25519 private key), base16 encoded , ccHotVkHex :: Text -- | Constitutional committee hot verification key hash (hot credential) (blake2b_224 digest of a consitutional committee hot verification key), bech32 encoded prefixed with 'cc_hot' , ccHot :: Text -- | Constitutional committee hot verification key hash (hot credential) (blake2b_224 digest of a consitutional committee hot verification key), base16 encoded , ccHotHex :: Text -- | Constitutional committee hot script hash (hot credential) (blake2b_224 digest of a serialized constitutional committee hot script prepended with 00000011 byte), bech32 encoded prefixed with 'cc_hot' -- script: all [ccHot, active_from 5001] , ccHotScript1 :: Text -- | Constitutional committee hot script hash (hot credential) (blake2b_224 digest of a serialized constitutional committee hot script), base16 encoded -- script: all [ccHot, active_from 5001] , ccHotScript1Hex :: Text -- | Constitutional committee hot script hash (hot credential) (blake2b_224 digest of a serialized constitutional committee hot script prepended with 00000011 byte), bech32 encoded prefixed with 'cc_hot' -- script: any [ccHot, all [active_from 5001, active_until 6001]] , ccHotScript2 :: Text -- | Constitutional committee hot script hash (hot credential) (blake2b_224 digest of a serialized constitutional committee hot script), base16 encoded -- script: any [ccHot, all [active_from 5001, active_until 6001]] , ccHotScript2Hex :: Text } deriving (Eq, Show) data GoldenTestGovernance = GoldenTestGovernance { -- | Mnemonic mnemonic :: [Text] -- | Account ix , accountIx :: Word32 -- | Expected Keys and Hashes , expectedKeysHashes :: KeysHashes } goldenTestGovernance :: GoldenTestGovernance -> SpecWith () goldenTestGovernance GoldenTestGovernance{..} = it ("governance keys/hashes for " <> show mnemonic <> " and accIx="<>show accountIx) $ do let (Right mw) = mkSomeMnemonic @'[9,12,15,18,21,24] mnemonic let sndFactor = mempty let rootXPrv = genMasterKeyFromMnemonic mw sndFactor :: Shelley 'RootK XPrv let Just accIx = indexFromWord32 @(Index 'Hardened _) accountIx let acctXPrv = deriveAccountPrivateKey rootXPrv accIx let drepXPrv = deriveDRepPrivateKey acctXPrv let drepXPrvTxt = bech32With CIP5.drep_xsk $ getExtendedKeyAddr drepXPrv let drepXPrvTxtHex = tob16text . unAddress $ getExtendedKeyAddr drepXPrv let drepPrvTxt = bech32With CIP5.drep_sk $ getPrivateKeyAddr drepXPrv let drepPrvTxtHex = T.decodeUtf8 $ encode EBase16 $ unAddress $ getPrivateKeyAddr drepXPrv let drepXPubTxt = bech32With CIP5.drep_xvk $ getPublicKeyAddr $ toXPub <$> drepXPrv let drepXPubTxtHex = tob16text . unAddress $ getPublicKeyAddr $ toXPub <$> drepXPrv let drepPubTxt = bech32With CIP5.drep_vk $ getVerKey $ toXPub <$> drepXPrv let drepPubTxtHex = tob16text . unAddress $ getVerKey $ toXPub <$> drepXPrv let drepKeyHash = toKeyHash Representative $ toXPub <$> drepXPrv let drepTxt = keyHashToText drepKeyHash CIP0129 let drepTxtHex = tob16text . digest $ drepKeyHash let drepScriptHash1 = toScriptHash (script1 drepKeyHash) let drepScript1Txt = toScriptTxt drepScriptHash1 CIP5.drep let drepScript1TxtHex = tob16text . unScriptHash $ drepScriptHash1 let drepScriptHash2 = toScriptHash (script2 drepKeyHash) let drepScript2Txt = toScriptTxt drepScriptHash2 CIP5.drep let drepScript2TxtHex = tob16text . unScriptHash $ drepScriptHash2 let coldXPrv = deriveCCColdPrivateKey acctXPrv let coldXPrvTxt = bech32With CIP5.cc_cold_xsk $ getExtendedKeyAddr coldXPrv let coldXPrvTxtHex = tob16text . unAddress $ getExtendedKeyAddr coldXPrv let coldPrvTxt = bech32With CIP5.cc_cold_sk $ getPrivateKeyAddr coldXPrv let coldPrvTxtHex = T.decodeUtf8 $ encode EBase16 $ unAddress $ getPrivateKeyAddr coldXPrv let coldXPubTxt = bech32With CIP5.cc_cold_xvk $ getPublicKeyAddr $ toXPub <$> coldXPrv let coldXPubTxtHex = tob16text . unAddress $ getPublicKeyAddr $ toXPub <$> coldXPrv let coldPubTxt = bech32With CIP5.cc_cold_vk $ getVerKey $ toXPub <$> coldXPrv let coldPubTxtHex = tob16text . unAddress $ getVerKey $ toXPub <$> coldXPrv let coldKeyHash = toKeyHash CommitteeCold $ toXPub <$> coldXPrv let coldTxt = keyHashToText coldKeyHash CIP0129 let coldTxtHex = tob16text . digest $ coldKeyHash let coldScriptHash1 = toScriptHash (script1 coldKeyHash) let coldScript1Txt = toScriptTxt coldScriptHash1 CIP5.cc_cold let coldScript1TxtHex = tob16text . unScriptHash $ coldScriptHash1 let coldScriptHash2 = toScriptHash (script2 coldKeyHash) let coldScript2Txt = toScriptTxt coldScriptHash2 CIP5.cc_cold let coldScript2TxtHex = tob16text . unScriptHash $ coldScriptHash2 let hotXPrv = deriveCCHotPrivateKey acctXPrv let hotXPrvTxt = bech32With CIP5.cc_hot_xsk $ getExtendedKeyAddr hotXPrv let hotXPrvTxtHex = tob16text . unAddress $ getExtendedKeyAddr hotXPrv let hotPrvTxt = bech32With CIP5.cc_hot_sk $ getPrivateKeyAddr hotXPrv let hotPrvTxtHex = T.decodeUtf8 $ encode EBase16 $ unAddress $ getPrivateKeyAddr hotXPrv let hotXPubTxt = bech32With CIP5.cc_hot_xvk $ getPublicKeyAddr $ toXPub <$> hotXPrv let hotXPubTxtHex = tob16text . unAddress $ getPublicKeyAddr $ toXPub <$> hotXPrv let hotPubTxt = bech32With CIP5.cc_hot_vk $ getVerKey $ toXPub <$> hotXPrv let hotPubTxtHex = tob16text . unAddress $ getVerKey $ toXPub <$> hotXPrv let hotKeyHash = toKeyHash CommitteeHot $ toXPub <$> hotXPrv let hotTxt = keyHashToText hotKeyHash CIP0129 let hotTxtHex = tob16text . digest $ hotKeyHash let hotScriptHash1 = toScriptHash (script1 hotKeyHash) let hotScript1Txt = toScriptTxt hotScriptHash1 CIP5.cc_hot let hotScript1TxtHex = tob16text . unScriptHash $ hotScriptHash1 let hotScriptHash2 = toScriptHash (script2 hotKeyHash) let hotScript2Txt = toScriptTxt hotScriptHash2 CIP5.cc_hot let hotScript2TxtHex = tob16text . unScriptHash $ hotScriptHash2 let derivedKeysHashes = KeysHashes { drepXsk = drepXPrvTxt , drepXskHex = drepXPrvTxtHex , drepSk = drepPrvTxt , drepSkHex = drepPrvTxtHex , drepXvk = drepXPubTxt , drepXvkHex = drepXPubTxtHex , drepVk = drepPubTxt , drepVkHex = drepPubTxtHex , drep = drepTxt , drepHex = drepTxtHex , drepScript1 = drepScript1Txt , drepScript1Hex = drepScript1TxtHex , drepScript2 = drepScript2Txt , drepScript2Hex = drepScript2TxtHex , ccColdXsk = coldXPrvTxt , ccColdXskHex = coldXPrvTxtHex , ccColdSk = coldPrvTxt , ccColdSkHex = coldPrvTxtHex , ccColdXvk = coldXPubTxt , ccColdXvkHex = coldXPubTxtHex , ccColdVk = coldPubTxt , ccColdVkHex = coldPubTxtHex , ccCold = coldTxt , ccColdHex = coldTxtHex , ccColdScript1 = coldScript1Txt , ccColdScript1Hex = coldScript1TxtHex , ccColdScript2 = coldScript2Txt , ccColdScript2Hex = coldScript2TxtHex , ccHotXsk = hotXPrvTxt , ccHotXskHex = hotXPrvTxtHex , ccHotSk = hotPrvTxt , ccHotSkHex = hotPrvTxtHex , ccHotXvk = hotXPubTxt , ccHotXvkHex = hotXPubTxtHex , ccHotVk = hotPubTxt , ccHotVkHex = hotPubTxtHex , ccHot = hotTxt , ccHotHex = hotTxtHex , ccHotScript1 = hotScript1Txt , ccHotScript1Hex = hotScript1TxtHex , ccHotScript2 = hotScript2Txt , ccHotScript2Hex = hotScript2TxtHex } derivedKeysHashes `shouldBe` expectedKeysHashes where getVerKey = unsafeMkAddress . pubToBytes . xpubToPub . getKey toKeyHash role = KeyHash role . hashCredential . pubToBytes . xpubToPub . getKey script1 keyhash = RequireAllOf [RequireSignatureOf keyhash, ActiveFromSlot 5001] script2 keyhash = RequireAnyOf [ RequireSignatureOf keyhash , RequireAllOf [ ActiveFromSlot 5001, ActiveUntilSlot 6001] ] toScriptTxt (ScriptHash bytes) hrp = bech32With hrp $ unsafeMkAddress bytes data TestVector = TestVector { -- | The extended root private key, bech32 encoded prefixed with 'root_xsk' rootXPrv :: Text -- | The extended 0th account private key, bech32 encoded prefixed with 'acct_xsk' , accXPrv0 :: Text -- | The extended 1st account private key, bech32 encoded prefixed with 'acct_xsk' , accXPrv1 :: Text -- | The extended 0th address private key, bech32 encoded prefixed with 'addr_xsk' , addrXPrv0 :: Text -- | The extended 0th address public key, bech32 encoded prefixed with 'addr_xvk' , addrXPub0 :: Text -- | The extended 1st address private key, bech32 encoded prefixed with 'addr_xsk' , addrXPrv1 :: Text -- | The extended 1st address public key, bech32 encoded prefixed with 'addr_xvk' , addrXPub1 :: Text -- | The extended 1442nd address private key, bech32 encoded prefixed with 'addr_xsk' , addrXPrv1442 :: Text -- | The extended 1442nd address public key, bech32 encoded prefixed with 'addr_xvk' , addrXPub1442 :: Text -- | The payment address for 0th address key, with a networking tag 0, 3 and 6, respectively. -- Each bech32 encoded prefixed with 'addr' , paymentAddr0 :: [Text] -- | The payment address for 1st address key, with a networking tag 0, 3 and 6, respectively. -- Each bech32 encoded prefixed with 'addr' , paymentAddr1 :: [Text] -- | The payment address for 1442nd address key, with a networking tag 0, 3 and 6, respectively. -- Each bech32 encoded prefixed with 'addr' , paymentAddr1442 :: [Text] -- | Delegation addresses for the 0th address key and the 0th account delegation key, -- with a networking tag 0, 3 and 6, respectively. Each bech32 encoded prefixed with 'addr' , delegationAddr0Stake0 :: [Text] -- | Delegation addresses for the 1st address key and the 0th account delegation key, -- with a networking tag 0, 3 and 6, respectively. Each bech32 encoded prefixed with 'addr' , delegationAddr1Stake0 :: [Text] -- | Delegation addresses for the 1442nd address key and the 0th account delegation key, -- with a networking tag 0, 3 and 6, respectively. Each bech32 encoded prefixed with 'addr' , delegationAddr1442Stake0 :: [Text] -- | Delegation addresses for the 0th address key and the 1st account delegation key, -- with a networking tag 0, 3 and 6, respectively. Each bech32 encoded prefixed with 'addr' , delegationAddr0Stake1 :: [Text] -- | Delegation addresses for the 1st address key and the 1st account delegation key, -- with a networking tag 0, 3 and 6, respectively. Each bech32 encoded prefixed with 'addr' , delegationAddr1Stake1 :: [Text] -- | Delegation addresses for the 1442nd address key and the 1st account delegation key, -- with a networking tag 0, 3 and 6, respectively. Each bech32 encoded prefixed with 'addr' , delegationAddr1442Stake1 :: [Text] -- | Pointer addresses for the 0th address key and the delegation certificate located in slot 1, -- transaction index 2, certificte list index 3, with a networking tag 0, 3 and 6, respectively. -- Each bech32 encoded prefixed with 'addr' , pointerAddr0Slot1 :: [Text] -- | Pointer addresses for the 0th address key and the delegation certificate located in slot 24157, -- transaction index 177, certificte list index 42, with a networking tag 0, 3 and 6, respectively. -- Each bech32 encoded prefixed with 'addr' , pointerAddr0Slot2 :: [Text] -- | Corresponding Mnemonic , mnemonic :: [Text] } deriving Show data InspectVector a = InspectVector { addrXPub0 :: a , addrXPub1 :: a , addrXPub1442 :: a , paymentAddr0 :: [a] , paymentAddr1 :: [a] , paymentAddr1442 :: [a] , delegationAddr0Stake0 :: [a] , delegationAddr1Stake0 :: [a] , delegationAddr1442Stake0 :: [a] , delegationAddr0Stake1 :: [a] , delegationAddr1Stake1 :: [a] , delegationAddr1442Stake1 :: [a] , pointerAddr0Slot1 :: [a] , pointerAddr0Slot2 :: [a] } deriving (Generic, Show, Functor) deriving anyclass ToJSON testVectors :: [Text] -> SpecWith () testVectors mnemonic = describe (show $ T.unpack <$> mnemonic) $ do let (Right mw) = mkSomeMnemonic @'[9,12,15,18,21,24] mnemonic let sndFactor = mempty let rootK = genMasterKeyFromMnemonic mw sndFactor :: Shelley 'RootK XPrv let rootXPrv = bech32With CIP5.root_xsk $ getExtendedKeyAddr rootK let Just accIx0 = indexFromWord32 @(Index 'Hardened _) 0x80000000 let acctK0 = deriveAccountPrivateKey rootK accIx0 let accXPrv0 = bech32With CIP5.acct_xsk $ getExtendedKeyAddr acctK0 let Just accIx1 = indexFromWord32 @(Index 'Hardened _) 0x80000001 let acctK1 = deriveAccountPrivateKey rootK accIx1 let accXPrv1 = bech32With CIP5.acct_xsk $ getExtendedKeyAddr acctK1 let Just addIx0 = indexFromWord32 @(Index 'Soft _) 0x00000000 let addrK0prv = deriveAddressPrivateKey acctK0 UTxOExternal addIx0 let addrXPrv0 = bech32With CIP5.addr_xsk $ getExtendedKeyAddr addrK0prv let addrXPub0 = bech32With CIP5.addr_xvk $ getPublicKeyAddr $ toXPub <$> addrK0prv let Just addIx1 = indexFromWord32 @(Index 'Soft _) 0x00000001 let addrK1prv = deriveAddressPrivateKey acctK0 UTxOExternal addIx1 let addrXPrv1 = bech32With CIP5.addr_xsk $ getExtendedKeyAddr addrK1prv let addrXPub1 = bech32With CIP5.addr_xvk $ getPublicKeyAddr $ toXPub <$> addrK1prv let Just addIx1442 = indexFromWord32 @(Index 'Soft _) 0x000005a2 let addrK1442prv = deriveAddressPrivateKey acctK0 UTxOExternal addIx1442 let addrXPrv1442 = bech32With CIP5.addr_xsk $ getExtendedKeyAddr addrK1442prv let addrXPub1442 = bech32With CIP5.addr_xvk $ getPublicKeyAddr $ toXPub <$> addrK1442prv let networkTags = rights $ mkNetworkDiscriminant <$> [0,3,6] let paymentAddr0 = getPaymentAddr addrK0prv <$> networkTags let paymentAddr1 = getPaymentAddr addrK1prv <$> networkTags let paymentAddr1442 = getPaymentAddr addrK1442prv <$> networkTags let slot1 = ChainPointer 1 2 3 let pointerAddr0Slot1 = getPointerAddr addrK0prv slot1 <$> networkTags let slot2 = ChainPointer 24157 177 42 let pointerAddr0Slot2 = getPointerAddr addrK0prv slot2 <$> networkTags let stakeKPub0 = toXPub <$> deriveDelegationPrivateKey acctK0 let delegationAddr0Stake0 = getDelegationAddr addrK0prv (DelegationFromExtendedKey stakeKPub0) <$> networkTags let delegationAddr1Stake0 = getDelegationAddr addrK1prv (DelegationFromExtendedKey stakeKPub0) <$> networkTags let delegationAddr1442Stake0 = getDelegationAddr addrK1442prv (DelegationFromExtendedKey stakeKPub0) <$> networkTags let stakeKPub1 = toXPub <$> deriveDelegationPrivateKey acctK1 let delegationAddr0Stake1 = getDelegationAddr addrK0prv (DelegationFromExtendedKey stakeKPub1) <$> networkTags let delegationAddr1Stake1 = getDelegationAddr addrK1prv (DelegationFromExtendedKey stakeKPub1) <$> networkTags let delegationAddr1442Stake1 = getDelegationAddr addrK1442prv (DelegationFromExtendedKey stakeKPub1) <$> networkTags let vec = TestVector {..} let inspectVec = InspectVector {..} it "should generate correct addresses" $ do goldenTextLazy ("addresses_" <> shortHex (T.intercalate "_" mnemonic)) (pShowOpt defaultOutputOptionsNoColor vec) it "should inspect correctly" $ do goldenByteStringLazy ("inspects_" <> shortHex (T.intercalate "_" mnemonic)) $ goldenEncodeJSON $ toInspect <$> inspectVec where getPaymentAddr addrKPrv net = bech32 $ paymentAddress net (PaymentFromExtendedKey (toXPub <$> addrKPrv)) getPointerAddr addrKPrv ptr net = bech32 $ pointerAddress net (PaymentFromExtendedKey (toXPub <$> addrKPrv)) ptr getDelegationAddr addrKPrv stakeKPub net = bech32 $ delegationAddress net (PaymentFromExtendedKey (toXPub <$> addrKPrv)) stakeKPub toInspect :: Text -> Value toInspect = fromMaybe (String "couldn't inspect") . (Shelley.inspectAddress Nothing <=< fromBech32) -- | Make a short name for a mnemonic by hashing it and taking the first 8 characters shortHex :: Text -> Text shortHex = T.take 8 . T.decodeUtf8 . BAE.convertToBase BAE.Base16 . hashByteString . T.encodeUtf8 where hashByteString :: ByteString -> ByteString hashByteString = BA.convert . hashWith SHA3_256 getExtendedKeyAddr :: Shelley depth XPrv -> Address getExtendedKeyAddr = unsafeMkAddress . xprvToBytes . getKey getPrivateKeyAddr :: Shelley depth XPrv -> Address getPrivateKeyAddr = unsafeMkAddress . xprvPrivateKey . getKey getPublicKeyAddr :: Shelley depth XPub -> Address getPublicKeyAddr = unsafeMkAddress . xpubToBytes . getKey goldenEncodeJSON :: ToJSON a => a -> BL.ByteString goldenEncodeJSON = Aeson.encodePretty' cfg where cfg = Aeson.defConfig { Aeson.confCompare = compare } prop_roundtripTextEncoding :: (Address -> Text) -- ^ encode to 'Text' -> (Text -> Maybe Address) -- ^ decode from 'Text' -> Shelley 'PaymentK XPub -- ^ An arbitrary public key -> NetworkDiscriminant Shelley -- ^ An arbitrary network discriminant -> Property prop_roundtripTextEncoding encode' decode addXPub discrimination = (result == pure address) & counterexample (unlines [ "Address " <> T.unpack (encode' address) , "↳ " <> maybe "ø" (T.unpack . encode') result ]) & label (show $ addressDiscrimination @Shelley discrimination) where address = paymentAddress discrimination (PaymentFromExtendedKey addXPub) result = decode (encode' address) prop_roundtripTextEncodingDelegation :: (Address -> Text) -- ^ encode to 'Text' -> (Text -> Maybe Address) -- ^ decode from 'Text' -> Shelley 'PaymentK XPub -- ^ An arbitrary address public key -> Shelley 'DelegationK XPub -- ^ An arbitrary delegation public key -> NetworkDiscriminant Shelley -- ^ An arbitrary network discriminant -> Property prop_roundtripTextEncodingDelegation encode' decode addXPub delegXPub discrimination = (result == pure address) & counterexample (unlines [ "Address " <> T.unpack (encode' address) , "↳ " <> maybe "ø" (T.unpack . encode') result ]) & label (show $ addressDiscrimination @Shelley discrimination) where address = delegationAddress discrimination (PaymentFromExtendedKey addXPub) (DelegationFromExtendedKey delegXPub) result = decode (encode' address) prop_roundtripTextEncodingPointer :: (Address -> Text) -- ^ encode to 'Text' -> (Text -> Maybe Address) -- ^ decode from 'Text' -> Shelley 'PaymentK XPub -- ^ An arbitrary address public key -> ChainPointer -- ^ An arbitrary delegation key locator -> NetworkDiscriminant Shelley -- ^ An arbitrary network discriminant -> Property prop_roundtripTextEncodingPointer encode' decode addXPub ptr discrimination = (result == pure address) & counterexample (unlines [ "Address " <> T.unpack (encode' address) , "↳ " <> maybe "ø" (T.unpack . encode') result ]) & label (show $ addressDiscrimination @Shelley discrimination) where address = pointerAddress discrimination (PaymentFromExtendedKey addXPub) ptr result = decode (encode' address) goldenTextLazy :: Text -> TL.Text -> Golden TL.Text goldenTextLazy name output = Golden { output = output , encodePretty = TL.unpack , writeToFile = TL.writeFile , readFromFile = TL.readFile , testName = T.unpack name , directory = "test/golden" , failFirstTime = False } goldenByteStringLazy :: Text -> BL.ByteString -> Golden BL.ByteString goldenByteStringLazy name output = Golden { output = output , encodePretty = TL.unpack . TLE.decodeUtf8 , writeToFile = \ fp -> BL.writeFile fp . normalizeLBS , readFromFile = fmap normalizeLBS . BL.readFile , testName = T.unpack name , directory = "test/golden" , failFirstTime = False } -- This should be sufficent to convert Windows "\r\n" newlines to UNIX "\n" newlines -- as used by both Mac and Linux. normalizeLBS :: BL.ByteString -> BL.ByteString normalizeLBS = BL.filter (/= fromIntegral (Char.ord '\r')) {------------------------------------------------------------------------------- Arbitrary Instances -------------------------------------------------------------------------------} newtype SndFactor = SndFactor ScrubbedBytes deriving stock (Eq, Show) deriving newtype (ByteArrayAccess) instance Arbitrary SndFactor where arbitrary = do n <- choose (0, 64) bytes <- BS.pack <$> vector n return $ SndFactor $ BA.convert bytes tob16text :: ByteString -> Text tob16text = T.decodeUtf8 . encode EBase16 b16encode :: Text -> ByteString b16encode = encode EBase16 . T.encodeUtf8 b16decode :: Text -> Either String ByteString b16decode = fromBase16 . T.encodeUtf8