cardano-wallet-core-2022.7.1: The Wallet Backend for a Cardano node.
Safe Haskell None
Language Haskell2010

Cardano.Wallet.Primitive.Delegation.State

Description

Module for DelegationState .

Synopsis

Creation

data DelegationState k Source #

Delegation state

Goals

  1. Allow a wallet to have an arbitrary number of stake keys
  2. Ensure those stake keys can be automatically discovered on-chain
  3. Ensure the wallet is always aware of all stake keys it registers, even in the case of concurrent user actions on multiple wallet instances, and old wallet software.

How

We track a consecutive range of keys that is extended with delegation of the next unused key, and shrunk with key de-registration. We use a PointerUTxO to ensure that transactions changing the state can't be accepted to the ledger in any other order than intended. We also need some special care regarding stake key 0, which old wallet software could try to de-register.

Diagram

Diagram of states, where the list denotes active (registered and delegating) keys.

Here we assume the minUTxOValue is 1 ada.

Note that intermediate steps for the PointerUTxO should be skipped within a transaction. E.g. to transition from [] to [0,1,2] we should deposit 1 ada to key 3, skipping key 2.

See the implementation of setPortfolioOf and applyTx for more details.

┌────────────────────┐           ┌────────────────────┐                     ┌────────────────────┐            ┌─────────────────────┐
│                    │           │                    │                     │                    │            │                     │
│                    │           │                    │       Pointer       │                    │            │                     │
│                    │──────────▶│                    │ ──────deposit──────▶│                    │ ─────────▶ │                     │ ─────────▶
│                    │           │                    │                     │       [0,1]        │            │       [0,1,2]       │
│         []         │           │        [0]         │                     │1 ada held by key 2 │            │ 1 ada held by key 3 │
│                    │           │                    │                     │                    │            │                     │
│                    │           │                    │       Pointer       │                    │            │                     │
│                    │◀──────────│                    │ ◀─────deposit ──────│                    │◀────────── │                     │◀──────────
│                    │           │                    │       returned      │                    │            │                     │
└────────────────────┘◀──┐       └────────────────────┘                     └────────────────────▲            ▲─────────────────────▲            ▲
                         └───┐                                                     │       ▲     └─┐         ┌┘      │       ▲      └─┐         ┌┘
Normal states                └───┐                                                 │       │       └─┐     ┌─┘       │       │        └─┐     ┌─┘
                                 └───┐                                             │       │         └─┐ ┌─┘         │       │          └─┐ ┌─┘
╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳└───┐╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳╳│╳╳╳╳╳╳╳│╳╳╳╳╳╳╳╳╳╳╳│ │╳╳╳╳╳╳╳╳╳╳╳│╳╳╳╳╳╳╳│╳╳╳╳╳╳▶     ├─┤
                                         └───┐                                     │       │         ┌─┘ └─┐         │       │          ┌─┘ └─┐
States caused by                             └────┐Pointer                         ▼       │       ┌─┘     └─┐       ▼       │        ┌─┘     └─┐
old wallet                                        └deposit                  ┌────────────────────┐─┘         └┬─────────────────────┐─┘         └─
de-registering                                     returned─┐               │                    │            │                     │
stake-key 0                                                 └────┐          │                    │ ─────────▶ │                     │ ─────────▶
of multi-stake                                                   └────┐     │                    │            │                     │
key wallet                                                            └──── │        [1]         │            │        [1,2]        │
                                                                            │1 ada held by key 2 │            │ 1 ada held by key 3 │
                                                                            │                    │            │                     │
                                                                            │                    │◀────────── │                     │◀──────────
                                                                            │                    │            │                     │
                                                                            │                    │            │                     │
                                                                            └────────────────────┘            └─────────────────────┘

Constructors

DelegationState

Fields

Instances

Instances details
( Eq (k ' AccountK XPub ), Eq (k ' AddressK XPub )) => Eq ( DelegationState k) Source #
Instance details

Defined in Cardano.Wallet.Primitive.Delegation.State

( Show (k ' AccountK XPub ), Show (k ' AddressK XPub )) => Show ( DelegationState k) Source #
Instance details

Defined in Cardano.Wallet.Primitive.Delegation.State

Generic ( DelegationState k) Source #
Instance details

Defined in Cardano.Wallet.Primitive.Delegation.State

( NFData (k ' AccountK XPub ), NFData (k ' AddressK XPub )) => NFData ( DelegationState k) Source #
Instance details

Defined in Cardano.Wallet.Primitive.Delegation.State

type Rep ( DelegationState k) Source #
Instance details

Defined in Cardano.Wallet.Primitive.Delegation.State

type Rep ( DelegationState k) = D1 (' MetaData "DelegationState" "Cardano.Wallet.Primitive.Delegation.State" "cardano-wallet-core-2022.7.1-AGKhlyz9liLKN3QqZD1gj" ' False ) ( C1 (' MetaCons "DelegationState" ' PrefixI ' True ) ( S1 (' MetaSel (' Just "rewardAccountKey") ' NoSourceUnpackedness ' NoSourceStrictness ' DecidedLazy ) ( Rec0 (k ' AccountK XPub )) :*: S1 (' MetaSel (' Just "state") ' NoSourceUnpackedness ' NoSourceStrictness ' DecidedLazy ) ( Rec0 State )))

initialDelegationState :: k ' AccountK XPub -> DelegationState k Source #

Construct the initial delegation state.

Operations

presentableKeys :: SoftDerivation k => DelegationState k -> [k ' AddressK XPub ] Source #

All stake keys worth listing to the user.

May include: 1. Active stake keys 2. The next un-active key

NOTE: In theory we might want also present stake keys that are unexpectedly registered, as they could be de-registered to reclaim the deposit, but this should in-practice never happen.

If sn denotes the state with n registered and delegating keys: >>> presentableKeys s0 [0] >>> presentableKeys s1 [0, 1] >>> presentableKeys s2 [0, 1, 2]

activeKeys :: SoftDerivation k => DelegationState k -> [k ' AddressK XPub ] Source #

For testing. Returns all registered and delegating stake keys.

For Testing

data State Source #

The internal state, without the account key.

TODO: Perhaps we should model this as S = S1 * S2, where S1 = Bool, S2 = ix * UTxOPointer - having two "concurrent" states tracking stake keys, where the first one is identical to legacy single-stake key wallets.

Maybe that would help simplify applyTx and setPortfolioOf ...

Constructors

Zero

No active stake keys. The initial state of a new wallet.

One

The first stake-key (index 0) is registered and either delegating or about to be delegating.

More

There is more than one active stake keys. Can only be reached using wallets with support for multiple stake keys.

Fields

Instances

Instances details
Eq State Source #
Instance details

Defined in Cardano.Wallet.Primitive.Delegation.State

Show State Source #
Instance details

Defined in Cardano.Wallet.Primitive.Delegation.State

Generic State Source #
Instance details

Defined in Cardano.Wallet.Primitive.Delegation.State

NFData State Source #
Instance details

Defined in Cardano.Wallet.Primitive.Delegation.State

type Rep State Source #
Instance details

Defined in Cardano.Wallet.Primitive.Delegation.State

data Key0Status Source #

Is key 0 still registered? For compatibility with single-stake-key wallets, we need to track this.

>>> activeKeys (More (toEnum 3) p ValidKey0)
[0, 1, 2]
>>> activeKeys (More (toEnum 3) p MissingKey0)
[1, 2]

(pseudocode; requires a bit more boilerplate to compile)

See the implementation of applyTx for how it is used.

Chain following model

data Tx Source #

A transaction type specific to DelegationState .

Intended to be converted both from and to a more real transaction type.

When constructing a real transaction from Tx , these outputs should appear before other outputs. In the theoretical event that there's also a user-specified output with the same payment key as the pointer output, applyTx will track the first one as the new pointer.

Constructors

Tx

data Cert Source #

Constructors

RegisterKey RewardAccount
Delegate RewardAccount

Which pool we're delegating to is here (and for now) irrelevant. The main thing is that there exists a witness on-chain for this stake key (registration certs don't require witnesses)

TODO: We may also want to add the PoolId here.

DeRegisterKey RewardAccount

applyTx :: forall k. ( SoftDerivation k, ToRewardAccount k, MkKeyFingerprint k Address , MkKeyFingerprint k (k ' AddressK XPub )) => Tx -> Hash "Tx" -> DelegationState k -> DelegationState k Source #

Apply a Tx to a DelegationState .

Expects the PointerUTxO to be correctly managed, and will panic otherwise.

setPortfolioOf Source #

Arguments

:: ( SoftDerivation k, ToRewardAccount k)
=> DelegationState k
-> Coin

minUTxOVal

-> (k ' AddressK XPub -> Address )

A way to construct an Address

-> ( RewardAccount -> Bool )

Whether or not the key is registered.

TODO: Need a Set or Map for the real implementation with LSQ.

-> Int

Target number of stake keys.

-> Maybe Tx

Given a DelegationState , produce a Tx registering or de-registering stake-keys, in order to have n stake-keys.

E.g. setPortfolioOf s0 _ _ 2 creates a tx which after application causes the state to have activeKeys == [0,1]

Returns Nothing if the target n is already reached.