Skip to content

Commit

Permalink
client/asset/dcr: refundTx must determine spent status
Browse files Browse the repository at this point in the history
If lookupTxOutput indicates spend status is  unknown, we must search for
a spending transaction so that the caller can initiate a redemption
search if they are the taker, otherwise they have to wait for revoke.
  • Loading branch information
chappjc committed Jan 5, 2023
1 parent 1d26996 commit caa6858
Showing 1 changed file with 29 additions and 3 deletions.
32 changes: 29 additions & 3 deletions client/asset/dcr/dcr.go
Original file line number Diff line number Diff line change
Expand Up @@ -3074,14 +3074,40 @@ func (dcr *ExchangeWallet) refundTx(coinID, contract dex.Bytes, val uint64, refu
if utxo == nil {
return nil, asset.CoinNotFoundError
}
if spent == 1 {
val = uint64(utxo.Value)

switch spent {
case 0: // unspent, proceed to create refund tx
case 1: // spent!
// Refund MUST signal to caller that it is spent via
// asset.CoinNotFoundError so that it knows to begin looking for the
// counterparty's redeem and move on to redeem too.
// counterparty's redeem and move on to redeem too. TODO: attempt to
// identify if it was manually refunded with the backup transaction,
// in which case we can skip broadcast and record the spending
// transaction we may locate as below.
return nil, fmt.Errorf("contract %s:%d is spent (%w)", txHash, vout, asset.CoinNotFoundError)
case -1: // unknown, we must scan for spending tx
// First find the block containing the output itself.
scriptAddr, err := stdaddr.NewAddressScriptHashV0(contract, dcr.chainParams)
if err != nil {
return nil, fmt.Errorf("error encoding contract address: %w", err)
}
_, pkScript := scriptAddr.PaymentScript()
outFound, _, err := dcr.externalTxOutput(dcr.ctx, newOutPoint(txHash, vout),
pkScript, time.Now().Add(-60*24*time.Hour)) // search up to 60 days ago
if err != nil {
return nil, err // possibly the contract is still in mempool
}
spent, err := dcr.isOutputSpent(dcr.ctx, outFound) // => findTxOutSpender
if err != nil {
return nil, fmt.Errorf("error checking if contract %v:%d is spent: %w", txHash, vout, err)
}
if spent {
return nil, fmt.Errorf("contract %s:%d is spent (%w)", txHash, vout, asset.CoinNotFoundError)
}
}
val = uint64(utxo.Value)
}

sender, _, lockTime, _, err := dexdcr.ExtractSwapDetails(contract, dcr.chainParams)
if err != nil {
return nil, fmt.Errorf("error extracting swap addresses: %w", err)
Expand Down

0 comments on commit caa6858

Please sign in to comment.