Skip to content

Commit

Permalink
rework 'TransactionLayer' to play well with RoundRobin MA selection a…
Browse files Browse the repository at this point in the history
…lgs.

  The main change compared to before is the unification of all 'mkStdTx', 'mkDelegationJoinTx' and 'mkDelegationQuitTx' under one single interface 'mkTransaction'. We know for sure that this is possible because that's exactly how things are implemented behind the scene in the cardano-wallet package. This is a quite disruptive change, but should help really help simplifying the coin selection code which has grown large and complex over the past months with many pitfalls and logic duplication here and there.

  Another major change is the introduction of a 'TransactionCtx' type which should help unifying the caller interface in a more elegant way, instead of having to hand-craft every single argument by hand depending on the function to call. The main idea behind this 'TransactionCtx' is that it contains details about the transaction that are known prior to constructing the transaction. Typically, they'd come from the surrounding context (e.g. the current time) or, be user-provided.
  • Loading branch information
KtorZ committed Jan 27, 2021
1 parent 395b954 commit bc3d0a6
Showing 1 changed file with 63 additions and 79 deletions.
142 changes: 63 additions & 79 deletions lib/core/src/Cardano/Wallet/Transaction.hs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ module Cardano.Wallet.Transaction
-- * Interface
TransactionLayer (..)
, DelegationAction (..)
, TransactionCtx (..)

-- * Errors
, ErrMkTx (..)
Expand All @@ -33,22 +34,26 @@ import Cardano.Api.Typed
( AnyCardanoEra )
import Cardano.Wallet.Primitive.AddressDerivation
( Depth (..), Passphrase )
import Cardano.Wallet.Primitive.CoinSelection
( CoinSelection (..) )
import Cardano.Wallet.Primitive.Fee
( Fee, FeePolicy )
import Cardano.Wallet.Primitive.CoinSelection.MA.RoundRobin
( SelectionCriteria, SelectionResult, SelectionSkeleton )
import Cardano.Wallet.Primitive.Types
( PoolId, SlotNo (..) )
( PoolId, ProtocolParameters, SlotNo (..) )
import Cardano.Wallet.Primitive.Types.Address
( Address (..) )
import Cardano.Wallet.Primitive.Types.Coin
( Coin (..) )
import Cardano.Wallet.Primitive.Types.TokenMap
( TokenMap )
import Cardano.Wallet.Primitive.Types.Tx
( SealedTx (..), Tx (..), TxMetadata )
( SealedTx (..), Tx (..), TxMetadata, TxOut )
import Cardano.Wallet.Primitive.Types.UTxOIndex
( UTxOIndex )
import Data.ByteString
( ByteString )
import Data.List.NonEmpty
( NonEmpty )
import Data.Quantity
( Quantity (..) )
( Quantity )
import Data.Text
( Text )
import Data.Word
Expand All @@ -57,18 +62,18 @@ import GHC.Generics
( Generic )

data TransactionLayer k = TransactionLayer
{ mkStdTx
{ mkTransaction
:: AnyCardanoEra
-- Era for which the transaction should be created.
-> (XPrv, Passphrase "encryption")
-- Reward account
-> (Address -> Maybe (k 'AddressK XPrv, Passphrase "encryption"))
-- Key store
-> SlotNo
-- Transaction expiry (TTL) slot.
-> Maybe TxMetadata
-- User or application-defined metadata to embed in the transaction.
-> CoinSelection
-> ProtocolParameters
-- Current protocol parameters
-> TransactionCtx
-- An additional context about the transaction
-> SelectionResult TxOut
-- A balanced coin selection where all change addresses have been
-- assigned.
-> Either ErrMkTx (Tx, SealedTx)
Expand All @@ -80,80 +85,45 @@ data TransactionLayer k = TransactionLayer
-- This expects as a first argument a mean to compute or lookup private
-- key corresponding to a particular address.

, mkDelegationJoinTx
:: AnyCardanoEra
-- Era for which the transaction should be created.
-> PoolId
-- Pool Id to which we're planning to delegate
-> (XPrv, Passphrase "encryption")
-- Reward account
-> (Address -> Maybe (k 'AddressK XPrv, Passphrase "encryption"))
-- Key store
-> SlotNo
-- Transaction expiry (TTL) slot.
-> CoinSelection
-- A balanced coin selection where all change addresses have been
-- assigned.
-> Either ErrMkTx (Tx, SealedTx)
-- ^ Construct a transaction containing a certificate for delegating to
-- a stake pool.
--
-- The certificate is a combination of the 'PoolId' and the public key
-- of the reward account. (Note that this is an address key and
-- HD account keys are something different)

, mkDelegationQuitTx
:: AnyCardanoEra
-- Era for which the transaction should be created.
-> (XPrv, Passphrase "encryption")
-- Reward account
-> (Address -> Maybe (k 'AddressK XPrv, Passphrase "encryption"))
-- Key store
-> SlotNo
-- Transaction expiry (TTL) slot.
-> CoinSelection
-- A balanced coin selection where all change addresses have been
-- assigned.
-> Either ErrMkTx (Tx, SealedTx)
-- ^ Construct a transaction containing a certificate for quiting from
-- a stake pool.
--
-- The certificate is the public key of the reward account.
, initSelectionCriteria
:: ProtocolParameters
-- Current protocol parameters
-> TransactionCtx
-- Additional information about the transaction
-> UTxOIndex
-- Available UTxO from which inputs should be selected.
-> NonEmpty TxOut
-- A list of target outputs
-> SelectionCriteria

, initDelegationSelection
:: Coin
-- Current fee policy
-> DelegationAction
-- What sort of action is going on
-> CoinSelection
-- ^ An initial selection where 'deposit' and/or 'reclaim' have been set
-- accordingly.
, calcMinimumCost
:: ProtocolParameters
-- Current protocol parameters
-> TransactionCtx
-- Additional information about the transaction
-> SelectionSkeleton
-- An intermediate representation of an ongoing selection
-> Coin
-- ^ Compute a minimal fee amount necessary to pay for a given selection
-- This also include necessary deposits.

, minimumFee
:: FeePolicy
-> Maybe DelegationAction
-> Maybe TxMetadata
-> CoinSelection
-> Fee
-- ^ Compute a minimal fee amount necessary to pay for a given
-- coin-selection.
, calcMinimumCoinValue
:: ProtocolParameters
-- Current protocol parameters
-> TokenMap
-- A bundle of native assets
-> Coin
-- ^ The minimum ada value needed in a UTxO carrying the asset bundle

, estimateMaxNumberOfInputs
:: Quantity "byte" Word16
-- Max tx size
-- Transaction max size in bytes
-> Maybe TxMetadata
-- Metadata associated with the transaction
-- Metadata associated with the transaction.
-> Word8
-- desired number of outputs
-- Number of outputs in transaction
-> Word8
-- ^ Calculate a "theoretical" maximum number of inputs given a maximum
-- transaction size and desired number of outputs.
--
-- The actual transaction size cannot be known until it has been fully
-- determined by coin selection.
--
-- This estimate will err on the side of permitting more inputs,
-- resulting in a transaction which may be too large.
-- ^ Approximate maximum number of inputs.

, decodeSignedTx
:: AnyCardanoEra
Expand All @@ -162,6 +132,20 @@ data TransactionLayer k = TransactionLayer
-- ^ Decode an externally-signed transaction to the chain producer
}

-- | Some additional context about a transaction. This typically contains
-- details that are known upfront about the transaction and are used to
-- construct it from inputs selected from the wallet's UTxO.
data TransactionCtx = TransactionCtx
{ txWithdrawal :: Coin
-- ^ Withdrawal amount from a reward account, can be zero.
, txMetadata :: Maybe TxMetadata
-- ^ User or application-defined metadata to embed in the transaction.
, txTimeToLive :: SlotNo
-- ^ Transaction expiry (TTL) slot.
, txDelegationAction :: Maybe DelegationAction
-- ^ An additional delegation to take.
} deriving (Show, Eq)

-- | Whether the user is attempting any particular delegation action.
data DelegationAction = RegisterKeyAndJoin PoolId | Join PoolId | Quit
deriving (Show, Eq, Generic)
Expand Down

0 comments on commit bc3d0a6

Please sign in to comment.