Add ticket hash to payfee request. (#38)

This commit is contained in:
Jamie Holdstock 2020-05-20 08:09:07 +01:00 committed by GitHub
parent d31c24b531
commit cf55092c21
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 16 additions and 155 deletions

View File

@ -36,9 +36,7 @@ func TestDatabase(t *testing.T) {
tests := map[string]func(*testing.T){ tests := map[string]func(*testing.T){
"testInsertFeeAddress": testInsertFeeAddress, "testInsertFeeAddress": testInsertFeeAddress,
"testGetTicketByHash": testGetTicketByHash, "testGetTicketByHash": testGetTicketByHash,
"testGetFeesByFeeAddress": testGetFeesByFeeAddress,
"testInsertFeeAddressVotingKey": testInsertFeeAddressVotingKey, "testInsertFeeAddressVotingKey": testInsertFeeAddressVotingKey,
"testGetInactiveFeeAddresses": testGetInactiveFeeAddresses,
"testUpdateExpireAndFee": testUpdateExpireAndFee, "testUpdateExpireAndFee": testUpdateExpireAndFee,
"testUpdateVoteBits": testUpdateVoteBits, "testUpdateVoteBits": testUpdateVoteBits,
} }
@ -121,45 +119,6 @@ func testGetTicketByHash(t *testing.T) {
} }
} }
func testGetFeesByFeeAddress(t *testing.T) {
// Insert a ticket into the database.
ticket := exampleTicket()
err := db.InsertFeeAddress(ticket)
if err != nil {
t.Fatalf("error storing ticket in database: %v", err)
}
// Retrieve ticket using its fee address.
retrieved, err := db.GetTicketByFeeAddress(ticket.FeeAddress)
if err != nil {
t.Fatalf("error retrieving ticket by fee address: %v", err)
}
// Check it is the correct ticket.
if retrieved.FeeAddress != ticket.FeeAddress {
t.Fatal("retrieved ticket FeeAddress didnt match expected")
}
// Error if non-existent ticket requested.
_, err = db.GetTicketByFeeAddress("Not a real fee address")
if err == nil {
t.Fatal("expected an error while retrieving a non-existent ticket")
}
// Insert another ticket into the database with the same fee address.
ticket.Hash = ticket.Hash + "2"
err = db.InsertFeeAddress(ticket)
if err != nil {
t.Fatalf("error storing ticket in database: %v", err)
}
// Error when more than one ticket matches
_, err = db.GetTicketByFeeAddress(ticket.FeeAddress)
if err == nil {
t.Fatal("expected an error when multiple tickets are found")
}
}
func testInsertFeeAddressVotingKey(t *testing.T) { func testInsertFeeAddressVotingKey(t *testing.T) {
// Insert a ticket into the database. // Insert a ticket into the database.
ticket := exampleTicket() ticket := exampleTicket()
@ -189,39 +148,6 @@ func testInsertFeeAddressVotingKey(t *testing.T) {
} }
} }
func testGetInactiveFeeAddresses(t *testing.T) {
// Insert a ticket into the database.
ticket := exampleTicket()
err := db.InsertFeeAddress(ticket)
if err != nil {
t.Fatalf("error storing ticket in database: %v", err)
}
// Insert a ticket with empty voting key into the database.
ticket.Hash = ticket.Hash + "2"
newFeeAddr := ticket.FeeAddress + "2"
ticket.FeeAddress = newFeeAddr
ticket.VotingKey = ""
err = db.InsertFeeAddress(ticket)
if err != nil {
t.Fatalf("error storing ticket in database: %v", err)
}
// Retrieve unused fee address from database.
feeAddrs, err := db.GetInactiveFeeAddresses()
if err != nil {
t.Fatalf("error retrieving inactive fee addresses: %v", err)
}
// Check we have one value, and its the expected one.
if len(feeAddrs) != 1 {
t.Fatal("expected 1 unused fee address")
}
if feeAddrs[0] != newFeeAddr {
t.Fatal("fee address didnt match expected")
}
}
func testUpdateExpireAndFee(t *testing.T) { func testUpdateExpireAndFee(t *testing.T) {
// Insert a ticket into the database. // Insert a ticket into the database.
ticket := exampleTicket() ticket := exampleTicket()

View File

@ -73,61 +73,6 @@ func (vdb *VspDatabase) InsertFeeAddressVotingKey(address, votingKey string, vot
}) })
} }
func (vdb *VspDatabase) GetInactiveFeeAddresses() ([]string, error) {
var addrs []string
err := vdb.db.View(func(tx *bolt.Tx) error {
ticketBkt := tx.Bucket(vspBktK).Bucket(ticketBktK)
c := ticketBkt.Cursor()
for k, v := c.First(); k != nil; k, v = c.Next() {
var ticket Ticket
err := json.Unmarshal(v, &ticket)
if err != nil {
return fmt.Errorf("could not unmarshal ticket: %v", err)
}
if ticket.VotingKey == "" {
addrs = append(addrs, ticket.FeeAddress)
}
}
return nil
})
return addrs, err
}
func (vdb *VspDatabase) GetTicketByFeeAddress(feeAddr string) (*Ticket, error) {
var tickets []Ticket
err := vdb.db.View(func(tx *bolt.Tx) error {
ticketBkt := tx.Bucket(vspBktK).Bucket(ticketBktK)
c := ticketBkt.Cursor()
for k, v := c.First(); k != nil; k, v = c.Next() {
var ticket Ticket
err := json.Unmarshal(v, &ticket)
if err != nil {
return fmt.Errorf("could not unmarshal ticket: %v", err)
}
if ticket.FeeAddress == feeAddr {
tickets = append(tickets, ticket)
}
}
return nil
})
if err != nil {
return nil, err
}
if len(tickets) != 1 {
return nil, fmt.Errorf("expected 1 ticket with fee address %s, found %d", feeAddr, len(tickets))
}
return &tickets[0], nil
}
func (vdb *VspDatabase) GetTicketByHash(hash string) (Ticket, error) { func (vdb *VspDatabase) GetTicketByHash(hash string) (Ticket, error) {
var ticket Ticket var ticket Ticket
err := vdb.db.View(func(tx *bolt.Tx) error { err := vdb.db.View(func(tx *bolt.Tx) error {

View File

@ -262,7 +262,7 @@ func payFee(c *gin.Context) {
voteBits := payFeeRequest.VoteBits voteBits := payFeeRequest.VoteBits
feeTxBytes, err := hex.DecodeString(payFeeRequest.Hex) feeTxBytes, err := hex.DecodeString(payFeeRequest.FeeTx)
if err != nil { if err != nil {
log.Warnf("Failed to decode tx: %v", err) log.Warnf("Failed to decode tx: %v", err)
sendErrorResponse("failed to decode transaction", http.StatusBadRequest, c) sendErrorResponse("failed to decode transaction", http.StatusBadRequest, c)
@ -279,14 +279,12 @@ func payFee(c *gin.Context) {
// TODO: DB - check expiration given during fee address request // TODO: DB - check expiration given during fee address request
validFeeAddrs, err := db.GetInactiveFeeAddresses() ticket, err := db.GetTicketByHash(payFeeRequest.TicketHash)
if err != nil { if err != nil {
log.Errorf("GetInactiveFeeAddresses error: %v", err) log.Warnf("Invalid ticket from %s", c.ClientIP())
sendErrorResponse("database error", http.StatusInternalServerError, c) sendErrorResponse("invalid ticket", http.StatusBadRequest, c)
return return
} }
var feeAddr string
var feeAmount dcrutil.Amount var feeAmount dcrutil.Amount
const scriptVersion = 0 const scriptVersion = 0
@ -300,28 +298,19 @@ findAddress:
return return
} }
for _, addr := range addresses { for _, addr := range addresses {
addrStr := addr.Address() if addr.Address() == ticket.FeeAddress {
for _, validFeeAddr := range validFeeAddrs {
if addrStr == validFeeAddr {
feeAddr = validFeeAddr
feeAmount = dcrutil.Amount(txOut.Value) feeAmount = dcrutil.Amount(txOut.Value)
break findAddress break findAddress
} }
} }
} }
}
if feeAddr == "" { if feeAmount == 0 {
log.Warnf("feeTx did not include any payments") log.Warnf("FeeTx for ticket %s did not include any payments for address %s", ticket.Hash, ticket.FeeAddress)
sendErrorResponse("feeTx did not include any payments", http.StatusBadRequest, c) sendErrorResponse("feetx did not include any payments for fee address", http.StatusBadRequest, c)
return return
} }
ticket, err := db.GetTicketByFeeAddress(feeAddr)
if err != nil {
log.Errorf("GetFeeByAddress: %v", err)
sendErrorResponse("database error", http.StatusInternalServerError, c)
return
}
voteAddr, err := dcrutil.DecodeAddress(ticket.CommitmentAddress, cfg.NetParams) voteAddr, err := dcrutil.DecodeAddress(ticket.CommitmentAddress, cfg.NetParams)
if err != nil { if err != nil {
log.Errorf("DecodeAddress: %v", err) log.Errorf("DecodeAddress: %v", err)

View File

@ -26,7 +26,8 @@ type feeAddressResponse struct {
type PayFeeRequest struct { type PayFeeRequest struct {
Timestamp int64 `json:"timestamp" binding:"required"` Timestamp int64 `json:"timestamp" binding:"required"`
Hex string `json:"feetx" binding:"required"` TicketHash string `json:"tickethash" binding:"required"`
FeeTx string `json:"feetx" binding:"required"`
VotingKey string `json:"votingkey" binding:"required"` VotingKey string `json:"votingkey" binding:"required"`
VoteBits uint16 `json:"votebits" binding:"required"` VoteBits uint16 `json:"votebits" binding:"required"`
} }