Skip to content

Commit

Permalink
vsp: Recalculate ticket live/expiry heights.
Browse files Browse the repository at this point in the history
Previously the live & expiry heights were only being set once upon
feePayment initialization, which meant that an unmined ticket added to
the VSP client would have heights set to zero forever.

With this change, if either of the values are found to be zero, we check
if the ticket has been mined yet and the heights are recalculated to
their correct values if so.
  • Loading branch information
jholdstock authored and jrick committed Aug 8, 2023
1 parent 7fbedb9 commit 8722867
Showing 1 changed file with 44 additions and 17 deletions.
61 changes: 44 additions & 17 deletions internal/vsp/feepayment.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,47 @@ func parseTicket(ticket *wire.MsgTx, params *chaincfg.Params) (
return
}

// calcHeights checks if the ticket has been mined, and if so, sets the live
// height and expiry height fields. Should be called with mutex already held.
func (fp *feePayment) calcHeights() {
_, minedHeight, err := fp.client.wallet.TxBlock(fp.ctx, &fp.ticketHash)
if err != nil {
// This is not expected to ever error, as the ticket has already been
// fetched from the wallet at least one before this point is reached.
fp.client.log.Errorf("Failed to query block which mines ticket: %v", err)
return
}

if minedHeight < 2 {
return
}

// Note the off-by-one; this is correct. Tickets become live one block after
// the params would indicate.
fp.ticketLive = minedHeight + int32(fp.params.TicketMaturity) + 1
fp.ticketExpires = fp.ticketLive + int32(fp.params.TicketExpiry)
}

// expiryHeight returns the height at which the ticket expires. Returns zero if
// the block is not yet mined. Should be called with mutex already held.
func (fp *feePayment) expiryHeight() int32 {
if fp.ticketExpires == 0 {
fp.calcHeights()
}

return fp.ticketExpires
}

// liveHeight returns the height at which the ticket becomes live. Returns zero
// if the block is not yet mined. Should be called with mutex already held.
func (fp *feePayment) liveHeight() int32 {
if fp.ticketLive == 0 {
fp.calcHeights()
}

return fp.ticketLive
}

func (fp *feePayment) ticketSpent() bool {
ctx := fp.ctx
ticketOut := wire.OutPoint{Hash: fp.ticketHash, Index: 0, Tree: 1}
Expand All @@ -150,7 +191,7 @@ func (fp *feePayment) ticketExpired() bool {
_, tipHeight := w.MainChainTip(ctx)

fp.mu.Lock()
expires := fp.ticketExpires
expires := fp.expiryHeight()
fp.mu.Unlock()

return expires > 0 && tipHeight >= expires
Expand Down Expand Up @@ -232,20 +273,6 @@ func (c *Client) feePayment(ctx context.Context, ticketHash *chainhash.Hash, pai
return nil
}

_, ticketHeight, err := w.TxBlock(ctx, ticketHash)
if err != nil {
// This is not expected to ever error, as the ticket was fetched
// from the wallet in the above call.
fp.client.log.Errorf("failed to query block which mines ticket: %v", err)
return nil
}
if ticketHeight >= 2 {
// Note the off-by-one; this is correct. Tickets become live
// one block after the params would indicate.
fp.ticketLive = ticketHeight + int32(c.params.TicketMaturity) + 1
fp.ticketExpires = fp.ticketLive + int32(c.params.TicketExpiry)
}

fp.votingAddr, fp.commitmentAddr, err = parseTicket(ticket, c.params)
if err != nil {
fp.client.log.Errorf("%v is not a ticket: %v", ticketHash, err)
Expand Down Expand Up @@ -326,8 +353,8 @@ func (fp *feePayment) next() time.Duration {
_, tipHeight := w.MainChainTip(fp.ctx)

fp.mu.Lock()
ticketLive := fp.ticketLive
ticketExpires := fp.ticketExpires
ticketLive := fp.liveHeight()
ticketExpires := fp.expiryHeight()
fp.mu.Unlock()

var jitter time.Duration
Expand Down

0 comments on commit 8722867

Please sign in to comment.