Add ticket hash to payfee request. (#38)
This commit is contained in:
parent
d31c24b531
commit
cf55092c21
@ -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()
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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 {
|
feeAmount = dcrutil.Amount(txOut.Value)
|
||||||
if addrStr == validFeeAddr {
|
break findAddress
|
||||||
feeAddr = validFeeAddr
|
|
||||||
feeAmount = dcrutil.Amount(txOut.Value)
|
|
||||||
break findAddress
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if feeAddr == "" {
|
|
||||||
log.Warnf("feeTx did not include any payments")
|
if feeAmount == 0 {
|
||||||
sendErrorResponse("feeTx did not include any payments", http.StatusBadRequest, c)
|
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 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)
|
||||||
|
|||||||
@ -25,10 +25,11 @@ 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"`
|
||||||
VotingKey string `json:"votingkey" binding:"required"`
|
FeeTx string `json:"feetx" binding:"required"`
|
||||||
VoteBits uint16 `json:"votebits" binding:"required"`
|
VotingKey string `json:"votingkey" binding:"required"`
|
||||||
|
VoteBits uint16 `json:"votebits" binding:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type payFeeResponse struct {
|
type payFeeResponse struct {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user