Skip to content

Commit 98c9c70

Browse files
committed
vsp: More fixes for vsp fee confirmation tracking
This includes the following fixes for vspClient tracking: * Schedule all fee payments for reconcile payment, regardless of fee tx status. * Remove unvotable tickets from jobs and attempt to revoke tickets * Catch signature errors from SignTransaction attempt * Handle payfee error for expired fee tx from vspd. Abandon current fee tx and then retry to make a fresh one.
1 parent c18b824 commit 98c9c70

File tree

2 files changed

+46
-11
lines changed

2 files changed

+46
-11
lines changed

internal/vsp/feepayment.go

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212

1313
"decred.org/dcrwallet/errors"
1414
"decred.org/dcrwallet/internal/uniformprng"
15+
"decred.org/dcrwallet/rpc/client/dcrd"
1516
"decred.org/dcrwallet/wallet"
1617
"decred.org/dcrwallet/wallet/txrules"
1718
"decred.org/dcrwallet/wallet/txsizes"
@@ -189,15 +190,20 @@ func (c *Client) feePayment(ticketHash *chainhash.Hash, policy Policy) (fp *feeP
189190
if fp == nil {
190191
return
191192
}
193+
var schedule bool
192194
c.mu.Lock()
193195
fp2 := c.jobs[*ticketHash]
194196
if fp2 != nil {
195197
fp.stop()
196198
fp = fp2
197199
} else {
198200
c.jobs[*ticketHash] = fp
201+
schedule = true
199202
}
200203
c.mu.Unlock()
204+
if schedule {
205+
fp.schedule("reconcile payment", fp.reconcilePayment)
206+
}
201207
}()
202208

203209
ctx := context.Background()
@@ -250,9 +256,9 @@ func (c *Client) feePayment(ticketHash *chainhash.Hash, policy Policy) (fp *feeP
250256
return nil
251257
}
252258

259+
fp.state = unprocessed // XXX fee created, but perhaps not submitted with vsp.
253260
feeHash, err := w.VSPFeeHashForTicket(ctx, ticketHash)
254261
if err != nil {
255-
fp.state = unprocessed
256262
// caller must schedule next method, as paying the fee may
257263
// require using provided transaction inputs.
258264
return fp
@@ -271,9 +277,7 @@ func (c *Client) feePayment(ticketHash *chainhash.Hash, policy Policy) (fp *feeP
271277
}
272278

273279
fp.feeTx = fee
274-
fp.fee = -1 // XXX fee amount (not needed anymore?)
275-
fp.state = unprocessed // XXX fee created, but perhaps not submitted with vsp.
276-
fp.schedule("reconcile payment", fp.reconcilePayment)
280+
fp.fee = -1 // XXX fee amount (not needed anymore?)
277281

278282
return fp
279283
}
@@ -427,8 +431,6 @@ func (fp *feePayment) receiveFeeAddress() error {
427431
fp.feeAddr = feeAddr
428432
fp.mu.Unlock()
429433

430-
_ = fp.makeFeeTx(nil)
431-
fp.schedule("reconcile payment", fp.reconcilePayment)
432434
return nil
433435
}
434436

@@ -471,8 +473,6 @@ func (fp *feePayment) makeFeeTx(tx *wire.MsgTx) error {
471473

472474
// XXX fp.fee == -1?
473475
if fee == 0 {
474-
// XXX locking
475-
// this schedules paying the fee
476476
err := fp.receiveFeeAddress()
477477
if err != nil {
478478
return err
@@ -560,12 +560,17 @@ func (fp *feePayment) makeFeeTx(tx *wire.MsgTx) error {
560560

561561
// sign
562562
sigErrs, err := w.SignTransaction(ctx, tx, txscript.SigHashAll, nil, nil, nil)
563-
if err != nil {
563+
if err != nil || len(sigErrs) > 0 {
564564
log.Errorf("failed to sign transaction: %v", err)
565+
sigErrStr := ""
565566
for _, sigErr := range sigErrs {
566567
log.Errorf("\t%v", sigErr)
568+
sigErrStr = fmt.Sprintf("\t%v", sigErr) + " "
567569
}
568-
return err
570+
if err != nil {
571+
return err
572+
}
573+
return fmt.Errorf(sigErrStr)
569574
}
570575

571576
err = w.SetPublished(ctx, &feeHash, false)
@@ -731,7 +736,23 @@ func (fp *feePayment) reconcilePayment() error {
731736
if feeTx == nil || len(feeTx.TxOut) == 0 {
732737
err := fp.makeFeeTx(nil)
733738
if err != nil {
734-
fp.schedule("reconcile payment", fp.reconcilePayment)
739+
var apiErr *BadRequestError
740+
if errors.As(err, &apiErr) && apiErr.Code == codeTicketCannotVote {
741+
fp.remove("ticket cannot vote")
742+
// Attempt to Revoke Tickets, we're not returning any errors here
743+
// and just logging.
744+
n, err := w.NetworkBackend()
745+
if err != nil {
746+
log.Errorf("unable to get network backend for revoking tickets %v", err)
747+
} else {
748+
if rpc, ok := n.(*dcrd.RPC); ok {
749+
err := w.RevokeTickets(ctx, rpc)
750+
if err != nil {
751+
log.Errorf("cannot revoke vsp tickets %v", err)
752+
}
753+
}
754+
}
755+
}
735756
return err
736757
}
737758
}
@@ -865,6 +886,17 @@ func (fp *feePayment) submitPayment() (err error) {
865886
err = fp.client.post(ctx, "/api/v3/payfee", fp.commitmentAddr,
866887
&payfeeResponse, json.RawMessage(requestBody))
867888
if err != nil {
889+
var apiErr *BadRequestError
890+
if errors.As(err, &apiErr) && apiErr.Code == codeFeeExpired {
891+
// Fee has been expired, so abandon current feetx, set fp.feeTx
892+
// to nil and retry submit payment to make a new fee tx.
893+
feeHash := feeTx.TxHash()
894+
err := w.AbandonTransaction(ctx, &feeHash)
895+
if err != nil {
896+
log.Errorf("error abandoning expired fee tx %v", err)
897+
}
898+
fp.feeTx = nil
899+
}
868900
return fmt.Errorf("payfee: %w", err)
869901
}
870902

wallet/wallet.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5481,6 +5481,9 @@ func (w *Wallet) VSPFeeHashForTicket(ctx context.Context, ticketHash *chainhash.
54815481
feeHash = data.FeeHash
54825482
return nil
54835483
})
5484+
if err == nil && feeHash == (chainhash.Hash{}) {
5485+
err = errors.E(errors.NotExist)
5486+
}
54845487
return feeHash, err
54855488
}
54865489

0 commit comments

Comments
 (0)