Copyright | © 2018-2020 IOHK |
---|---|
License | Apache-2.0 |
Safe Haskell | None |
Language | Haskell2010 |
This module contains types for address discovery. The two address discovery schemes implemented are:
Synopsis
-
class
IsOurs
s entity
where
- isOurs :: entity -> s -> ( Maybe ( NonEmpty DerivationIndex ), s)
-
class
IsOurs
s
Address
=>
IsOwned
s key
where
- isOwned :: s -> (key ' RootK XPrv , Passphrase "encryption") -> Address -> Maybe (key ' AddressK XPrv , Passphrase "encryption")
-
class
GenChange
s
where
- type ArgGenChange s :: Type
- genChange :: ArgGenChange s -> s -> ( Address , s)
-
class
CompareDiscovery
s
where
- compareDiscovery :: s -> Address -> Address -> Ordering
-
class
KnownAddresses
s
where
- knownAddresses :: s -> [( Address , AddressState , NonEmpty DerivationIndex )]
-
class
GetPurpose
(key ::
Depth
->
Type
->
Type
)
where
- getPurpose :: Index ' Hardened ' PurposeK
-
class
GetAccount
s (key ::
Depth
->
Type
->
Type
) | s -> key
where
- getAccount :: s -> key ' AccountK XPub
- coinTypeAda :: Index ' Hardened ' CoinTypeK
-
class
MaybeLight
s
where
- maybeDiscover :: Maybe (LightDiscoverTxs s)
-
newtype
DiscoverTxs
addr txs s =
DiscoverTxs
{
- discoverTxs :: forall m. Monad m => (addr -> m txs) -> s -> m (txs, s)
- data PendingIxs k
- emptyPendingIxs :: PendingIxs k
- pendingIxsToList :: PendingIxs k -> [ Index ' Soft k]
- pendingIxsFromList :: [ Index ' Soft k] -> PendingIxs k
- nextChangeIndex :: forall (key :: Depth -> Type -> Type ) k. Pool ( KeyFingerprint "payment" key) ( Index ' Soft k) -> PendingIxs k -> ( Index ' Soft k, PendingIxs k)
- updatePendingIxs :: Index ' Soft k -> PendingIxs k -> PendingIxs k
Abstractions
class IsOurs s entity where Source #
Checks whether or not a given entity belongs to us.
This abstraction exists to give us the ability to keep the wallet business logic agnostic to the address derivation and discovery mechanisms.
This is needed because two different address schemes lives on Cardano:
-
A hierarchical random scheme:
rather
custom
made, with several flaws; this is the original and now legacy address scheme. - A hierarchical sequential scheme: a new scheme based on the BIP-0044 specification, which is better suited for our present needs.
In practice, we will need a wallet that can support both, even if not at the same time, and this little abstraction can buy us this without introducing too much overhead.
:: entity | |
-> s | |
-> ( Maybe ( NonEmpty DerivationIndex ), s) |
Returns derivation path if the entity is ours, otherwise Nothing. |
Instances
class IsOurs s Address => IsOwned s key where Source #
More powerful than
isOurs
, this abstractions offer the underlying state
the ability to find / compute the address private key corresponding to a
given known address.
Requiring
IsOwned
as a constraint supposed that there is a way to recover
the root private key of a particular wallet. This isn't true for externally
owned wallet which would delegate its key management to a third party (like
a hardware Ledger or Trezor).
:: s | |
-> (key ' RootK XPrv , Passphrase "encryption") | |
-> Address | |
-> Maybe (key ' AddressK XPrv , Passphrase "encryption") |
Derive the private key corresponding to an address. Careful, this operation can be costly. Note that the state is discarded from this function as we do not intend to discover any addresses from this operation; This is merely a lookup from known addresses. |
Instances
IsOwned ( RndState n) ByronKey Source # | |
|
|
KnownNat p => IsOwned ( RndAnyState n p) ByronKey Source # | |
Defined in Cardano.Wallet.Primitive.AddressDiscovery.Random isOwned :: RndAnyState n p -> ( ByronKey ' RootK XPrv , Passphrase "encryption") -> Address -> Maybe ( ByronKey ' AddressK XPrv , Passphrase "encryption") Source # |
|
( IsOurs ( SeqState n k) Address , SupportsDiscovery n k, AddressIndexDerivationType k ~ ' Soft ) => IsOwned ( SeqState n k) k Source # | |
( AddressIndexDerivationType k ~ ' Soft , KnownNat p) => IsOwned ( SeqAnyState n k p) k Source # | |
Defined in Cardano.Wallet.Primitive.AddressDiscovery.Sequential isOwned :: SeqAnyState n k p -> (k ' RootK XPrv , Passphrase "encryption") -> Address -> Maybe (k ' AddressK XPrv , Passphrase "encryption") Source # |
class GenChange s where Source #
Abstracting over change address generation. In theory, this is only needed for sending transactions on a wallet following a particular scheme. This abstractions allows for defining an heuristic to pick new change address. For instance, in BIP-44, change addresses belong to a particular change chain (also called "Internal Chain").
type ArgGenChange s :: Type Source #
:: ArgGenChange s | |
-> s | |
-> ( Address , s) |
Generate a new change address for the given scheme. The rules for generating a new change address depends on the underlying scheme. |
Instances
class CompareDiscovery s where Source #
Ordering addresses by discovery date.
If
a1
has been discovered before
a2
, then the following equation holds:
compareDiscovery s a1 a2 == LT
If
a1
has been discovered after
a2
, then the following equation holds:
compareDiscovery s a1 a2 == GT
Note that, if an address isn't known it is considered not discovered and therefore, is always _greater than_ any known address.
Instances
CompareDiscovery ( RndState n) Source # | |
|
|
CompareDiscovery ( RndAnyState n p) Source # | |
Defined in Cardano.Wallet.Primitive.AddressDiscovery.Random compareDiscovery :: RndAnyState n p -> Address -> Address -> Ordering Source # |
|
SupportsDiscovery n k => CompareDiscovery ( SeqState n k) Source # | |
SupportsDiscovery n k => CompareDiscovery ( SharedState n k) Source # | |
Defined in Cardano.Wallet.Primitive.AddressDiscovery.Shared compareDiscovery :: SharedState n k -> Address -> Address -> Ordering Source # |
|
SupportsDiscovery n k => CompareDiscovery ( SeqAnyState n k p) Source # | |
Defined in Cardano.Wallet.Primitive.AddressDiscovery.Sequential compareDiscovery :: SeqAnyState n k p -> Address -> Address -> Ordering Source # |
class KnownAddresses s where Source #
Extract the list of all known addresses.
NOTE: Change addresses aren't considered "known" until they've been used. The rationale is that, we don't want users or consumers of the wallet to be using change addresses prematurely.
knownAddresses :: s -> [( Address , AddressState , NonEmpty DerivationIndex )] Source #
Instances
class GetPurpose (key :: Depth -> Type -> Type ) where Source #
Instances
class GetAccount s (key :: Depth -> Type -> Type ) | s -> key where Source #
getAccount :: s -> key ' AccountK XPub Source #
Instances
GetAccount ( SeqState n k) k Source # | |
GetAccount ( SharedState n k) k Source # | |
Defined in Cardano.Wallet.Primitive.AddressDiscovery.Shared getAccount :: SharedState n k -> k ' AccountK XPub Source # |
coinTypeAda :: Index ' Hardened ' CoinTypeK Source #
One master node (seed) can be used for unlimited number of independent cryptocoins such as Bitcoin, Litecoin or Namecoin. However, sharing the same space for various cryptocoins has some disadvantages.
This level creates a separate subtree for every cryptocoin, avoiding reusing addresses across cryptocoins and improving privacy issues.
Coin type is a constant, set for each cryptocoin. For Cardano this constant is set to 1815' (or 0x80000717). 1815 is the birthyear of our beloved Ada Lovelace.
Hardened derivation is used at this level.
class MaybeLight s where Source #
Checks whether the address discovery state
s
works in light-mode
and returns a procedure for discovering addresses
if that is indeed the case.
maybeDiscover :: Maybe (LightDiscoverTxs s) Source #
Instances
MaybeLight ( RndState n) Source # | |
Defined in Cardano.Wallet.Primitive.AddressDiscovery.Random maybeDiscover :: Maybe (LightDiscoverTxs ( RndState n)) Source # |
|
MaybeLight ( RndAnyState n p) Source # | |
Defined in Cardano.Wallet.Primitive.AddressDiscovery.Random maybeDiscover :: Maybe (LightDiscoverTxs ( RndAnyState n p)) Source # |
|
DelegationAddress n ShelleyKey => MaybeLight ( SeqState n ShelleyKey ) Source # | |
Defined in Cardano.Wallet.Primitive.AddressDerivation.Shelley maybeDiscover :: Maybe (LightDiscoverTxs ( SeqState n ShelleyKey )) Source # |
|
PaymentAddress n IcarusKey => MaybeLight ( SeqState n IcarusKey ) Source # | |
MaybeLight ( SharedState n k) Source # | |
Defined in Cardano.Wallet.Primitive.AddressDiscovery.Shared maybeDiscover :: Maybe (LightDiscoverTxs ( SharedState n k)) Source # |
|
MaybeLight ( SeqAnyState n k p) Source # | |
Defined in Cardano.Wallet.Primitive.AddressDiscovery.Sequential maybeDiscover :: Maybe (LightDiscoverTxs ( SeqAnyState n k p)) Source # |
newtype DiscoverTxs addr txs s Source #
Function that discovers transactions based on an address.
DiscoverTxs | |
|
data PendingIxs k Source #
An ordered set of pending indexes. This keep track of indexes used
Instances
emptyPendingIxs :: PendingIxs k Source #
An empty pending set of change indexes.
NOTE: We do not define a
Monoid
instance here because there's no rational
of combining two pending sets.
pendingIxsToList :: PendingIxs k -> [ Index ' Soft k] Source #
pendingIxsFromList :: [ Index ' Soft k] -> PendingIxs k Source #
Construct a
PendingIxs
from a list, ensuring that it is a set of indexes
in descending order.
nextChangeIndex :: forall (key :: Depth -> Type -> Type ) k. Pool ( KeyFingerprint "payment" key) ( Index ' Soft k) -> PendingIxs k -> ( Index ' Soft k, PendingIxs k) Source #
Get the next change index; If every available indexes have already been taken, we'll rotate the pending set and re-use already provided indexes.
updatePendingIxs :: Index ' Soft k -> PendingIxs k -> PendingIxs k Source #
Update the set of pending indexes by discarding every indexes _below_ the given index.
Why is that?
Because we really do care about the higher index that was last used in order to know from where we can generate new indexes.