HORIZON HASKELLDocslts/ghc-9.14.xd82dee82026-10-12Search names, modules, packages, or :: a typeCtrl K

GHC 9.14.1 · lts/ghc-9.14.x · d82dee8 · 2026-10-12

Modulecardano-addresses-4.0.2Haskell2010

Cardano.Address.Style.Icarus

  • 4 types
  • 22 values

This module provides an implementation of:

  • GenMasterKey: for generating Icarus master keys from mnemonic sentences

  • HardDerivation: for hierarchical hard derivation of parent to child keys

  • SoftDerivation: for hierarchical soft derivation of parent to child keys

  • PaymentAddress: for constructing addresses from a public key

We call Icarus addresses the new format of Cardano addresses which came after Byron. This is the format initially used in Yoroi and now also used by Daedalus.

A cryptographic key for sequential-scheme address derivation, with phantom-types to disambiguate key types.

let rootPrivateKey = Icarus 'RootK XPrv
let accountPubKey  = Icarus 'AccountK XPub
let addressPubKey  = Icarus 'PaymentK XPub

Icarus

5 declarations
newtypenewtype Icarus (depth :: Depth) key
#
Instances16HasNetworkDiscriminant, PaymentAddress, GenMasterKey, HardDerivation, SoftDerivation, Functor, …
datadata Role
#

Role the key assumes

Instances7Bounded, Eq, Ord, Show, Generic, NFData, …
  • Bounded RoleDefined in cardano-addresses-4.0.2 · Cardano.Address.Style.Icarus
  • Eq RoleDefined in cardano-addresses-4.0.2 · Cardano.Address.Style.Icarus
  • Ord RoleDefined in cardano-addresses-4.0.2 · Cardano.Address.Style.Icarus
  • Show RoleDefined in cardano-addresses-4.0.2 · Cardano.Address.Style.Icarus
  • Generic RoleDefined in cardano-addresses-4.0.2 · Cardano.Address.Style.Icarus
  • NFData RoleDefined in cardano-addresses-4.0.2 · Cardano.Address.Style.Icarus
  • type Rep Role = D1 ('MetaData "Role" "Cardano.Address.Style.Icarus" "cardano-addresses-4.0.2-IfBlVg9kl2D9r65sjHkHQ2" 'False) (C1 ('MetaCons "UTxOExternal" 'PrefixI 'False) U1 :+: C1 ('MetaCons "UTxOInternal" 'PrefixI 'False) U1)Defined in cardano-addresses-4.0.2 · Cardano.Address.Style.Icarus

Key Derivation

5 declarations

Example:

Generating a root key from SomeMnemonic
>>> :set -XOverloadedStrings
>>> :set -XTypeApplications
>>> :set -XDataKinds
>>> :set -XFlexibleContexts
>>> import Cardano.Mnemonic ( mkSomeMnemonic )
>>> import Cardano.Address ( base58 )
>>> import Cardano.Address.Derivation ( toXPub )
>>> import qualified Cardano.Address.Style.Icarus as Icarus
>>>
>>> let (Right mw) = mkSomeMnemonic @'[15] ["network","empty","cause","mean","expire","private","finger","accident","session","problem","absurd","banner","stage","void","what"]
>>> let sndFactor = mempty -- Or alternatively, a second factor mnemonic transformed to bytes via someMnemonicToBytes
>>> let rootK = Icarus.genMasterKeyFromMnemonic mw sndFactor :: Icarus 'RootK XPrv
Deriving child keys

Let's consider the following 3rd, 4th and 5th derivation paths 0'/0/14 accIx assumes values from 2147483648 (ie. 0x80000000) to 4294967295 (ie. 0xFFFFFFFF) addIx assume values from 0 to 2147483647 (ie. 7FFFFFFF)

>>> let Just accIx = indexFromWord32 0x80000000
// this is the same as
>>> let accIx = minBound @(Index 'Hardened 'AccountK)
>>> let acctK = Icarus.deriveAccountPrivateKey rootK accIx
>>> let Just addIx = indexFromWord32 0x00000014
>>> let addrK = Icarus.deriveAddressPrivateKey acctK Icarus.UTxOExternal addIx
>>> base58 $ Icarus.paymentAddress Icarus.icarusMainnet (toXPub $ addrK)
>>>Ae2tdPwUPEZ8XpsjgQPH2cJdtohkYrxJ3i5y6mVsrkZZkdpdn6mnr4Rt6wG

Addresses

7 declarations
datadata AddressInfo
#

The result of eitherInspectAddress for Icarus addresses.

Instances5Eq, Show, Generic, ToJSON, Rep
valueinspectAddress :: MonadThrow m => Address -> m Value
#

How to go from address root and the payment address

Example:
>>> :set -XOverloadedStrings
>>> :set -XTypeApplications
>>> :set -XDataKinds
>>> :set -XFlexibleContexts
>>> import Cardano.Mnemonic ( mkSomeMnemonic )
>>> import qualified Cardano.Address.Style.Icarus as Icarus
>>> import Cardano.Address.Derivation ( toXPub )
>>> import Cardano.Address ( base58 )
>>> let (Right mw) = mkSomeMnemonic '[12] ["moon","fox","ostrich","quick","cactus","raven","wasp","intact","first","ring","crumble","error"]
>>> let sndFactor = mempty
>>> let rootK = Icarus.genMasterKeyFromMnemonic mw sndFactor :: Icarus 'RootK XPrv
>>> let Just accIx = indexFromWord32 0x80000000
>>> let acctK = Icarus.deriveAccountPrivateKey rootK accIx
>>> let Just addIx = indexFromWord32 0x00000014
>>> let addrK = Icarus.deriveAddressPrivateKey acctK Icarus.UTxOExternal addIx
>>> (toXPub $ addrK)
Icarus {getKey = XPub {xpubPublicKey = "223148230206187135253SO151216183210]}s:151134174q173207184202EM176170220216235&1243", xpubChaincode = ChainCode "\160196&8~208165241138SOH222ETX*150&214185196 153DC2167165243155136228255229~d253"}}
>>> base58 $ Icarus.paymentAddress icarusMainnet (toXPub $ addrK)
Ae2tdPwUPEYyzBcNXkFWKywMiZ9eSd96dQxhBQd371foiH16Y7gFgLBj9G5

>>> import Cardano.Codec.Cbor
>>> import Crypto.Hash.Algorithms (Blake2b_224, SHA3_256)
>>> import Crypto.Hash (hash)
>>> let blake2b224 = hash _ Blake2b_224
>>> let sha3256 = hash _ @SHA3_256
>>> import qualified Codec.CBOR.Encoding as CBOR
>>> let encodeXPub = CBOR.encodeBytes (xpubToBytes . Icarus.getKey $ icarusAddrKPub)
>>> let encodeSpendingData = CBOR.encodeListLen 2 <> CBOR.encodeWord8 0 <> encodeXPub
>>> let encodeAttrs = CBOR.encodeMapLen 0
>>> import qualified Data.ByteArray as BA
>>> let rootAddr = BA.convert $ blake2b224 $ sha3256 $ CBOR.toStrictByteString $ mempty <> CBOR.encodeListLen 3 <> CBOR.encodeWord8 0 <> encodeSpendingData <> encodeAttrs
>>> encode EBase16 rootAddr
"1fdde02c9e087474aa7ab0a46ae2f6d316a92cd0fa2d4e8b1c2eebdf"

Usage from the command-line:

 echo Ae2tdPwUPEYyzBcNXkFWKywMiZ9eSd96dQxhBQd371foiH16Y7gFgLBj9G5 | cardano-address address inspect
{
   "stake_reference": "none",
   "address_style": Icarus,
   "address_root": "1fdde02c9e087474aa7ab0a46ae2f6d316a92cd0fa2d4e8b1c2eebdf",
   "network_tag": null,
   "address_type": 8
}

Determines whether an Address is an Icarus address.

Returns a JSON object with information about the address, or throws ErrInspectAddress if the address isn't an icarus address. @since 2.0.0

datadata ErrInspectAddress
#

Possible errors from inspecting a Shelley address

Instances6Eq, Show, Generic, Exception, ToJSON, Rep

Network Discrimination

5 declarations

Unsafe

4 declarations
valueliftXPrv :: XPrv -> Icarus depth XPrv
#

Unsafe backdoor for constructing an Icarus key from a raw XPrv. this is unsafe because it lets the caller choose the actually derivation depth.

This can be useful however when serializing / deserializing such a type, or to speed up test code (and avoid having to do needless derivations from a master key down to an address key for instance).

valueliftXPub :: XPub -> Icarus depth XPub
#

Unsafe backdoor for constructing an Icarus key from a raw XPub. this is unsafe because it lets the caller choose the actually derivation depth.

This can be useful however when serializing / deserializing such a type, or to speed up test code (and avoid having to do needless derivations from a master key down to an address key for instance).