Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vesting Feature Improvement #74

Open
14 tasks done
devfull opened this issue Aug 16, 2022 · 0 comments
Open
14 tasks done

Vesting Feature Improvement #74

devfull opened this issue Aug 16, 2022 · 0 comments
Assignees

Comments

@devfull
Copy link
Contributor

devfull commented Aug 16, 2022

Overview

This task is to fix and improve the vesting feature. The current data structure
used in the native script generation module has several flaws.

  • The input specification of a private sale does not map investor address to
    their allocation. Currently, a list is used instead, this allows the same
    address to appear several times.

  • The tranche proportions are not given as a proper ratio, but as a quantity
    out of an implicit total. This is error prone and yield to uncanny
    calculations.

  • The integer partition of the total allocation in tranches does not take into
    account the incorrect possibility of rounding amounts to zero neither the
    minimum of ADA per UTxO required to build the scripts.

  • The current datatypes expect slots instead of POSIX time. Some logic for
    finding the right slots for the native scripts properties is specific to the
    vesting feature. Conversion between POSIX time and slots should be handled by
    this module. Also, the current specification has times seen as relative
    durations, not as absolute points in time. This contrains the tranches to be
    sequential and contiguous.

  • The splitting in tranches operation yields in a single step a consolidated
    data structure, as a single map with lists as values, representing tranches
    informations inside the map structure. While it is efficient, this design can be
    difficult to grasp. There is no intermediate datatype and the implementation
    further blur this design choice by doing several tasks within the splitting
    operation such as allocation partitioning, slot calculation and address
    deserialization.

    Besides leading to weak composability, the intermediate custom map lose
    asset class information required later, forcing to have both the intermediate
    map and the original structure in the signature of final output generators.

    Another approach would be to use a list of maps as the resulting data
    structure of the splitting operation, instead of a map to lists. The only
    drawback is the algorithmic complexity of maps union, which should take into
    account that all maps share the same keys.

  • While this custom intermediate map has a structure very close to the output
    corresponding to the database file, this is not so true for the distribution
    file. This may have been a source of confusion in the implementation of the
    distribution file generator. It is broken by accumulating again all the
    partitioned allocations to be sent to the first tranche script.

    Also for better interoperability and traceability, it would be nice if the
    database file also contained the computed script address and amounts required by
    the distribution file. Then, the distribution file data would be a strict subset
    of the database file data. This would allow a nice pipeline : splitting, feeding
    database generator, feeding distribution generator.

  • Furthermore, the current feature has no tests and no arbitrary instances.

Changed Specification

The new specification gives the following datatypes. Note the proximity between
PrivateSale and PrivateSaleTranche.

type Allocation = Natural

newtype InvestorAddress = InvestorAddress { unInvestorAddress :: Text }

data TrancheProperties = TrancheProperties
    { proportion :: Ratio Natural
    , unlockTime :: POSIXTime
    }

data PrivateSale = PrivateSale
    { tranchesProperties :: NonEmpty TrancheProperties
    , assetClass :: AssetClass
    , allocationByAddress :: NEMap InvestorAddress Allocation
    }

data PrivateSaleTranche = PrivateSaleTranche
    { trancheUnlockTime :: POSIXTime
    , trancheAssetClass :: AssetClass
    , trancheAllocationByAddress :: NEMap InvestorAddress Allocation
    }

data NativeScript = NativeScript
    { requireSignature :: PubKeyHash
    , requireTimeAfter :: POSIXTime
    }

data NativeScriptInfo = NativeScriptInfo
    { requiring :: NativeScript
    , recipient :: Recipient
    }

data DatabaseOutput = DatabaseOutput
    { lockedAssetClass :: AssetClass
    , lockedFunds :: NEMap InvestorAddress (NonEmpty NativeScriptInfo)
    }

Features

The resolution of this issue requires the following tasks:

  • Redesign the solution with new data structures
  • Partition total allocation based on tranches ratios
  • Assert partitioned allocations can have a minimum
  • Handle POSIX time to slot conversion logic
  • Split PrivateSale in list of PrivateSaleTranche
  • Generate final structure for database
  • Generate final structure for distribution
  • Write all property based tests

Minimum UTxO

The calculation of the minimum UTxO is a feature frequently needed. The issue
is furthermore to improve the way of obtaining this value by not depending
anymore on cardano-cli and use instead Cardano.Api.

For user-friendliness, calculateMinimumUTxO is reimplemented for accepting
simple value or asset class instead of fully constructed TxOut that requires
valid address. This implies the following tasks:

  • Reimplement calculateMinimumUTxO
  • Construct default protocol parameters
  • Convert from Plutus values

The validity of the calculation is based on the source Cardano/Api/Fees.hs
and the documentation from cardano-ledger (after fixing a small typo with
IntersectMBO/cardano-ledger#3012).

Tests

In order to write the tests, the following extra components are required:

  • Generator of random well-formed address with cardano-address
  • Arbitrary instances for several Plutus datatypes
  • Arbitrary instances for well-formed inputs and intermediate structures
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant