From 29268467f9dbada1eaceb4bc251fe4ad9597c906 Mon Sep 17 00:00:00 2001 From: jholdstock Date: Mon, 15 Jun 2020 12:10:10 +0100 Subject: [PATCH] Delete tickets with no information. --- background/background.go | 24 +++++++++++++++++++++++- database/database_test.go | 1 + database/ticket.go | 12 ++++++++++++ database/ticket_test.go | 24 ++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 1 deletion(-) diff --git a/background/background.go b/background/background.go index 4c399ce..0723b87 100644 --- a/background/background.go +++ b/background/background.go @@ -3,6 +3,7 @@ package background import ( "context" "encoding/json" + "errors" "sync" "time" @@ -10,6 +11,7 @@ import ( "github.com/decred/dcrd/chaincfg/v3" "github.com/decred/vspd/database" "github.com/decred/vspd/rpc" + "github.com/jrick/wsrpc/v2" ) var ( @@ -28,6 +30,9 @@ const ( // requiredConfs is the number of confirmations required to consider a // ticket purchase or a fee transaction to be final. requiredConfs = 6 + // errNoTxInfo is defined in dcrd/dcrjson. Copying here so we dont need to + // import the whole package. + errNoTxInfo = -5 ) // Notify is called every time a block notification is received from dcrd. @@ -76,9 +81,26 @@ func blockConnected() { for _, ticket := range unconfirmed { tktTx, err := dcrdClient.GetRawTransaction(ticket.Hash) if err != nil { - log.Errorf("GetRawTransaction error: %v", err) + // errNoTxInfo here probably indicates a tx which was never mined + // and has been removed from the mempool. For example, a ticket + // purchase tx close to an sdiff change, or a ticket purchase tx + // which expired. Remove it from the db. + var e *wsrpc.Error + if errors.As(err, &e) && e.Code == errNoTxInfo { + log.Infof("Removing unconfirmed ticket from db - no information available "+ + "about transaction %s", err.Error()) + + err = db.DeleteTicket(ticket) + if err != nil { + log.Errorf("DeleteTicket error: %v", err) + } + } else { + log.Errorf("GetRawTransaction error: %v", err) + } + continue } + if tktTx.Confirmations >= requiredConfs { ticket.Confirmed = true err = db.UpdateTicket(ticket) diff --git a/database/database_test.go b/database/database_test.go index c85e322..4032753 100644 --- a/database/database_test.go +++ b/database/database_test.go @@ -28,6 +28,7 @@ func TestDatabase(t *testing.T) { "testTicketFeeExpired": testTicketFeeExpired, "testFilterTickets": testFilterTickets, "testAddressIndex": testAddressIndex, + "testDeleteTicket": testDeleteTicket, } for testName, test := range tests { diff --git a/database/ticket.go b/database/ticket.go index 2010970..06cb4c3 100644 --- a/database/ticket.go +++ b/database/ticket.go @@ -103,6 +103,18 @@ func (vdb *VspDatabase) InsertNewTicket(ticket Ticket) error { }) } +func (vdb *VspDatabase) DeleteTicket(ticket Ticket) error { + return vdb.db.Update(func(tx *bolt.Tx) error { + ticketBkt := tx.Bucket(vspBktK).Bucket(ticketBktK) + + err := ticketBkt.Delete([]byte(ticket.Hash)) + if err != nil { + return fmt.Errorf("could not delete ticket: %v", err) + } + + return nil + }) +} func (vdb *VspDatabase) UpdateTicket(ticket Ticket) error { return vdb.db.Update(func(tx *bolt.Tx) error { ticketBkt := tx.Bucket(vspBktK).Bucket(ticketBktK) diff --git a/database/ticket_test.go b/database/ticket_test.go index 18fc543..482baed 100644 --- a/database/ticket_test.go +++ b/database/ticket_test.go @@ -55,6 +55,30 @@ func testInsertNewTicket(t *testing.T) { } } +func testDeleteTicket(t *testing.T) { + // Insert a ticket into the database. + ticket := exampleTicket() + err := db.InsertNewTicket(ticket) + if err != nil { + t.Fatalf("error storing ticket in database: %v", err) + } + + // Delete ticket + err = db.DeleteTicket(ticket) + if err != nil { + t.Fatalf("error deleting ticket: %v", err) + } + + // Nothing should be in the db. + _, found, err := db.GetTicketByHash(ticket.Hash) + if err != nil { + t.Fatalf("error retrieving ticket by ticket hash: %v", err) + } + if found { + t.Fatal("expected found==false") + } +} + func testGetTicketByHash(t *testing.T) { ticket := exampleTicket() // Insert a ticket into the database.