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

client: bond reserves #2103

Merged
merged 10 commits into from Feb 24, 2023
Merged

client: bond reserves #2103

merged 10 commits into from Feb 24, 2023

Commits on Feb 24, 2023

  1. client/{asset,core}: RefundBond broadcasts too

    The asset.Bonder.RefundBond method now broadcasts, as it was supposed
    to from the beginning. Only MakeBondTx required broadcasting in the
    consumer.
    chappjc committed Feb 24, 2023
    Configuration menu
    Copy the full SHA
    a6ccc12 View commit details
    Browse the repository at this point in the history
  2. client/{asset,core,webserver}: BondLocked balance category

    This adds the client.WalletBalance.BondLocked field, which parallels
    the ContractLocked field. These are used for core to supplement the
    wallet's reported balance with values that the wallet does not
    include in the balance itself because they are not spendable by the
    wallet alone (core authors the spending tx).
    
    This also updates the web UI's TypeScript to include bondLocked
    when appropriate.  This also fixes a bug where contractLocked was
    not included on the wallets page's "Locked" balance category.
    
    This also adds to DCR's implementation fields for reserves tracking.
    The values are included in the reported asset.Balance. Subsequent
    commits will add the ability modify the reserves, and for funding
    methods to respect the reserves.
    chappjc committed Feb 24, 2023
    Configuration menu
    Copy the full SHA
    f0fb1e9 View commit details
    Browse the repository at this point in the history
  3. client/asset/dcr: respect reserves in funding

    This updates the DCR wallet's transaction funding method and helpers to
    respect the reserves added in the previous commit.
    
    To do so without creating sizing transactions to actively isolate the
    reserved value, we add new coin selection functions that we use exclude
    UTXOs from transaction funding. The objective of these coin selection
    functions is different from order funding coin selection.
    
    The main helper, leastOverFund, attempts to pick a subset of the provided
    UTXOs to reach the required amount with the objective of minimizing the
    total amount of the selected UTXOs. This is different from the objective
    used when funding orders, which is to minimize the number of UTXOs (to
    minimize fees).
    
    NOTE: The provided UTXO set MUST be sorted in ascending order (smallest
    first, largest last)!
    
    leastOverFund begins by partitioning the UTXO slice before the smallest
    single UTXO that is large enough to fully fund the requested amount, if
    it exists. If the smaller set is insufficient, the single largest UTXO
    is returned. If instead the set of smaller UTXOs has enough total
    value, it will search for a subset that reaches the amount with least
    over-funding (see subsetSmallBias and subsetLargeBias). If that subset
    has less combined value than the single sufficiently-large UTXO (if it
    exists), the subset will be returned, otherwise the single UTXO will be
    returned.
    
    We also modify the "enough" functions and their constructors with
    excess (change) reporting in a new return from the enough function.
    The constructor also accepts a flag indicating if this returned value
    should be set to zero. The tryFund helper now returns the final excess
    value when it completes UTXO selection. This is used in the
    (*ExchangeWallet).fund method, and in other callers, to discern if
    there would be sufficient remaining in the wallet (including this
    change) to satisfy a reserved amount. This amount is an input to fund
    called "keep". If change should not be considered "kept" (e.g. no
    preceding split txn, or mixing sends change to umixed account where it
    is unusable for reserves), caller should return 0 extra from the enough
    func (via the enough func's constructor flag).
    chappjc committed Feb 24, 2023
    Configuration menu
    Copy the full SHA
    298bf4a View commit details
    Browse the repository at this point in the history
  4. client/{asset,core}: reserves track as bonds are spend/refunded

    This updates DCR's backend to begin modifying the reserves fields
    as bonds are created (locked UTXOs) and spend (unlock UTXOs into
    balance). Subsequent commits add the new exported wallet
    interface methods for a consumer (core) to prepare and adjust the
    reserves for the client's needs.
    
    This also modifies the wallet's MakeBondTx method signature with
    an additional return, an "abandon" function" to be used if the
    consumer decides not to broadcast the generated bond transaction.
    This function both unlocks the bond's funding utxos, and reverts
    the reserves updates that were made when the transaction was
    created.
    chappjc committed Feb 24, 2023
    Configuration menu
    Copy the full SHA
    a0f82aa View commit details
    Browse the repository at this point in the history
  5. client/{asset,core}: ReserveBondFunds and dexAccount.tierChange

    This adds the new Bonder methods, RegisterUnspent and ReserveBondFunds:
    
    RegisterUnspent informs the wallet of a certain amount already locked in
    unspent bonds that will eventually be refunded with RefundBond. This
    should be used prior to ReserveBondFunds. This alone does not enable
    reserves enforcement, and it should be called on bring-up when existing
    bonds that may refund to this wallet are known. Once ReserveBondFunds is
    called, even with 0 for future bonds, these live bond amounts will
    become enforced reserves when they are refunded via RefundBond.
    
    ReserveBondFunds (un)reserves funds for creation of future bonds.
    MakeBondTx will create transactions that decrement these reserves, while
    RefundBond will replenish the reserves. If the wallet's available
    balance should be respected when adding reserves, the boolean argument
    may be set to indicate this, in which case the return value indicates if
    it was able to reserve the funds. In this manner, funds may be
    pre-reserved so that when the wallet receives funds (from either
    external deposits or refunding of live bonds), they will go directly
    into locked balance. When the reserves are decremented to zero (by the
    amount that they were incremented), all enforcement including any fee
    buffering is disabled. Previously registered unspent/active bonds are
    not forgotten however; they total amount of these are tracked in case
    the wallet is used for reserves again in the future.
    
    In core.Core, the new wallet reserves methods are used to maintain
    adequate reserves based on the account's target tier and observed tier
    change. The dexAccount type has new fields to support this:
    - tierChange int64, is the total tier change that needs to be actuated
      with wallet reserves. Facilitates maintenance with changing tier.
    - totalReserved int64, helps track and debug the total amount reserved
      with the wallet's ReserveBondFunds method *only* for this dexAccount.
    
    Use of ReserveBondFunds and RegisterUnspent, facilitated by the new
    dexAccount fields, happens in:
    - connectWallets() via initialize(), after connectDEX(). Here it
      calls RegisterUnspent for all known bonds across all dexConnections.
    - authDEX. On reconnect, any observed tier change is acctuated with
      wallet reserves. Initial auth on login is handled slightly
      differently, (re)reserving the full required amount given the known
      unspent bonds.
    - handleTier change, which is called on penalization only, updates
      the tierChange field of the dexAccount.
    - rotateBonds. Any tierChange value is actuated with reserves.
    - PostBond. When making the initial bond for a new account, with
      maintenance enabled, ReserveBondFunds is used to pre-reseve. Here
      the boolean input is true, and the return is checked to ensure the
      wallet is sufficiently funded to increase reserves by the requested
      amount for the new bonds.
    - UpdateBondOptions. When modifying target tier or changing the bond
      asset. The boolean input and output are also used here.
    
    Also, remove the (*Core).connectAccount helper that should only be used
    on Core startup.
    chappjc committed Feb 24, 2023
    Configuration menu
    Copy the full SHA
    128e05f View commit details
    Browse the repository at this point in the history
  6. Configuration menu
    Copy the full SHA
    f7d4d0a View commit details
    Browse the repository at this point in the history
  7. Configuration menu
    Copy the full SHA
    ced3851 View commit details
    Browse the repository at this point in the history
  8. Configuration menu
    Copy the full SHA
    6b83f90 View commit details
    Browse the repository at this point in the history
  9. Configuration menu
    Copy the full SHA
    375951a View commit details
    Browse the repository at this point in the history
  10. Configuration menu
    Copy the full SHA
    76d5f64 View commit details
    Browse the repository at this point in the history