Skip to content

Commit

Permalink
client/trade: Return counterPartyConfirms error.
Browse files Browse the repository at this point in the history
Because the return data cannot all be trusted if the method has an
error, return that error up to the caller rather than just logging and
returning with possibly false values.

For swaps using contracts it is ok for the swap to be status none, in
which case we cannot check the lock time or confirmations on chain yet.
Do not log an error in this case.
  • Loading branch information
JoeGruffins authored and chappjc committed Apr 28, 2022
1 parent 83ccb74 commit c3327ea
Showing 1 changed file with 31 additions and 15 deletions.
46 changes: 31 additions & 15 deletions client/core/trade.go
Original file line number Diff line number Diff line change
Expand Up @@ -842,38 +842,36 @@ func (t *trackedTrade) processCancelMatch(msgMatch *msgjson.Match) error {
//
// This method accesses match fields and MUST be called with the trackedTrade
// mutex lock held for reads.
func (t *trackedTrade) counterPartyConfirms(ctx context.Context, match *matchTracker) (have, needed uint32, changed, spent, expired bool) {
func (t *trackedTrade) counterPartyConfirms(ctx context.Context, match *matchTracker) (have, needed uint32, changed, spent, expired bool, err error) {
fail := func(err error) (uint32, uint32, bool, bool, bool, error) {
return 0, 0, false, false, false, err
}

// Counter-party's swap is the "to" asset.
needed = t.wallets.toAsset.SwapConf

// Check the confirmations on the counter-party's swap. If counterSwap is
// not set, we shouldn't be here, but catch this just in case.
if match.counterSwap == nil {
t.dc.log.Warnf("counterPartyConfirms: No AuditInfo available to check!")
return
return fail(errors.New("counterPartyConfirms: No AuditInfo available to check!"))
}

wallet := t.wallets.toWallet
coin := match.counterSwap.Coin

_, lockTime, err := wallet.LocktimeExpired(match.MetaData.Proof.CounterContract)
if err != nil {
t.dc.log.Errorf("Error checking if locktime has expired on taker's contract on order %s, "+
"match %s: %v", t.ID(), match, err)
return fail(fmt.Errorf("error checking if locktime has expired on taker's contract on order %s, "+
"match %s: %w", t.ID(), match, err))
}
expired = time.Until(lockTime) < 0 // not necessarily refundable, but can be at any moment

have, spent, err = wallet.SwapConfirmations(ctx, coin.ID(),
match.MetaData.Proof.CounterContract, match.MetaData.Stamp)
if err != nil {
if !errors.Is(err, asset.ErrSwapNotInitiated) {
// No need to log an error if swap not initiated as this
// is expected for newly made swaps involving contracts.
t.dc.log.Errorf("Failed to get confirmations of the counter-party's swap %s (%s) "+
"for match %s, order %v: %v",
coin, t.wallets.toAsset.Symbol, match, t.UID(), err)
}
return
return fail(fmt.Errorf("failed to get confirmations of the counter-party's swap %s (%s) "+
"for match %s, order %v: %w",
coin, t.wallets.toAsset.Symbol, match, t.UID(), err))
}

// Log the pending swap status at new heights only.
Expand Down Expand Up @@ -1076,7 +1074,16 @@ func (t *trackedTrade) isSwappable(ctx context.Context, match *matchTracker) boo
coinIDString(toAssetID, match.MetaData.Proof.MakerSwap), unbip(toAssetID))
// If the maker is the counterparty, we can determine swappability
// based on the confirmations.
confs, req, changed, spent, expired := t.counterPartyConfirms(ctx, match)
confs, req, changed, spent, expired, err := t.counterPartyConfirms(ctx, match)
if err != nil {
if !errors.Is(err, asset.ErrSwapNotInitiated) {
// We cannot get the swap data yet but there is no need
// to log an error if swap not initiated as this is
// expected for newly made swaps involving contracts.
t.dc.log.Errorf("isSwappable: %v", err)
}
return false
}
if spent {
t.dc.log.Errorf("Counter-party's swap is spent before we could broadcast our own")
match.MetaData.Proof.SelfRevoked = true
Expand Down Expand Up @@ -1163,7 +1170,16 @@ func (t *trackedTrade) isRedeemable(ctx context.Context, match *matchTracker) bo
case order.TakerSwapCast:
if match.Side == order.Maker {
// Check the confirmations on the taker's swap.
confs, req, changed, spent, expired := t.counterPartyConfirms(ctx, match)
confs, req, changed, spent, expired, err := t.counterPartyConfirms(ctx, match)
if err != nil {
if !errors.Is(err, asset.ErrSwapNotInitiated) {
// We cannot get the swap data yet but there is no need
// to log an error if swap not initiated as this is
// expected for newly made swaps involving contracts.
t.dc.log.Errorf("isRedeemable: %v", err)
}
return false
}
if spent {
t.dc.log.Errorf("Order %s, match %s counter-party's swap is spent before we could redeem", t.ID(), match)
match.MetaData.Proof.SelfRevoked = true
Expand Down

0 comments on commit c3327ea

Please sign in to comment.