From 638214db89050a6615c127a80ab96529c7fc29cb Mon Sep 17 00:00:00 2001 From: Jonathan Chappelow Date: Mon, 13 Feb 2023 17:56:29 -0600 Subject: [PATCH] distinguish very first auth from subsequent login auth for reserves --- client/core/bond.go | 4 ++++ client/core/core.go | 37 +++++++++++++++++++++++-------------- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/client/core/bond.go b/client/core/bond.go index a2d556f139..8350f7cfd5 100644 --- a/client/core/bond.go +++ b/client/core/bond.go @@ -1099,6 +1099,10 @@ func (c *Core) PostBond(form *PostBondForm) (*PostBondResult, error) { "Consider using UpdateBondOptions instead.", targetTier, autoBondAsset, wallet.amtString(maxBondedAmt)) } else if maintain { // new account with tier maintenance enabled + // Fully pre-reserve funding with the wallet before making and + // transactions. bondConfirmed will call authDEX, which will recognize + // that it is the first authorization of the account with the DEX via + // the totalReserves and isAuthed fields of dexAccount. mod := bondOverlap * form.Bond if !wallet.ReserveBondFunds(int64(mod), true) { return nil, newError(bondAssetErr, "insufficient available balance to reserve %v for bonds plus fees", diff --git a/client/core/core.go b/client/core/core.go index 703e83d811..3cc0135231 100644 --- a/client/core/core.go +++ b/client/core/core.go @@ -6047,7 +6047,7 @@ func (c *Core) authDEX(dc *dexConnection) error { bond *asset.Bond confs uint32 } - var toPost []queuedBond + var toPost, toConfirmLocally []queuedBond // Identify bonds we consider live that are either pending or missing from // server. In either case, do c.monitorBondConfs (will be immediate postBond @@ -6081,7 +6081,7 @@ func (c *Core) authDEX(dc *dexConnection) error { bondIDStr, symb) // unexpected, but postbond again // Unknown on server. postBond at required confs. - c.log.Infof("Posting locally-confirmed bond %v (%s).", bondIDStr, symb) + c.log.Infof("Preparing to post locally-confirmed bond %v (%s).", bondIDStr, symb) toPost = append(toPost, queuedBond{assetBond(bond), bondAsset.Confs}) continue } @@ -6102,11 +6102,8 @@ func (c *Core) authDEX(dc *dexConnection) error { _, found := remoteLiveBonds[key] if found { - // It's live server-side. Confirm it locally. - c.log.Debugf("Confirming pending bond %v that is confirmed server side", bondIDStr) - if err = c.bondConfirmed(dc, bond.AssetID, bond.CoinID, tier /* no change */); err != nil { - c.log.Errorf("Unable to confirm bond %s: %v", bondIDStr, err) - } + // It's live server-side. Confirm it locally (db and slices). + toConfirmLocally = append(toConfirmLocally, queuedBond{assetBond(bond), 0}) bondedTiers += bond.Amount / bondAsset.Amt continue } @@ -6134,10 +6131,15 @@ func (c *Core) authDEX(dc *dexConnection) error { // Set the account as authenticated. c.log.Infof("Authenticated connection to %s, acct %v, %d active bonds, %d active orders, %d active matches, score %d, tier %d", dc.acct.host, acctID, len(result.ActiveBonds), len(result.ActiveOrderStatuses), len(result.ActiveMatches), result.Score, tier) - // Flag as authenticated before bondConfirmed / monitorBondConfs, which may - // call authDEX if not flagged as such. + updatedAssets := make(assetMap) + // Flag as authenticated before bondConfirmed and monitorBondConfs, which + // may call authDEX if not flagged as such. dc.acct.authMtx.Lock() - firstAuth := !dc.acct.isAuthed + // Reasons we are here: (1) first auth after login, (2) re-auth on + // reconnect, (3) bondConfirmed for the initial bond for the account. + // totalReserved is non-zero in #3, but zero in #1. There are no reserves + // actions to take in #3 since PostBond reserves prior to post. + loginAuth := !dc.acct.isAuthed && dc.acct.totalReserved == 0 dc.acct.isAuthed = true dc.acct.tierChange += tier - dc.acct.tier dc.acct.tier = tier @@ -6145,7 +6147,7 @@ func (c *Core) authDEX(dc *dexConnection) error { c.log.Debugf("Tier/bonding with %v: tier = %v, tierChange = %v, targetTier = %v, bondedTiers = %v, legacy = %v", dc.acct.host, tier, dc.acct.tierChange, dc.acct.targetTier, bondedTiers, legacyFeePaid) // If tier maintenance is enabled AND tier changed, update reserves. - if dc.acct.targetTier > 0 && (dc.acct.tierChange != 0 || firstAuth) { + if dc.acct.targetTier > 0 && (dc.acct.tierChange != 0 || loginAuth) { if bondAsset := bondAssets[dc.acct.bondAsset]; bondAsset == nil { c.log.Warnf("Selected bond asset %s is not supported by %s", unbip(dc.acct.bondAsset), dc.acct.host) } else if bondWallet, ok := c.wallet(bondAsset.ID); ok { @@ -6156,7 +6158,7 @@ func (c *Core) authDEX(dc *dexConnection) error { // reserves reduction (and vice versa). var future int64 - if firstAuth { + if loginAuth { // If we are enabling reserves enforcement for spendable // balance, we need to subtract how much we have already locked // in bonds from the full amount based on the target tier. When @@ -6191,7 +6193,7 @@ func (c *Core) authDEX(dc *dexConnection) error { bondWallet.ReserveBondFunds(future, false) dc.log.Infof("Total reserved for %v is now %v (%v more future in bonds)", dc.acct.host, bondWallet.amtStringSigned(dc.acct.totalReserved), bondWallet.amtStringSigned(future)) - + updatedAssets.count(bondAsset.ID) dc.acct.tierChange = 0 // tier change is now actuated with wallet reserves } } @@ -6200,6 +6202,14 @@ func (c *Core) authDEX(dc *dexConnection) error { for _, pending := range toPost { c.monitorBondConfs(dc, pending.bond, pending.confs, true) } + for _, confirmed := range toConfirmLocally { + bond := confirmed.bond + bondIDStr := coinIDString(bond.AssetID, bond.CoinID) + c.log.Debugf("Confirming pending bond %v that is confirmed server side", bondIDStr) + if err = c.bondConfirmed(dc, bond.AssetID, bond.CoinID, tier /* no change */); err != nil { + c.log.Errorf("Unable to confirm bond %s: %v", bondIDStr, err) + } + } localBondMap := make(map[string]struct{}, len(localActiveBonds)+len(localPendingBonds)) for _, dbBond := range localActiveBonds { @@ -6245,7 +6255,6 @@ func (c *Core) authDEX(dc *dexConnection) error { } exceptions, matchConflicts := dc.compareServerMatches(matches) - updatedAssets := make(assetMap) for oid, matchAnomalies := range exceptions { trade := matchAnomalies.trade missing, extras := matchAnomalies.missing, matchAnomalies.extra